Forráskód Böngészése

ConstEval updates, better const struct support

Brian Fiete 4 éve
szülő
commit
be929c3626

+ 3 - 0
BeefySysLib/util/Heap.cpp

@@ -231,6 +231,9 @@ ContiguousHeap::AllocRef ContiguousHeap::Alloc(int size)
 		blockList->PushBack(CH_ABS_TO_REL(block));
 
 		mFreeList.Add(CH_ABS_TO_REL(block));
+
+		if (mFreeIdx >= mFreeList.mSize)
+			mFreeIdx = 0;
 	}
 }
 

+ 65 - 35
IDEHelper/Backend/BeIRCodeGen.cpp

@@ -790,29 +790,47 @@ void BeIRCodeGen::Read(BeValue*& beValue)
 			BE_MEM_END("ParamType_Const_AggZero");
 			return;
 		}
-		else if (constType == BfConstType_Array)
+		else if (constType == BfConstType_Agg)
 		{
 			CMD_PARAM(BeType*, type);
 			CMD_PARAM(CmdParamVec<BeConstant*>, values);
 
-			auto arrayType = (BeSizedArrayType*)type;
-			int fillCount = (int)(arrayType->mLength - values.size());
-			if (fillCount > 0)
+			if (type->IsSizedArray())
 			{
-				auto lastValue = values.back();
-				for (int i = 0; i < fillCount; i++)
-					values.push_back(lastValue);
+				auto arrayType = (BeSizedArrayType*)type;
+				int fillCount = (int)(arrayType->mLength - values.size());
+				if (fillCount > 0)
+				{
+					auto lastValue = values.back();
+					for (int i = 0; i < fillCount; i++)
+						values.push_back(lastValue);
+				}
+			}
+			else
+			{
+				BF_ASSERT(type->IsStruct());
 			}
 
 			auto constStruct = mBeModule->mOwnedValues.Alloc<BeStructConstant>();
-			constStruct->mType = type;
-			for (auto val : values)
+			constStruct->mType = type;			
+			for (int i = 0; i < (int)values.size(); i++)
 			{
+				auto val = values[i];
 				BeConstant* constant = BeValueDynCast<BeConstant>(val);
 				constStruct->mMemberValues.push_back(constant);
 #ifdef _DEBUG
-				auto memberType = constant->GetType();
-				BF_ASSERT(memberType == arrayType->mElementType);
+				if (type->IsSizedArray())
+				{
+					auto arrayType = (BeSizedArrayType*)type;
+					auto memberType = constant->GetType();
+					BF_ASSERT(memberType == arrayType->mElementType);
+				}
+				else
+				{
+					auto structType = (BeStructType*)type;
+					auto memberType = constant->GetType();
+					BF_ASSERT(memberType == structType->mMembers[i].mType);
+				}
 #endif
 			}
 			beValue = constStruct;
@@ -1140,22 +1158,46 @@ void BeIRCodeGen::HandleNextCmd()
 			SetResult(curId, mBeContext->CreateVectorType(elementType, length));
 		}
 		break;	
-	case BfIRCmd_CreateConstStruct:
+	case BfIRCmd_CreateConstAgg:
 		{
 			CMD_PARAM(BeType*, type);
-			CMD_PARAM(CmdParamVec<BeValue*>, values)			
-			auto constStruct = mBeModule->mOwnedValues.Alloc<BeStructConstant>();						
-			constStruct->mType = type;
-			BF_ASSERT(type->IsStruct());			
+			CMD_PARAM(CmdParamVec<BeValue*>, values);
 
-			FixValues((BeStructType*)type, values);
+			auto constStruct = mBeModule->mOwnedValues.Alloc<BeStructConstant>();
+			constStruct->mType = type;
+			
+			if (type->IsStruct())
+			{				
+				FixValues((BeStructType*)type, values);
 
-			BF_ASSERT(((BeStructType*)type)->mMembers.size() == values.size());
-			for (int i = 0; i < (int)values.size(); i++)			
+				BF_ASSERT(((BeStructType*)type)->mMembers.size() == values.size());
+				for (int i = 0; i < (int)values.size(); i++)
+				{
+					auto val = values[i];
+					BF_ASSERT(mBeContext->AreTypesEqual(((BeStructType*)type)->mMembers[i].mType, val->GetType()));
+					constStruct->mMemberValues.push_back(BeValueDynCast<BeConstant>(val));
+				}
+			}
+			else
 			{
-				auto val = values[i];
-				BF_ASSERT(mBeContext->AreTypesEqual(((BeStructType*)type)->mMembers[i].mType, val->GetType()));
-				constStruct->mMemberValues.push_back(BeValueDynCast<BeConstant>(val));
+				BF_ASSERT(type->IsSizedArray());
+				auto arrayType = (BeSizedArrayType*)type;
+
+				int fillCount = (int)(arrayType->mLength - values.size());
+				if (fillCount > 0)
+				{
+					auto lastValue = values.back();
+					for (int i = 0; i < fillCount; i++)
+						values.push_back(lastValue);
+				}
+
+				BF_ASSERT(arrayType->mLength == values.size());
+				for (int i = 0; i < (int)values.size(); i++)
+				{
+					auto val = values[i];
+					BF_ASSERT(mBeContext->AreTypesEqual(((BeSizedArrayType*)type)->mElementType, val->GetType()));
+					constStruct->mMemberValues.push_back(BeValueDynCast<BeConstant>(val));
+				}
 			}
 			SetResult(curId, constStruct);
 		}
@@ -1167,19 +1209,7 @@ void BeIRCodeGen::HandleNextCmd()
 			beConst->mType = type;
 			SetResult(curId, beConst);
 		}
-		break;
-	case BfIRCmd_CreateConstArray:
-		{
-			CMD_PARAM(BeType*, type);
-			CMD_PARAM(CmdParamVec<BeConstant*>, values);
-
-			auto constStruct = mBeModule->mOwnedValues.Alloc<BeStructConstant>();
-			constStruct->mType = type;
-			for (auto val : values)
-				constStruct->mMemberValues.push_back(BeValueDynCast<BeConstant>(val));
-			SetResult(curId, constStruct);
-		}
-		break;
+		break;	
 	case BfIRCmd_CreateConstString:
 		{
 			CMD_PARAM(String, str);			

+ 58 - 27
IDEHelper/Backend/BeMCContext.cpp

@@ -2864,6 +2864,39 @@ BeMCOperand BeMCContext::CreateLoad(const BeMCOperand& mcTarget)
 	return result;
 }
 
+static bool NeedsDecompose(BeConstant* constant)
+{
+	if (auto arrayConst = BeValueDynCast<BeStructConstant>(constant))
+	{
+		for (auto& val : arrayConst->mMemberValues)
+		{
+			if (NeedsDecompose(val))
+				return true;			
+		}
+		return false;
+	}
+
+	if (auto globalVar = BeValueDynCast<BeGlobalVariable>(constant))
+	{
+		return true;
+	}
+	else if (auto castConst = BeValueDynCast<BeCastConstant>(constant))
+	{
+		return true;
+	}	
+	else if (auto castConst = BeValueDynCast<BeBitCastInst>(constant))
+	{
+		if (auto targetConstant = BeValueDynCast<BeConstant>(castConst->mValue))
+			return NeedsDecompose(targetConstant);
+	}
+	else if (auto castConst = BeValueDynCast<BeGEPConstant>(constant))
+	{		
+		return NeedsDecompose(castConst->mTarget);
+	}
+
+	return false;
+}
+
 void BeMCContext::CreateStore(BeMCInstKind instKind, const BeMCOperand& val, const BeMCOperand& ptr)
 {
 	BeMCOperand mcVal = val;
@@ -2871,33 +2904,30 @@ void BeMCContext::CreateStore(BeMCInstKind instKind, const BeMCOperand& val, con
 
 	if (mcVal.mKind == BeMCOperandKind_ConstAgg)
 	{
-		bool needsDecompose = false;
-
-		if (auto arrayConst = BeValueDynCast<BeStructConstant>(mcVal.mConstant))
+		if (auto aggConst = BeValueDynCast<BeStructConstant>(mcVal.mConstant))
 		{
-			for (auto& val : arrayConst->mMemberValues)
-			{
-				if (auto globalVar = BeValueDynCast<BeGlobalVariable>(val))
-				{
-					needsDecompose = true;
-				}
-				else if (auto castConst = BeValueDynCast<BeCastConstant>(val))
-				{
-					needsDecompose = true;
-				}
-			}
-
-			if (needsDecompose)
+			if (NeedsDecompose(mcVal.mConstant))
 			{
 				int offset = 0;
 
-				auto arrayType = arrayConst->GetType();
-				BEMC_ASSERT(arrayType->IsSizedArray());
-				auto sizedArrayType = (BeSizedArrayType*)arrayType;
-
-				for (auto& val : arrayConst->mMemberValues)
-				{
-					auto destOperand = AllocVirtualReg(mModule->mContext->GetPointerTo(sizedArrayType->mElementType));
+				auto aggType = aggConst->GetType();
+				
+				for (int memberIdx = 0; memberIdx < (int)aggConst->mMemberValues.size(); memberIdx++)
+				{					
+					auto val = aggConst->mMemberValues[memberIdx];
+					BeType* elemType = NULL;
+					if (aggType->IsSizedArray())
+						elemType = ((BeSizedArrayType*)aggType)->mElementType;
+					else
+					{
+						auto& memberInfo = ((BeStructType*)aggType)->mMembers[memberIdx];
+						offset = memberInfo.mByteOffset;
+						elemType = memberInfo.mType;
+					}
+					if (elemType->mSize == 0)
+						continue;
+					
+					auto destOperand = AllocVirtualReg(mModule->mContext->GetPointerTo(elemType));
 					auto vregInfo = GetVRegInfo(destOperand);
 					vregInfo->mDefOnFirstUse = true;
 					vregInfo->mRelTo = mcPtr;
@@ -2905,12 +2935,13 @@ void BeMCContext::CreateStore(BeMCInstKind instKind, const BeMCOperand& val, con
 
 					vregInfo->mRelOffset = BeMCOperand::FromImmediate(offset);
 
-					destOperand.mKind = BeMCOperandKind_VRegLoad;
+					//destOperand.mKind = BeMCOperandKind_VRegLoad;
 
 					auto elementVal = GetOperand(val);
-					AllocInst(instKind, destOperand, elementVal);
+					//AllocInst(instKind, destOperand, elementVal);
+					CreateStore(instKind, elementVal, destOperand);
 
-					offset += sizedArrayType->mElementType->mSize;
+					offset += elemType->mSize;
 				}
 				return;
 			}
@@ -15742,7 +15773,7 @@ void BeMCContext::Generate(BeFunction* function)
 	mDbgPreferredRegs[32] = X64Reg_R8;*/
 
 	//mDbgPreferredRegs[8] = X64Reg_RAX;
-	//mDebugging = (function->mName == "DoCallback");
+	mDebugging = (function->mName == "?SetDefaults@KeySettings@BeefTest@bf@@QEAAXXZ");
 	//		|| (function->mName == "?MethodA@TestProgram@BeefTest@bf@@CAXXZ");
 	// 		|| (function->mName == "?Hey@Blurg@bf@@SAXXZ")
 	// 		;

+ 1 - 3
IDEHelper/Backend/BeModule.cpp

@@ -3111,9 +3111,7 @@ BeBlock* BeModule::CreateBlock(const StringImpl& name)
 void BeModule::AddBlock(BeFunction* function, BeBlock* block)
 {
 	block->mFunction = function;
-	function->mBlocks.push_back(block);
-
-	//block->mFuncRelId = function->mCurElementId++;
+	function->mBlocks.push_back(block);	
 }
 
 void BeModule::RemoveBlock(BeFunction* function, BeBlock* block)

+ 2 - 4
IDEHelper/Backend/BeModule.h

@@ -530,8 +530,7 @@ public:
 	Array<BeBlock*> mBlocks;		
 	Array<BeFunctionParam> mParams;
 	BeDbgFunction* mDbgFunction;
-	BeGlobalVariable* mRemapBindVar;
-	int mCurElementId;
+	BeGlobalVariable* mRemapBindVar;	
 
 public:
 	BeFunction()
@@ -548,8 +547,7 @@ public:
 		mNoFramePointerElim = false;
 		mIsDLLExport = false;
 		mIsDLLImport = false;
-		mRemapBindVar = NULL;
-		mCurElementId = 0;
+		mRemapBindVar = NULL;		
 	}	
 
 	BeFunctionType* GetFuncType()

+ 11 - 8
IDEHelper/Compiler/BfCompiler.cpp

@@ -434,6 +434,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
 	mStaticInitAfterAttributeTypeDef = NULL;	
 	mStaticInitPriorityAttributeTypeDef = NULL;
 	mStringTypeDef = NULL;
+	mStringViewTypeDef = NULL;
 	mThreadStaticAttributeTypeDef = NULL;
 	mTypeTypeDef = NULL;
 	mUnboundAttributeTypeDef = NULL;	
@@ -1359,7 +1360,7 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
 		StringT<128> typesVariableName;
 		BfMangler::MangleStaticFieldName(typesVariableName, GetMangleKind(), typeDefType->ToTypeInstance(), "sTypes", typeDefPtrType);
 		auto arrayType = bfModule->mBfIRBuilder->GetSizedArrayType(bfModule->mBfIRBuilder->MapType(typeDefType), (int)typeDataVector.size());
-		auto typeDataConst = bfModule->mBfIRBuilder->CreateConstArray(arrayType, typeDataVector);
+		auto typeDataConst = bfModule->mBfIRBuilder->CreateConstAgg_Value(arrayType, typeDataVector);
 		BfIRValue typeDataArray = bfModule->mBfIRBuilder->CreateGlobalVariable(arrayType, true, BfIRLinkageType_External,
 			typeDataConst, typesVariableName);
 
@@ -1401,7 +1402,7 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
 	{
 		auto elemType = bfModule->CreatePointerType(bfModule->GetPrimitiveType(BfTypeCode_Int8));
 		auto arrayType = bfModule->mBfIRBuilder->GetSizedArrayType(bfModule->mBfIRBuilder->MapType(elemType), (int)forceLinkValues.size());
-		auto typeDataConst = bfModule->mBfIRBuilder->CreateConstArray(arrayType, forceLinkValues);
+		auto typeDataConst = bfModule->mBfIRBuilder->CreateConstAgg_Value(arrayType, forceLinkValues);
 		BfIRValue typeDataArray = bfModule->mBfIRBuilder->CreateGlobalVariable(arrayType, true, BfIRLinkageType_Internal,
 			typeDataConst, "FORCELINK_MODULES");
 	}
@@ -1431,7 +1432,7 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
 		stringList.Add(bfModule->mBfIRBuilder->CreateConstNull(stringPtrIRType));
 
 		BfIRType stringArrayType = bfModule->mBfIRBuilder->GetSizedArrayType(stringPtrIRType, (int)stringList.size());
-		auto stringArray = bfModule->mBfIRBuilder->CreateConstArray(stringArrayType, stringList);
+		auto stringArray = bfModule->mBfIRBuilder->CreateConstAgg_Value(stringArrayType, stringList);
 		
 		auto stringArrayVar = bfModule->mBfIRBuilder->CreateGlobalVariable(stringArrayType, true, BfIRLinkageType_External, stringArray, stringsVariableName);
 		
@@ -1459,7 +1460,7 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
 		}
 
 		BfIRType stringArrayType = bfModule->mBfIRBuilder->GetSizedArrayType(stringPtrIRType, (int)usedStringIdMap.size());
-		auto stringArray = bfModule->mBfIRBuilder->CreateConstArray(stringArrayType, stringList);
+		auto stringArray = bfModule->mBfIRBuilder->CreateConstAgg_Value(stringArrayType, stringList);
 
 		auto stringArrayVar = bfModule->mBfIRBuilder->CreateGlobalVariable(stringArrayType, true, BfIRLinkageType_External, stringArray, stringsVariableName);
 
@@ -5378,10 +5379,11 @@ void BfCompiler::PopulateReified()
 									{
 										auto& checkMethodInstanceGroup = typeInst->mMethodInstanceGroups[checkMethodDef->mIdx];
 										auto checkMethodInstance = checkMethodInstanceGroup.mDefault;
-										if (checkMethodInstance == NULL)
-											continue;
-										if ((checkMethodDef->mIsExtern) && (checkMethodInstance->IsReifiedAndImplemented()))
-											forceMethod = true;
+										if (checkMethodInstance != NULL)											
+										{
+											if ((checkMethodDef->mIsExtern) && (checkMethodInstance->IsReifiedAndImplemented()))
+												forceMethod = true;
+										}
 										checkMethodDef = checkMethodDef->mNextWithSameName;
 									}
 								}
@@ -6632,6 +6634,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
 	mStaticInitAfterAttributeTypeDef = _GetRequiredType("System.StaticInitAfterAttribute");
 	mStaticInitPriorityAttributeTypeDef = _GetRequiredType("System.StaticInitPriorityAttribute");
 	mStringTypeDef = _GetRequiredType("System.String");
+	mStringViewTypeDef = _GetRequiredType("System.StringView");
 	mTestAttributeTypeDef = _GetRequiredType("System.TestAttribute");
 	mThreadStaticAttributeTypeDef = _GetRequiredType("System.ThreadStaticAttribute");
 	mTypeTypeDef = _GetRequiredType("System.Type");

+ 1 - 0
IDEHelper/Compiler/BfCompiler.h

@@ -349,6 +349,7 @@ public:
 	BfTypeDef* mActionTypeDef;
 	BfTypeDef* mEnumTypeDef;
 	BfTypeDef* mStringTypeDef;
+	BfTypeDef* mStringViewTypeDef;
 	BfTypeDef* mTypeTypeDef;
 	BfTypeDef* mValueTypeTypeDef;	
 	BfTypeDef* mResultTypeDef;

+ 14 - 2
IDEHelper/Compiler/BfConstResolver.cpp

@@ -59,7 +59,14 @@ BfTypedValue BfConstResolver::Resolve(BfExpression* expr, BfType* wantType, BfCo
 			if (initializer != NULL)
 			{
 				if (auto invocationExpr = BfNodeDynCast<BfInvocationExpression>(initializer))
-					arraySize = (int)invocationExpr->mArguments.size();				
+				{
+					if (auto memberRefExpr = BfNodeDynCast<BfMemberReferenceExpression>(invocationExpr->mTarget))
+					{
+						// Dot-initialized
+						if (memberRefExpr->mTarget == NULL)
+							arraySize = (int)invocationExpr->mArguments.size();
+					}					
+				}
 			}
 
 			if (arraySize != -1)
@@ -67,6 +74,11 @@ BfTypedValue BfConstResolver::Resolve(BfExpression* expr, BfType* wantType, BfCo
 				mResult = BfTypedValue(mModule->GetConstValue(arraySize), mModule->GetPrimitiveType(BfTypeCode_IntPtr));
 				return mResult;
 			}
+			else
+			{
+				mResult = BfTypedValue(mModule->mBfIRBuilder->GetUndefConstValue(BfTypeCode_IntPtr), mModule->GetPrimitiveType(BfTypeCode_IntPtr));
+				return mResult;
+			}
 		}
 	}
 
@@ -411,7 +423,7 @@ bool BfConstResolver::PrepareMethodArguments(BfAstNode* targetSrc, BfMethodMatch
 	if (expandedParamsElementType != NULL)
 	{				
 		auto arrayType = mModule->mBfIRBuilder->GetSizedArrayType(mModule->mBfIRBuilder->MapType(expandedParamsElementType), (int)expandedParamsConstValues.size());
-		auto constArray = mModule->mBfIRBuilder->CreateConstArray(arrayType, expandedParamsConstValues);
+		auto constArray = mModule->mBfIRBuilder->CreateConstAgg(arrayType, expandedParamsConstValues);
 		llvmArgs.push_back(constArray);
 	}	
 

+ 126 - 57
IDEHelper/Compiler/BfExprEvaluator.cpp

@@ -2628,6 +2628,25 @@ BfAutoComplete* BfExprEvaluator::GetAutoComplete()
 	return mModule->mCompiler->mResolvePassData->mAutoComplete;
 }
 
+bool BfExprEvaluator::IsConstEval()
+{
+	return (mModule->mIsConstModule) || ((mBfEvalExprFlags & BfEvalExprFlags_ConstExpr) != 0);
+}
+
+bool BfExprEvaluator::IsConstEvalEntry()
+{
+	if (mModule->mIsConstModule)
+		return false;
+	return ((mBfEvalExprFlags & BfEvalExprFlags_ConstExpr) != 0);
+}
+
+int BfExprEvaluator::GetStructRetIdx(BfMethodInstance* methodInstance, bool forceStatic)
+{
+	if (IsConstEval())
+		return -1;
+	return methodInstance->GetStructRetIdx(forceStatic);
+}
+
 BfType* BfExprEvaluator::BindGenericType(BfAstNode* node, BfType* bindType)
 {	
 	if ((mModule->mCurMethodState == NULL) || (mModule->mCurMethodInstance == NULL) || (bindType == NULL))
@@ -3165,7 +3184,7 @@ void BfExprEvaluator::GetLiteral(BfAstNode* refNode, const BfVariant& variant)
 				if (sizedArray->mElementCount > charValues.size())
 					charValues.Add(mModule->mBfIRBuilder->CreateConst(BfTypeCode_Char8, 0));
 
-				mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConstArray(mModule->mBfIRBuilder->MapType(sizedArray), charValues), sizedArray);
+				mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConstAgg(mModule->mBfIRBuilder->MapType(sizedArray), charValues), sizedArray);
 				return;
 			}
 		}
