2
0
Эх сурвалжийг харах

Added type initializer blocks

Brian Fiete 4 жил өмнө
parent
commit
879b15ecd8

+ 9 - 3
IDEHelper/Compiler/BfCompiler.cpp

@@ -6910,16 +6910,22 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
 					{
 					{
 						if ((methodInstGroup.mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference) ||
 						if ((methodInstGroup.mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference) ||
 							(methodInstGroup.mOnDemandKind == BfMethodOnDemandKind_NoDecl_AwaitingReference))
 							(methodInstGroup.mOnDemandKind == BfMethodOnDemandKind_NoDecl_AwaitingReference))
-						{
-							queuedMoreMethods = true;
+						{							
 							if ((methodInstGroup.mDefault != NULL) && (methodInstGroup.mDefault->mIsForeignMethodDef))
 							if ((methodInstGroup.mDefault != NULL) && (methodInstGroup.mDefault->mIsForeignMethodDef))
 							{
 							{
 								mContext->mUnreifiedModule->GetMethodInstance(typeInst, methodInstGroup.mDefault->mMethodDef, BfTypeVector(),
 								mContext->mUnreifiedModule->GetMethodInstance(typeInst, methodInstGroup.mDefault->mMethodDef, BfTypeVector(),
 									(BfGetMethodInstanceFlags)(BfGetMethodInstanceFlag_ForeignMethodDef | BfGetMethodInstanceFlag_UnspecializedPass | BfGetMethodInstanceFlag_ExplicitResolveOnlyPass));
 									(BfGetMethodInstanceFlags)(BfGetMethodInstanceFlag_ForeignMethodDef | BfGetMethodInstanceFlag_UnspecializedPass | BfGetMethodInstanceFlag_ExplicitResolveOnlyPass));
+								queuedMoreMethods = true;
 							}
 							}
 							else
 							else
-								mContext->mUnreifiedModule->GetMethodInstance(typeInst, typeInst->mTypeDef->mMethods[methodInstGroup.mMethodIdx], BfTypeVector(),
+							{
+								auto methodDef = typeInst->mTypeDef->mMethods[methodInstGroup.mMethodIdx];
+								if (methodDef->mMethodType == BfMethodType_Init)
+									continue;
+								mContext->mUnreifiedModule->GetMethodInstance(typeInst, methodDef, BfTypeVector(),
 									(BfGetMethodInstanceFlags)(BfGetMethodInstanceFlag_UnspecializedPass | BfGetMethodInstanceFlag_ExplicitResolveOnlyPass));
 									(BfGetMethodInstanceFlags)(BfGetMethodInstanceFlag_UnspecializedPass | BfGetMethodInstanceFlag_ExplicitResolveOnlyPass));
+								queuedMoreMethods = true;
+							}
 						}
 						}
 					}
 					}
 				}
 				}

+ 16 - 4
IDEHelper/Compiler/BfDefBuilder.cpp

