Browse Source

Fixed on-demand method issues

Brian Fiete 4 years ago
parent
commit
d0d89a552e

+ 0 - 5
IDEHelper/Compiler/BfIRCodeGen.cpp

@@ -3344,11 +3344,6 @@ void BfIRCodeGen::HandleNextCmd()
 				int intrinId = -1;
 				if (mIntrinsicReverseMap.TryGetValue(funcPtr, &intrinId))
 				{
-					if (intrinId == BfIRIntrinsic__PLATFORM)
-					{
-						NOP;
-					}
-
 					if (intrinId == BfIRIntrinsic_MemSet)
 					{
 						int align = 1;

+ 88 - 22
IDEHelper/Compiler/BfModule.cpp

@@ -1301,7 +1301,9 @@ void BfModule::StartNewRevision(RebuildKind rebuildKind, bool force)
 					for (auto& methodGroup : typeInst->mMethodInstanceGroups)
 					{
 						if ((methodGroup.mOnDemandKind == BfMethodOnDemandKind_NoDecl_AwaitingReference) ||
-							(methodGroup.mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference))
+							(methodGroup.mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingDecl) ||
+							(methodGroup.mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference) ||
+							(methodGroup.mOnDemandKind == BfMethodOnDemandKind_InWorkList))
 						{
 							oldOnDemandCount++;
 						}
@@ -1320,7 +1322,8 @@ void BfModule::StartNewRevision(RebuildKind rebuildKind, bool force)
 	
 	if (!mIsDeleting)
 		Init();
-	mOnDemandMethodCount += oldOnDemandCount;	
+	mOnDemandMethodCount += oldOnDemandCount;
+	VerifyOnDemandMethods();
 }
 
 void BfModule::StartExtension()
@@ -2720,6 +2723,34 @@ void BfModule::SetFail()
 	}	
 }
 
+void BfModule::VerifyOnDemandMethods()
+{
+#ifdef _DEBUG
+// 	if (mParentModule != NULL)
+// 	{
+// 		BF_ASSERT(mOnDemandMethodCount == 0);
+// 		mParentModule->VerifyOnDemandMethods();
+// 		return;
+// 	}
+// 
+// 	int onDemandCount = 0;
+// 	for (auto type : mOwnedTypeInstances)
+// 	{
+// 		auto typeInst = type->ToTypeInstance();
+// 		for (auto& methodGroup : typeInst->mMethodInstanceGroups)
+// 		{
+// 			if ((methodGroup.mOnDemandKind == BfMethodOnDemandKind_NoDecl_AwaitingReference) ||
+// 				(methodGroup.mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference) ||
+// 				(methodGroup.mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingDecl) ||
+// 				(methodGroup.mOnDemandKind == BfMethodOnDemandKind_InWorkList))
+// 				onDemandCount++;
+// 		}
+// 	}
+// 
+// 	BF_ASSERT(mOnDemandMethodCount == onDemandCount);
+#endif
+}
+
 bool BfModule::IsSkippingExtraResolveChecks()
 {
 	if (mIsConstModule)
@@ -9687,12 +9718,14 @@ BfMethodInstance* BfModule::GetRawMethodInstanceAtIdx(BfTypeInstance* typeInstan
 			if ((methodGroup.mOnDemandKind == BfMethodOnDemandKind_NoDecl_AwaitingReference) || (methodGroup.mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingDecl))
 				methodGroup.mOnDemandKind = BfMethodOnDemandKind_Decl_AwaitingDecl;
 			
-			return declModule->GetMethodInstance(typeInstance, typeInstance->mTypeDef->mMethods[methodIdx], BfTypeVector(), (BfGetMethodInstanceFlags)(BfGetMethodInstanceFlag_UnspecializedPass | BfGetMethodInstanceFlag_Unreified)).mMethodInstance;
+			BfGetMethodInstanceFlags useFlags = (BfGetMethodInstanceFlags)(BfGetMethodInstanceFlag_MethodInstanceOnly | BfGetMethodInstanceFlag_UnspecializedPass | BfGetMethodInstanceFlag_Unreified);
+			return declModule->GetMethodInstance(typeInstance, typeInstance->mTypeDef->mMethods[methodIdx], BfTypeVector(), useFlags).mMethodInstance;
 		}
 		else
 		{
 			auto declModule = typeInstance->mModule;
-			return declModule->GetMethodInstance(typeInstance, typeInstance->mTypeDef->mMethods[methodIdx], BfTypeVector(), (BfGetMethodInstanceFlags)(BfGetMethodInstanceFlag_UnspecializedPass)).mMethodInstance;
+			BfGetMethodInstanceFlags useFlags = (BfGetMethodInstanceFlags)(BfGetMethodInstanceFlag_MethodInstanceOnly | BfGetMethodInstanceFlag_UnspecializedPass);
+			return declModule->GetMethodInstance(typeInstance, typeInstance->mTypeDef->mMethods[methodIdx], BfTypeVector(), useFlags).mMethodInstance;
 		}
 	}
 	auto methodInstance = typeInstance->mMethodInstanceGroups[methodIdx].mDefault;