@@ -4913,7 +4932,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
 		}
 		else
 		{						
-			auto val = mModule->GetDefaultTypedValue(returnType, true, (methodInstance->GetStructRetIdx() != -1) ? BfDefaultValueKind_Addr : BfDefaultValueKind_Value);
+			auto val = mModule->GetDefaultTypedValue(returnType, true, (GetStructRetIdx(methodInstance) != -1) ? BfDefaultValueKind_Addr : BfDefaultValueKind_Value);
 			if (val.mKind == BfTypedValueKind_Addr)
 				val.mKind = BfTypedValueKind_RestrictedTempAddr;
 			return val;
@@ -4921,7 +4940,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
 	};
 
 	mModule->PopulateType(origReturnType, BfPopulateType_Data);
-	if (methodInstance->GetStructRetIdx() != -1)
+	if (GetStructRetIdx(methodInstance) != -1)
 	{
 		// We need to ensure that mReceivingValue has the correct type, otherwise it's possible that a conversion operator needs to be applied
 		//  This happens for returning Result<T>'s with a 'T' value
@@ -4982,25 +5001,42 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
 		return result;
 	}
 
+	bool forceBind = false;
+
 	if (mModule->mCompiler->mCEMachine != NULL)
-	{
+	{		
 		if (mModule->mIsConstModule)
-		{
+		{						
 			mModule->mCompiler->mCEMachine->QueueMethod(methodInstance, func);
 		}
 		else if ((mBfEvalExprFlags & BfEvalExprFlags_ConstExpr) != 0)
 		{
-			auto constRet = mModule->mCompiler->mCEMachine->Call(targetSrc, mModule, methodInstance, irArgs, CeEvalFlags_None);
-			if (constRet)
-				return constRet;
+			if (mFunctionBindResult != NULL)
+			{
+				forceBind = true;
+			}
+			else if (mUsedAsStatement)
+			{
+				// Don't allow use in a cascade
+			}
+			else
+			{
+				CeEvalFlags evalFlags = CeEvalFlags_None;				
+				auto constRet = mModule->mCompiler->mCEMachine->Call(targetSrc, mModule, methodInstance, irArgs, evalFlags, mExpectingType);
+				if (constRet)
+					return constRet;
+			}
 		}
 	}
 
-	if (((!func) && (methodInstance->mIsUnspecialized)) || (mModule->mBfIRBuilder->mIgnoreWrites))
+	if (!forceBind)
 	{
-		// We don't actually submit method calls for unspecialized methods
-		//  - this includes all methods in unspecialized types
-		return _GetDefaultReturnValue();
+		if (((!func) && (methodInstance->mIsUnspecialized)) || (mModule->mBfIRBuilder->mIgnoreWrites))
+		{
+			// We don't actually submit method calls for unspecialized methods
+			//  - this includes all methods in unspecialized types
+			return _GetDefaultReturnValue();
+		}
 	}
 
 	if (methodInstance->mVirtualTableIdx != -1)
@@ -5137,12 +5173,12 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
 	}
 	
 	if (mFunctionBindResult != NULL)
-	{			
+	{
 		mFunctionBindResult->mFunc = funcCallInst;
 		if (irArgs.size() != 0)
 		{
 			auto targetType = methodInstance->mMethodInstanceGroup->mOwner;
-			if ((targetType->IsValueType()) && (targetType->IsSplattable()) && (!methodDef->HasNoThisSplat()))
+			if ((targetType->IsValueType()) && (targetType->IsSplattable()) && (!methodDef->HasNoThisSplat()) && (!IsConstEval()))
 				mFunctionBindResult->mTarget = BfTypedValue(irArgs[0], targetType, BfTypedValueKind_SplatHead);
 			else
 				mFunctionBindResult->mTarget = BfTypedValue(irArgs[0], targetType, targetType->IsComposite() ? BfTypedValueKind_Addr : BfTypedValueKind_Value);
@@ -5150,7 +5186,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
 		else
 		{
 			mFunctionBindResult->mTarget = BfTypedValue();
-		}		
+		}
 
 		return BfTypedValue();
 	}
@@ -5214,7 +5250,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
 	if (sret != NULL)
 	{
 		SizedArray<BfIRValue, 8> sretIRArgs; 
-		int sretIdx = methodInstance->GetStructRetIdx();
+		int sretIdx = GetStructRetIdx(methodInstance);
 		int inIdx = 0;
 		for (int outIdx = 0; outIdx < irArgs.size() + 1; outIdx++)
 		{
@@ -5256,7 +5292,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
 		if (methodInstance->mIsIntrinsic)
 			break;
 
-		if (argIdx == methodInstance->GetStructRetIdx())
+		if (argIdx == GetStructRetIdx(methodInstance))
 		{
 			mModule->mBfIRBuilder->Call_AddAttribute(callInst, argIdx + 1, BfIRAttribute_StructRet);
 			argIdx++;
@@ -5303,7 +5339,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
 					mModule->PopulateType(paramType, BfPopulateType_Data);
 
 					auto typeInst = paramType->ToTypeInstance();
-					if ((typeInst != NULL) && (typeInst->mIsCRepr) && (typeInst->IsSplattable()))
+					if ((typeInst != NULL) && (typeInst->mIsCRepr) && (typeInst->IsSplattable()) && (!IsConstEval()))
 					{
 						// We're splatting
 					}
@@ -5346,7 +5382,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
 				doingThis = false;
 				continue;
 			}
-			bool isSplatted = methodInstance->GetParamIsSplat(thisIdx); // (resolvedTypeRef->IsSplattable()) && (!methodDef->mIsMutating);
+			bool isSplatted = methodInstance->GetParamIsSplat(thisIdx) && (!IsConstEval()); // (resolvedTypeRef->IsSplattable()) && (!methodDef->mIsMutating);
 			if (isSplatted)
 			{
 				BfTypeUtils::SplatIterate(_HandleParamType, paramType);
@@ -5380,7 +5416,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
 				continue;
 			}
 			
-			if (methodInstance->GetParamIsSplat(paramIdx))
+			if ((methodInstance->GetParamIsSplat(paramIdx)) && (!IsConstEval()))
 			{
 				BfTypeUtils::SplatIterate(_HandleParamType, paramType);
 				paramIdx++;
@@ -5575,6 +5611,7 @@ void BfExprEvaluator::SplatArgs(BfTypedValue value, SizedArrayImpl<BfIRValue>& i
 		else if (!checkType->IsValuelessType())
 		{
 			auto loadedVal = mModule->LoadValue(curValue);
+			loadedVal = mModule->PrepareConst(loadedVal);
 			irArgs.push_back(loadedVal.mValue);
 		}
 	};
@@ -5595,7 +5632,7 @@ void BfExprEvaluator::PushArg(BfTypedValue argVal, SizedArrayImpl<BfIRValue>& ir
 		return;	
 
 	bool wantSplat = false;
-	if ((argVal.mType->IsSplattable()) && (!disableSplat))
+	if ((argVal.mType->IsSplattable()) && (!disableSplat) && (!IsConstEval()))
 	{
 		disableLowering = true;
 		auto argTypeInstance = argVal.mType->ToTypeInstance();
@@ -5610,15 +5647,19 @@ void BfExprEvaluator::PushArg(BfTypedValue argVal, SizedArrayImpl<BfIRValue>& ir
 	else
 	{		
 		if (argVal.mType->IsComposite())
-		{
-			if (isIntrinsic)
+		{	
+			if ((mBfEvalExprFlags & BfEvalExprFlags_ConstExpr) != 0)
 			{
-				// We can handle composites either by value or not
+				// Const eval entry - we want any incoming consts as they are
 			}
+			else if (isIntrinsic)
+			{
+				// We can handle composites either by value or not
+			}			
 			else
 				argVal = mModule->MakeAddressable(argVal);
 			
-			if ((!disableLowering) && (!isIntrinsic))
+			if ((!IsConstEval()) && (!disableLowering) && (!isIntrinsic))
 			{
 				BfTypeCode loweredTypeCode = BfTypeCode_None;
 				BfTypeCode loweredTypeCode2 = BfTypeCode_None;				
@@ -5678,7 +5719,7 @@ void BfExprEvaluator::PushThis(BfAstNode* targetSrc, BfTypedValue argVal, BfMeth
 				mResultLocalVar->mWrittenToId = mModule->mCurMethodState->GetRootMethodState()->mCurAccessId++;			
 		}
 			
-		if (((argVal.mType->IsComposite()) || (argVal.mType->IsTypedPrimitive())))		
+		if (((argVal.mType->IsComposite()) || (argVal.mType->IsTypedPrimitive())))
 		{
 			if ((argVal.IsReadOnly()) || (!argVal.IsAddr()))
 			{
@@ -5708,14 +5749,22 @@ void BfExprEvaluator::PushThis(BfAstNode* targetSrc, BfTypedValue argVal, BfMeth
 
 	if (argVal.mType->IsValuelessType())
 		return;
+	
+	auto owner = methodInstance->GetOwner();
+
+	bool allowThisSplatting;
+	if (mModule->mIsConstModule)
+		allowThisSplatting = owner->IsTypedPrimitive() || owner->IsValuelessType();
+	else
+		allowThisSplatting = methodInstance->AllowsThisSplatting();
 
-	if ((!methodInstance->AllowsThisSplatting()) || (methodDef->mIsMutating))
+	if ((!allowThisSplatting) || (methodDef->mIsMutating))
 	{
 		argVal = mModule->MakeAddressable(argVal);
 		irArgs.push_back(argVal.mValue);
 		return;
 	}
-
+	
 	auto thisType = methodInstance->GetThisType();
 	PushArg(argVal, irArgs, !methodInstance->AllowsThisSplatting(), thisType->IsPointer());
 }
@@ -6007,7 +6056,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
 		}
 		else
 		{
-			wantsSplat = methodInstance->GetParamIsSplat(paramIdx);			
+			wantsSplat = methodInstance->GetParamIsSplat(paramIdx) && (!IsConstEval());
 			if (methodInstance->IsImplicitCapture(paramIdx))
 			{
 				auto paramType = methodInstance->GetParamType(paramIdx);
@@ -6031,14 +6080,14 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
 					{						
 						if (wantsSplat)
 						{
-SplatArgs(lookupVal, irArgs);
+							SplatArgs(lookupVal, irArgs);
 						}
 						else if (paramType->IsRef())
 						{
-						irArgs.push_back(lookupVal.mValue);
+							irArgs.push_back(lookupVal.mValue);
 						}
 						else
-						PushArg(lookupVal, irArgs, true);
+							PushArg(lookupVal, irArgs, true);
 					}
 				}
 				paramIdx++;
@@ -6474,7 +6523,7 @@ SplatArgs(lookupVal, irArgs);
 				else
 				{
 					// We need to make a temp and get the addr of that
-					if ((!wantsSplat) && (!argValue.IsValuelessType()) && (!argValue.IsAddr()))
+					if ((!wantsSplat) && (!argValue.IsValuelessType()) && (!argValue.IsAddr()) && (!IsConstEvalEntry()))
 					{
 						argValue = mModule->MakeAddressable(argValue);
 					}
@@ -10828,7 +10877,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
 			hasThis = true;
 			methodInstance->GetIRFunctionInfo(mModule, irReturnType, irParamTypes);			
 			int thisIdx = 0;
-			if (methodInstance->GetStructRetIdx() == 0)
+			if (GetStructRetIdx(methodInstance) == 0)
 				thisIdx = 1;
 			irParamTypes[thisIdx] = mModule->mBfIRBuilder->MapType(useTypeInstance);
 		}
@@ -10846,10 +10895,10 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
 		auto funcType = mModule->mBfIRBuilder->CreateFunctionType(irReturnType, irParamTypes);
 		funcValue = mModule->mBfIRBuilder->CreateFunction(funcType, BfIRLinkageType_External, methodName);
 
-		if (methodInstance->GetStructRetIdx() != -1)
+		if (GetStructRetIdx(methodInstance) != -1)
 		{			
-			mModule->mBfIRBuilder->Func_AddAttribute(funcValue, methodInstance->GetStructRetIdx() + 1, BfIRAttribute_NoAlias);
-			mModule->mBfIRBuilder->Func_AddAttribute(funcValue, methodInstance->GetStructRetIdx() + 1, BfIRAttribute_StructRet);
+			mModule->mBfIRBuilder->Func_AddAttribute(funcValue, GetStructRetIdx(methodInstance) + 1, BfIRAttribute_NoAlias);
+			mModule->mBfIRBuilder->Func_AddAttribute(funcValue, GetStructRetIdx(methodInstance) + 1, BfIRAttribute_StructRet);
 		}
 
 		auto srcCallingConv = mModule->GetIRCallingConvention(methodInstance);
@@ -10867,9 +10916,9 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
 		SizedArray<BfIRValue, 8> irArgs;
 
 		int argIdx = 0;
-		if (bindMethodInstance->GetStructRetIdx() == 0)
+		if (GetStructRetIdx(bindMethodInstance) == 0)
 		{
-			irArgs.push_back(mModule->mBfIRBuilder->GetArgument(methodInstance->GetStructRetIdx()));
+			irArgs.push_back(mModule->mBfIRBuilder->GetArgument(GetStructRetIdx(methodInstance)));
 			argIdx++;
 		}
 		
@@ -10889,7 +10938,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
 			}
 			
 			int thisIdx = 0;
-			if (methodInstance->GetStructRetIdx() == 0)
+			if (GetStructRetIdx(methodInstance) == 0)
 				thisIdx = 1;
 			auto fieldPtr = mModule->mBfIRBuilder->CreateInBoundsGEP(mModule->mBfIRBuilder->GetArgument(thisIdx), 0, gepIdx);
 			BfTypedValue typedVal(fieldPtr, fieldType, true);
@@ -10900,16 +10949,16 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
 		if (hasThis)
 			argIdx++;
 		
-		if (bindMethodInstance->GetStructRetIdx() == 1)
+		if (GetStructRetIdx(bindMethodInstance) == 1)
 		{
-			irArgs.push_back(mModule->mBfIRBuilder->GetArgument(methodInstance->GetStructRetIdx()));
+			irArgs.push_back(mModule->mBfIRBuilder->GetArgument(GetStructRetIdx(methodInstance)));
 			argIdx++;
 		}
 
 		for (int paramIdx = 0; paramIdx < methodInstance->GetParamCount(); paramIdx++)
 		{
 			auto paramType = methodInstance->GetParamType(paramIdx);
-			if (paramType->IsSplattable())
+			if ((paramType->IsSplattable()) && (!IsConstEval()))
 			{
 				BfTypeUtils::SplatIterate([&](BfType* checkType) { irArgs.push_back(mModule->mBfIRBuilder->GetArgument(argIdx++)); }, paramType);
 			}
@@ -10923,12 +10972,12 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
 		if (mModule->mCompiler->mOptions.mAllowHotSwapping)
 			bindFuncVal = mModule->mBfIRBuilder->RemapBindFunction(bindFuncVal);
 		auto callInst = mModule->mBfIRBuilder->CreateCall(bindFuncVal, irArgs);
-		if (bindMethodInstance->GetStructRetIdx() != -1)
-			mModule->mBfIRBuilder->Call_AddAttribute(callInst, bindMethodInstance->GetStructRetIdx() + 1, BfIRAttribute_StructRet);
+		if (GetStructRetIdx(bindMethodInstance) != -1)
+			mModule->mBfIRBuilder->Call_AddAttribute(callInst, GetStructRetIdx(bindMethodInstance) + 1, BfIRAttribute_StructRet);
 		auto destCallingConv = mModule->GetIRCallingConvention(bindMethodInstance);
 		if (destCallingConv != BfIRCallingConv_CDecl)
 			mModule->mBfIRBuilder->SetCallCallingConv(callInst, destCallingConv);
-		if ((methodInstance->mReturnType->IsValuelessType()) || (methodInstance->GetStructRetIdx() != -1))
+		if ((methodInstance->mReturnType->IsValuelessType()) || (GetStructRetIdx(methodInstance) != -1))
 		{
 			mModule->mBfIRBuilder->CreateRetVoid();
 		}
@@ -11777,15 +11826,15 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam
 
 	SizedArray<BfIRType, 3> newTypes;	
 
-	if ((invokeMethodInstance != NULL) && (invokeMethodInstance->GetStructRetIdx(forceStatic) == 0))
+	if ((invokeMethodInstance != NULL) && (GetStructRetIdx(invokeMethodInstance, forceStatic) == 0))
 		newTypes.push_back(origParamTypes[0]);
 	if (!methodDef->mIsStatic)
 		newTypes.push_back(mModule->mBfIRBuilder->MapType(useTypeInstance));
-	if ((invokeMethodInstance != NULL) && (invokeMethodInstance->GetStructRetIdx(forceStatic) == 1))
+	if ((invokeMethodInstance != NULL) && (GetStructRetIdx(invokeMethodInstance, forceStatic) == 1))
 		newTypes.push_back(origParamTypes[1]);
 
 	int paramStartIdx = 0;
-	if ((invokeMethodInstance != NULL) && (invokeMethodInstance->GetStructRetIdx(forceStatic) != -1))
+	if ((invokeMethodInstance != NULL) && (GetStructRetIdx(invokeMethodInstance, forceStatic) != -1))
 		paramStartIdx++;
 	if (!methodDef->mIsStatic)
 		paramStartIdx++;
@@ -13143,11 +13192,17 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
 	else
 	{
 		if (isAppendAlloc)
-			allocValue = mModule->AppendAllocFromType(resolvedTypeRef, appendSizeValue, appendAllocAlign);
+		{
+			allocValue = mModule->AppendAllocFromType(resolvedTypeRef, appendSizeValue, appendAllocAlign);			
+		}
 		else
 		{
 			allocValue = mModule->AllocFromType(resolvedTypeRef, allocTarget, appendSizeValue, BfIRValue(), 0, BfAllocFlags_None, allocAlign);
 		}
+		if (((mBfEvalExprFlags & BfEvalExprFlags_ConstExpr) != 0) && (mModule->mCompiler->mCEMachine != NULL))
+		{
+			mModule->mCompiler->mCEMachine->SetAppendAllocInfo(mModule, allocValue, appendSizeValue);
+		}
 		mResult = BfTypedValue(allocValue, resultType);
 	}
 
@@ -13195,7 +13250,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
 					{
 						mModule->AssertErrorState();
 					}
-					else
+					else if ((mBfEvalExprFlags & BfEvalExprFlags_ConstExpr) == 0)
 					{
 						SizedArray<BfIRValue, 1> irArgs;
 						irArgs.push_back(mResult.mValue);
@@ -13203,7 +13258,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
 					}
 				}
 
-				if ((isStackAlloc) && (mModule->mCompiler->mOptions.mEnableRealtimeLeakCheck))
+				if ((!mModule->mIsConstModule) && (isStackAlloc) && (mModule->mCompiler->mOptions.mEnableRealtimeLeakCheck))
 				{
 					BfMethodInstance* markMethod = mModule->GetRawMethodByName(mModule->mContext->mBfObjectType, "GCMarkMembers");
 					BF_ASSERT(markMethod != NULL);
@@ -13267,9 +13322,16 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
 			}
 			if (!typeInstance->IsValuelessType())
 				bindResult.mIRArgs.Insert(0, mResult.mValue);
-			CreateCall(objCreateExpr, bindResult.mMethodInstance, bindResult.mFunc, false, bindResult.mIRArgs);
+			auto result = CreateCall(objCreateExpr, bindResult.mMethodInstance, bindResult.mFunc, false, bindResult.mIRArgs);
+			if ((result) && (!result.mType->IsVoid()))
+				mResult = result;
 		}
 	}
+
+	if (((mBfEvalExprFlags & BfEvalExprFlags_ConstExpr) != 0) && (mModule->mCompiler->mCEMachine != NULL))
+	{
+		mModule->mCompiler->mCEMachine->ClearAppendAllocInfo();
+	}
 }
 
 void BfExprEvaluator::Visit(BfBoxExpression* boxExpr)
@@ -13460,6 +13522,8 @@ BfTypedValue BfExprEvaluator::MakeCallableTarget(BfAstNode* targetSrc, BfTypedVa
 
 	if ((target.mType->IsStruct()) && (!target.IsAddr()))
 	{
+		if (IsConstEvalEntry())
+			return target;
 		target = mModule->MakeAddressable(target);
 	}
 
@@ -13494,7 +13558,7 @@ BfTypedValue BfExprEvaluator::MakeCallableTarget(BfAstNode* targetSrc, BfTypedVa
 				auto ptrType = mModule->CreatePointerType(primStructType);
 				target = BfTypedValue(mModule->mBfIRBuilder->CreateBitCast(target.mValue, mModule->mBfIRBuilder->MapType(ptrType)), primStructType, true);
 			}
-			else if ((primStructType->IsSplattable()) && (target.IsSplat()))
+			else if ((primStructType->IsSplattable()) && (target.IsSplat()) && (!IsConstEval()))
 			{
 				target.mType = primStructType;
 				target.mKind = BfTypedValueKind_SplatHead;								
@@ -14865,7 +14929,9 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
 							else
 								mResult = BfTypedValue(mModule->CreateAlloca(expectingType), expectingType, BfTypedValueKind_TempAddr);
 							
-							MatchConstructor(target, methodBoundExpr, mResult, expectingType->ToTypeInstance(), argValues, false, false);																					
+							auto ctorResult = MatchConstructor(target, methodBoundExpr, mResult, expectingType->ToTypeInstance(), argValues, false, false);																					
+							if ((ctorResult) && (!ctorResult.mType->IsVoid()))
+								mResult = ctorResult;							
 							mModule->ValidateAllocation(expectingType, invocationExpr->mTarget);
 
 							return;
@@ -15364,6 +15430,9 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
 		}
 	}
 
+	if ((isCascade) && (cascadeOperatorToken != NULL) && ((mBfEvalExprFlags & BfEvalExprFlags_ConstExpr) != 0))
+		mModule->Fail("Cascade operator cannot be used in const evaluation", cascadeOperatorToken);
+
 	SetAndRestoreValue<bool> prevUsedAsStatement(mUsedAsStatement, mUsedAsStatement || isCascade);
 	ResolveArgValues(argValues, resolveArgsFlags);
 	mResult = MatchMethod(methodNodeSrc, methodBoundExpr, thisValue, allowImplicitThis, bypassVirtual, targetFunctionName, argValues, methodGenericArguments, checkedKind);		
@@ -15875,7 +15944,7 @@ BfTypedValue BfExprEvaluator::GetResult(bool clearResult, bool resolveGenericTyp
 					}
 					else
 					{
-						auto val = mModule->GetDefaultTypedValue(returnType, true, (methodInstance.mMethodInstance->GetStructRetIdx() != -1) ? BfDefaultValueKind_Addr : BfDefaultValueKind_Value);
+						auto val = mModule->GetDefaultTypedValue(returnType, true, (GetStructRetIdx(methodInstance.mMethodInstance) != -1) ? BfDefaultValueKind_Addr : BfDefaultValueKind_Value);
 						if (val.mKind == BfTypedValueKind_Addr)
 							val.mKind = BfTypedValueKind_TempAddr;
 						return val;
@@ -17390,7 +17459,7 @@ void BfExprEvaluator::InitializedSizedArray(BfSizedArrayType* arrayType, BfToken
 				return mModule->mBfIRBuilder->CreateConstStructZero(mModule->mBfIRBuilder->MapType(checkArrayType)); 
 			}
 			else
-				return mModule->mBfIRBuilder->CreateConstArray(mModule->mBfIRBuilder->MapType(checkArrayType), members);
+				return mModule->mBfIRBuilder->CreateConstAgg(mModule->mBfIRBuilder->MapType(checkArrayType), members);
 		};
 
 		_GetValues(arrayType, openToken, valueExprs, commas, closeToken, false);

+ 3 - 0
IDEHelper/Compiler/BfExprEvaluator.h

@@ -383,6 +383,9 @@ public:
 	void FinishExpressionResult();	
 	virtual bool CheckAllowValue(const BfTypedValue& typedValue, BfAstNode* refNode);
 	BfAutoComplete* GetAutoComplete();	
+	bool IsConstEval();
+	bool IsConstEvalEntry();
+	int GetStructRetIdx(BfMethodInstance* methodInstance, bool forceStatic = false);
 	BfTypedValue SetupNullConditional(BfTypedValue target, BfTokenNode* dotToken);
 	void Evaluate(BfAstNode* astNode, bool propogateNullConditional = false, bool ignoreNullConditional = false, bool allowSplat = true);	
 	BfType* BindGenericType(BfAstNode* node, BfType* bindType);

+ 42 - 51
IDEHelper/Compiler/BfIRBuilder.cpp

@@ -406,12 +406,12 @@ int BfIRConstHolder::IsZero(BfIRValue value)
 	if (constant->mConstType == BfConstType_AggZero)
 		return 1;
 
-	if (constant->mConstType == BfConstType_Array)
+	if (constant->mConstType == BfConstType_Agg)
 	{
-		auto constArr = (BfConstantArray*)constant;
-		for (int i = 0; i < constArr->mValues.mSize; i++)
+		auto constAgg = (BfConstantAgg*)constant;
+		for (int i = 0; i < constAgg->mValues.mSize; i++)
 		{
-			int elemResult = IsZero(constArr->mValues[i]);
+			int elemResult = IsZero(constAgg->mValues[i]);
 			if (elemResult != 1)
 				return elemResult;
 		}
@@ -454,17 +454,17 @@ int BfIRConstHolder::CheckConstEquality(BfIRValue lhs, BfIRValue rhs)
 		return (constLHS->mUInt64 == constRHS->mUInt64) ? 1 : 0;
 	}
 	
-	if (constLHS->mConstType == BfConstType_Array)
+	if (constLHS->mConstType == BfConstType_Agg)
 	{
-		auto arrayLHS = (BfConstantArray*)constLHS;
-		auto arrayRHS = (BfConstantArray*)constRHS;
+		auto aggLHS = (BfConstantAgg*)constLHS;
+		auto aggRHS = (BfConstantAgg*)constRHS;
 		
-		if (arrayLHS->mValues.mSize != arrayRHS->mValues.mSize)
+		if (aggLHS->mValues.mSize != aggRHS->mValues.mSize)
 			return -1;
 
-		for (int i = 0; i < arrayLHS->mValues.mSize; i++)
+		for (int i = 0; i < aggLHS->mValues.mSize; i++)
 		{
-			int elemResult = CheckConstEquality(arrayLHS->mValues[i], arrayRHS->mValues[i]);
+			int elemResult = CheckConstEquality(aggLHS->mValues[i], aggRHS->mValues[i]);
 			if (elemResult != 1)
 				return elemResult;
 		}
@@ -641,18 +641,18 @@ BfIRValue BfIRConstHolder::CreateConst(BfConstant* fromConst, BfIRConstHolder* f
 		auto aggZero = (BfConstant*)fromConst;
 		return CreateConstStructZero(fromConst->mIRType);
 	}
-	else if (fromConst->mConstType == BfConstType_Array)
+	else if (fromConst->mConstType == BfConstType_Agg)
 	{
-		auto constArray = (BfConstantArray*)fromConst;
+		auto constAgg = (BfConstantAgg*)fromConst;
 
 		BfSizedVector<BfIRValue, 8> copiedVals;
-		copiedVals.reserve(constArray->mValues.size());
-		for (auto fromVal : constArray->mValues)
+		copiedVals.reserve(constAgg->mValues.size());
+		for (auto fromVal : constAgg->mValues)
 		{
 			auto elementConst = fromHolder->GetConstant(fromVal);
 			copiedVals.push_back(CreateConst(elementConst, fromHolder));
 		}
-		return CreateConstArray(constArray->mType, copiedVals);
+		return CreateConstAgg(constAgg->mType, copiedVals);
 	}
 	else if ((IsInt(fromConst->mTypeCode)) || (fromConst->mTypeCode == BfTypeCode_Boolean) || (fromConst->mTypeCode == BfTypeCode_StringId))
 	{		
@@ -722,10 +722,10 @@ BfIRValue BfIRConstHolder::CreateConstStructZero(BfIRType aggType)
 	return irValue;
 }
 
-BfIRValue BfIRConstHolder::CreateConstArray(BfIRType type, const BfSizedArray<BfIRValue>& values)
+BfIRValue BfIRConstHolder::CreateConstAgg(BfIRType type, const BfSizedArray<BfIRValue>& values)
 {
-	BfConstantArray* constant = mTempAlloc.Alloc<BfConstantArray>();
-	constant->mConstType = BfConstType_Array;
+	BfConstantAgg* constant = mTempAlloc.Alloc<BfConstantAgg>();
+	constant->mConstType = BfConstType_Agg;
 	constant->mType = type = type;
 	auto irValue = BfIRValue(BfIRValueFlags_Const, mTempAlloc.GetChunkedId(constant));
 
@@ -1286,17 +1286,17 @@ String BfIRBuilder::ToString(BfIRValue irValue)
 			BfIRValue targetConst(BfIRValueFlags_Const, bitcast->mTarget);
 			return ToString(targetConst) + " IntToPtr " + ToString(bitcast->mToType);
 		}
-		else if (constant->mConstType == BfConstType_Array)
+		else if (constant->mConstType == BfConstType_Agg)
 		{
-			auto constArray = (BfConstantArray*)constant;
-			String str = ToString(constArray->mType);
+			auto constAgg = (BfConstantAgg*)constant;
+			String str = ToString(constAgg->mType);
 			str += "(";
 
-			for (int i = 0; i < (int)constArray->mValues.size(); i++)
+			for (int i = 0; i < (int)constAgg->mValues.size(); i++)
 			{
 				if (i > 0)
 					str += ", ";
-				str += ToString(constArray->mValues[i]);
+				str += ToString(constAgg->mValues[i]);
 			}
 			str += ");";
 			return str;
@@ -1915,9 +1915,9 @@ void BfIRBuilder::Write(const BfIRValue& irValue)
 				Write(constant->mIRType);
 			}
 			break;
-		case (int)BfConstType_Array:
+		case (int)BfConstType_Agg:
 			{
-				auto arrayConst = (BfConstantArray*)constant;
+				auto arrayConst = (BfConstantAgg*)constant;
 				Write(arrayConst->mType);
 				Write(arrayConst->mValues);
 			}
@@ -2316,9 +2316,9 @@ void BfIRBuilder::CreateTypeDeclaration(BfType* type, bool forceDbgDefine)
 		if (arrayType->mElementType->IsValuelessType())		
 			irType = elementIrType;		
 		else if (arrayType->mElementType->IsSizeAligned())
-			irType = GetSizedArrayType(MapType(arrayType->mElementType), arrayType->mElementCount);
+			irType = GetSizedArrayType(MapType(arrayType->mElementType), BF_MAX(arrayType->mElementCount, 0));
 		else
-			irType = GetSizedArrayType(MapType(mModule->GetPrimitiveType(BfTypeCode_Int8)), arrayType->mSize);				
+			irType = GetSizedArrayType(MapType(mModule->GetPrimitiveType(BfTypeCode_Int8)), BF_MAX(arrayType->mSize, 0));
 
 		if (wantDIData)				
 			diType = DbgCreateArrayType((int64)arrayType->mSize * 8, arrayType->mAlign * 8, DbgGetType(arrayType->mElementType), arrayType->mElementCount);
@@ -2710,7 +2710,7 @@ void BfIRBuilder::CreateDbgTypeDefinition(BfType* type)
 								if (isOptimized)
 									continue;
 
-								if ((constant->mConstType == BfConstType_Array) ||
+								if ((constant->mConstType == BfConstType_Agg) ||
 									(constant->mConstType == BfConstType_AggZero) ||
 									(constant->mTypeCode == BfTypeCode_NullPtr))
 								{										
@@ -3555,6 +3555,7 @@ BfIRType BfIRBuilder::GetPointerTo(BfIRType type)
 
 BfIRType BfIRBuilder::GetSizedArrayType(BfIRType elementType, int length)
 {
+	BF_ASSERT(length >= 0);
 	if (mIgnoreWrites)
 	{
 		auto constSizedArrayType = mTempAlloc.Alloc<BfConstantSizedArrayType>();
@@ -3570,7 +3571,7 @@ BfIRType BfIRBuilder::GetSizedArrayType(BfIRType elementType, int length)
 		return retType;
 	}
 	else
-	{
+	{		
 		BfIRType retType = WriteCmd(BfIRCmd_GetSizedArrayType, elementType, length);
 		NEW_CMD_INSERTED_IRTYPE;
 		return retType;
@@ -3584,27 +3585,13 @@ BfIRType BfIRBuilder::GetVectorType(BfIRType elementType, int length)
 	return retType;	
 }
 
-BfIRValue BfIRBuilder::CreateConstStruct(BfIRType type, const BfSizedArray<BfIRValue>& values)
-{
-	BfIRValue retVal = WriteCmd(BfIRCmd_CreateConstStruct, type, values);
-	NEW_CMD_INSERTED_IRVALUE;
-	return retVal;
-}
-
-/*BfIRValue BfIRBuilder::CreateConstStructZero(BfIRType type)
+BfIRValue BfIRBuilder::CreateConstAgg_Value(BfIRType type, const BfSizedArray<BfIRValue>& values)
 {
-	BfIRValue retVal = WriteCmd(BfIRCmd_CreateConstStructZero, type);
+	BfIRValue retVal = WriteCmd(BfIRCmd_CreateConstAgg, type, values);
 	NEW_CMD_INSERTED_IRVALUE;
 	return retVal;
 }
 
-BfIRValue BfIRBuilder::CreateConstArray(BfIRType type, const BfSizedArray<BfIRValue>& values)
-{
-	BfIRValue retVal = WriteCmd(BfIRCmd_CreateConstArray, type, values);
-	NEW_CMD_INSERTED_IRVALUE;
-	return retVal;
-}*/
-
 BfIRValue BfIRBuilder::CreateConstString(const StringImpl& str)
 {
 	BfIRValue retVal = WriteCmd(BfIRCmd_CreateConstString, str);
@@ -3620,8 +3607,8 @@ BfIRValue BfIRBuilder::ConstToMemory(BfIRValue constVal)
 		return *value;
 	
 	BfIRType constType;
-	if (constant->mConstType == BfConstType_Array)
-		constType = ((BfConstantArray*)constant)->mType;
+	if (constant->mConstType == BfConstType_Agg)
+		constType = ((BfConstantAgg*)constant)->mType;
 	else if (constant->mConstType == BfConstType_AggZero)
 		constType = constant->mIRType;
 	else if (constant->mTypeCode == BfTypeCode_NullPtr)
@@ -4181,9 +4168,9 @@ BfIRValue BfIRBuilder::CreateExtractValue(BfIRValue val, int idx)
 	auto aggConstant = GetConstant(val);
 	if (aggConstant != NULL)
 	{
-		if (aggConstant->mConstType == BfConstType_Array)
+		if (aggConstant->mConstType == BfConstType_Agg)
 		{
-			auto arrayConstant = (BfConstantArray*)aggConstant;
+			auto arrayConstant = (BfConstantAgg*)aggConstant;
 			return arrayConstant->mValues[idx];
 		}
 		
@@ -4223,7 +4210,7 @@ BfIRValue BfIRBuilder::CreateExtractValue(BfIRValue val, BfIRValue idx)
 	auto arrConst = GetConstant(val);
 	if (arrConst != NULL)
 	{
-		if ((arrConst->mConstType == BfConstType_Array) || (arrConst->mConstType == BfConstType_AggZero))
+		if ((arrConst->mConstType == BfConstType_Agg) || (arrConst->mConstType == BfConstType_AggZero))
 		{
 			BfIRValue arrMemVal = ConstToMemory(val);
 			auto valAddr = CreateInBoundsGEP(arrMemVal, CreateConst(BfTypeCode_IntPtr, 0), idx);
@@ -4670,6 +4657,11 @@ BfIRFunction BfIRBuilder::CreateFunction(BfIRFunctionType funcType, BfIRLinkageT
 	NEW_CMD_INSERTED_IRVALUE;	
 	mFunctionMap[name] = retVal;
 
+	if ((mModule->mIsConstModule) && (name.Contains("Dbg_")))
+	{
+		NOP;
+	}
+
 	//BfLogSys(mModule->mSystem, "BfIRBuilder::CreateFunction: %d %s Module:%p\n", retVal.mId, name.c_str(), mModule);
 
 	return retVal;
@@ -4955,7 +4947,6 @@ void BfIRBuilder::CreateObjectAccessCheck(BfIRValue value, bool useAsm)
 	NEW_CMD_INSERTED_IRBLOCK;
 	if (!mIgnoreWrites)
 	{
-		BF_ASSERT(!value.IsConst());
 		BF_ASSERT(!retBlock.IsFake());
 		mActualInsertBlock = retBlock;
 	}

+ 7 - 8
IDEHelper/Compiler/BfIRBuilder.h

@@ -121,7 +121,7 @@ enum BfConstType
 	BfConstType_IntToPtr,
 	BfConstType_TypeOf,
 	BfConstType_AggZero,
-	BfConstType_Array,
+	BfConstType_Agg,
 	BfConstType_ArrayZero,
 	BfConstType_ArrayZero8,
 	BfConstType_Undef,
@@ -160,10 +160,9 @@ enum BfIRCmd : uint8
 	BfIRCmd_GetPointerToType,
 	BfIRCmd_GetSizedArrayType,
 	BfIRCmd_GetVectorType,
-
-	BfIRCmd_CreateConstStruct,
+	
 	BfIRCmd_CreateConstStructZero,
-	BfIRCmd_CreateConstArray,
+	BfIRCmd_CreateConstAgg,
 	BfIRCmd_CreateConstArrayZero,
 	BfIRCmd_CreateConstString,
 	BfIRCmd_ConfigConst,
@@ -855,7 +854,7 @@ struct BfConstantExtractValue
 	int mIdx0;	
 };
 
-struct BfConstantArray
+struct BfConstantAgg
 {
 	BfConstType mConstType;
 	BfIRType mType;
@@ -900,7 +899,7 @@ public:
 	BfIRValue CreateConstNull();
 	BfIRValue CreateConstNull(BfIRType nullType);
 	BfIRValue CreateConstStructZero(BfIRType aggType);
-	BfIRValue CreateConstArray(BfIRType type, const BfSizedArray<BfIRValue>& values);
+	BfIRValue CreateConstAgg(BfIRType type, const BfSizedArray<BfIRValue>& values);
 	BfIRValue CreateConstArrayZero(BfIRType type, int count);
 	BfIRValue CreateConstArrayZero(int count);
 	BfIRValue CreateTypeOf(BfType* type);
@@ -1115,8 +1114,8 @@ public:
 	BfIRType GetPointerTo(BfIRType type);
 	BfIRType GetSizedArrayType(BfIRType elementType, int length);
 	BfIRType GetVectorType(BfIRType elementType, int length);
-
-	BfIRValue CreateConstStruct(BfIRType type, const BfSizedArray<BfIRValue>& values);	
+	
+	BfIRValue CreateConstAgg_Value(BfIRType type, const BfSizedArray<BfIRValue>& values);
 	BfIRValue CreateConstString(const StringImpl& string);
 	BfIRValue ConstToMemory(BfIRValue constVal);
 	BfIRValue GetConfigConst(BfIRConfigConst constType, BfTypeCode typeCode);

+ 58 - 24
IDEHelper/Compiler/BfIRCodeGen.cpp

@@ -882,27 +882,44 @@ void BfIRCodeGen::Read(llvm::Value*& llvmValue, BfIRCodeGenEntry** codeGenEntry)
 			llvmValue = llvm::ConstantExpr::getPtrToInt(target, llvmToType);
 			return;
 		}
+		else if (constType == BfConstType_IntToPtr)
+		{
+			CMD_PARAM(llvm::Constant*, target);
+			CMD_PARAM(llvm::Type*, toType);
+			llvmValue = llvm::ConstantExpr::getIntToPtr(target, toType);
+			return;
+		}
 		else if (constType == BfConstType_AggZero)
 		{
 			CMD_PARAM(llvm::Type*, type);
 			llvmValue = llvm::ConstantAggregateZero::get(type);
 			return;
 		}
-		else if (constType == BfConstType_Array)
+		else if (constType == BfConstType_Agg)
 		{
 			CMD_PARAM(llvm::Type*, type);
 			CMD_PARAM(CmdParamVec<llvm::Constant*>, values);
 
-			auto arrayType = (llvm::ArrayType*)type;
-			int fillCount = (int)(arrayType->getNumElements() - values.size());
-			if (fillCount > 0)
+			if (auto arrayType = llvm::dyn_cast<llvm::ArrayType>(type))
 			{
-				auto lastValue = values.back();				
-				for (int i = 0; i < fillCount; i++)
-					values.push_back(lastValue);				
+				int fillCount = (int)(arrayType->getNumElements() - values.size());
+				if (fillCount > 0)
+				{
+					auto lastValue = values.back();
+					for (int i = 0; i < fillCount; i++)
+						values.push_back(lastValue);
+				}
+				llvmValue = llvm::ConstantArray::get(arrayType, values);
 			}
-
-			llvmValue = llvm::ConstantArray::get((llvm::ArrayType*)type, values);
+			else if (auto structType = llvm::dyn_cast<llvm::StructType>(type))
+			{
+				llvmValue = llvm::ConstantStruct::get(structType, values);
+			}
+			else
+			{
+				Fail("Bad type");
+			}
+						
 			return;
 		}
 
@@ -1616,19 +1633,43 @@ void BfIRCodeGen::HandleNextCmd()
 			SetResult(curId, llvm::FixedVectorType::get(elementType, length));
 		}
 		break;	
-	case BfIRCmd_CreateConstStruct:
+	case BfIRCmd_CreateConstAgg:
 		{
 			CMD_PARAM(llvm::Type*, type);
 			CMD_PARAM(CmdParamVec<llvm::Value*>, values)
 			llvm::SmallVector<llvm::Constant*, 8> copyValues; 
-			FixValues((llvm::StructType*)type, values);
-			for (auto val : values)
+
+			if (auto arrayType = llvm::dyn_cast<llvm::ArrayType>(type))
+			{
+				for (auto val : values)
+				{
+					auto constValue = llvm::dyn_cast<llvm::Constant>(val);
+					BF_ASSERT(constValue != NULL);
+					copyValues.push_back(constValue);
+				}
+
+				int fillCount = (int)(arrayType->getNumElements() - copyValues.size());
+				if (fillCount > 0)
+				{
+					auto lastValue = copyValues.back();
+					for (int i = 0; i < fillCount; i++)
+						copyValues.push_back(lastValue);
+				}
+				SetResult(curId, llvm::ConstantArray::get(arrayType, copyValues));
+			}
+			else if (auto structType = llvm::dyn_cast<llvm::StructType>(type))
 			{
-				auto constValue = llvm::dyn_cast<llvm::Constant>(val);
-				BF_ASSERT(constValue != NULL);
-				copyValues.push_back(constValue);
+				FixValues(structType, values);
+				for (auto val : values)
+				{
+					auto constValue = llvm::dyn_cast<llvm::Constant>(val);
+					BF_ASSERT(constValue != NULL);
+					copyValues.push_back(constValue);
+				}
+				SetResult(curId, llvm::ConstantStruct::get(structType, copyValues));
 			}
-			SetResult(curId, llvm::ConstantStruct::get((llvm::StructType*)type, copyValues));
+			else
+				Fail("Bad type");
 		}
 		break;
 	case BfIRCmd_CreateConstStructZero:
@@ -1636,14 +1677,7 @@ void BfIRCodeGen::HandleNextCmd()
 			CMD_PARAM(llvm::Type*, type);
 			SetResult(curId, llvm::ConstantAggregateZero::get(type));
 		}
-		break;
-	case BfIRCmd_CreateConstArray:
-		{
-			CMD_PARAM(llvm::Type*, type);
-			CMD_PARAM(CmdParamVec<llvm::Constant*>, values);
-			SetResult(curId, llvm::ConstantArray::get((llvm::ArrayType*)type, values));
-		}
-		break;
+		break;	
 	case BfIRCmd_CreateConstString:
 		{
 			CMD_PARAM(String, str);

+ 140 - 81
IDEHelper/Compiler/BfModule.cpp

@@ -1530,7 +1530,7 @@ BfIRValue BfModule::CreateStringObjectValue(const StringImpl& str, int stringId,
 		
 		SizedArray<BfIRValue, 8> typeValueParams;
 		GetConstClassValueParam(classVDataGlobal, typeValueParams);		
-		auto objData = mBfIRBuilder->CreateConstStruct(mBfIRBuilder->MapTypeInst(stringTypeInst->mBaseType, BfIRPopulateType_Full), typeValueParams);
+		auto objData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(stringTypeInst->mBaseType, BfIRPopulateType_Full), typeValueParams);
 
 		auto lenByteCount = stringTypeInst->mFieldInstances[0].mResolvedType->mSize;
 
@@ -1558,7 +1558,7 @@ BfIRValue BfModule::CreateStringObjectValue(const StringImpl& str, int stringId,
 			typeValueParams[fieldInstance->mDataIdx] = GetDefaultValue(fieldInstance->mResolvedType);
 		}
 
-		stringValData = mBfIRBuilder->CreateConstStruct(mBfIRBuilder->MapTypeInst(stringTypeInst, BfIRPopulateType_Full), typeValueParams);
+		stringValData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(stringTypeInst, BfIRPopulateType_Full), typeValueParams);
 	}
 		
 	mBfIRBuilder->PopulateType(stringTypeInst);
@@ -4823,7 +4823,7 @@ BfIRValue BfModule::CreateClassVDataExtGlobal(BfTypeInstance* declTypeInst, BfTy
 			BfIRLinkageType_External, BfIRValue(), classVDataName);	
 
 	BfIRType extVTableType = mBfIRBuilder->GetSizedArrayType(voidPtrIRType, (int)vData.size());
-	BfIRValue extVTableConst = mBfIRBuilder->CreateConstArray(extVTableType, vData);
+	BfIRValue extVTableConst = mBfIRBuilder->CreateConstAgg_Value(extVTableType, vData);
 	mBfIRBuilder->GlobalVar_SetInitializer(globalVariable, extVTableConst);
 	mClassVDataExtRefs[mapEntry] = globalVariable;
 
@@ -4966,7 +4966,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 	SizedArray<BfIRValue, 4> typeValueParams;
 	GetConstClassValueParam(typeTypeData, typeValueParams);
 	
-	BfIRValue objectData = mBfIRBuilder->CreateConstStruct(mBfIRBuilder->MapTypeInst(mContext->mBfObjectType, BfIRPopulateType_Full), typeValueParams);
+	BfIRValue objectData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(mContext->mBfObjectType, BfIRPopulateType_Full), typeValueParams);
 
 	StringT<128> typeDataName;
 	if ((typeInstance != NULL) && (!typeInstance->IsTypeAlias()))
@@ -5078,7 +5078,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 		GetConstValue(typeCode, byteType), // mTypeCode
 		GetConstValue(type->mAlign, byteType),
 	};
-	auto typeData = mBfIRBuilder->CreateConstStruct(mBfIRBuilder->MapTypeInst(mContext->mBfTypeType, BfIRPopulateType_Full), typeDataParams);
+	auto typeData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(mContext->mBfTypeType, BfIRPopulateType_Full), typeDataParams);
 		
 	if (typeInstance == NULL)
 	{
@@ -5096,7 +5096,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 				};
 
 				auto reflectPointerType = ResolveTypeDef(mCompiler->mReflectPointerType)->ToTypeInstance();
-				auto pointerTypeData = mBfIRBuilder->CreateConstStruct(mBfIRBuilder->MapTypeInst(reflectPointerType, BfIRPopulateType_Full), pointerTypeDataParms);
+				auto pointerTypeData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectPointerType, BfIRPopulateType_Full), pointerTypeDataParms);
 				typeDataVar = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapTypeInst(reflectPointerType), true,
 					BfIRLinkageType_External, pointerTypeData, typeDataName);				
 				mBfIRBuilder->GlobalVar_SetAlignment(typeDataVar, mSystem->mPtrSize);
@@ -5113,7 +5113,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 				};
 
 				auto reflectRefType = ResolveTypeDef(mCompiler->mReflectRefType)->ToTypeInstance();
-				auto refTypeData = mBfIRBuilder->CreateConstStruct(mBfIRBuilder->MapTypeInst(reflectRefType, BfIRPopulateType_Full), refTypeDataParms);
+				auto refTypeData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectRefType, BfIRPopulateType_Full), refTypeDataParms);
 				typeDataVar = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapTypeInst(reflectRefType), true,
 					BfIRLinkageType_External, refTypeData, typeDataName);
 				mBfIRBuilder->GlobalVar_SetAlignment(typeDataVar, mSystem->mPtrSize);
@@ -5130,7 +5130,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 				};
 
 				auto reflectSizedArrayType = ResolveTypeDef(mCompiler->mReflectSizedArrayType)->ToTypeInstance();
-				auto sizedArrayTypeData = mBfIRBuilder->CreateConstStruct(mBfIRBuilder->MapTypeInst(reflectSizedArrayType, BfIRPopulateType_Full), sizedArrayTypeDataParms);
+				auto sizedArrayTypeData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectSizedArrayType, BfIRPopulateType_Full), sizedArrayTypeDataParms);
 				typeDataVar = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapTypeInst(reflectSizedArrayType), true,
 					BfIRLinkageType_External, sizedArrayTypeData, typeDataName);
 				mBfIRBuilder->GlobalVar_SetAlignment(typeDataVar, mSystem->mPtrSize);
@@ -5663,7 +5663,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 					BfIRLinkageType_External, BfIRValue(), classVDataName);
 
 				BfIRType extVTableType = mBfIRBuilder->GetSizedArrayType(voidPtrIRType, (int)ifaceMethodExtData.size());
-				BfIRValue extVTableConst = mBfIRBuilder->CreateConstArray(extVTableType, ifaceMethodExtData);
+				BfIRValue extVTableConst = mBfIRBuilder->CreateConstAgg_Value(extVTableType, ifaceMethodExtData);
 				mBfIRBuilder->GlobalVar_SetInitializer(ifaceMethodExtVar, extVTableConst);
 			}
 