@@ -479,11 +479,19 @@ BfMethodDef* BfDefBuilder::CreateMethodDef(BfMethodDeclaration* methodDeclaratio
 	if (auto ctorDeclaration = BfNodeDynCast<BfConstructorDeclaration>(methodDeclaration))
 	if (auto ctorDeclaration = BfNodeDynCast<BfConstructorDeclaration>(methodDeclaration))
 	{
 	{
 		methodDef->mIsMutating = true;
 		methodDef->mIsMutating = true;
-		methodDef->mMethodType = BfMethodType_Ctor;
-		if (methodDef->mIsStatic)
-			methodDef->mName = "__BfStaticCtor";
+		if (methodDeclaration->mOpenParen != NULL)
+		{
+			methodDef->mMethodType = BfMethodType_Ctor;
+			if (methodDef->mIsStatic)
+				methodDef->mName = "__BfStaticCtor";
+			else
+				methodDef->mName = "__BfCtor";
+		}
 		else
 		else
-			methodDef->mName = "__BfCtor";
+		{
+			methodDef->mMethodType = BfMethodType_Init;
+			methodDef->mName = "__BfInit";
+		}
 	}
 	}
 	else if (methodDeclaration->IsA<BfDestructorDeclaration>())
 	else if (methodDeclaration->IsA<BfDestructorDeclaration>())
 	{		
 	{		
@@ -1133,6 +1141,10 @@ BfMethodDef* BfDefBuilder::AddMethod(BfTypeDef* typeDef, BfMethodType methodType
 			methodDef->mName = "__BfCtorClear";
 			methodDef->mName = "__BfCtorClear";
 			methodDef->mIsNoReflect = true;
 			methodDef->mIsNoReflect = true;
 		}
 		}
+		else if (methodType == BfMethodType_Init)
+		{
+			methodDef->mName = "__BfInit";
+		}
 		else if (methodType == BfMethodType_Dtor)
 		else if (methodType == BfMethodType_Dtor)
 		{
 		{
 			if (isStatic)
 			if (isStatic)

+ 106 - 62
IDEHelper/Compiler/BfModule.cpp

@@ -12058,6 +12058,9 @@ BfModule* BfModule::GetOrCreateMethodModule(BfMethodInstance* methodInstance)
 
 
 BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfMethodDef* methodDef, const BfTypeVector& methodGenericArguments, BfGetMethodInstanceFlags flags, BfTypeInstance* foreignType)
 BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfMethodDef* methodDef, const BfTypeVector& methodGenericArguments, BfGetMethodInstanceFlags flags, BfTypeInstance* foreignType)
 {
 {
+	if (methodDef->mMethodType == BfMethodType_Init)
+		return BfModuleMethodInstance();
+
 	if (((flags & BfGetMethodInstanceFlag_ForceInline) != 0) && (mCompiler->mIsResolveOnly))
 	if (((flags & BfGetMethodInstanceFlag_ForceInline) != 0) && (mCompiler->mIsResolveOnly))
 	{
 	{
 		// Don't bother inlining for resolve-only
 		// Don't bother inlining for resolve-only
@@ -12679,11 +12682,7 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM
 		if ((prevIRFunc) && (!prevIRFunc.IsFake()))
 		if ((prevIRFunc) && (!prevIRFunc.IsFake()))
 			methodInstance->mIRFunction = prevIRFunc; // Take it over		
 			methodInstance->mIRFunction = prevIRFunc; // Take it over		
 	}
 	}
-		
-	/*// 24 bits for typeid, 20 for method id, 20 for specialization index
-	methodInstance->mMethodId = ((int64)typeInst->mTypeId) + ((int64)methodInstGroup->mMethodIdx << 24);
-	if (methodInstGroup->mMethodSpecializationMap != NULL)
-		methodInstance->mMethodId += ((int64)methodInstGroup->mMethodSpecializationMap->size() << 44);*/
+
 	methodInstance->mMethodDef = methodDef;
 	methodInstance->mMethodDef = methodDef;
 	methodInstance->mAlwaysInline = methodDef->mAlwaysInline;
 	methodInstance->mAlwaysInline = methodDef->mAlwaysInline;
 	methodInstance->mMethodInstanceGroup = methodInstGroup;
 	methodInstance->mMethodInstanceGroup = methodInstGroup;
@@ -12711,10 +12710,9 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM
 		}
 		}
 	}
 	}
 
 
-	if (methodDef->mDeclaringType->mTypeDeclaration != typeInst->mTypeDef->mTypeDeclaration)
+	if (methodDef->mMethodType == BfMethodType_Init)
 	{
 	{
-		// With extensions we can have multiple definitions of the same method
-		//methodInstance->mMangleWithIdx = true;
+		methodInstance->mMangleWithIdx = true;
 	}
 	}
 
 
 	BfModule* declareModule = GetOrCreateMethodModule(methodInstance);
 	BfModule* declareModule = GetOrCreateMethodModule(methodInstance);