@@ -9715,7 +9748,7 @@ BfMethodInstance* BfModule::GetRawMethodInstance(BfTypeInstance* typeInstance, B
 		return GetMethodInstance(typeInstance, methodDef, BfTypeVector()).mMethodInstance;
 	}
 
-	return GetRawMethodInstanceAtIdx(typeInstance, methodDef->mIdx);
+	return GetRawMethodInstanceAtIdx(typeInstance, methodDef->mIdx, NULL);
 }
 
 BfMethodInstance* BfModule::GetRawMethodByName(BfTypeInstance* typeInstance, const StringImpl& methodName, int paramCount, bool checkBase, bool allowMixin)
@@ -12724,6 +12757,7 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM
 					methodInstance->UndoDeclaration(!methodInstance->mIRFunction.IsFake());
 					doingRedeclare = true;
 					mOnDemandMethodCount++;
+					VerifyOnDemandMethods();
 				}
 			}
 			else
@@ -12879,8 +12913,14 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM
 					AddMethodToWorkList(methodInstance);
 			}
 			else
-			{
+			{				
 				methodInstance->mMethodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_Referenced;
+				auto owningModule = methodInstance->GetOwner()->mModule;
+				if (!owningModule->mIsScratchModule)
+				{
+					owningModule->mOnDemandMethodCount--;
+					owningModule->VerifyOnDemandMethods();
+				}
 			}
 		}
 
@@ -13140,6 +13180,11 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM
 		addToWorkList = false;
 	}
 
+	if ((flags & BfGetMethodInstanceFlag_MethodInstanceOnly) != 0)
+	{
+		addToWorkList = false;
+	}
+
 // 	if ((flags & BfGetMethodInstanceFlag_NoReference) != 0)
 // 		addToWorkList = false;
 	
@@ -17793,11 +17838,11 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
 	}
 
 	BfMethodInstance* defaultMethodInstance = methodInstance->mMethodInstanceGroup->mDefault;
-
-	BF_ASSERT(methodInstance->mMethodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_NotSet);
-
+	
 	if (!mIsConstModule)
 	{
+		BF_ASSERT(methodInstance->mMethodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_NotSet);
+
 		if ((methodInstance->mMethodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_AlwaysInclude) &&
 			(methodInstance->mMethodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_Referenced))
 		{
@@ -17815,6 +17860,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
 			}
 
 			methodInstance->mMethodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_Referenced;
+			VerifyOnDemandMethods();
 		}
 	}
 
@@ -18057,12 +18103,20 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
 		
 		BF_ASSERT(unspecializedMethodInstance != methodInstance);
 		if (!unspecializedMethodInstance->mHasBeenProcessed)
-		{			
-			// Make sure the unspecialized method is processed so we can take its bindings
+		{
+			if (mIsConstModule)
+			{
+				// This will have already been populated by CeMachine
+				methodState.mGenericTypeBindings = &methodInstance->GetMethodInfoEx()->mGenericTypeBindings;
+			}
+			else
+			{				
+				// Make sure the unspecialized method is processed so we can take its bindings
 
-			// Clear mCurMethodState so we don't think we're in a local method
-			SetAndRestoreValue<BfMethodState*> prevMethodState_Unspec(mCurMethodState, prevMethodState.mPrevVal);
-			mContext->ProcessMethod(unspecializedMethodInstance);
+				// Clear mCurMethodState so we don't think we're in a local method
+				SetAndRestoreValue<BfMethodState*> prevMethodState_Unspec(mCurMethodState, prevMethodState.mPrevVal);
+				mContext->ProcessMethod(unspecializedMethodInstance);
+			}
 		}
 		methodState.mGenericTypeBindings = &unspecializedMethodInstance->GetMethodInfoEx()->mGenericTypeBindings;
 	}