@@ -5764,7 +5764,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 	
 	// Fields
 	BfType* reflectFieldDataType = ResolveTypeDef(mCompiler->mReflectFieldDataDef);
-	BfIRValue emptyValueType = mBfIRBuilder->CreateConstStruct(mBfIRBuilder->MapTypeInst(reflectFieldDataType->ToTypeInstance()->mBaseType), SizedArray<BfIRValue, 1>());
+	BfIRValue emptyValueType = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectFieldDataType->ToTypeInstance()->mBaseType), SizedArray<BfIRValue, 1>());
 	
 	auto _HandleCustomAttrs = [&](BfCustomAttributes* customAttributes)
 	{
@@ -5930,7 +5930,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 		for (uint8 val : data)
 			dataValues.push_back(GetConstValue8(val));
 		auto dataArrayType = mBfIRBuilder->GetSizedArrayType(mBfIRBuilder->MapType(byteType), (int)data.size());
-		auto customAttrConst = mBfIRBuilder->CreateConstArray(dataArrayType, dataValues);
+		auto customAttrConst = mBfIRBuilder->CreateConstAgg_Value(dataArrayType, dataValues);
 
 		BfIRValue customAttrArray = mBfIRBuilder->CreateGlobalVariable(dataArrayType, true, BfIRLinkageType_Internal,
 			customAttrConst, typeDataName + StrFormat(".customAttr%d", customAttrIdx));
@@ -6039,7 +6039,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 				GetConstValue(FieldFlags_SpecialName | FieldFlags_EnumPayload, shortType), // mFlags
 				GetConstValue(-1, intType), // mCustomAttributesIdx
 			};