@@ -15574,6 +15572,8 @@ void BfModule::EmitCtorBody(bool& skipBody)
 	{
 	{
 		// If we had a 'this' initializer, that other ctor will have initialized our fields
 		// If we had a 'this' initializer, that other ctor will have initialized our fields
 
 
+		//auto 
+				
 		if ((!mCompiler->mIsResolveOnly) || 
 		if ((!mCompiler->mIsResolveOnly) || 
 			(mCompiler->mResolvePassData->mAutoComplete == NULL) ||
 			(mCompiler->mResolvePassData->mAutoComplete == NULL) ||
 			(mCompiler->mResolvePassData->mAutoComplete->mResolveType == BfResolveType_ShowFileSymbolReferences))
 			(mCompiler->mResolvePassData->mAutoComplete->mResolveType == BfResolveType_ShowFileSymbolReferences))
@@ -15581,6 +15581,61 @@ void BfModule::EmitCtorBody(bool& skipBody)
 			bool hadInlineInitBlock = false;
 			bool hadInlineInitBlock = false;
 			BfScopeData scopeData;
 			BfScopeData scopeData;
 			
 			
+			auto _CheckInitBlock = [&](BfAstNode* node)
+			{
+				if (!hadInlineInitBlock)
+				{
+					if ((mBfIRBuilder->DbgHasInfo()) && (!mCurTypeInstance->IsUnspecializedType()) && (mHasFullDebugInfo))
+					{
+						UpdateSrcPos(baseCtorNode);
+
+						if (methodDef->mBody == NULL)
+							SetIllegalSrcPos();
+
+						// NOP so we step onto the open paren of the method so we can choose to set into the field initializers or step over them
+						EmitEnsureInstructionAt();
+
+						BfType* thisType = mCurTypeInstance;
+						if (thisType->IsValueType())
+							thisType = CreateRefType(thisType);
+
+						SizedArray<BfIRMDNode, 1> diParamTypes;
+						BfIRMDNode diFuncType = mBfIRBuilder->DbgCreateSubroutineType(diParamTypes);
+
+						mCurMethodState->AddScope(&scopeData);
+						NewScopeState();
+
+						int flags = 0;
+						mCurMethodState->mCurScope->mDIInlinedAt = mBfIRBuilder->DbgGetCurrentLocation();
+						BF_ASSERT(mCurMethodState->mCurScope->mDIInlinedAt);
+						// mCurMethodState->mCurScope->mDIInlinedAt may still be null ifwe don't have an explicit ctor
+						mCurMethodState->mCurScope->mDIScope = mBfIRBuilder->DbgCreateFunction(mBfIRBuilder->DbgGetTypeInst(mCurTypeInstance), "this$initFields", "", mCurFilePosition.mFileInstance->mDIFile,
+							mCurFilePosition.mCurLine + 1, diFuncType, false, true, mCurFilePosition.mCurLine + 1, flags, false, BfIRValue());
+
+						UpdateSrcPos(node);
+
+						auto diVariable = mBfIRBuilder->DbgCreateAutoVariable(mCurMethodState->mCurScope->mDIScope,
+							"this", mCurFilePosition.mFileInstance->mDIFile, mCurFilePosition.mCurLine, mBfIRBuilder->DbgGetType(thisType));
+
+						//
+						{
+							auto loadedThis = GetThis();
+
+							// LLVM can't handle two variables pointing to the same value
+							BfIRValue copiedThisPtr;
+							copiedThisPtr = CreateAlloca(thisType);
+							auto storeInst = mBfIRBuilder->CreateStore(loadedThis.mValue, copiedThisPtr);
+							mBfIRBuilder->ClearDebugLocation(storeInst);
+							mBfIRBuilder->DbgInsertDeclare(copiedThisPtr, diVariable);
+						}
+
+						hadInlineInitBlock = true;
+					}
+				}
+
+				UpdateSrcPos(node);
+			};
+
 			for (auto fieldDef : typeDef->mFields)
 			for (auto fieldDef : typeDef->mFields)
 			{
 			{
 				// For extensions, only handle these fields in the appropriate extension
 				// For extensions, only handle these fields in the appropriate extension
@@ -15613,57 +15668,7 @@ void BfModule::EmitCtorBody(bool& skipBody)
 
 
 					if (fieldDef->mInitializer != NULL)
 					if (fieldDef->mInitializer != NULL)
 					{
 					{
-						if (!hadInlineInitBlock)
-						{
-							if ((mBfIRBuilder->DbgHasInfo()) && (!mCurTypeInstance->IsUnspecializedType()) && (mHasFullDebugInfo))
-							{
-								UpdateSrcPos(baseCtorNode);
-
-								if (methodDef->mBody == NULL)
-									SetIllegalSrcPos();
-
-								// NOP so we step onto the open paren of the method so we can choose to set into the field initializers or step over them
-								EmitEnsureInstructionAt();
-
-								BfType* thisType = mCurTypeInstance;
-								if (thisType->IsValueType())
-									thisType = CreateRefType(thisType);
-
-								SizedArray<BfIRMDNode, 1> diParamTypes;
-								BfIRMDNode diFuncType = mBfIRBuilder->DbgCreateSubroutineType(diParamTypes);
-
-								mCurMethodState->AddScope(&scopeData);
-								NewScopeState();
-
-								int flags = 0;
-								mCurMethodState->mCurScope->mDIInlinedAt = mBfIRBuilder->DbgGetCurrentLocation();
-								BF_ASSERT(mCurMethodState->mCurScope->mDIInlinedAt);
-								// mCurMethodState->mCurScope->mDIInlinedAt may still be null ifwe don't have an explicit ctor
-								mCurMethodState->mCurScope->mDIScope = mBfIRBuilder->DbgCreateFunction(mBfIRBuilder->DbgGetTypeInst(mCurTypeInstance), "this$initFields", "", mCurFilePosition.mFileInstance->mDIFile,
-									mCurFilePosition.mCurLine + 1, diFuncType, false, true, mCurFilePosition.mCurLine + 1, flags, false, BfIRValue());
-
-								UpdateSrcPos(fieldDef->mInitializer);
-
-								auto diVariable = mBfIRBuilder->DbgCreateAutoVariable(mCurMethodState->mCurScope->mDIScope,
-									"this", mCurFilePosition.mFileInstance->mDIFile, mCurFilePosition.mCurLine, mBfIRBuilder->DbgGetType(thisType));
-
-								//
-								{
-									auto loadedThis = GetThis();
-
-									// LLVM can't handle two variables pointing to the same value
-									BfIRValue copiedThisPtr;
-									copiedThisPtr = CreateAlloca(thisType);
-									auto storeInst = mBfIRBuilder->CreateStore(loadedThis.mValue, copiedThisPtr);
-									mBfIRBuilder->ClearDebugLocation(storeInst);
-									mBfIRBuilder->DbgInsertDeclare(copiedThisPtr, diVariable);
-								}
-
-								hadInlineInitBlock = true;
-							}
-						}
-
-						UpdateSrcPos(fieldDef->mInitializer);
+						_CheckInitBlock(fieldDef->mInitializer);
 					}
 					}
 
 
 					BfIRValue fieldAddr;
 					BfIRValue fieldAddr;
@@ -15688,6 +15693,30 @@ void BfModule::EmitCtorBody(bool& skipBody)
 				}
 				}
 			}
 			}
 
 