@@ -22020,17 +22074,25 @@ genericParam->mExternType = GetPrimitiveType(BfTypeCode_Var);
 				mFuncReferences[methodInstance] = func;
 		}
 	}
-		
-	if (addToWorkList)
+	
+	if (methodInstance->mMethodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_NotSet)
 	{
-		bool wasAwaitingDecl = methodInstance->mMethodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingDecl;
-		if (wasAwaitingDecl)
-			methodInstance->mMethodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_Decl_AwaitingReference;		
+		methodInstance->mMethodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_Decl_AwaitingDecl;
+		auto owningModule = methodInstance->GetOwner()->mModule;
+		if (!owningModule->mIsScratchModule)
+			owningModule->mOnDemandMethodCount++;
+		VerifyOnDemandMethods();		
+	}
 
+	bool wasAwaitingDecl = methodInstance->mMethodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingDecl;
+	if (wasAwaitingDecl)
+		methodInstance->mMethodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_Decl_AwaitingReference;
+
+	if (addToWorkList)
+	{
 		if ((!methodDef->mIsAbstract) && (!methodInstance->mIgnoreBody))
-		{
-			if (!wasAwaitingDecl)
-				AddMethodToWorkList(methodInstance);			
+		{			
+			AddMethodToWorkList(methodInstance);
 		}
 		else
 		{			
@@ -22043,6 +22105,10 @@ genericParam->mExternType = GetPrimitiveType(BfTypeCode_Var);
 				methodInstance->mIRFunction = BfIRFunction();
 			}
 		}
+	}	
+	else
+	{
+		//BF_ASSERT(methodInstance->mMethodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference);
 	}
 		
 	if ((!methodInstance->IsSpecializedGenericMethodOrType()) && (!mCurTypeInstance->IsBoxed()) && 

+ 2 - 1
IDEHelper/Compiler/BfModule.h

@@ -1481,6 +1481,7 @@ public:
 	bool CheckProtection(BfProtectionCheckFlags& flags, BfTypeInstance* memberOwner, BfProject* memberProject, BfProtection memberProtection, BfTypeInstance* lookupStartType);
 	void SetElementType(BfAstNode* astNode, BfSourceElementType elementType);	
 	void SetFail();
+	void VerifyOnDemandMethods();
 	bool IsSkippingExtraResolveChecks();
 	BfError* Fail(const StringImpl& error, BfAstNode* refNode = NULL, bool isPersistent = false);
 	BfError* FailInternal(const StringImpl& error, BfAstNode* refNode = NULL);
@@ -1852,7 +1853,7 @@ public:
 	BfTypedValue CreateValueFromExpression(BfExprEvaluator& exprEvaluator, BfExpression* expr, BfType* wantTypeRef = NULL, BfEvalExprFlags flags = BfEvalExprFlags_None, BfType** outOrigType = NULL);
 	BfTypedValue CreateValueFromExpression(BfExpression* expr, BfType* wantTypeRef = NULL, BfEvalExprFlags flags = BfEvalExprFlags_None, BfType** outOrigType = NULL);
 	BfTypedValue GetOrCreateVarAddr(BfExpression* expr);
-	BfMethodInstance* GetRawMethodInstanceAtIdx(BfTypeInstance* typeInstance, int methodIdx, const char* assertName = NULL);	
+	BfMethodInstance* GetRawMethodInstanceAtIdx(BfTypeInstance* typeInstance, int methodIdx, const char* assertName = NULL);
 	BfMethodInstance* GetRawMethodInstance(BfTypeInstance* typeInstance, BfMethodDef* methodDef);
 	BfMethodInstance* GetRawMethodByName(BfTypeInstance* typeInstance, const StringImpl& methodName, int paramCount = -1, bool checkBase = false, bool allowMixin = false);
 	BfMethodInstance* GetUnspecializedMethodInstance(BfMethodInstance* methodInstance, bool useUnspecializedType = true); // Unspecialized owner type and unspecialized method type		

+ 59 - 17
IDEHelper/Compiler/BfModuleTypeUtils.cpp

@@ -366,6 +366,11 @@ bool BfModule::ValidateGenericConstraints(BfTypeReference* typeRef, BfTypeInstan
 
 bool BfModule::AreConstraintsSubset(BfGenericParamInstance* checkInner, BfGenericParamInstance* checkOuter)
 {
+	if (checkOuter == NULL)
+		return true;
+	if (checkInner == NULL)
+		return false;
+
 	// Added new flags?
 	if ((checkInner->mGenericParamFlags | checkOuter->mGenericParamFlags) != checkOuter->mGenericParamFlags)
 	{
@@ -4318,7 +4323,10 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
 			if (!boxedRequired)
 			{
 				if (wantsOnDemandMethods)
+				{
 					methodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_NoDecl_AwaitingReference;
+					mOnDemandMethodCount++;
+				}
 				continue;
 			}
 		}
@@ -4329,7 +4337,8 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
 		if ((methodDef->mName == BF_METHODNAME_DYNAMICCAST) && (typeInstance->IsValueType()))
 			continue; // This is just a placeholder for boxed types
 
-		methodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_AlwaysInclude;
+		if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_NotSet)
+			methodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_AlwaysInclude;
 		
 		if (wantsOnDemandMethods)
 		{	
@@ -4429,18 +4438,26 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
 
 			if (!implRequired)
 			{
-				if (!mIsScratchModule)
-					mOnDemandMethodCount++;
+				BF_ASSERT(methodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_NotSet);
+				if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_AlwaysInclude)
+				{
+					if (!mIsScratchModule)
+						mOnDemandMethodCount++;
+				}
 
 				if (!declRequired)
 				{
-					methodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_NoDecl_AwaitingReference;
+					if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_AlwaysInclude)
+						methodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_NoDecl_AwaitingReference;
 					continue;
 				}
 				else
 				{
-					methodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_Decl_AwaitingDecl;
+					if (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_AlwaysInclude)
+						methodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_Decl_AwaitingDecl;
 				}
+
+				VerifyOnDemandMethods();
 			}
 		}		
 	}