-			auto payloadFieldData = mBfIRBuilder->CreateConstStruct(mBfIRBuilder->MapTypeInst(reflectFieldDataType->ToTypeInstance(), BfIRPopulateType_Full), payloadFieldVals);
+			auto payloadFieldData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectFieldDataType->ToTypeInstance(), BfIRPopulateType_Full), payloadFieldVals);
 			fieldTypes.push_back(payloadFieldData);
 		}
 
@@ -6054,7 +6054,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 			GetConstValue(FieldFlags_SpecialName | FieldFlags_EnumDiscriminator, shortType), // mFlags
 			GetConstValue(-1, intType), // mCustomAttributesIdx
 		};
-		auto dscrFieldData = mBfIRBuilder->CreateConstStruct(mBfIRBuilder->MapTypeInst(reflectFieldDataType->ToTypeInstance(), BfIRPopulateType_Full), dscrFieldVals);
+		auto dscrFieldData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectFieldDataType->ToTypeInstance(), BfIRPopulateType_Full), dscrFieldVals);
 		fieldTypes.push_back(dscrFieldData);
 	}	
 
@@ -6132,7 +6132,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 			GetConstValue(fieldFlags, shortType), // mFlags
 			GetConstValue(customAttrIdx, intType), // mCustomAttributesIdx
 		};