+			mCurTypeInstance->mTypeDef->PopulateMemberSets();
+			BfMemberSetEntry* entry = NULL;
+			BfMethodDef* initMethodDef = NULL;
+			mCurTypeInstance->mTypeDef->mMethodSet.TryGetWith(String("__BfInit"), &entry);
+			if (entry != NULL)
+				initMethodDef = (BfMethodDef*)entry->mMemberDef;
+
+			SizedArray<BfAstNode*, 8> initBodies;
+
+			for (; initMethodDef != NULL; initMethodDef = initMethodDef->mNextWithSameName)
+			{
+				if (initMethodDef->mDeclaringType != methodDef->mDeclaringType)
+					continue;
+				if (initMethodDef->mMethodType != BfMethodType_Init)
+					continue;
+				initBodies.Insert(0, initMethodDef->mBody);
+			}
+
+			for (auto body : initBodies)
+			{
+				_CheckInitBlock(body);
+				VisitEmbeddedStatement(body);
+			}
+
 			if (hadInlineInitBlock)
 			if (hadInlineInitBlock)
 			{
 			{
 				RestoreScopeState();
 				RestoreScopeState();
@@ -15718,6 +15747,22 @@ void BfModule::EmitCtorBody(bool& skipBody)
 							CreateValueFromExpression(fieldDef->mInitializer, wantType, BfEvalExprFlags_FieldInitializer);
 							CreateValueFromExpression(fieldDef->mInitializer, wantType, BfEvalExprFlags_FieldInitializer);
 						}
 						}
 					}
 					}