@@ -4468,7 +4485,13 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
 				continue;
 
 			int prevWorklistSize = (int)mContext->mMethodWorkList.size();
-			auto moduleMethodInstance = GetMethodInstance(typeInstance, methodDef, BfTypeVector(), ((methodDef->mGenericParams.size() != 0) || (typeInstance->IsUnspecializedType())) ? BfGetMethodInstanceFlag_UnspecializedPass : BfGetMethodInstanceFlag_None);
+
+			auto flags = ((methodDef->mGenericParams.size() != 0) || (typeInstance->IsUnspecializedType())) ? BfGetMethodInstanceFlag_UnspecializedPass : BfGetMethodInstanceFlag_None;
+
+			if (methodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_AlwaysInclude)
+				flags = (BfGetMethodInstanceFlags)(flags | BfGetMethodInstanceFlag_MethodInstanceOnly);
+
+			auto moduleMethodInstance = GetMethodInstance(typeInstance, methodDef, BfTypeVector(), flags);
 
 			auto methodInstance = moduleMethodInstance.mMethodInstance;
 			if (methodInstance == NULL)
@@ -4608,13 +4631,15 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
 								if (boxedMethodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_NoDecl_AwaitingReference)
 								{
 									boxedMethodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_Decl_AwaitingDecl;
-									if (!mIsScratchModule)
-										mOnDemandMethodCount++;									
+									VerifyOnDemandMethods();
 								}
 							}							
 
+							auto methodFlags = matchedMethod->mIsForeignMethodDef ? BfGetMethodInstanceFlag_ForeignMethodDef : BfGetMethodInstanceFlag_None;
+							methodFlags = (BfGetMethodInstanceFlags)(methodFlags | BfGetMethodInstanceFlag_MethodInstanceOnly);
+							
 							auto moduleMethodInstance = GetMethodInstance(typeInstance, matchedMethod->mMethodDef, BfTypeVector(),
-								matchedMethod->mIsForeignMethodDef ? BfGetMethodInstanceFlag_ForeignMethodDef : BfGetMethodInstanceFlag_None,
+								methodFlags,
 								matchedMethod->GetForeignType());
 							auto methodInstance = moduleMethodInstance.mMethodInstance;
 							UniqueSlotVirtualMethod(methodInstance);