-		auto fieldData = mBfIRBuilder->CreateConstStruct(mBfIRBuilder->MapTypeInst(reflectFieldDataType->ToTypeInstance(), BfIRPopulateType_Full), fieldVals);
+		auto fieldData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectFieldDataType->ToTypeInstance(), BfIRPopulateType_Full), fieldVals);
 		fieldTypes.push_back(fieldData);		
 	}	
 
@@ -6214,15 +6214,15 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 				splatOffsets.Add(GetConstValue(0, intType));
 			}			
 
-			BfIRValue splatTypesConst = mBfIRBuilder->CreateConstArray(mBfIRBuilder->MapType(reflectFieldSplatDataType->mFieldInstances[0].mResolvedType), splatTypes);
-			BfIRValue splatOffsetsConst = mBfIRBuilder->CreateConstArray(mBfIRBuilder->MapType(reflectFieldSplatDataType->mFieldInstances[1].mResolvedType), splatOffsets);
+			BfIRValue splatTypesConst = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapType(reflectFieldSplatDataType->mFieldInstances[0].mResolvedType), splatTypes);
+			BfIRValue splatOffsetsConst = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapType(reflectFieldSplatDataType->mFieldInstances[1].mResolvedType), splatOffsets);
 			SizedArray<BfIRValue, 8> splatVals =
 			{
 				emptyValueType,
 				splatTypesConst,
 				splatOffsetsConst
 			};
-			auto fieldSplatData = mBfIRBuilder->CreateConstStruct(mBfIRBuilder->MapTypeInst(reflectFieldSplatDataType->ToTypeInstance(), BfIRPopulateType_Full), splatVals);
+			auto fieldSplatData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectFieldSplatDataType->ToTypeInstance(), BfIRPopulateType_Full), splatVals);
 			BfIRValue fieldDataArray = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapType(reflectFieldSplatDataType), true, BfIRLinkageType_Internal,
 				fieldSplatData, typeDataName + ".splats");
 
@@ -6234,7 +6234,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 	else
 	{
 		BfIRType fieldDataConstType = mBfIRBuilder->GetSizedArrayType(reflectFieldDataIRType, (int)fieldTypes.size());
-		BfIRValue fieldDataConst = mBfIRBuilder->CreateConstArray(fieldDataConstType, fieldTypes);
+		BfIRValue fieldDataConst = mBfIRBuilder->CreateConstAgg_Value(fieldDataConstType, fieldTypes);
 		BfIRValue fieldDataArray = mBfIRBuilder->CreateGlobalVariable(fieldDataConstType, true, BfIRLinkageType_Internal,
 			fieldDataConst, "fields." + typeDataName);
 		fieldDataPtr = mBfIRBuilder->CreateBitCast(fieldDataArray, fieldDataPtrType);
@@ -6409,7 +6409,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 					GetConstValue((int32)paramFlags, shortType),
 					GetConstValue(customAttrIdx, intType) // defaultIdx
 				};
-			auto paramData = mBfIRBuilder->CreateConstStruct(mBfIRBuilder->MapType(reflectParamDataType, BfIRPopulateType_Full), paramDataVals);
+			auto paramData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapType(reflectParamDataType, BfIRPopulateType_Full), paramDataVals);
 			paramVals.Add(paramData);
 		}
 	
@@ -6417,7 +6417,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 		if (paramVals.size() > 0)
 		{
 			BfIRType paramDataArrayType = mBfIRBuilder->GetSizedArrayType(mBfIRBuilder->MapType(reflectParamDataType, BfIRPopulateType_Full), (int)paramVals.size());
-			BfIRValue paramDataConst = mBfIRBuilder->CreateConstArray(paramDataArrayType, paramVals);
+			BfIRValue paramDataConst = mBfIRBuilder->CreateConstAgg_Value(paramDataArrayType, paramVals);
 
 			BfIRValue paramDataArray = mBfIRBuilder->CreateGlobalVariable(paramDataArrayType, true, BfIRLinkageType_Internal,
 				paramDataConst, typeDataName + StrFormat(".params%d", methodIdx));
@@ -6477,7 +6477,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 				GetConstValue(vDataVal, intType),
 				GetConstValue(customAttrIdx, intType),
 			};
-		auto methodData = mBfIRBuilder->CreateConstStruct(mBfIRBuilder->MapTypeInst(reflectMethodDataType->ToTypeInstance(), BfIRPopulateType_Full), methodDataVals);		
+		auto methodData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectMethodDataType->ToTypeInstance(), BfIRPopulateType_Full), methodDataVals);
 		methodTypes.push_back(methodData);
 	}
 
@@ -6488,7 +6488,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 	else
 	{
 		BfIRType methodDataArrayType = mBfIRBuilder->GetSizedArrayType(mBfIRBuilder->MapType(reflectMethodDataType, BfIRPopulateType_Full), (int)methodTypes.size());
-		BfIRValue methodDataConst = mBfIRBuilder->CreateConstArray(methodDataArrayType, methodTypes);
+		BfIRValue methodDataConst = mBfIRBuilder->CreateConstAgg_Value(methodDataArrayType, methodTypes);
 		BfIRValue methodDataArray = mBfIRBuilder->CreateGlobalVariable(methodDataArrayType, true, BfIRLinkageType_Internal,
 			methodDataConst, "methods." + typeDataName);
 		methodDataPtr = mBfIRBuilder->CreateBitCast(methodDataArray, methodDataPtrType);
@@ -6517,7 +6517,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 				GetConstValue(interface.mStartVirtualIdx, intType),
 			};
 
-			auto interfaceData = mBfIRBuilder->CreateConstStruct(mBfIRBuilder->MapTypeInst(reflectInterfaceDataType->ToTypeInstance(), BfIRPopulateType_Full), interfaceDataVals);
+			auto interfaceData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectInterfaceDataType->ToTypeInstance(), BfIRPopulateType_Full), interfaceDataVals);
 			interfaces.push_back(interfaceData);
 
 			for (int methodIdx = 0; methodIdx < (int)interface.mInterfaceType->mMethodInstanceGroups.size(); methodIdx++)
@@ -6535,7 +6535,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 		}
 
 		BfIRType interfaceDataArrayType = mBfIRBuilder->GetSizedArrayType(mBfIRBuilder->MapType(reflectInterfaceDataType, BfIRPopulateType_Full), (int)interfaces.size());
-		BfIRValue interfaceDataConst = mBfIRBuilder->CreateConstArray(interfaceDataArrayType, interfaces);
+		BfIRValue interfaceDataConst = mBfIRBuilder->CreateConstAgg_Value(interfaceDataArrayType, interfaces);
 		BfIRValue interfaceDataArray = mBfIRBuilder->CreateGlobalVariable(interfaceDataArrayType, true, BfIRLinkageType_Internal,
 			interfaceDataConst, "interfaces." + typeDataName);
 		interfaceDataPtr = mBfIRBuilder->CreateBitCast(interfaceDataArray, interfaceDataPtrType);
@@ -6575,7 +6575,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 		if (!methods.IsEmpty())
 		{
 			BfIRType methodDataArrayType = mBfIRBuilder->GetSizedArrayType(mBfIRBuilder->MapType(voidPtrType, BfIRPopulateType_Full), (int)methods.size());
-			BfIRValue methodDataConst = mBfIRBuilder->CreateConstArray(methodDataArrayType, methods);
+			BfIRValue methodDataConst = mBfIRBuilder->CreateConstAgg_Value(methodDataArrayType, methods);
 			BfIRValue methodDataArray = mBfIRBuilder->CreateGlobalVariable(methodDataArrayType, true, BfIRLinkageType_Internal,
 				methodDataConst, "imethods." + typeDataName);
 			interfaceMethodTable = mBfIRBuilder->CreateBitCast(methodDataArray, voidPtrPtrIRType);
@@ -6606,7 +6606,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 	if (customAttrs.size() > 0)
 	{
 		BfIRType customAttrsArrayType = mBfIRBuilder->GetSizedArrayType(voidPtrIRType, (int)customAttrs.size());
-		BfIRValue customAttrsConst =  mBfIRBuilder->CreateConstArray(customAttrsArrayType, customAttrs);
+		BfIRValue customAttrsConst =  mBfIRBuilder->CreateConstAgg_Value(customAttrsArrayType, customAttrs);
 		BfIRValue customAttrsArray = mBfIRBuilder->CreateGlobalVariable(customAttrsArrayType, true, BfIRLinkageType_Internal,
 			customAttrsConst, "customAttrs." + typeDataName);
 		customAttrDataPtr = mBfIRBuilder->CreateBitCast(customAttrsArray, voidPtrPtrIRType);
@@ -6649,7 +6649,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 		};
 
 	BfIRType typeInstanceDataType = mBfIRBuilder->MapTypeInst(typeInstanceType->ToTypeInstance(), BfIRPopulateType_Full);
-	auto typeInstanceData = mBfIRBuilder->CreateConstStruct(typeInstanceDataType, typeDataVals);
+	auto typeInstanceData = mBfIRBuilder->CreateConstAgg_Value(typeInstanceDataType, typeDataVals);
 		
 	if (!needsTypeData)
 	{
@@ -6666,7 +6666,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 		};
 		auto reflectUnspecializedGenericType = ResolveTypeDef(mCompiler->mReflectUnspecializedGenericType);
 		typeInstanceDataType = mBfIRBuilder->MapTypeInst(reflectUnspecializedGenericType->ToTypeInstance(), BfIRPopulateType_Full);
-		typeInstanceData = mBfIRBuilder->CreateConstStruct(typeInstanceDataType, unspecializedData);
+		typeInstanceData = mBfIRBuilder->CreateConstAgg_Value(typeInstanceDataType, unspecializedData);
 	}
 	else if (typeInstance->IsGenericTypeInstance())
 	{
@@ -6681,7 +6681,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 		auto typeIRType = mBfIRBuilder->MapType(typeIdType);
 		auto typePtrIRType = mBfIRBuilder->GetPointerTo(typeIRType);
 		auto genericArrayType = mBfIRBuilder->GetSizedArrayType(typeIRType, (int)resolvedTypes.size());
-		BfIRValue resolvedTypesConst = mBfIRBuilder->CreateConstArray(genericArrayType, resolvedTypes);
+		BfIRValue resolvedTypesConst = mBfIRBuilder->CreateConstAgg_Value(genericArrayType, resolvedTypes);
 		BfIRValue resolvedTypesArray = mBfIRBuilder->CreateGlobalVariable(genericArrayType, true, BfIRLinkageType_Internal,
 			resolvedTypesConst, "resolvedTypes." + typeDataName);
 		BfIRValue resovledTypesPtr = mBfIRBuilder->CreateBitCast(resolvedTypesArray, typePtrIRType);
@@ -6694,7 +6694,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 			};
 
 		typeInstanceDataType = mBfIRBuilder->MapTypeInst(reflectSpecializedGenericType->ToTypeInstance(), BfIRPopulateType_Full);