+
+					tempTypeDef->PopulateMemberSets();
+					BfMemberSetEntry* entry = NULL;
+					BfMethodDef* initMethodDef = NULL;
+					tempTypeDef->mMethodSet.TryGetWith(String("__BfInit"), &entry);
+					if (entry != NULL)
+						initMethodDef = (BfMethodDef*)entry->mMemberDef;
+					SizedArray<BfAstNode*, 8> initBodies;
+					for (; initMethodDef != NULL; initMethodDef = initMethodDef->mNextWithSameName)
+					{
+						if (initMethodDef->mMethodType != BfMethodType_Init)
+							continue;
+						initBodies.Insert(0, initMethodDef->mBody);						
+					}
+					for (auto body : initBodies)					
+						VisitEmbeddedStatement(body);					
 				}
 				}
 			}
 			}
 
 
@@ -15731,7 +15776,7 @@ void BfModule::EmitCtorBody(bool& skipBody)
 						MarkFieldInitialized(fieldInst);
 						MarkFieldInitialized(fieldInst);
 				}
 				}
 			}
 			}
-		}
+		}		
 	}
 	}
 
 
 	// Call base ctor (if applicable)
 	// Call base ctor (if applicable)
@@ -18996,7 +19041,6 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
 	{
 	{
 		if ((skipEndChecks) || (methodDef->mBody == NULL))
 		if ((skipEndChecks) || (methodDef->mBody == NULL))
 			break;
 			break;
-
 		LocalVariableDone(localVar, true);
 		LocalVariableDone(localVar, true);
 	}
 	}
 
 