@@ -4916,7 +4941,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
 						if ((hasDefaultImpl) && (matchedMethod == NULL))
 						{
 							auto methodDef = bestMethodInst->mMethodDef;
-							BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_ForeignMethodDef;
+							BfGetMethodInstanceFlags flags = (BfGetMethodInstanceFlags)(BfGetMethodInstanceFlag_ForeignMethodDef | BfGetMethodInstanceFlag_MethodInstanceOnly);
 							if ((methodDef->mGenericParams.size() != 0) || (typeInstance->IsUnspecializedType()))
 								flags = (BfGetMethodInstanceFlags)(flags | BfGetMethodInstanceFlag_UnspecializedPass);
 							auto methodInst = GetMethodInstance(typeInstance, methodDef, BfTypeVector(), flags, ifaceInst);
@@ -4927,7 +4952,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
 								BfMethodInstance* newMethodInstance = methodInst.mMethodInstance;
 								BF_ASSERT(newMethodInstance->mIsForeignMethodDef);					
 								if (newMethodInstance->mMethodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference)
-									mOnDemandMethodCount++;
+									mOnDemandMethodCount++;								
 								continue;
 							}
 						}
@@ -5006,6 +5031,8 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
 		}
 	}
 
+	VerifyOnDemandMethods();
+
 	ambiguityContext.Finish();
 	CheckAddFailType();
 
@@ -5083,6 +5110,8 @@ void BfModule::AddMethodToWorkList(BfMethodInstance* methodInstance)
 			}
 
 			AddMethodToWorkList(defaultMethod);
+			// This should put all the specialized methods in the worklist, including us
+			return;
 		}
 	}
 
@@ -5132,16 +5161,34 @@ void BfModule::AddMethodToWorkList(BfMethodInstance* methodInstance)
 
 			BF_ASSERT(methodInstance->mMethodInstanceGroup->mOnDemandKind != BfMethodOnDemandKind_Referenced);
 			if (!mIsScratchModule)
-			{					
+			{				
 				auto onDemandModule = owningModule;
 				if (owningModule->mParentModule != NULL)
 					onDemandModule = owningModule->mParentModule;
+
+				owningModule->VerifyOnDemandMethods();
 				
 				if (methodInstance->mMethodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_NotSet)
 					owningModule->mOnDemandMethodCount++;
 				BF_ASSERT(onDemandModule->mOnDemandMethodCount > 0);
+
+				VerifyOnDemandMethods();
 			}
 			methodInstance->mMethodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_InWorkList;
+
+			if (methodInstance->mMethodInstanceGroup->mMethodSpecializationMap != NULL)
+			{
+				for (auto& kv : *methodInstance->mMethodInstanceGroup->mMethodSpecializationMap)
+				{
+					auto specMethodInstance = kv.mValue;
+					if ((!specMethodInstance->mDeclModule->mIsModuleMutable) && (!specMethodInstance->mDeclModule->mReifyQueued))
+					{
+						specMethodInstance->mDeclModule->PrepareForIRWriting(specMethodInstance->GetOwner());
+					}
+					specMethodInstance->mDeclModule->AddMethodToWorkList(specMethodInstance);
+				}
+			}
+			
 		}
 	}
 	else
@@ -9078,11 +9125,6 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
 			genericTypeInst->mGenericTypeInfo->mTypeGenericArguments.push_back(genericArg);
 			genericTypeInst->mGenericTypeInfo->mTypeGenericArgumentRefs.push_back(genericArgRef);
 
-			if (genericArg->IsConstExprValue())
-			{
-				NOP;
-			}
-
 			genericParamIdx++;
 		}
 

+ 39 - 13
IDEHelper/Compiler/CeMachine.cpp

@@ -1154,6 +1154,23 @@ void CeBuilder::HandleParams()
 	}
 }
 