-		typeInstanceData = mBfIRBuilder->CreateConstStruct(typeInstanceDataType, specGenericData);
+		typeInstanceData = mBfIRBuilder->CreateConstAgg_Value(typeInstanceDataType, specGenericData);
 			
 		if (typeInstance->IsArray())
 		{
@@ -6712,7 +6712,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 			};
 			auto reflectArrayType = ResolveTypeDef(mCompiler->mReflectArrayType);
 			typeInstanceDataType = mBfIRBuilder->MapTypeInst(reflectArrayType->ToTypeInstance(), BfIRPopulateType_Full);
-			typeInstanceData = mBfIRBuilder->CreateConstStruct(typeInstanceDataType, arrayData);
+			typeInstanceData = mBfIRBuilder->CreateConstAgg_Value(typeInstanceDataType, arrayData);
 		}
 	}
 		
@@ -6742,7 +6742,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
 
 		vData[0] = mBfIRBuilder->CreateBitCast(typeDataVar, voidPtrIRType);
 		auto classVDataConstDataType = mBfIRBuilder->GetSizedArrayType(voidPtrIRType, (int)vData.size());
-		auto classVDataConstData = mBfIRBuilder->CreateConstArray(classVDataConstDataType, vData);
+		auto classVDataConstData = mBfIRBuilder->CreateConstAgg_Value(classVDataConstDataType, vData);
 
 		mBfIRBuilder->GlobalVar_SetInitializer(classVDataVar, classVDataConstData);		
 		if (mCompiler->mOptions.mObjectHasDebugFlags)
@@ -8276,7 +8276,7 @@ BfIRValue BfModule::GetDbgRawAllocData(BfType* type)
 	dataValues.Add(typeDataRef);
 	dataValues.Add(markFuncPtr);
 	dataValues.Add(mBfIRBuilder->CreateConst(BfTypeCode_Int32, stackCount));
-	BfIRValue dataStruct = mBfIRBuilder->CreateConstStruct(mBfIRBuilder->MapType(dbgRawAllocDataType, BfIRPopulateType_Full), dataValues);
+	BfIRValue dataStruct = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapType(dbgRawAllocDataType, BfIRPopulateType_Full), dataValues);
 	allocDataValue = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapType(dbgRawAllocDataType), true, BfIRLinkageType_Internal, dataStruct, "__allocData_" + BfSafeMangler::Mangle(type));
 
 	mDbgRawAllocDataRefs.TryAdd(type, allocDataValue);
@@ -8874,7 +8874,7 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget
 			auto classVDataType = ResolveTypeDef(mCompiler->mClassVDataTypeDef);			
 			auto vData = mBfIRBuilder->CreateBitCast(vDataRef, mBfIRBuilder->MapTypeInstPtr(classVDataType->ToTypeInstance()));			
 
-			if (mCompiler->mOptions.mObjectHasDebugFlags)
+			if ((mCompiler->mOptions.mObjectHasDebugFlags) && (!mIsConstModule))
 			{
 				SizedArray<BfIRValue, 4> llvmArgs;
 				llvmArgs.push_back(vData);
@@ -10367,9 +10367,9 @@ void BfModule::CurrentAddToConstHolder(BfIRValue& irVal)
 		return;
 	}
 
-	if (constant->mConstType == BfConstType_Array)
+	if (constant->mConstType == BfConstType_Agg)
 	{
-		auto constArray = (BfConstantArray*)constant;
+		auto constArray = (BfConstantAgg*)constant;
 		
 		SizedArray<BfIRValue, 8> newVals;
 		for (auto val : constArray->mValues)
@@ -10379,7 +10379,7 @@ void BfModule::CurrentAddToConstHolder(BfIRValue& irVal)
 			newVals.push_back(newVal);			
 		}
 
-		irVal = mCurTypeInstance->GetOrCreateConstHolder()->CreateConstArray(constArray->mType, newVals);
+		irVal = mCurTypeInstance->GetOrCreateConstHolder()->CreateConstAgg(constArray->mType, newVals);
 		return;
 	}
 