@@ -21410,7 +21454,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
 	if ((((mCurMethodInstance->mIsUnspecialized) || (mCurMethodInstance->mMethodDef->mGenericParams.size() == 0))) &&
 	if ((((mCurMethodInstance->mIsUnspecialized) || (mCurMethodInstance->mMethodDef->mGenericParams.size() == 0))) &&
 		(!methodDef->mIsLocalMethod))
 		(!methodDef->mIsLocalMethod))
 	{
 	{
-		if (!methodInstance->mIsForeignMethodDef)
+		if ((!methodInstance->mIsForeignMethodDef) && (methodDef->mMethodType != BfMethodType_Init))
 		{
 		{
 			typeDef->PopulateMemberSets();
 			typeDef->PopulateMemberSets();
 			BfMethodDef* nextMethod = NULL;
 			BfMethodDef* nextMethod = NULL;

+ 9 - 0
IDEHelper/Compiler/BfModuleTypeUtils.cpp

@@ -4318,6 +4318,12 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
 					declRequired = false;
 					declRequired = false;
 			}
 			}
 
 
+			if (methodDef->mMethodType == BfMethodType_Init)
+			{
+				declRequired = false;
+				implRequired = false;
+			}
+
 			if (!implRequired)
 			if (!implRequired)
 			{
 			{
 				if (!mIsScratchModule)
 				if (!mIsScratchModule)
@@ -4350,6 +4356,9 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
 			continue;
 			continue;
 		}
 		}
 
 
+		if (methodDef->mMethodType == BfMethodType_Init)
+			continue;
+
 		int prevWorklistSize = (int)mContext->mMethodWorkList.size();
 		int prevWorklistSize = (int)mContext->mMethodWorkList.size();
 		auto moduleMethodInstance = GetMethodInstance(typeInstance, methodDef, BfTypeVector(), ((methodDef->mGenericParams.size() != 0) || (typeInstance->IsUnspecializedType())) ? BfGetMethodInstanceFlag_UnspecializedPass : BfGetMethodInstanceFlag_None);
 		auto moduleMethodInstance = GetMethodInstance(typeInstance, methodDef, BfTypeVector(), ((methodDef->mGenericParams.size() != 0) || (typeInstance->IsUnspecializedType())) ? BfGetMethodInstanceFlag_UnspecializedPass : BfGetMethodInstanceFlag_None);
 				
 				

+ 12 - 1
IDEHelper/Compiler/BfReducer.cpp

@@ -5774,8 +5774,19 @@ BfAstNode* BfReducer::ReadTypeMember(BfTokenNode* tokenNode, int depth, BfAstNod
 		ctorDecl->mReturnType = NULL;
 		ctorDecl->mReturnType = NULL;
 		ReplaceNode(tokenNode, ctorDecl);
 		ReplaceNode(tokenNode, ctorDecl);
 		MEMBER_SET(ctorDecl, mThisToken, tokenNode);
 		MEMBER_SET(ctorDecl, mThisToken, tokenNode);
+		if (auto block = BfNodeDynCast<BfBlock>(mVisitorPos.GetNext()))
+		{			
+			mVisitorPos.MoveNext();
+			MEMBER_SET(ctorDecl, mBody, block);
 
 
-		ParseMethod(ctorDecl, &params, &commas);
+			if (IsNodeRelevant(ctorDecl))
+			{
+				SetAndRestoreValue<BfMethodDeclaration*> prevMethodDeclaration(mCurMethodDecl, ctorDecl);
+				HandleBlock(block);
+			}
+		}
+		else
+			ParseMethod(ctorDecl, &params, &commas);
 		return ctorDecl;
 		return ctorDecl;
 	}
 	}
 
 

+ 2 - 1
IDEHelper/Compiler/BfSystem.h

@@ -635,13 +635,14 @@ public:
 enum BfMethodType : uint8
 enum BfMethodType : uint8
 {
 {
 	BfMethodType_Ignore,
 	BfMethodType_Ignore,
-	BfMethodType_Normal,	
+	BfMethodType_Normal,
 	BfMethodType_PropertyGetter,
 	BfMethodType_PropertyGetter,
 	BfMethodType_PropertySetter,
 	BfMethodType_PropertySetter,
 	BfMethodType_CtorCalcAppend,
 	BfMethodType_CtorCalcAppend,
 	BfMethodType_Ctor,
 	BfMethodType_Ctor,
 	BfMethodType_CtorNoBody,
 	BfMethodType_CtorNoBody,
 	BfMethodType_CtorClear,
 	BfMethodType_CtorClear,
+	BfMethodType_Init,
 	BfMethodType_Dtor,
 	BfMethodType_Dtor,
 	BfMethodType_Operator,
 	BfMethodType_Operator,
 	BfMethodType_Mixin,
 	BfMethodType_Mixin,