+void CeBuilder::ProcessMethod(BfMethodInstance* methodInstance, BfMethodInstance* dupMethodInstance)
+{
+	auto irCodeGen = mCeMachine->mCeModule->mBfIRBuilder->mBeIRCodeGen;
+	auto irBuilder = mCeMachine->mCeModule->mBfIRBuilder;
+	auto beModule = irCodeGen->mBeModule;
+		
+	dupMethodInstance->mIsReified = true;
+	dupMethodInstance->mInCEMachine = false; // Only have the original one
+	
+	mCeMachine->mCeModule->mHadBuildError = false;
+	auto irState = irBuilder->GetState();
+	auto beState = irCodeGen->GetState();
+	mCeMachine->mCeModule->ProcessMethod(dupMethodInstance, true);
+	irCodeGen->SetState(beState);
+	irBuilder->SetState(irState);
+}
+
 void CeBuilder::Build()
 {
 	auto irCodeGen = mCeMachine->mCeModule->mBfIRBuilder->mBeIRCodeGen;
@@ -1164,32 +1181,41 @@ void CeBuilder::Build()
 
 	auto methodInstance = mCeFunction->mMethodInstance;
 	
+
 	if (methodInstance != NULL)
 	{
+		BfMethodInstance dupMethodInstance;
+		dupMethodInstance.CopyFrom(methodInstance);
 		auto methodDef = methodInstance->mMethodDef;
 
-		BfMethodInstance dupMethodInstance;
-		dupMethodInstance.CopyFrom(methodInstance);		
-		dupMethodInstance.mIsReified = true;
-		dupMethodInstance.mInCEMachine = false; // Only have the original one
+		bool isGenericVariation = (methodInstance->mIsUnspecializedVariation) || (methodInstance->GetOwner()->IsUnspecializedTypeVariation());				
+		int dependentGenericStartIdx = 0;
+		if (methodInstance->mMethodInfoEx != NULL)
+			dependentGenericStartIdx = (int)methodInstance->mMethodInfoEx->mMethodGenericArguments.size();
+		if ((((methodInstance->mMethodInfoEx != NULL) && ((int)methodInstance->mMethodInfoEx->mMethodGenericArguments.size() > dependentGenericStartIdx)) ||
+			((methodInstance->GetOwner()->IsGenericTypeInstance()) && (!isGenericVariation) && (!methodInstance->mMethodDef->mIsLocalMethod))))
+		{
+			auto unspecializedMethodInstance = mCeMachine->mCeModule->GetUnspecializedMethodInstance(methodInstance, !methodInstance->mMethodDef->mIsLocalMethod);
+			if (!unspecializedMethodInstance->mHasBeenProcessed)
+			{
+				BfMethodInstance dupUnspecMethodInstance;
+				dupUnspecMethodInstance.CopyFrom(unspecializedMethodInstance);
+				ProcessMethod(unspecializedMethodInstance, &dupUnspecMethodInstance);
+				dupMethodInstance.GetMethodInfoEx()->mGenericTypeBindings = dupUnspecMethodInstance.mMethodInfoEx->mGenericTypeBindings;
+			}
+		}
 
 		int startFunctionCount = (int)beModule->mFunctions.size();
+		ProcessMethod(methodInstance, &dupMethodInstance);		
 		
-		mCeMachine->mCeModule->mHadBuildError = false;
-		auto irState = irBuilder->GetState();
-		auto beState = irCodeGen->GetState();		
-		mCeMachine->mCeModule->ProcessMethod(&dupMethodInstance, true);
-		irCodeGen->SetState(beState);
-		irBuilder->SetState(irState);
-
 		if (!dupMethodInstance.mIRFunction)
 		{
 			mCeFunction->mFailed = true;
 			return;
-		}
+		}		
+		mBeFunction = (BeFunction*)irCodeGen->GetBeValue(dupMethodInstance.mIRFunction.mId);
 
 		mIntPtrType = irCodeGen->mBeContext->GetPrimitiveType((mPtrSize == 4) ? BeTypeCode_Int32 : BeTypeCode_Int64);
-		mBeFunction = (BeFunction*)irCodeGen->GetBeValue(dupMethodInstance.mIRFunction.mId);
 
 		for (int funcIdx = startFunctionCount; funcIdx < (int)beModule->mFunctions.size(); funcIdx++)
 		{

+ 1 - 0
IDEHelper/Compiler/CeMachine.h

@@ -556,6 +556,7 @@ public:
 	void EmitBinaryOp(CeOp iOp, CeOp fOp, const CeOperand& lhs, const CeOperand& rhs, CeOperand& result);
 	void EmitUnaryOp(CeOp iOp, CeOp fOp, const CeOperand& val, CeOperand& result);
 	void EmitSizedOp(CeOp op, const CeOperand& operand, CeOperand* result, bool allowNonStdSize);
+	void ProcessMethod(BfMethodInstance* methodInstance, BfMethodInstance* dupMethodInstance);
 	void Build();
 };