@@ -10485,6 +10485,12 @@ BfIRValue BfModule::ConstantToCurrent(BfConstant* constant, BfIRConstHolder* con
 {
 	if (constant->mTypeCode == BfTypeCode_NullPtr)
 	{
+		if ((wantType == NULL) && (constant->mIRType.mKind == BfIRTypeData::TypeKind_TypeId))
+			wantType = mContext->mTypes[constant->mIRType.mId];
+
+		if (wantType == NULL)
+			return constHolder->CreateConstNull();
+
 		return GetDefaultValue(wantType);
 	}
 
@@ -10501,18 +10507,49 @@ BfIRValue BfModule::ConstantToCurrent(BfConstant* constant, BfIRConstHolder* con
 		}
 	}
 
-	if (constant->mConstType == BfConstType_Array)
-	{
-		auto elementType = wantType->GetUnderlyingType();
-		auto constArray = (BfConstantArray*)constant;
+	if (constant->mConstType == BfConstType_Agg)
+	{		
+		auto constArray = (BfConstantAgg*)constant;
+
+		if ((wantType == NULL) && (constArray->mType.mKind == BfIRTypeData::TypeKind_TypeId))
+			wantType = mContext->mTypes[constArray->mType.mId];
 
 		SizedArray<BfIRValue, 8> newVals;
-		for (auto val : constArray->mValues)
+		if (wantType->IsSizedArray())
 		{
-			newVals.push_back(ConstantToCurrent(constHolder->GetConstant(val), constHolder, elementType));
+			auto elementType = wantType->GetUnderlyingType();			
+			for (auto val : constArray->mValues)
+			{
+				newVals.Add(ConstantToCurrent(constHolder->GetConstant(val), constHolder, elementType));
+			}
 		}
+		else
+		{
+			auto wantTypeInst = wantType->ToTypeInstance();
+			if (wantTypeInst->mBaseType != NULL)
+			{
+				auto baseVal = ConstantToCurrent(constHolder->GetConstant(constArray->mValues[0]), constHolder, wantTypeInst->mBaseType);
+				newVals.Add(baseVal);
+			}
 
-		return mBfIRBuilder->CreateConstArray(mBfIRBuilder->MapType(wantType), newVals);
+			for (auto& fieldInstance : wantTypeInst->mFieldInstances)
+			{
+				if (fieldInstance.mDataIdx < 0)
+					continue;				
+				auto val = constArray->mValues[fieldInstance.mDataIdx];
+				BfIRValue memberVal = ConstantToCurrent(constHolder->GetConstant(val), constHolder, fieldInstance.mResolvedType);
+				if (fieldInstance.mDataIdx == newVals.mSize)
+					newVals.Add(memberVal);
+				else
+				{
+					while (fieldInstance.mDataIdx >= newVals.mSize)
+						newVals.Add(BfIRValue());
+					newVals[fieldInstance.mDataIdx] = memberVal;
+				}
+			}
+		}
+
+		return mBfIRBuilder->CreateConstAgg(mBfIRBuilder->MapType(wantType), newVals);
 	}
 
 	return mBfIRBuilder->CreateConst(constant, constHolder);	
@@ -11290,6 +11327,17 @@ BfTypedValue BfModule::LoadValue(BfTypedValue typedValue, BfAstNode* refNode, bo
 	return BfTypedValue(loadedVal, typedValue.mType, false);
 }
 
+BfTypedValue BfModule::PrepareConst(BfTypedValue& typedValue)
+{
+	if (!typedValue.mValue.IsConst())
+		return typedValue;
+
+	auto constant = mBfIRBuilder->GetConstant(typedValue.mValue);
+	if (constant->mTypeCode == BfTypeCode_StringId)
+		return GetTypedValueFromConstant(constant, mBfIRBuilder, typedValue.mType);
+	return typedValue;
+}
+
 BfTypedValue BfModule::LoadOrAggregateValue(BfTypedValue typedValue)
 {
 	if (typedValue.IsSplat())
@@ -11303,6 +11351,7 @@ BfTypedValue BfModule::AggregateSplat(BfTypedValue typedValue, BfIRValue* valueA
 {
 	if (!typedValue.IsSplat())
 		return typedValue;
+	BF_ASSERT(!mIsConstModule);
 	if (typedValue.mType->IsValuelessType())
 		return typedValue;
 
@@ -11399,6 +11448,8 @@ void BfModule::AggregateSplatIntoAddr(BfTypedValue typedValue, BfIRValue addrVal
 	if (typedValue.mType->IsValuelessType())
 		return;
 
+	BF_ASSERT(!mIsConstModule);
+
 	/*static int sCallIdx = 0;
 	if (!mCompiler->mIsResolveOnly)
 		sCallIdx++;
@@ -11523,6 +11574,8 @@ BfTypedValue BfModule::RemoveReadOnly(BfTypedValue typedValue)
 
 BfIRValue BfModule::ExtractSplatValue(BfTypedValue typedValue, int componentIdx, BfType* wantType, bool* isAddr)
 {
+	BF_ASSERT(!mIsConstModule);
+
 	BfIRValue val;
 	if (typedValue.mValue.IsArg())
 	{
@@ -13510,7 +13563,7 @@ void BfModule::DoLocalVariableDebugInfo(BfLocalVariable* localVarDef, bool doAli
 				isConstant =
 					(constant->mConstType < BfConstType_GlobalVar) ||
 					(constant->mConstType == BfConstType_AggZero) ||
-					(constant->mConstType == BfConstType_Array);
+					(constant->mConstType == BfConstType_Agg);
 				if (isConstant)
 				{
 					if (localVarDef->mResolvedType->IsComposite())
@@ -13639,7 +13692,7 @@ void BfModule::CreateDIRetVal()
 	{		
 		BfType* dbgType = mCurMethodInstance->mReturnType;
 		BfIRValue dbgValue = mCurMethodState->mRetVal.mValue;
-		if (mCurMethodInstance->GetStructRetIdx() != -1)
+		if ((!mIsConstModule) && (mCurMethodInstance->GetStructRetIdx() != -1))
 		{
 			BF_ASSERT(mCurMethodState->mRetValAddr);
 			dbgType = CreatePointerType(dbgType);
@@ -14255,7 +14308,7 @@ void BfModule::MarkScopeLeft(BfScopeData* scopeData)
 
 void BfModule::CreateReturn(BfIRValue val)
 {
-	if (mCurMethodInstance->GetStructRetIdx() != -1)
+	if ((!mIsConstModule) && (mCurMethodInstance->GetStructRetIdx() != -1))
 	{
 		// Store to sret
 		BF_ASSERT(val);
@@ -14274,7 +14327,8 @@ void BfModule::CreateReturn(BfIRValue val)
 	{
 		BfTypeCode loweredReturnType = BfTypeCode_None;
 		BfTypeCode loweredReturnType2 = BfTypeCode_None;
-		mCurMethodInstance->GetLoweredReturnType(&loweredReturnType, &loweredReturnType2);
+		if (!mIsConstModule)
+			mCurMethodInstance->GetLoweredReturnType(&loweredReturnType, &loweredReturnType2);
 
 		if (loweredReturnType != BfTypeCode_None)
 		{
@@ -14341,7 +14395,7 @@ void BfModule::EmitDefaultReturn()
 	{
 		if (mCurMethodInstance->mReturnType->IsVoid())
 			mBfIRBuilder->CreateRetVoid();
-		else if (mCurMethodInstance->GetStructRetIdx() == -1)		
+		else if ((!mIsConstModule) && (mCurMethodInstance->GetStructRetIdx() == -1))
 			mBfIRBuilder->CreateRet(GetDefaultValue(mCurMethodInstance->mReturnType));
 	}
 
@@ -14450,18 +14504,18 @@ void BfModule::CreateDelegateInvokeMethod()
 	if (mCurMethodInstance->mReturnType->IsValueType())
 		mBfIRBuilder->PopulateType(mCurMethodInstance->mReturnType, BfIRPopulateType_Full);
 		
-	if (mCurMethodInstance->GetStructRetIdx() != 0)
+	if ((!mIsConstModule) && (mCurMethodInstance->GetStructRetIdx() != 0))
 		memberFuncArgs.push_back(BfIRValue()); // Push 'target'
 
 	int thisIdx = 0;
-	if (mCurMethodInstance->GetStructRetIdx() != -1)
+	if ((!mIsConstModule) && (mCurMethodInstance->GetStructRetIdx() != -1))
 	{		
 		thisIdx = mCurMethodInstance->GetStructRetIdx() ^ 1;
 		staticFuncArgs.push_back(mBfIRBuilder->GetArgument(mCurMethodInstance->GetStructRetIdx()));
 		memberFuncArgs.push_back(mBfIRBuilder->GetArgument(mCurMethodInstance->GetStructRetIdx()));
 	}
 
-	if (mCurMethodInstance->GetStructRetIdx() == 0)
+	if ((!mIsConstModule) && (mCurMethodInstance->GetStructRetIdx() == 0))
 		memberFuncArgs.push_back(BfIRValue()); // Push 'target'
 
 	mCurMethodInstance->GetIRFunctionInfo(this, origReturnType, staticParamTypes, true);
@@ -14500,7 +14554,7 @@ void BfModule::CreateDelegateInvokeMethod()
 		auto funcPtrPtr = mBfIRBuilder->CreateBitCast(fieldPtr, memberFuncPtrPtr);
 		auto funcPtr = mBfIRBuilder->CreateLoad(funcPtrPtr);		
 		nonStaticResult = mBfIRBuilder->CreateCall(funcPtr, memberFuncArgs);
-		if (mCurMethodInstance->GetStructRetIdx() != -1)
+		if ((!mIsConstModule) && (mCurMethodInstance->GetStructRetIdx() != -1))
 			mBfIRBuilder->Call_AddAttribute(nonStaticResult, mCurMethodInstance->GetStructRetIdx() + 1, BfIRAttribute_StructRet);
 		if (callingConv != BfIRCallingConv_CDecl)
 			mBfIRBuilder->SetCallCallingConv(nonStaticResult, callingConv);
@@ -14518,7 +14572,7 @@ void BfModule::CreateDelegateInvokeMethod()
 		auto funcPtrPtr = mBfIRBuilder->CreateBitCast(fieldPtr, staticFuncPtrPtr);
 		auto funcPtr = mBfIRBuilder->CreateLoad(funcPtrPtr);		
 		staticResult = mBfIRBuilder->CreateCall(funcPtr, staticFuncArgs);
-		if (mCurMethodInstance->GetStructRetIdx() != -1)
+		if ((!mIsConstModule) && (mCurMethodInstance->GetStructRetIdx() != -1))
 		{
 			// Note: since this is a forced static invocation, we know the sret will be the first parameter
 			mBfIRBuilder->Call_AddAttribute(staticResult, 0 + 1, BfIRAttribute_StructRet);
@@ -14535,7 +14589,8 @@ void BfModule::CreateDelegateInvokeMethod()
 
 	mBfIRBuilder->AddBlock(doneBB);
 	mBfIRBuilder->SetInsertPoint(doneBB);
-	if ((mCurMethodInstance->mReturnType->IsValuelessType()) || (mCurMethodInstance->GetStructRetIdx() != -1))
+	if ((mCurMethodInstance->mReturnType->IsValuelessType()) || 
+		((!mIsConstModule) && (mCurMethodInstance->GetStructRetIdx() != -1)))
 	{
 		mBfIRBuilder->CreateRetVoid();
 	}
@@ -14544,7 +14599,7 @@ void BfModule::CreateDelegateInvokeMethod()
 		BfIRType loweredIRReturnType;
 		BfTypeCode loweredTypeCode = BfTypeCode_None;
 		BfTypeCode loweredTypeCode2 = BfTypeCode_None;
-		if (mCurMethodInstance->GetLoweredReturnType(&loweredTypeCode, &loweredTypeCode2))
+		if ((!mIsConstModule) && (mCurMethodInstance->GetLoweredReturnType(&loweredTypeCode, &loweredTypeCode2)))
 			loweredIRReturnType = GetIRLoweredType(loweredTypeCode, loweredTypeCode2);
 		else
 			loweredIRReturnType = mBfIRBuilder->MapType(mCurMethodInstance->mReturnType);
@@ -14624,7 +14679,7 @@ BfTypedValue BfModule::TryConstCalcAppend(BfMethodInstance* methodInst, SizedArr
 		int argCount = 0;
 		if (!paramType->IsValuelessType())		
 		{			
-			if (methodInst->GetParamIsSplat(paramIdx))
+			if ((!mIsConstModule) && (methodInst->GetParamIsSplat(paramIdx)))
 				argCount = paramType->GetSplatCount();
 			else
 				argCount = 1;
@@ -15449,7 +15504,7 @@ void BfModule::SetupIRMethod(BfMethodInstance* methodInstance, BfIRFunction func
 
 	while (argIdx < argCount)
 	{
-		if (argIdx == methodInstance->GetStructRetIdx())
+		if ((!mIsConstModule) && (argIdx == methodInstance->GetStructRetIdx()))
 		{
 			mBfIRBuilder->Func_AddAttribute(func, argIdx + 1, BfIRAttribute_NoAlias);
 			mBfIRBuilder->Func_AddAttribute(func, argIdx + 1, BfIRAttribute_StructRet);
@@ -15473,8 +15528,8 @@ void BfModule::SetupIRMethod(BfMethodInstance* methodInstance, BfIRFunction func
 				resolvedTypeRef = mCurMethodState->mClosureState->mClosureType;
 			else
 				resolvedTypeRef = methodInstance->GetThisType();
-			isSplattable = (resolvedTypeRef->IsSplattable()) && (methodInstance->AllowsThisSplatting());
-			tryLowering = methodInstance->AllowsThisSplatting();
+			isSplattable = (!mIsConstModule) && (resolvedTypeRef->IsSplattable()) && (methodInstance->AllowsThisSplatting());
+			tryLowering = (!mIsConstModule) && (methodInstance->AllowsThisSplatting());
         }
 		else
 		{
@@ -15482,7 +15537,7 @@ void BfModule::SetupIRMethod(BfMethodInstance* methodInstance, BfIRFunction func
         	resolvedTypeRef = methodInstance->GetParamType(paramIdx);
 			if (resolvedTypeRef->IsMethodRef())
 				isSplattable = true;
-			else if ((resolvedTypeRef->IsSplattable()) && (methodInstance->AllowsSplatting()))
+			else if ((!mIsConstModule) && (resolvedTypeRef->IsSplattable()) && (methodInstance->AllowsSplatting()))
 			{
 				auto resolvedTypeInst = resolvedTypeRef->ToTypeInstance();
 				if ((resolvedTypeInst != NULL) && (resolvedTypeInst->mIsCRepr))
@@ -16620,7 +16675,7 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp
 	
 	int argIdx = 0;
 	
-	if (argIdx == methodInstance->GetStructRetIdx())
+	if ((!mIsConstModule) && (argIdx == methodInstance->GetStructRetIdx()))
 		argIdx++;
 
 	if (!methodDef->mIsStatic)
@@ -16636,12 +16691,12 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp
 		else
 			paramVar->mValue = mBfIRBuilder->GetFakeVal();
 				
-		if ((thisType->IsSplattable()) && (methodInstance->AllowsThisSplatting()))		
+		if ((!mIsConstModule) && (thisType->IsSplattable()) && (methodInstance->AllowsThisSplatting()))		
 		{
 			if (!thisType->IsTypedPrimitive())
 				paramVar->mIsSplat = true;
 		}
-		else if ((!methodDef->mIsMutating) && (methodInstance->mCallingConvention == BfCallingConvention_Unspecified))
+		else if ((!mIsConstModule) && (!methodDef->mIsMutating) && (methodInstance->mCallingConvention == BfCallingConvention_Unspecified))
 			paramVar->mIsLowered = thisType->GetLoweredType(BfTypeUsage_Parameter, &loweredTypeCode, &loweredTypeCode2) != BfTypeCode_None;
 
 		auto thisTypeInst = thisType->ToTypeInstance();
@@ -16690,7 +16745,7 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp
 		}		
 	}
 
-	if (argIdx == methodInstance->GetStructRetIdx())
+	if ((!mIsConstModule) && (argIdx == methodInstance->GetStructRetIdx()))
 		argIdx++;
 
 	bool hadParams = false;
@@ -16730,7 +16785,7 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp
 			}
 			else if (resolvedType->IsComposite() && resolvedType->IsSplattable())
 			{
-				if (methodInstance->AllowsSplatting())
+				if ((!mIsConstModule) && (methodInstance->AllowsSplatting()))
 				{
 					int splatCount = resolvedType->GetSplatCount();
 					if (argIdx + splatCount <= mCompiler->mOptions.mMaxSplatRegs)
@@ -16744,7 +16799,7 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp
 			paramVar->mValue = mBfIRBuilder->GetFakeVal();
 		}
 
-		paramVar->mIsLowered = resolvedType->GetLoweredType(BfTypeUsage_Parameter, &loweredTypeCode, &loweredTypeCode2) != BfTypeCode_None;
+		paramVar->mIsLowered = (!mIsConstModule) && resolvedType->GetLoweredType(BfTypeUsage_Parameter, &loweredTypeCode, &loweredTypeCode2) != BfTypeCode_None;
 		paramVar->mIsStruct = resolvedType->IsComposite() && !resolvedType->IsTypedPrimitive();
 		paramVar->mParamIdx = paramIdx;
 		paramVar->mIsImplicitParam = methodInstance->IsImplicitCapture(paramIdx);
@@ -17291,7 +17346,7 @@ void BfModule::EmitGCMarkMembers()
 							auto baseValue = Cast(NULL, thisValue, methodBaseType, BfCastFlags_Explicit);
 
 							SizedArray<BfIRValue, 1> args;							
-							if (moduleMethodInst.mMethodInstance->GetParamIsSplat(-1))
+							if ((!mIsConstModule) && (moduleMethodInst.mMethodInstance->GetParamIsSplat(-1)))
 							{
 								BfExprEvaluator exprEvaluator(this);
 								exprEvaluator.SplatArgs(baseValue, args);
@@ -17945,7 +18000,8 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
 				flags |= llvm::DINode::FlagStaticMember;
 			else
 			{
-				if ((mCurTypeInstance->IsValuelessType()) || (mCurTypeInstance->IsSplattable()))
+				if ((mCurTypeInstance->IsValuelessType()) || 
+					((!mIsConstModule) && (mCurTypeInstance->IsSplattable())))
 					flags |= llvm::DINode::FlagStaticMember;
 			}
 			flags |= llvm::DINode::FlagPrototyped;
@@ -18095,7 +18151,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
 			if ((isThis) && (thisType->IsValuelessType()))
 				isThis = false;
 
-			if (methodInstance->GetStructRetIdx() == argIdx)
+			if ((!mIsConstModule) && (methodInstance->GetStructRetIdx() == argIdx))
 			{
 				argIdx++;
 				if (argIdx == irParamCount)
@@ -18118,7 +18174,8 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
 				paramVar->mIsReadOnly = true;
 			}
 			
-			bool wantsAddr = (wantsDIVariables) || (!paramVar->mIsReadOnly) || (paramVar->mResolvedType->GetLoweredType(BfTypeUsage_Parameter));
+			bool wantsAddr = (wantsDIVariables) || (!paramVar->mIsReadOnly) || 
+				((!mIsConstModule) && (paramVar->mResolvedType->GetLoweredType(BfTypeUsage_Parameter)));
 
 			if (paramVar->mResolvedType->IsMethodRef())
 				wantsAddr = false;			
@@ -18259,7 +18316,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
 		int splatAddrIdx = 0;		
 		while (localIdx < (int)methodState.mLocals.size())
 		{
-			if (argIdx == methodInstance->GetStructRetIdx())
+			if ((!mIsConstModule) && (argIdx == methodInstance->GetStructRetIdx()))
 				argIdx++;
 
 			int curLocalIdx = localIdx++;
@@ -18695,7 +18752,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
 				{
 					BF_ASSERT(innerType->IsUnspecializedType());
 				}
-				else if (methodInstance->GetStructRetIdx() != -1)
+				else if ((!mIsConstModule) && (methodInstance->GetStructRetIdx() != -1))
 				{
 					mBfIRBuilder->PopulateType(methodInstance->mReturnType);
 					auto returnType = BfTypedValue(mBfIRBuilder->GetArgument(methodInstance->GetStructRetIdx()), methodInstance->mReturnType, true);
@@ -19071,8 +19128,8 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
 		{			
 			mBfIRBuilder->PopulateType(mCurMethodInstance->mReturnType);
 			
-			if (mCurMethodInstance->GetStructRetIdx() != -1)
-			{			
+			if ((!mIsConstModule) && (mCurMethodInstance->GetStructRetIdx() != -1))
+			{
 				auto ptrType = CreatePointerType(mCurMethodInstance->mReturnType);
 				auto allocaInst = AllocLocalVariable(ptrType, "__return.addr", false);				
 				auto storeInst = mBfIRBuilder->CreateStore(mBfIRBuilder->GetArgument(mCurMethodInstance->GetStructRetIdx()), allocaInst);
@@ -19264,7 +19321,8 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
 
 	if (mCurMethodState->mIRExitBlock)
 	{
-		if ((mCurMethodState->mRetVal) && (mCurMethodInstance->GetStructRetIdx() == -1))
+		if ((mCurMethodState->mRetVal) && 
+			((mIsConstModule) || (mCurMethodInstance->GetStructRetIdx() == -1)))
 		{			
 			auto loadedVal = mBfIRBuilder->CreateLoad(mCurMethodState->mRetVal.mValue);
 			
@@ -19303,7 +19361,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
 	{
 		if ((!mCurMethodState->mHadReturn) && (!mCurMethodState->mIRExitBlock))
 		{
-			if ((irParamCount == 0) && (!IsTargetingBeefBackend()) && (mCompiler->mOptions.mAllowHotSwapping))
+			if ((!mIsConstModule) && (irParamCount == 0) && (!IsTargetingBeefBackend()) && (mCompiler->mOptions.mAllowHotSwapping))
 			{
 				// This may be a case where we only emit 4 bytes, whereas we need 5 for a hot replace jump
 				mBfIRBuilder->EnsureFunctionPatchable();
@@ -19347,7 +19405,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
 	{
 		// If we hot swap, we want to make sure at least one method refers to this extern method so it gets pulled in
 		//  incase it gets called later by some hot-loaded coded
-		if ((mCompiler->mOptions.mAllowHotSwapping) && (mCurMethodInstance->mIRFunction) && (!mCurMethodInstance->mIRFunction.IsFake()))
+		if ((mCompiler->mOptions.mAllowHotSwapping) && (mCurMethodInstance->mIRFunction) && (!mCurMethodInstance->mIRFunction.IsFake()) && (mCurTypeInstance != mContext->mBfObjectType))
 			CreateFakeCallerMethod(mangledName);
 		mBfIRBuilder->Func_DeleteBody(mCurMethodInstance->mIRFunction);
 	}
@@ -21405,7 +21463,7 @@ genericParam->mExternType = GetPrimitiveType(BfTypeCode_Var);
 		{
 			BfTypeCode loweredTypeCode = BfTypeCode_None;
 			BfTypeCode loweredTypeCode2 = BfTypeCode_None;
-			if (!methodDef->mIsMutating)
+			if ((!mIsConstModule) && (!methodDef->mIsMutating))
 				thisType->GetLoweredType(BfTypeUsage_Parameter, &loweredTypeCode, &loweredTypeCode2);
 			argIdx++;
 			if (loweredTypeCode2 != BfTypeCode_None)
@@ -21413,7 +21471,7 @@ genericParam->mExternType = GetPrimitiveType(BfTypeCode_Var);
 		}
 	}
 
-	if (methodInstance->GetStructRetIdx() != -1)
+	if ((!mIsConstModule) && (methodInstance->GetStructRetIdx() != -1))
 		argIdx++;
 
 	for (int paramIdx = 0; paramIdx < mCurMethodInstance->mParams.size(); paramIdx++)
@@ -21449,7 +21507,8 @@ genericParam->mExternType = GetPrimitiveType(BfTypeCode_Var);
 			{
 				BfTypeCode loweredTypeCode = BfTypeCode_None;
 				BfTypeCode loweredTypeCode2 = BfTypeCode_None;				
-				checkType->GetLoweredType(BfTypeUsage_Parameter, &loweredTypeCode, &loweredTypeCode2);
+				if (!mIsConstModule)
+					checkType->GetLoweredType(BfTypeUsage_Parameter, &loweredTypeCode, &loweredTypeCode2);
 				argIdx++;
 				if (loweredTypeCode2 != BfTypeCode_None)
 					argIdx++;

+ 1 - 0
IDEHelper/Compiler/BfModule.h

@@ -1593,6 +1593,7 @@ public:
 	BfTypedValue RemoveRef(BfTypedValue typedValue);
 	BfTypedValue LoadOrAggregateValue(BfTypedValue typedValue);
 	BfTypedValue LoadValue(BfTypedValue typedValue, BfAstNode* refNode = NULL, bool isVolatile = false);	
+	BfTypedValue PrepareConst(BfTypedValue& typedValue);
 	void AggregateSplatIntoAddr(BfTypedValue typedValue, BfIRValue addrVal);
 	BfTypedValue AggregateSplat(BfTypedValue typedValue, BfIRValue* valueArrPtr = NULL);	
 	BfTypedValue MakeAddressable(BfTypedValue typedValue);

+ 47 - 7
IDEHelper/Compiler/BfModuleTypeUtils.cpp

@@ -5328,6 +5328,8 @@ BfPrimitiveType* BfModule::GetPrimitiveType(BfTypeCode typeCode)
 
 BfIRType BfModule::GetIRLoweredType(BfTypeCode loweredTypeCode, BfTypeCode loweredTypeCode2)
 {
+	BF_ASSERT(!mIsConstModule);
+
 	BF_ASSERT(loweredTypeCode != BfTypeCode_None);	
 	if (loweredTypeCode2 == BfTypeCode_None)	
 		return mBfIRBuilder->GetPrimitiveType(loweredTypeCode);	
@@ -9798,7 +9800,7 @@ BfIRValue BfModule::CastToFunction(BfAstNode* srcNode, const BfTypedValue& targe
 }
 
 BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfType* toType, BfCastFlags castFlags, BfCastResultFlags* resultFlags)
-{	
+{
 	bool silentFail = ((castFlags & BfCastFlags_SilentFail) != 0);
 	bool explicitCast = (castFlags & BfCastFlags_Explicit) != 0;
 	bool ignoreErrors = mIgnoreErrors || ((castFlags & BfCastFlags_SilentFail) != 0);
@@ -10763,11 +10765,40 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
 		}
 	}
 
-	if ((typedVal.mValue.IsConst()) && (toType->IsPointer()) && (toType->GetUnderlyingType() == GetPrimitiveType(BfTypeCode_Char8)) && (typedVal.mType->IsInstanceOf(mCompiler->mStringTypeDef)))
+	if (typedVal.mValue.IsConst())
 	{
-		int stringId = GetStringPoolIdx(typedVal.mValue, mBfIRBuilder);
-		if (stringId >= 0)
-			return GetStringCharPtr(stringId);
+		if ((toType->IsPointer()) && (toType->GetUnderlyingType() == GetPrimitiveType(BfTypeCode_Char8)) && (typedVal.mType->IsInstanceOf(mCompiler->mStringTypeDef)))
+		{
+			int stringId = GetStringPoolIdx(typedVal.mValue, mBfIRBuilder);
+			if (stringId >= 0)
+				return GetStringCharPtr(stringId);
+		}
+		else if ((toType->IsInstanceOf(mCompiler->mStringViewTypeDef)))
+		{
+			int stringId = GetStringPoolIdx(typedVal.mValue, mBfIRBuilder);
+			if (stringId >= 0)
+			{
+				int strLen = 0;
+				String str;
+				BfStringPoolEntry* entry = NULL;
+				if (mContext->mStringObjectIdMap.TryGetValue(stringId, &entry))
+				{
+					auto svTypeInst = toType->ToTypeInstance();
+
+					mBfIRBuilder->PopulateType(svTypeInst);					
+
+					auto stringCharPtr = GetStringCharPtr(stringId);					
+					SizedArray<BfIRValue, 2> spanFieldVals;
+					spanFieldVals.Add(mBfIRBuilder->CreateConstStructZero(mBfIRBuilder->MapType(svTypeInst->mBaseType->mBaseType)));
+					spanFieldVals.Add(stringCharPtr);
+					spanFieldVals.Add(mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, entry->mString.mLength));					
+
+					SizedArray<BfIRValue, 2> svFieldVals;
+					svFieldVals.Add(mBfIRBuilder->CreateConstAgg(mBfIRBuilder->MapType(svTypeInst->mBaseType), spanFieldVals));
+					return mBfIRBuilder->CreateConstAgg(mBfIRBuilder->MapType(svTypeInst), svFieldVals);
+				}				
+			}
+		}
 	}
 
 	// Check user-defined operators
@@ -11275,6 +11306,15 @@ BfTypedValue BfModule::Cast(BfAstNode* srcNode, const BfTypedValue& typedVal, Bf
 
 	PopulateType(toType, ((castFlags & BfCastFlags_NoConversionOperator) != 0) ? BfPopulateType_Data : BfPopulateType_DataAndMethods);
 
+	if ((toType->IsSizedArray()) && (typedVal.mType->IsSizedArray()))
+	{
+		// Retain our type if we're casting from a known-sized array to an unknown-sized arrays
+		if ((toType->IsUndefSizedArray()) && ((typedVal.mType->GetUnderlyingType()) == (toType->GetUnderlyingType())))
+		{
+			return typedVal;
+		}
+	}
+
 	if ((castFlags & BfCastFlags_Force) != 0)
 	{
 		if (toType->IsValuelessType())
@@ -11575,11 +11615,11 @@ BfTypedValue BfModule::GetIntCoercible(const BfTypedValue& typedValue)
 	if (typedValue.mValue.IsConst())
 	{		
 		auto constant = mBfIRBuilder->GetConstant(typedValue.mValue);
-		if (constant->mConstType == BfConstType_Array)
+		if (constant->mConstType == BfConstType_Agg)
 		{
 			uint64 intVal = 0;
 
-			auto constantArray = (BfConstantArray*)constant;
+			auto constantArray = (BfConstantAgg*)constant;
 			int memberIdx = 0;			
 			for (int memberIdx = 0; memberIdx < (int)constantArray->mValues.size(); memberIdx++)
 			{

+ 23 - 12
IDEHelper/Compiler/BfResolvedTypeUtils.cpp

@@ -1096,7 +1096,7 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
 
 	BfTypeCode loweredReturnTypeCode = BfTypeCode_None;
 	BfTypeCode loweredReturnTypeCode2 = BfTypeCode_None;	
-	if (GetLoweredReturnType(&loweredReturnTypeCode, &loweredReturnTypeCode2))
+	if ((!module->mIsConstModule) && (GetLoweredReturnType(&loweredReturnTypeCode, &loweredReturnTypeCode2)))
 	{
 		auto irReturnType = module->GetIRLoweredType(loweredReturnTypeCode, loweredReturnTypeCode2);
 		returnType = irReturnType;
@@ -1106,7 +1106,7 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
 		auto voidType = module->GetPrimitiveType(BfTypeCode_None);
 		returnType = module->mBfIRBuilder->MapType(voidType);
 	}
-	else if (GetStructRetIdx(forceStatic) != -1)
+	else if ((!module->mIsConstModule) && (GetStructRetIdx(forceStatic) != -1))
 	{
 		auto voidType = module->GetPrimitiveType(BfTypeCode_None);
 		returnType = module->mBfIRBuilder->MapType(voidType);
@@ -1125,11 +1125,9 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
 	{
 		returnType = module->mBfIRBuilder->MapType(mReturnType);
 	}	
-
 	
-
 	for (int paramIdx = -1; paramIdx < GetParamCount(); paramIdx++)
-	{			
+	{
 		BfType* checkType = NULL;
 		if (paramIdx == -1)
 		{
@@ -1150,7 +1148,7 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
 		else
 		{
 			checkType = GetParamType(paramIdx);
-		}		
+		}
 
 		/*if (GetParamName(paramIdx) == "this")
 		{
@@ -1161,11 +1159,15 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
 		bool doSplat = false;
 		if (paramIdx == -1)
 		{
-			if ((checkType->IsSplattable()) && (AllowsThisSplatting()))
+			if ((!mMethodDef->mIsMutating) && (checkType->IsTypedPrimitive()))
+			{
+				checkType = checkType->GetUnderlyingType();
+			}
+			else if ((!module->mIsConstModule) && (checkType->IsSplattable()) && (AllowsThisSplatting()))
 			{
 				doSplat = true;
 			}
-			else if ((!mMethodDef->mIsMutating) && (mCallingConvention == BfCallingConvention_Unspecified))
+			else if ((!module->mIsConstModule) && (!mMethodDef->mIsMutating) && (mCallingConvention == BfCallingConvention_Unspecified))
 				checkLowered = true;
 		}
 		else
@@ -1174,11 +1176,15 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
 			{
 				doSplat = true;
 			}
-			else if ((checkType->IsSplattable()) && (AllowsSplatting()))
+			else if (checkType->IsTypedPrimitive())
+			{
+				checkType = checkType->GetUnderlyingType();
+			}
+			else if ((!module->mIsConstModule) && (checkType->IsSplattable()) && (AllowsSplatting()))
 			{
 				doSplat = true;
 			}
-			else
+			else if (!module->mIsConstModule)
 				checkLowered = true;
 		}
 
@@ -1258,7 +1264,7 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
 			paramIdx++; // Skip over the explicit 'this'
 	}
 
-	if (GetStructRetIdx(forceStatic) == 1)
+	if ((!module->mIsConstModule) && (GetStructRetIdx(forceStatic) == 1))
 	{		
 		BF_SWAP(paramTypes[0], paramTypes[1]);
 	}
@@ -3082,7 +3088,12 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash
 				if (typedVal)
 				{
 					auto constant = ctx->mModule->mBfIRBuilder->GetConstant(typedVal.mValue);
-					if (constant->mConstType == BfConstType_Undef)
+					if (constant == NULL)
+					{
+						ctx->mFailed = true;
+						ctx->mModule->Fail("Array size not a constant value", arrayType->mParams[0]);
+					}
+					else if (constant->mConstType == BfConstType_Undef)
 					{
 						elementCount = -1; // Marker for undef
 					}

+ 2 - 0
IDEHelper/Compiler/BfResolvedTypeUtils.h

@@ -528,6 +528,7 @@ public:
 	virtual bool IsObjectOrInterface() { return false; }
 	virtual bool IsString() { return false; }
 	virtual bool IsSizedArray() { return false; }
+	virtual bool IsUndefSizedArray() { return false; }
 	virtual bool IsUnknownSizedArray() { return false; }
 	virtual bool IsArray() { return false; }	
 	virtual bool IsDelegate() { return false; }
@@ -2277,6 +2278,7 @@ public:
 	virtual bool NeedsExplicitAlignment() override { return mElementType->NeedsExplicitAlignment(); }
 
 	virtual bool IsSizedArray() override { return true; }
+	virtual bool IsUndefSizedArray() override { return mElementCount == -1; }
 		
 	virtual bool IsWrappableType() override { return true; }
 	virtual bool IsValueType() override { return true; } // Is a type of struct

+ 18 - 17
IDEHelper/Compiler/BfStmtEvaluator.cpp

@@ -1594,9 +1594,6 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD
 			}
 		}
 	};
-
-	PopulateType(resolvedType);
-	AddDependency(resolvedType, mCurTypeInstance, BfDependencyMap::DependencyFlag_LocalUsage);
 	
 	localDef->mResolvedType = resolvedType;
 	localDef->mIsReadOnly = isReadOnly;
@@ -1656,8 +1653,9 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD
 			{
 				BfConstResolver constResolver(this);
 				initValue = constResolver.Resolve(varDecl->mInitializer, resolvedType, BfConstResolveFlag_RemapFromStringId);
-				if (!initValue)
-					initValue = GetDefaultTypedValue(resolvedType);				
+				if (!initValue)							
+					initValue = GetDefaultTypedValue(resolvedType);
+				
 			}
 			else if (varDecl->mInitializer->IsA<BfUninitializedExpression>())				
 			{				
@@ -1680,15 +1678,12 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD
 
 				if ((!handledVarInit) && (initValue))
 					initValue = Cast(varDecl->mInitializer, initValue, resolvedType, BfCastFlags_PreferAddr);
-
-				// Why did we remove this?
-// 				if ((valExprEvaluator.mResultIsTempComposite) && (initValue.IsAddr()))
-// 				{
-// 					BF_ASSERT(initValue.mType->IsComposite());
-// 					localDef->mAddr = initValue.mValue;
-// 					handledVarInit = true;
-// 					handledVarStore = true;
-// 				}
+			}
+						
+			if ((initValue) && (resolvedType->IsUndefSizedArray()))
+			{
+				resolvedType = initValue.mType;
+				unresolvedType = resolvedType;
 			}
 		}
 		if ((!handledVarInit) && (!isConst))
@@ -1728,10 +1723,15 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD
 		}
 		else
 		{
-			BF_ASSERT(!localDef->mResolvedType->IsRef());
+			BF_ASSERT(!resolvedType->IsRef());
 		}
 	}
 
+	PopulateType(resolvedType);
+	AddDependency(resolvedType, mCurTypeInstance, BfDependencyMap::DependencyFlag_LocalUsage);
+
+	localDef->mResolvedType = resolvedType;
+
 	_CheckConst();
 
 	if ((initValue.mKind == BfTypedValueKind_TempAddr) && (!initHandled))
@@ -1771,6 +1771,7 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD
 		initValue = LoadValue(initValue);
 		if (initValue.IsSplat())
 		{
+			BF_ASSERT(!mIsConstModule);
 			if (!localDef->mAddr)
 				localDef->mAddr = AllocLocalVariable(resolvedType, localDef->mName);
 			AggregateSplatIntoAddr(initValue, localDef->mAddr);
@@ -4945,12 +4946,12 @@ void BfModule::Visit(BfReturnStatement* returnStmt)
 	BfType* origType;
 	BfExprEvaluator exprEvaluator(this);
 	bool alreadyWritten = false;
-	if (mCurMethodInstance->GetStructRetIdx() != -1)	
+	if ((!mIsConstModule) && (mCurMethodInstance->GetStructRetIdx() != -1))
 		exprEvaluator.mReceivingValue = &mCurMethodState->mRetVal;	
 	if (mCurMethodInstance->mMethodDef->mIsReadOnly)
 		exprEvaluator.mAllowReadOnlyReference = true;
 	auto retValue = CreateValueFromExpression(exprEvaluator, returnStmt->mExpression, expectingReturnType, BfEvalExprFlags_AllowRefExpr, &origType);	
-	if (mCurMethodInstance->GetStructRetIdx() != -1)
+	if ((!mIsConstModule) && (mCurMethodInstance->GetStructRetIdx() != -1))
 		alreadyWritten = exprEvaluator.mReceivingValue == NULL;
 	MarkScopeLeft(&mCurMethodState->mHeadScope);
 	

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 589 - 118
IDEHelper/Compiler/CeMachine.cpp


+ 49 - 9
IDEHelper/Compiler/CeMachine.h

@@ -55,6 +55,7 @@ typedef int addr_ce;
 enum CeErrorKind
 {
 	CeErrorKind_None,
+	CeErrorKind_Error,
 	CeErrorKind_GlobalVariable,
 	CeErrorKind_FunctionPointer,
 	CeErrorKind_Intrinsic
@@ -83,6 +84,7 @@ enum CeOp : int16
 	CeOp_FrameAddr_64,
 	CeOp_FrameAddrOfs_32,
 
+	CeOp_ConstData,
 	CeOp_ConstDataRef,
 	CeOp_Zero,
 	CEOP_SIZED(Const),
@@ -255,19 +257,39 @@ enum CeFunctionKind
 	CeFunctionKind_Char32_IsNumber,
 };
 
+class CeConstStructFixup
+{
+public:
+	enum Kind
+	{
+		Kind_None,
+		Kind_StringPtr,
+		Kind_StringCharPtr,
+	};
+
+public:
+	Kind mKind;
+	int mValue;
+	int mOffset;
+};
+
 class CeConstStructData
 {
 public:
 	Val128 mHash;
 	Array<uint8> mData;
+	Array<uint8> mFixedData;
+	Array<CeConstStructFixup> mFixups;
 	addr_ce mAddr;
 	int mBindExecuteId;
+	bool mQueueFixups;
 
 public:
 	CeConstStructData()
 	{
 		mBindExecuteId = -1;
 		mAddr = 0;
+		mQueueFixups = false;
 	}
 };
 
@@ -336,7 +358,8 @@ public:
 
 enum CeEvalFlags
 {
-	CeEvalFlags_None = 0	
+	CeEvalFlags_None = 0,
+	CeEvalFlags_Cascade = 1
 };
 
 enum CeOperandKind
@@ -346,7 +369,7 @@ enum CeOperandKind
 	CeOperandKind_AllocaAddr,
 	CeOperandKind_Block,
 	CeOperandKind_Immediate,
-	CeOperandKind_ConstAgg,	
+	CeOperandKind_ConstStructTableIdx,	
 	CeOperandKind_CallTableIdx
 };
 
@@ -360,6 +383,7 @@ public:
 		int mBlockIdx;
 		int mImmediate;
 		int mCallTableIdx;
+		int mStructTableIdx;
 		BeConstant* mConstant;
 	};
 	BeType* mType;
@@ -462,7 +486,7 @@ public:
 	CeMachine* mCeMachine;	
 	CeFunction* mCeFunction;
 	BeFunction* mBeFunction;	
-	CeOperand mReturnVal;	
+	CeOperand mReturnVal;
 	BeType* mIntPtrType;
 	int mPtrSize;	
 
@@ -554,6 +578,14 @@ public:
 	}
 };
 
+class CeAppendAllocInfo
+{
+public:
+	BfModule* mModule;
+	BfIRValue mAllocValue;
+	BfIRValue mAppendSizeValue;
+};
+
 class CeMachine
 {
 public:
@@ -575,14 +607,17 @@ public:
 	Dictionary<Val128, addr_ce> mConstDataMap;	
 	Dictionary<String, CeStaticFieldInfo> mStaticFieldMap;
 	HashSet<int> mStaticCtorExecSet;
+	CeAppendAllocInfo* mAppendAllocInfo;
 	
 	BfAstNode* mCurTargetSrc;
 	BfModule* mCurModule;	
+	BfType* mCurExpectingType;
 
 public:
 	CeMachine(BfCompiler* compiler);
 	~CeMachine();
-		
+	
+	BfError* Fail(const StringImpl& error);
 	BfError* Fail(const CeFrame& curFrame, const StringImpl& error);
 
 	void Init();	
@@ -592,14 +627,15 @@ public:
 	addr_ce GetString(int stringId);
 	addr_ce GetConstantData(BeConstant* constant);
 	BfType* GetBfType(int typeId);	
+	void PrepareConstStructEntry(CeConstStructData& constStructData);
 
 	BeContext* GetBeContext();
 	BeModule* GetBeModule();
 	void DerefMethodInfo(CeFunctionInfo* ceFunctionInfo);
-	void RemoveMethod(BfMethodInstance* methodInstance);	
-	int GetConstantSize(BfConstant* constant);
-	CeErrorKind WriteConstant(Array<uint8>& arr, BeConstant* constVal);
-	void WriteConstant(uint8* ptr, BfConstant* constant);
+	void RemoveMethod(BfMethodInstance* methodInstance);		
+	bool WriteConstant(BfModule* module, addr_ce addr, BfConstant* constant, BfType* type);
+	CeErrorKind WriteConstant(CeConstStructData& data, BeConstant* constVal);
+	BfIRValue CreateConstant(BfModule* module, uint8* ptr, BfType* type, BfType** outType = NULL);
 	void CreateFunction(BfMethodInstance* methodInstance, CeFunction* ceFunction);		
 	bool Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* startFramePtr);
 
@@ -612,7 +648,11 @@ public:
 	void QueueMethod(BfMethodInstance* methodInstance, BfIRValue func);
 	void QueueMethod(BfModuleMethodInstance moduleMethodInstance);
 	void QueueStaticField(BfFieldInstance* fieldInstance, const StringImpl& mangledFieldName);
-	BfTypedValue Call(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray<BfIRValue>& args, CeEvalFlags flags);
+
+	void SetAppendAllocInfo(BfModule* module, BfIRValue allocValue, BfIRValue appendSizeValue);
+	void ClearAppendAllocInfo();
+
+	BfTypedValue Call(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray<BfIRValue>& args, CeEvalFlags flags, BfType* expectingType);
 };
 
 NS_BF_END

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott