Kaynağa Gözat

Expanded const aggregate compatibility

Brian Fiete 4 yıl önce
ebeveyn
işleme
f665388e91

+ 22 - 0
BeefySysLib/util/SizedArray.h

@@ -485,6 +485,28 @@ public:
 		this->mSize--;
 	}
 
+	void RemoveAll(const std::function<bool(const T& val)>& func)
+	{
+		int outIdx = 0;
+		for (int i = 0; i < this->mSize; i++)
+		{
+			if (func(this->mVals[i]))
+			{
+				this->mVals[i].~T();
+			}
+			else 
+			{
+				if (i != outIdx)
+				{
+					new (&this->mVals[outIdx]) T(this->mVals[i]);
+				}
+
+				outIdx++;
+			}
+		}
+		this->mSize = outIdx;
+	}
+
 	void RemoveRange(intptr idx, intptr length)
 	{
 		BF_ASSERT(

+ 2 - 2
IDEHelper/Backend/BeContext.cpp

@@ -161,7 +161,7 @@ BeSizedArrayType* BeContext::CreateSizedArrayType(BeType* type, int length)
 	arrayType->mTypeCode = BeTypeCode_SizedArray;
 	arrayType->mElementType = type;
 	arrayType->mLength = length;
-	arrayType->mSize = type->mSize * length;
+	arrayType->mSize = type->GetStride() * length;
 	arrayType->mAlign = type->mAlign;
 	return arrayType;
 }
@@ -173,7 +173,7 @@ BeVectorType* BeContext::CreateVectorType(BeType* type, int length)
 	arrayType->mTypeCode = BeTypeCode_Vector;
 	arrayType->mElementType = type;
 	arrayType->mLength = length;
-	arrayType->mSize = type->mSize * length;
+	arrayType->mSize = type->GetStride() * length;
 	arrayType->mAlign = type->mAlign;
 	return arrayType;
 }

+ 5 - 0
IDEHelper/Backend/BeContext.h

@@ -91,6 +91,11 @@ public:
 
 	}
 
+	int GetStride()
+	{
+		return BF_ALIGN(mSize, mAlign);
+	}
+
 	bool IsPointer()
 	{
 		return (mTypeCode == BeTypeCode_Pointer) || (mTypeCode == BeTypeCode_NullPtr);

+ 33 - 7
IDEHelper/Backend/BeIRCodeGen.cpp

@@ -649,7 +649,7 @@ void BeIRCodeGen::Read(BeType*& beType)
 	else if (typeKind == BfIRType::TypeKind::TypeKind_TypeInstId)
 		beType = typeEntry.mInstBeType;
 	else if (typeKind == BfIRType::TypeKind::TypeKind_TypeInstPtrId)
-		beType = mBeContext->GetPointerTo(typeEntry.mInstBeType);	
+		beType = mBeContext->GetPointerTo(typeEntry.mInstBeType);
 	BE_MEM_END("BeType");
 }
 
@@ -838,28 +838,50 @@ void BeIRCodeGen::Read(BeValue*& beValue)
 			for (int i = 0; i < (int)values.size(); i++)
 			{
 				auto val = values[i];
-				BeConstant* constant = BeValueDynCast<BeConstant>(val);
-				constStruct->mMemberValues.push_back(constant);
+				BeConstant* constant = BeValueDynCast<BeConstant>(val);				
 #ifdef _DEBUG
 				if (type->IsSizedArray())
 				{
 					auto arrayType = (BeSizedArrayType*)type;
 					auto memberType = constant->GetType();
-					BF_ASSERT(memberType == arrayType->mElementType);
+					if (memberType != arrayType->mElementType)
+						Fail("ConstAgg array member type mismatch");
 				}
 				else if (type->IsVector())
 				{
 					auto vecType = (BeVectorType*)type;
 					auto memberType = constant->GetType();
-					BF_ASSERT(memberType == vecType->mElementType);
+					if (memberType != vecType->mElementType)
+						Fail("ConstAgg vector member type mismatch");
 				}
 				else
 				{
 					BF_ASSERT(type->IsStruct());
 					auto structType = (BeStructType*)type;
-					auto memberType = constant->GetType();
-					BF_ASSERT(memberType == structType->mMembers[i].mType);
+					auto valType = constant->GetType();					
+					if (structType->mIsOpaque)
+					{
+						Fail("ConstAgg with opaque struct");
+					}
+					else if (valType != structType->mMembers[i].mType)
+					{
+						if ((valType->IsSizedArray()) && (structType->mMembers[i].mType->IsSizedArray()))
+						{
+							auto valSizedType = (BeSizedArrayType*)valType;
+							auto memberSizedType = (BeSizedArrayType*)structType->mMembers[i].mType;
+							if ((valSizedType->mSize == 0) && (valSizedType->mElementType == memberSizedType->mElementType))
+							{								
+								constant->mType = memberSizedType;
+								constStruct->mMemberValues.Add(constant);
+								continue;
+							}
+						}
+
+						Fail("ConstAgg struct member type mismatch");
+					}
 				}
+
+				constStruct->mMemberValues.Add(constant);
 #endif
 			}
 			beValue = constStruct;
@@ -1151,10 +1173,14 @@ void BeIRCodeGen::HandleNextCmd()
 		{			
 			CMD_PARAM(BeType*, type);
 			CMD_PARAM(CmdParamVec<BeType*>, members);
+			CMD_PARAM(int, instSize);
+			CMD_PARAM(int, instAlign);
 			CMD_PARAM(bool, isPacked);
 			BF_ASSERT(type->mTypeCode == BeTypeCode_Struct);			
 			auto structType = (BeStructType*)type;
 			mBeContext->SetStructBody(structType, members, isPacked);
+			structType->mSize = instSize;
+			structType->mAlign = instAlign;
 		}
 		break;
 	case  BfIRCmd_Type:

+ 2 - 1
IDEHelper/Compiler/BfContext.h

@@ -130,7 +130,8 @@ public:
 		ResolveKind_ResolvingVarType,
 		ResolveKind_UnionInnerType,
 		ResolveKind_LocalVariable,
-		ResolveKind_Attributes
+		ResolveKind_Attributes,
+		ResolveKind_ConstField
 	};
 
 public:

+ 46 - 18
IDEHelper/Compiler/BfExprEvaluator.cpp

@@ -1330,6 +1330,7 @@ BfTypedValue BfMethodMatcher::ResolveArgTypedValue(BfResolvedArg& resolvedArg, B
 				auto prevBlock = mModule->mBfIRBuilder->GetInsertBlock();
 								
 				BfExprEvaluator exprEvaluator(mModule);									
+				exprEvaluator.mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags & BfEvalExprFlags_Comptime);
 				exprEvaluator.mBfEvalExprFlags = (BfEvalExprFlags)(exprEvaluator.mBfEvalExprFlags | BfEvalExprFlags_AllowIntUnknown | BfEvalExprFlags_NoAutoComplete);
 				if ((resolvedArg.mArgFlags & BfArgFlag_ParamsExpr) != 0)
 					exprEvaluator.mBfEvalExprFlags = (BfEvalExprFlags)(exprEvaluator.mBfEvalExprFlags | BfEvalExprFlags_AllowParamsExpr);
@@ -4465,7 +4466,13 @@ BfTypedValue BfExprEvaluator::LookupField(BfAstNode* targetSrc, BfTypedValue tar
 					}
 
 					if (fieldInstance->mConstIdx == -1)
-					{							
+					{	
+						if ((mBfEvalExprFlags & BfEvalExprFlags_DeclType) != 0)
+						{
+							// We don't need a real value
+							return BfTypedValue(mModule->GetDefaultValue(resolvedFieldType), resolvedFieldType);
+						}
+
 						curCheckType->mModule->ResolveConstField(curCheckType, fieldInstance, field);
 						if (fieldInstance->mConstIdx == -1)
 							return BfTypedValue(mModule->GetDefaultValue(resolvedFieldType), resolvedFieldType);
@@ -5353,7 +5360,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
 			else
 			{
 				CeEvalFlags evalFlags = CeEvalFlags_None;				
-				auto constRet = mModule->mCompiler->mCEMachine->Call(targetSrc, mModule, methodInstance, irArgs, evalFlags, mExpectingType);				
+				auto constRet = mModule->mCompiler->mCEMachine->Call(targetSrc, mModule, methodInstance, irArgs, evalFlags, mExpectingType);
 				if (constRet)
 				{
 					BF_ASSERT(!constRet.mType->IsVar());
@@ -5624,7 +5631,9 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
 	
 	if (returnType->IsComposite())
 		mModule->mBfIRBuilder->PopulateType(returnType);
-		
+	
+	methodInstance->mMethodInstanceGroup->mHasEmittedReference = true;
+
 	BfIRValue callInst;
 	int callIRArgCount = (int)irArgs.size();
 	if (sret != NULL)
@@ -7118,6 +7127,13 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
 			mModule->CheckStaticAccess(targetTypeInst);
 	}
 
+	if (methodInstance->mReturnType == NULL)
+	{
+		mModule->AssertErrorState();
+		mModule->Fail("Circular reference in method instance", targetSrc);
+		return BfTypedValue();
+	}
+
 	auto func = moduleMethodInstance.mFunc;	
 	BfTypedValue callResult = CreateCall(targetSrc, methodInstance, func, bypassVirtual, irArgs);	
 
@@ -7237,7 +7253,11 @@ BfTypedValue BfExprEvaluator::MatchConstructor(BfAstNode* targetSrc, BfMethodBou
 	// There should always be a constructor
 	BF_ASSERT(methodMatcher.mBestMethodDef != NULL);
 
-	auto moduleMethodInstance = mModule->GetMethodInstance(methodMatcher.mBestMethodTypeInstance, methodMatcher.mBestMethodDef, methodMatcher.mBestMethodGenericArguments);
+	auto moduleMethodInstance = mModule->GetMethodInstance(methodMatcher.mBestMethodTypeInstance, methodMatcher.mBestMethodDef, methodMatcher.mBestMethodGenericArguments);	
+	if (!mModule->CheckUseMethodInstance(moduleMethodInstance.mMethodInstance, targetSrc))
+	{
+		return BfTypedValue();
+	}
 
 	BfAutoComplete* autoComplete = GetAutoComplete();
 	if (autoComplete != NULL)
@@ -7321,7 +7341,7 @@ BfTypedValue BfExprEvaluator::ResolveArgValue(BfResolvedArg& resolvedArg, BfType
 			{
 				BfExprEvaluator exprEvaluator(mModule);
 				exprEvaluator.mReceivingValue = receivingValue;
-				BfEvalExprFlags flags = (BfEvalExprFlags)((mBfEvalExprFlags & BfEvalExprFlags_NoAutoComplete) | BfEvalExprFlags_NoCast);
+				BfEvalExprFlags flags = (BfEvalExprFlags)((mBfEvalExprFlags & (BfEvalExprFlags_NoAutoComplete | BfEvalExprFlags_Comptime)) | BfEvalExprFlags_NoCast);
 				if ((paramKind == BfParamKind_Params) || (paramKind == BfParamKind_DelegateParam))
 					flags = (BfEvalExprFlags)(flags | BfEvalExprFlags_AllowParamsExpr);
 
@@ -8556,7 +8576,9 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
 		prevBindResult.mPrevVal->mCheckedMultipleMethods = true;
 
 	BfModuleMethodInstance moduleMethodInstance = GetSelectedMethod(targetSrc, curTypeInst, methodDef, methodMatcher);
-	
+	if (!mModule->CheckUseMethodInstance(moduleMethodInstance.mMethodInstance, targetSrc))
+		return BfTypedValue();
+
 	if ((mModule->mCurMethodInstance != NULL) && (mModule->mCurMethodInstance->mIsUnspecialized))
 	{
 		if (methodMatcher.mHasVarArguments)
@@ -14851,6 +14873,10 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo
 		mModule->Fail("Failed to get selected mixin", targetSrc);
 		return;
 	}
+
+	if (!mModule->CheckUseMethodInstance(moduleMethodInstance.mMethodInstance, targetSrc))	
+		return;	
+
 	auto methodInstance = moduleMethodInstance.mMethodInstance;
 	PerformCallChecks(methodInstance, targetSrc);
 
@@ -17959,6 +17985,8 @@ void BfExprEvaluator::InitializedSizedArray(BfSizedArrayType* arrayType, BfToken
 
 					if (expr != NULL)
 					{	
+						auto evalFlags = (BfEvalExprFlags)(mBfEvalExprFlags & BfEvalExprFlags_Comptime);
+
 						bool tryDefer = false;						
  						if ((checkArrayType->IsComposite()) && 
  							((expr->IsA<BfInvocationExpression>()) || (expr->IsExact<BfTupleExpression>())))
@@ -17966,12 +17994,12 @@ void BfExprEvaluator::InitializedSizedArray(BfSizedArrayType* arrayType, BfToken
 							// We evaluate with a new scope because this expression may create variables that we don't want to be visible to other
 							//  non-deferred evaluations (since the value may actually be a FakeVal)
 							SetAndRestoreValue<bool> prevIgnoreWrites(mModule->mBfIRBuilder->mIgnoreWrites, true);
-							elementValue = mModule->CreateValueFromExpression(expr, checkArrayType->mElementType, BfEvalExprFlags_CreateConditionalScope);
+							elementValue = mModule->CreateValueFromExpression(expr, checkArrayType->mElementType, (BfEvalExprFlags)(evalFlags | BfEvalExprFlags_CreateConditionalScope));
 							deferredValue = !prevIgnoreWrites.mPrevVal && elementValue.mValue.IsFake();
  						}
 						else
 						{
-							elementValue = mModule->CreateValueFromExpression(expr, checkArrayType->mElementType);
+							elementValue = mModule->CreateValueFromExpression(expr, checkArrayType->mElementType, evalFlags);
 						}
 
 						if (!elementValue)
@@ -17981,8 +18009,8 @@ void BfExprEvaluator::InitializedSizedArray(BfSizedArrayType* arrayType, BfToken
 							elementValue = mModule->GetDefaultTypedValue(checkArrayType->mElementType);
 
 						// For now, we can't properly create const-valued non-size-aligned composites
-						if (checkArrayType->mElementType->NeedsExplicitAlignment())
-							isAllConst = false;
+// 						if (checkArrayType->mElementType->NeedsExplicitAlignment())
+// 							isAllConst = false;
 						if (!elementValue.mValue.IsConst())
 							isAllConst = false;
 						if (elementValue.IsAddr())
@@ -18173,14 +18201,8 @@ void BfExprEvaluator::InitializedSizedArray(BfSizedArrayType* arrayType, BfToken
 			auto allocArrayType = checkArrayType;
 			if (checkArrayType->IsUndefSizedArray())
 				allocArrayType = mModule->CreateSizedArrayType(checkArrayType->GetUnderlyingType(), (int)members.size());
-
-			if (checkArrayType->mElementType->IsStruct())
-			{
-				// This fixed cases where we have non-size-aligned initializers. Assume zero-initialized
-				return mModule->mBfIRBuilder->CreateConstStructZero(mModule->mBfIRBuilder->MapType(checkArrayType)); 
-			}
-			else
-				return mModule->mBfIRBuilder->CreateConstAgg(mModule->mBfIRBuilder->MapType(checkArrayType), members);
+			
+			return mModule->mBfIRBuilder->CreateConstAgg(mModule->mBfIRBuilder->MapType(checkArrayType), members);
 		};
 
 		_GetValues(arrayType, openToken, valueExprs, commas, closeToken, false);
@@ -18390,6 +18412,12 @@ void BfExprEvaluator::Visit(BfTupleExpression* tupleExpr)
 					continue;
 				irValues[fieldInstance->mDataIdx] = typedValues[fieldIdx].mValue;
 			}
+
+			for (auto& val : irValues)
+			{
+				if (!val)
+					val = mModule->mBfIRBuilder->CreateConstArrayZero(0);
+			}
 			
 			mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConstAgg(mModule->mBfIRBuilder->MapType(tupleType), irValues), tupleType);
 			return;

+ 42 - 13
IDEHelper/Compiler/BfIRBuilder.cpp

@@ -666,6 +666,10 @@ BfIRValue BfIRConstHolder::CreateConst(BfConstant* fromConst, BfIRConstHolder* f
 			return GetUndefConstValue(BfIRValue());
 		return GetUndefConstValue(constUndef->mType);
 	}
+	else if (fromConst->mConstType == BfConstType_ArrayZero8)
+	{
+		return CreateConstArrayZero(fromConst->mInt32);
+	}
 	else if ((IsInt(fromConst->mTypeCode)) || (fromConst->mTypeCode == BfTypeCode_Boolean) || (fromConst->mTypeCode == BfTypeCode_StringId))
 	{		
 		return CreateConst(fromConst->mTypeCode, fromConst->mUInt64);		
@@ -1287,6 +1291,10 @@ String BfIRBuilder::ToString(BfIRValue irValue)
 		{
 			return StrFormat("Constant %lld", constant->mInt64);
 		}
+		else if (constant->mTypeCode == BfTypeCode_StringId)
+		{
+			return StrFormat("StringId %d", constant->mInt64);
+		}
 		else if (constant->mConstType == BfConstType_GlobalVar)
 		{
 			if (mBfIRCodeGen != NULL)
@@ -1299,8 +1307,17 @@ String BfIRBuilder::ToString(BfIRValue irValue)
 				strStream.flush();
 				return outStr;
 			}
+			else if (mBeIRCodeGen != NULL)
+			{
+				auto gvConst = (BfGlobalVar*)constant;
+				auto val = mBeIRCodeGen->GetBeValue(gvConst->mStreamId);
+				String outStr;
+				BeDumpContext dumpCtx;				
+				dumpCtx.ToString(outStr, val);								
+				return outStr;
+			}
 			else
-				return "???";
+				return "GlobalVar???";
 		}		
 		else if (constant->mConstType == BfConstType_BitCast)
 		{
@@ -1344,7 +1361,7 @@ String BfIRBuilder::ToString(BfIRValue irValue)
 					str += ", ";
 				str += ToString(constAgg->mValues[i]);
 			}
-			str += ");";
+			str += ")";
 			return str;
 		}
 		else if (constant->mConstType == BfConstType_AggZero)
@@ -1390,7 +1407,7 @@ String BfIRBuilder::ToString(BfIRValue irValue)
 			return str;
 		}	
 		else
-			return "???";
+			return "Value???";
 	}
 	else
 	{
@@ -2369,7 +2386,7 @@ void BfIRBuilder::CreateTypeDeclaration(BfType* type, bool forceDbgDefine)
 		}
 		
 		irType = CreateStructType(name);
-		StructSetBody(irType, members, false);
+		StructSetBody(irType, members, type->mSize, type->mAlign, false);
 	}
 	else if (type->IsSizedArray())
 	{
@@ -2390,10 +2407,12 @@ void BfIRBuilder::CreateTypeDeclaration(BfType* type, bool forceDbgDefine)
 		
 		if (arrayType->mElementType->IsValuelessType())		
 			irType = elementIrType;		
-		else if (arrayType->mElementType->IsSizeAligned())
-			irType = GetSizedArrayType(MapType(arrayType->mElementType), BF_MAX(arrayType->mElementCount, 0));
 		else
-			irType = GetSizedArrayType(MapType(mModule->GetPrimitiveType(BfTypeCode_Int8)), BF_MAX(arrayType->mSize, 0));
+			irType = GetSizedArrayType(MapType(arrayType->mElementType), BF_MAX(arrayType->mElementCount, 0));
+// 		else if (arrayType->mElementType->IsSizeAligned())
+// 			irType = GetSizedArrayType(MapType(arrayType->mElementType), BF_MAX(arrayType->mElementCount, 0));
+// 		else
+// 			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);
@@ -2734,10 +2753,18 @@ void BfIRBuilder::CreateDbgTypeDefinition(BfType* type)
 
 						if (fieldInstance->mConstIdx != -1)
 						{
+							if (fieldInstance->GetFieldDef()->mName == "mMembers")
+							{
+								NOP;
+							}
+
 							constant = typeInstance->mConstHolder->GetConstantById(fieldInstance->mConstIdx);
 							staticValue = mModule->ConstantToCurrent(constant, typeInstance->mConstHolder, resolvedFieldType);
 						}
 
+						if (fieldInstance->mResolvedType->IsComposite())
+							PopulateType(fieldInstance->mResolvedType);
+
 						BfIRMDNode constDIType;
 						if (resolvedFieldType->IsTypedPrimitive())
 							constDIType = DbgGetType(resolvedFieldType->GetUnderlyingType());//resolvedFieldType->GetUnderlyingType()->mDIType ;
@@ -2806,7 +2833,8 @@ void BfIRBuilder::CreateDbgTypeDefinition(BfType* type)
 								}
 								else
 								{
-									mModule->FatalError(StrFormat("Invalid constant type for %s", staticVarName.c_str()));
+									// Ignore other types (for now)
+									continue;
 								}
 							}
 							
@@ -2835,8 +2863,9 @@ void BfIRBuilder::CreateDbgTypeDefinition(BfType* type)
 						{
 							int flags = 0;
 							String fieldName = fieldDef->mName;
-							if (constant != NULL)
-							{								
+							if ((constant != NULL) && 
+								((IsInt(constant->mTypeCode)) || (IsFloat(constant->mTypeCode))))
+							{
 								int64 writeVal = constant->mInt64;
 								if (constant->mTypeCode == BfTypeCode_Float)
 								{
@@ -3308,7 +3337,7 @@ void BfIRBuilder::CreateTypeDefinition_Data(BfModule* populateModule, BfTypeInst
 	}
 
 	if (!typeInstance->IsTypedPrimitive())
-		StructSetBody(MapTypeInst(typeInstance), irFieldTypes, /*isPacked || !isCRepr*/true);
+		StructSetBody(MapTypeInst(typeInstance), irFieldTypes, typeInstance->mInstSize, typeInstance->mInstAlign, true);
 
 	if (typeInstance->IsNullable())
 	{
@@ -3568,9 +3597,9 @@ BfIRType BfIRBuilder::CreateStructType(const BfSizedArray<BfIRType>& memberTypes
 	return retType;
 }
 
-void BfIRBuilder::StructSetBody(BfIRType type, const BfSizedArray<BfIRType>& memberTypes, bool isPacked)
+void BfIRBuilder::StructSetBody(BfIRType type, const BfSizedArray<BfIRType>& memberTypes, int size, int align, bool isPacked)
 {
-	WriteCmd(BfIRCmd_StructSetBody, type, memberTypes, isPacked);
+	WriteCmd(BfIRCmd_StructSetBody, type, memberTypes, size, align, isPacked);
 	NEW_CMD_INSERTED;
 }
 

+ 2 - 2
IDEHelper/Compiler/BfIRBuilder.h

@@ -588,7 +588,7 @@ struct BfIRTypeData
 		TypeKind_TypeId,
 		TypeKind_TypeCode,
 		TypeKind_TypeInstId,
-		TypeKind_TypeInstPtrId,
+		TypeKind_TypeInstPtrId,		
 		TypeKind_Stream,
 		TypeKind_SizedArray
 	};
@@ -1141,7 +1141,7 @@ public:
 	BfIRType GetPrimitiveType(BfTypeCode typeCode);	
 	BfIRType CreateStructType(const StringImpl& name);
 	BfIRType CreateStructType(const BfSizedArray<BfIRType>& memberTypes);
-	void StructSetBody(BfIRType type, const BfSizedArray<BfIRType>& memberTypes, bool isPacked);	
+	void StructSetBody(BfIRType type, const BfSizedArray<BfIRType>& memberTypes, int size, int align, bool isPacked);
 	BfIRType MapType(BfType* type, BfIRPopulateType populateType = BfIRPopulateType_Declaration);
 	BfIRType MapTypeInst(BfTypeInstance* typeInst, BfIRPopulateType populateType = BfIRPopulateType_Declaration);
 	BfIRType MapTypeInstPtr(BfTypeInstance* typeInst);

+ 114 - 13
IDEHelper/Compiler/BfIRCodeGen.cpp

@@ -712,7 +712,7 @@ void BfIRCodeGen::Read(BfIRTypeEntry*& type)
 	type = &GetTypeEntry(typeId);
 }
 
-void BfIRCodeGen::Read(llvm::Type*& llvmType)
+void BfIRCodeGen::Read(llvm::Type*& llvmType, BfIRTypeEntry** outTypeEntry)
 {
 	BfIRType::TypeKind typeKind = (BfIRType::TypeKind)mStream->Read();
 	if (typeKind == BfIRType::TypeKind::TypeKind_None)
@@ -759,6 +759,8 @@ void BfIRCodeGen::Read(llvm::Type*& llvmType)
 		llvmType = typeEntry.mInstLLVMType;
 	else if (typeKind == BfIRType::TypeKind::TypeKind_TypeInstPtrId)
 		llvmType = typeEntry.mInstLLVMType->getPointerTo();
+	if (outTypeEntry != NULL)
+		*outTypeEntry = &typeEntry;
 }
 
 void BfIRCodeGen::Read(llvm::FunctionType*& llvmType)
@@ -769,7 +771,7 @@ void BfIRCodeGen::Read(llvm::FunctionType*& llvmType)
 	llvmType = (llvm::FunctionType*)result.mLLVMType;
 }
 
-void BfIRCodeGen::Read(llvm::Value*& llvmValue, BfIRCodeGenEntry** codeGenEntry)
+void BfIRCodeGen::Read(llvm::Value*& llvmValue, BfIRCodeGenEntry** codeGenEntry, bool wantSizeAligned)
 {
 	BfIRParamType paramType = (BfIRParamType)mStream->Read();
 	if (paramType == BfIRParamType_None)
@@ -903,10 +905,20 @@ void BfIRCodeGen::Read(llvm::Value*& llvmValue, BfIRCodeGenEntry** codeGenEntry)
 			llvmValue = llvm::ConstantAggregateZero::get(type);
 			return;
 		}
+		else if (constType == BfConstType_ArrayZero8)
+		{
+			CMD_PARAM(int, count);
+			auto arrType = llvm::ArrayType::get(llvm::Type::getInt8Ty(*mLLVMContext), count);
+			llvmValue = llvm::ConstantAggregateZero::get(arrType);
+			return;
+		}
 		else if (constType == BfConstType_Agg)
 		{
-			CMD_PARAM(llvm::Type*, type);
-			CMD_PARAM(CmdParamVec<llvm::Constant*>, values);
+			BfIRTypeEntry* typeEntry = NULL;
+			llvm::Type* type = NULL;
+			Read(type, &typeEntry);			
+			CmdParamVec<llvm::Constant*> values;
+			Read(values, type->isArrayTy());
 
 			if (auto arrayType = llvm::dyn_cast<llvm::ArrayType>(type))
 			{
@@ -921,7 +933,31 @@ void BfIRCodeGen::Read(llvm::Value*& llvmValue, BfIRCodeGenEntry** codeGenEntry)
 			}
 			else if (auto structType = llvm::dyn_cast<llvm::StructType>(type))
 			{
-				llvmValue = llvm::ConstantStruct::get(structType, values);
+				for (int i = 0; i < (int)values.size(); i++)
+				{
+					if (values[i]->getType() != structType->getElementType(i))
+					{
+						auto valArrayType = llvm::dyn_cast<llvm::ArrayType>(values[i]->getType());
+						auto structArrayType = llvm::dyn_cast<llvm::ArrayType>(structType->getElementType(i));
+						if ((valArrayType != NULL) && (structArrayType != NULL))
+						{
+							if ((valArrayType->getNumElements() == 0) && (valArrayType->getElementType() == structArrayType->getElementType()))
+							{
+								values[i] = llvm::ConstantAggregateZero::get(structArrayType);
+							}
+						}
+					}
+				}
+
+				if ((wantSizeAligned) && (typeEntry != NULL))
+				{
+					auto alignedType = llvm::dyn_cast<llvm::StructType>(GetSizeAlignedType(typeEntry));
+					if (type != alignedType)
+						values.push_back(llvm::ConstantAggregateZero::get(alignedType->getElementType(alignedType->getNumElements() - 1)));
+					llvmValue = llvm::ConstantStruct::get(alignedType, values);
+				}
+				else
+					llvmValue = llvm::ConstantStruct::get(structType, values);
 			}
 			else if (auto vecType = llvm::dyn_cast<llvm::VectorType>(type))
 			{
@@ -1046,10 +1082,10 @@ void BfIRCodeGen::Read(llvm::Value*& llvmValue, BfIRCodeGenEntry** codeGenEntry)
 	}
 }
 
-void BfIRCodeGen::Read(llvm::Constant*& llvmConstant)
+void BfIRCodeGen::Read(llvm::Constant*& llvmConstant, bool wantSizeAligned)
 {
 	llvm::Value* value;
-	Read(value);
+	Read(value, NULL, wantSizeAligned);
 	if (value == NULL)
 	{
 		llvmConstant = NULL;
@@ -1312,6 +1348,54 @@ bool BfIRCodeGen::TryVectorCpy(llvm::Value* ptr, llvm::Value* val)
 	return true;
 }
 
+llvm::Type* BfIRCodeGen::GetSizeAlignedType(BfIRTypeEntry* typeEntry)
+{	
+	if ((typeEntry->mAlignLLVMType == NULL) && ((typeEntry->mSize & (typeEntry->mAlign - 1)) != 0))
+	{
+		auto structType = llvm::dyn_cast<llvm::StructType>(typeEntry->mLLVMType);
+		if (structType != NULL)
+		{
+			BF_ASSERT(structType->isPacked());
+
+			auto alignType = llvm::StructType::create(*mLLVMContext, (structType->getName().str() + "_ALIGNED").c_str());
+			llvm::SmallVector<llvm::Type*, 8> members;
+			for (int elemIdx = 0; elemIdx < (int)structType->getNumElements(); elemIdx++)
+			{
+				members.push_back(structType->getElementType(elemIdx));
+			}
+			int alignSize = BF_ALIGN(typeEntry->mSize, typeEntry->mAlign);
+			int fillSize = alignSize - typeEntry->mSize;
+			members.push_back(llvm::ArrayType::get(llvm::Type::getInt8Ty(*mLLVMContext), fillSize));
+			alignType->setBody(members, structType->isPacked());
+
+			typeEntry->mAlignLLVMType = alignType;
+			mAlignedTypeToNormalType[alignType] = structType;
+		}
+	}
+
+	if (typeEntry->mAlignLLVMType != NULL)
+		return typeEntry->mAlignLLVMType;
+
+	return typeEntry->mLLVMType;
+}
+
+llvm::Value* BfIRCodeGen::FixGEP(llvm::Value* fromValue, llvm::Value* result)
+{
+	if (auto ptrType = llvm::dyn_cast<llvm::PointerType>(fromValue->getType()))
+	{
+		if (auto arrayType = llvm::dyn_cast<llvm::ArrayType>(ptrType->getElementType()))
+		{
+			llvm::Type* normalType = NULL;
+			if (mAlignedTypeToNormalType.TryGetValue(arrayType->getElementType(), &normalType))
+			{
+				return mIRBuilder->CreateBitCast(result, normalType->getPointerTo());
+			}
+		}
+	}
+
+	return result;
+}
+
 void BfIRCodeGen::CreateMemSet(llvm::Value* addr, llvm::Value* val, llvm::Value* size, int alignment, bool isVolatile)
 {
 	auto sizeConst = llvm::dyn_cast<llvm::ConstantInt>(size);
@@ -1604,15 +1688,26 @@ void BfIRCodeGen::HandleNextCmd()
 			SetResult(curId, llvm::StructType::create(*mLLVMContext, typeName.c_str()));
 		}
 		break;	
-	case BfIRCmd_StructSetBody:
+	case BfIRCmd_StructSetBody:		
 		{
-			CMD_PARAM(llvm::Type*, type);
+			llvm::Type* type = NULL;
+			BfIRTypeEntry* typeEntry = NULL;
+
+			Read(type, &typeEntry);
 			CMD_PARAM(CmdParamVec<llvm::Type*>, members);
+			CMD_PARAM(int, instSize);
+			CMD_PARAM(int, instAlign);
 			CMD_PARAM(bool, isPacked);
+			
 			BF_ASSERT(llvm::isa<llvm::StructType>(type));
 			auto structType = (llvm::StructType*)type;
 			if (structType->isOpaque())
 				structType->setBody(members, isPacked);
+			if (typeEntry != NULL)
+			{
+				typeEntry->mSize = instSize;
+				typeEntry->mAlign = instAlign;
+			}
 		}
 		break;
 	case  BfIRCmd_Type:
@@ -1655,9 +1750,15 @@ void BfIRCodeGen::HandleNextCmd()
 		break;
 	case BfIRCmd_GetSizedArrayType:
 		{
-			CMD_PARAM(llvm::Type*, elementType);
+			llvm::Type* elementType = NULL;
+			BfIRTypeEntry* elementTypeEntry = NULL;
+
+			Read(elementType, &elementTypeEntry);
 			CMD_PARAM(int, length);
-			SetResult(curId, llvm::ArrayType::get(elementType, length));
+			if (elementTypeEntry != NULL)
+				SetResult(curId, llvm::ArrayType::get(GetSizeAlignedType(elementTypeEntry), length));
+			else
+				SetResult(curId, llvm::ArrayType::get(elementType, length));
 		}
 		break;	
 	case BfIRCmd_GetVectorType:
@@ -2056,7 +2157,7 @@ void BfIRCodeGen::HandleNextCmd()
 			CMD_PARAM(llvm::Value*, val);
 			CMD_PARAM(int, idx0);
 			CMD_PARAM(int, idx1);
-			SetResult(curId, mIRBuilder->CreateConstInBoundsGEP2_32(NULL, val, idx0, idx1));
+			SetResult(curId, FixGEP(val, mIRBuilder->CreateConstInBoundsGEP2_32(NULL, val, idx0, idx1)));
 		}
 		break;
 	case BfIRCmd_InBoundsGEP1:
@@ -2072,7 +2173,7 @@ void BfIRCodeGen::HandleNextCmd()
 			CMD_PARAM(llvm::Value*, idx0);
 			CMD_PARAM(llvm::Value*, idx1);
 			llvm::Value* indices[2] = { idx0, idx1 };			
-			SetResult(curId, mIRBuilder->CreateInBoundsGEP(val, llvm::makeArrayRef(indices)));
+			SetResult(curId, FixGEP(val, mIRBuilder->CreateInBoundsGEP(val, llvm::makeArrayRef(indices))));
 		}
 		break;
 	case BfIRCmd_IsNull:

+ 34 - 3
IDEHelper/Compiler/BfIRCodeGen.h

@@ -60,18 +60,24 @@ class BfIRTypeEntry
 {
 public:
 	int mTypeId;
+	int mSize;
+	int mAlign;
 	llvm::DIType* mDIType;
 	llvm::DIType* mInstDIType;
 	llvm::Type* mLLVMType;
+	llvm::Type* mAlignLLVMType;
 	llvm::Type* mInstLLVMType;	
 
 public:
 	BfIRTypeEntry()
 	{
 		mTypeId = -1;
+		mSize = -1;
+		mAlign = -1;
 		mDIType = NULL;
 		mInstDIType = NULL;
 		mLLVMType = NULL;
+		mAlignLLVMType = NULL;
 		mInstLLVMType = NULL;
 	}
 };
@@ -109,6 +115,7 @@ public:
 	Array<llvm::Constant*> mConfigConsts32;
 	Array<llvm::Constant*> mConfigConsts64;
 	Dictionary<llvm::Type*, llvm::Value*> mReflectDataMap;
+	Dictionary<llvm::Type*, llvm::Type*> mAlignedTypeToNormalType;
 
 public:		
 	void InitTarget();
@@ -127,6 +134,8 @@ public:
 	llvm::Type* GetElemType(llvm::Value* value);
 	bool TryMemCpy(llvm::Value* ptr, llvm::Value* val);	
 	bool TryVectorCpy(llvm::Value* ptr, llvm::Value* val);
+	llvm::Type* GetSizeAlignedType(BfIRTypeEntry* typeEntry);
+	llvm::Value* FixGEP(llvm::Value* fromValue, llvm::Value* result);
 
 public:
 	BfIRCodeGen();
@@ -146,10 +155,10 @@ public:
 	void Read(Val128& i);
 	void Read(bool& val);
 	void Read(BfIRTypeEntry*& type);
-	void Read(llvm::Type*& llvmType);
+	void Read(llvm::Type*& llvmType, BfIRTypeEntry** outTypeEntry = NULL);
 	void Read(llvm::FunctionType*& llvmType);
-	void Read(llvm::Value*& llvmValue, BfIRCodeGenEntry** codeGenEntry = NULL);
-	void Read(llvm::Constant*& llvmConstant);
+	void Read(llvm::Value*& llvmValue, BfIRCodeGenEntry** codeGenEntry = NULL, bool wantSizeAligned = false);
+	void Read(llvm::Constant*& llvmConstant, bool wantSizeAligned = false);
 	void Read(llvm::Function*& llvmFunc);
 	void Read(llvm::BasicBlock*& llvmBlock);
 	void Read(llvm::MDNode*& llvmMD);
@@ -167,6 +176,28 @@ public:
 		}
 	}
 
+	void Read(llvm::SmallVectorImpl<llvm::Value*>& vec, bool wantSizeAligned = false)
+	{
+		int len = (int)ReadSLEB128();
+		for (int i = 0; i < len; i++)
+		{
+			llvm::Value* result;
+			Read(result, NULL, wantSizeAligned);
+			vec.push_back(result);
+		}
+	}
+
+	void Read(llvm::SmallVectorImpl<llvm::Constant*>& vec, bool wantSizeAligned = false)
+	{
+		int len = (int)ReadSLEB128();
+		for (int i = 0; i < len; i++)
+		{
+			llvm::Constant* result;
+			Read(result, wantSizeAligned);
+			vec.push_back(result);
+		}
+	}
+
 	void HandleNextCmd() override;
 	void SetCodeGenOptions(BfCodeGenOptions codeGenOptions);
 	void SetConfigConst(int idx, int value) override;

+ 56 - 33
IDEHelper/Compiler/BfModule.cpp

@@ -4203,12 +4203,12 @@ BfTypedValue BfModule::GetFieldInitializerValue(BfFieldInstance* fieldInstance,
 			if (mCompiler->mCEMachine != NULL)
 				ceExecuteId = mCompiler->mCEMachine->mExecuteId;
 
-			BfTypeState typeState;
+			BfTypeState typeState;			
 			typeState.mTypeInstance = mCurTypeInstance;
 			typeState.mCurTypeDef = fieldDef->mDeclaringType;
 			typeState.mCurFieldDef = fieldDef;
 			SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
-
+			
 			BfConstResolver constResolver(this);
 			if (fieldType->IsVar())
 				return constResolver.Resolve(initializer);
@@ -4224,7 +4224,7 @@ BfTypedValue BfModule::GetFieldInitializerValue(BfFieldInstance* fieldInstance,
 				}
 				UpdateSrcPos(initializer);
 				auto result = constResolver.Resolve(initializer, fieldType, resolveFlags);
-				if (mCompiler->mCEMachine != NULL)
+				if ((mCompiler->mCEMachine != NULL) && (fieldInstance != NULL))
 				{
 					if (mCompiler->mCEMachine->mExecuteId != ceExecuteId)
 						fieldInstance->mHadConstEval = true;
@@ -4588,19 +4588,21 @@ void BfModule::CreateValueTypeEqualsMethod(bool strictEquals)
 		auto _SizedIndex = [&](BfIRValue target, BfIRValue index)
 		{
 			BfTypedValue result;
-			if (sizedArrayType->mElementType->IsSizeAligned())
-			{
-				auto ptrType = CreatePointerType(sizedArrayType->mElementType);
-				auto ptrValue = mBfIRBuilder->CreateBitCast(target, mBfIRBuilder->MapType(ptrType));
-				auto gepResult = mBfIRBuilder->CreateInBoundsGEP(ptrValue, index);
-				result = BfTypedValue(gepResult, sizedArrayType->mElementType, BfTypedValueKind_Addr);
-			}
-			else
-			{
+// 			if (sizedArrayType->mElementType->IsSizeAligned())
+// 			{
+// 				auto ptrType = CreatePointerType(sizedArrayType->mElementType);
+// 				auto ptrValue = mBfIRBuilder->CreateBitCast(target, mBfIRBuilder->MapType(ptrType));
+// 				auto gepResult = mBfIRBuilder->CreateInBoundsGEP(ptrValue, index);
+// 				result = BfTypedValue(gepResult, sizedArrayType->mElementType, BfTypedValueKind_Addr);
+// 			}
+// 			else
+// 			{
+// 				auto indexResult = CreateIndexedValue(sizedArrayType->mElementType, target, index);
+// 				result = BfTypedValue(indexResult, sizedArrayType->mElementType, BfTypedValueKind_Addr);
+// 			}
 
-				auto indexResult = CreateIndexedValue(sizedArrayType->mElementType, target, index);
-				result = BfTypedValue(indexResult, sizedArrayType->mElementType, BfTypedValueKind_Addr);
-			}
+			auto indexResult = CreateIndexedValue(sizedArrayType->mElementType, target, index, true);
+			result = BfTypedValue(indexResult, sizedArrayType->mElementType, BfTypedValueKind_Addr);
 
 			if (!result.mType->IsValueType())
 				result = LoadValue(result);
@@ -10732,6 +10734,12 @@ BfIRValue BfModule::ConstantToCurrent(BfConstant* constant, BfIRConstHolder* con
 					newVals[fieldInstance.mDataIdx] = memberVal;
 				}
 			}
+
+			for (auto& val : newVals)
+			{
+				if (!val)
+					val = mBfIRBuilder->CreateConstArrayZero(0);
+			}
 		}
 
 		return mBfIRBuilder->CreateConstAgg(mBfIRBuilder->MapType(wantType, BfIRPopulateType_Identity), newVals);
@@ -12034,21 +12042,26 @@ BfIRValue BfModule::ExtractValue(BfTypedValue typedValue, int dataIdx)
 
 BfIRValue BfModule::CreateIndexedValue(BfType* elementType, BfIRValue value, BfIRValue indexValue, bool isElementIndex)
 {
-	if (elementType->IsSizeAligned())
-	{
-		if (isElementIndex)
-			return mBfIRBuilder->CreateInBoundsGEP(value, GetConstValue(0), indexValue);
-		else
-			return mBfIRBuilder->CreateInBoundsGEP(value, indexValue);
-	}
-	
-	auto ptrType = CreatePointerType(elementType);
-	auto ofsVal = mBfIRBuilder->CreateNumericCast(indexValue, true, BfTypeCode_IntPtr);
-	auto ofsScaledVal = mBfIRBuilder->CreateMul(ofsVal, mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, elementType->GetStride()));
-	auto i8PtrType = mBfIRBuilder->GetPointerTo(mBfIRBuilder->GetPrimitiveType(BfTypeCode_Int8));
-	BfIRValue origPtrValue = mBfIRBuilder->CreateBitCast(value, i8PtrType);
-	BfIRValue newPtrValue = mBfIRBuilder->CreateInBoundsGEP(origPtrValue, ofsScaledVal);
-	return mBfIRBuilder->CreateBitCast(newPtrValue, mBfIRBuilder->MapType(ptrType));
+	if (isElementIndex)
+		return mBfIRBuilder->CreateInBoundsGEP(value, GetConstValue(0), indexValue);
+	else
+		return mBfIRBuilder->CreateInBoundsGEP(value, indexValue);
+
+// 	if (elementType->IsSizeAligned())
+// 	{
+// 		if (isElementIndex)
+// 			return mBfIRBuilder->CreateInBoundsGEP(value, GetConstValue(0), indexValue);
+// 		else
+// 			return mBfIRBuilder->CreateInBoundsGEP(value, indexValue);
+// 	}
+// 	
+// 	auto ptrType = CreatePointerType(elementType);
+// 	auto ofsVal = mBfIRBuilder->CreateNumericCast(indexValue, true, BfTypeCode_IntPtr);
+// 	auto ofsScaledVal = mBfIRBuilder->CreateMul(ofsVal, mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, elementType->GetStride()));
+// 	auto i8PtrType = mBfIRBuilder->GetPointerTo(mBfIRBuilder->GetPrimitiveType(BfTypeCode_Int8));
+// 	BfIRValue origPtrValue = mBfIRBuilder->CreateBitCast(value, i8PtrType);
+// 	BfIRValue newPtrValue = mBfIRBuilder->CreateInBoundsGEP(origPtrValue, ofsScaledVal);
+// 	return mBfIRBuilder->CreateBitCast(newPtrValue, mBfIRBuilder->MapType(ptrType));
 }
 
 BfIRValue BfModule::CreateIndexedValue(BfType* elementType, BfIRValue value, int indexValue, bool isElementIndex)
@@ -13345,6 +13358,14 @@ void BfModule::SetupMethodIdHash(BfMethodInstance* methodInstance)
 	methodInstance->mIdHash = (int64)hashCtx.Finish64();
 }
 
+bool BfModule::CheckUseMethodInstance(BfMethodInstance* methodInstance, BfAstNode* refNode)
+{
+	if (methodInstance->mHasBeenDeclared)
+		return true;
+	Fail(StrFormat("Circular reference in method instance '%s'", MethodToString(methodInstance).c_str()), refNode);
+	return false;
+}
+
 BfIRValue BfModule::GetInterfaceSlotNum(BfTypeInstance* ifaceType)
 {
 	BfIRValue globalValue;
@@ -21220,6 +21241,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
 	if (mCurMethodInstance->mMethodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_NoDecl_AwaitingReference)
 		mCurMethodInstance->mMethodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_Decl_AwaitingReference;
 
+	defer({ mCurMethodInstance->mHasBeenDeclared = true; });
 
 	// If we are doing this then we may end up creating methods when var types are unknown still, failing on splat/zero-sized info
 	BF_ASSERT((!mCurTypeInstance->mResolvingVarField) || (mBfIRBuilder->mIgnoreWrites));
@@ -21246,7 +21268,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
 		StackOverflow();
 
 	if (typeInstance->IsClosure())
-	{
+	{		
 		if (methodDef->mName == "Invoke")
 			return;
 	}
@@ -22511,7 +22533,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
 	}
 
 	mCompiler->mStats.mMethodDeclarations++;
-	mCompiler->UpdateCompletion();
+	mCompiler->UpdateCompletion();	
 }
 
 void BfModule::UniqueSlotVirtualMethod(BfMethodInstance* methodInstance)
@@ -23430,7 +23452,8 @@ void BfModule::DbgFinish()
 			{
 				if ((methodInstGroup.IsImplemented()) && (methodInstGroup.mDefault != NULL) && 					
 					(!methodInstGroup.mDefault->mMethodDef->mIsStatic) && (methodInstGroup.mDefault->mIsReified) && (!methodInstGroup.mDefault->mAlwaysInline) &&
-					((methodInstGroup.mOnDemandKind == BfMethodOnDemandKind_AlwaysInclude) || (methodInstGroup.mOnDemandKind == BfMethodOnDemandKind_Referenced)))
+					((methodInstGroup.mOnDemandKind == BfMethodOnDemandKind_AlwaysInclude) || (methodInstGroup.mOnDemandKind == BfMethodOnDemandKind_Referenced)) &&
+					(methodInstGroup.mHasEmittedReference))
 				{
 					hasConfirmedReference = true;
 				}

+ 3 - 1
IDEHelper/Compiler/BfModule.h

@@ -76,7 +76,8 @@ enum BfEvalExprFlags
 	BfEvalExprFlags_DisallowComptime = 0x100000,
 	BfEvalExprFlags_InCascade = 0x200000,
 	BfEvalExprFlags_InferReturnType = 0x400000,
-	BfEvalExprFlags_WasMethodRef = 0x800000
+	BfEvalExprFlags_WasMethodRef = 0x800000,
+	BfEvalExprFlags_DeclType = 0x1000000,
 };
 
 enum BfCastFlags
@@ -1918,6 +1919,7 @@ public:
 	BfModuleMethodInstance GetMethodInstance(BfMethodInstance* methodInstance, BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_None);
 	BfMethodInstance* GetOuterMethodInstance(BfMethodInstance* methodInstance); // Only useful for local methods
 	void SetupMethodIdHash(BfMethodInstance* methodInstance);
+	bool CheckUseMethodInstance(BfMethodInstance* methodInstance, BfAstNode* refNode);
 
 	// Type Data
 	BfIRValue CreateClassVDataGlobal(BfTypeInstance* typeInstance, int* outNumElements = NULL, String* outMangledName = NULL);

+ 1 - 1
IDEHelper/Compiler/BfModuleTypeUtils.cpp

@@ -1216,7 +1216,7 @@ void BfModule::PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType
 		}
 		if (arrayType->mElementCount > 0)
 		{
-			arrayType->mSize = (arrayType->mElementType->GetStride() * ((int)arrayType->mElementCount - 1)) + arrayType->mElementType->mSize;
+		 	arrayType->mSize = (int)(arrayType->mElementType->GetStride() * arrayType->mElementCount);
 			arrayType->mAlign = std::max((int32)arrayType->mElementType->mAlign, 1);
 		}
 		else if (arrayType->mElementCount < 0)

+ 1 - 1
IDEHelper/Compiler/BfResolvedTypeUtils.cpp

@@ -3440,7 +3440,7 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash
 					}
 					else
 					{
-						result = ctx->mModule->CreateValueFromExpression(exprModTypeRef->mTarget);
+						result = ctx->mModule->CreateValueFromExpression(exprModTypeRef->mTarget, NULL, BfEvalExprFlags_DeclType);
 					}
 				}
 								

+ 5 - 1
IDEHelper/Compiler/BfResolvedTypeUtils.h

@@ -817,7 +817,8 @@ public:
 	bool mIsUnspecialized:1;
 	bool mIsUnspecializedVariation:1;
 	bool mIsReified:1;
-	bool mHasBeenProcessed:1;	
+	bool mHasBeenDeclared:1;
+	bool mHasBeenProcessed:1;
 	bool mHasFailed:1;
 	bool mFailedConstraints:1;
 	bool mMangleWithIdx:1;
@@ -856,6 +857,7 @@ public:
 		mIsUnspecialized = false;		
 		mIsUnspecializedVariation = false;
 		mIsReified = true;
+		mHasBeenDeclared = false;
 		mHasBeenProcessed = false;
 		mHasFailed = false;
 		mFailedConstraints = false;
@@ -1256,6 +1258,7 @@ public:
 	int mRefCount; // External references from BfMethodRefType
 	BfMethodOnDemandKind mOnDemandKind;
 	bool mExplicitlyReflected;
+	bool mHasEmittedReference;
 
 public:
 	BfMethodInstanceGroup()
@@ -1267,6 +1270,7 @@ public:
 		mOnDemandKind = BfMethodOnDemandKind_NotSet;
 		mRefCount = 0;
 		mExplicitlyReflected = false;
+		mHasEmittedReference = false;
 	}
 
 	~BfMethodInstanceGroup();	

+ 4 - 6
IDEHelper/Compiler/BfStmtEvaluator.cpp

@@ -238,7 +238,7 @@ bool BfModule::AddDeferredCallEntry(BfDeferredCallEntry* deferredCallEntry, BfSc
 		instSize = dataPos;
 
 		deferIRType = mBfIRBuilder->CreateStructType(typeName);
-		mBfIRBuilder->StructSetBody(deferIRType, llvmTypes, false);
+		mBfIRBuilder->StructSetBody(deferIRType, llvmTypes, instSize, instAlign, false);
 		
 		auto prevInsertPoint = mBfIRBuilder->GetInsertBlock();
 		if (!isLooped)
@@ -356,7 +356,7 @@ bool BfModule::AddDeferredCallEntry(BfDeferredCallEntry* deferredCallEntry, BfSc
 			deferredMethodCallData->mAlign = instAlign;
 			deferredMethodCallData->mSize = instSize;
 			deferredMethodCallData->mDeferType = mBfIRBuilder->CreateStructType(typeName);
-			mBfIRBuilder->StructSetBody(deferredMethodCallData->mDeferType, llvmTypes, false);
+			mBfIRBuilder->StructSetBody(deferredMethodCallData->mDeferType, llvmTypes, instSize, instAlign, false);
 			deferredMethodCallData->mDeferTypePtr = mBfIRBuilder->GetPointerTo(deferredMethodCallData->mDeferType);
 		}
 
@@ -6572,10 +6572,8 @@ void BfModule::Visit(BfForEachStatement* forEachStmt)
 		}
 		else
 		{
-			BfIRValue ptrValue = mBfIRBuilder->CreateBitCast(target.mValue, mBfIRBuilder->MapType(ptrType));			
-			arrayItem = BfTypedValue(CreateIndexedValue(arrayType->mElementType, ptrValue, itrVal), arrayType->mElementType, true);
-			if (isRefExpression)
-				arrayItem = BfTypedValue(arrayItem.mValue, CreateRefType(arrayItem.mType));
+			target = MakeAddressable(target);
+			arrayItem = BfTypedValue(CreateIndexedValue(arrayType->mElementType, target.mValue, itrVal, true), arrayType->mElementType, true);
 		}
 		arrayItem = Cast(forEachStmt->mCollectionExpression, arrayItem, varType, BfCastFlags_Explicit);
 		if ((arrayItem) && (!arrayItem.mValue.IsFake()))

+ 80 - 32
IDEHelper/Compiler/CeMachine.cpp

@@ -978,7 +978,7 @@ CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca, bool allowImme
  				BF_ASSERT(ptrType->mElementType->mTypeCode == BeTypeCode_SizedArray);
  				auto arrayType = (BeSizedArrayType*)ptrType->mElementType;
  				elementType = arrayType->mElementType;
- 				byteOffset = gepConstant->mIdx1 * elementType->mSize;
+ 				byteOffset = gepConstant->mIdx1 * elementType->GetStride();
  			}
  
  			auto elementPtrType = mCeMachine->GetBeContext()->GetPointerTo(elementType);
@@ -987,13 +987,7 @@ CeOperand CeBuilder::GetOperand(BeValue* value, bool allowAlloca, bool allowImme
 			EmitFrameOffset(result);
 			EmitFrameOffset(mcVal);
 			Emit(&byteOffset, mPtrSize);
- 			
-// 			result = AllocRelativeVirtualReg(elementPtrType, result, GetImmediate(byteOffset), 1);
-//  			// The def is primary to create a single 'master location' for the GEP vreg to become legalized before use			
-//  			auto vregInfo = GetVRegInfo(result);
-//  			vregInfo->mDefOnFirstUse = true;
-//  			result.mKind = CeOperandKind_VReg;
- 
+
  			return result;
 		}
 		break;
@@ -1843,9 +1837,12 @@ void CeBuilder::Build()
 					if (castedInst->mRetValue != NULL)
 					{
 						auto mcVal = GetOperand(castedInst->mRetValue);
-						BF_ASSERT(mReturnVal.mKind == CeOperandKind_AllocaAddr);
-						EmitSizedOp(CeOp_Move_8, mcVal, NULL, true);
-						Emit((int32)mReturnVal.mFrameOfs);						
+						if (mcVal.mType->mSize > 0)
+						{
+							BF_ASSERT(mReturnVal.mKind == CeOperandKind_AllocaAddr);
+							EmitSizedOp(CeOp_Move_8, mcVal, NULL, true);
+							Emit((int32)mReturnVal.mFrameOfs);
+						}
 					}
 
 					if (instType == BeRetInst::TypeId)
@@ -1974,7 +1971,7 @@ void CeBuilder::Build()
 										Emit((CeOp)(CeOp_AddConst_I32));
 										EmitFrameOffset(result);
 										EmitFrameOffset(ceVal);
-										Emit((int32)(ceIdx1.mImmediate * arrayType->mElementType->mSize));
+										Emit((int32)(ceIdx1.mImmediate * arrayType->mElementType->GetStride()));
 									}
 								}
 								else
@@ -2012,7 +2009,7 @@ void CeBuilder::Build()
 										auto mcElementSize = FrameAlloc(mIntPtrType);
 										Emit(CeOp_Const_32);
 										EmitFrameOffset(mcElementSize);
-										Emit((int32)arrayType->mElementType->mSize);
+										Emit((int32)arrayType->mElementType->GetStride());
 
 										auto ofsValue = FrameAlloc(mIntPtrType);
 										Emit(CeOp_Mul_I32);
@@ -2030,7 +2027,7 @@ void CeBuilder::Build()
 										auto mcElementSize = FrameAlloc(mIntPtrType);
 										Emit(CeOp_Const_64);
 										EmitFrameOffset(mcElementSize);
-										Emit((int64)arrayType->mElementType->mSize);
+										Emit((int64)arrayType->mElementType->GetStride());
 
 										auto ofsValue = FrameAlloc(mIntPtrType);
 										Emit(CeOp_Mul_I64);
@@ -2064,13 +2061,13 @@ void CeBuilder::Build()
 							{
 								auto arrayType = (BeSizedArrayType*)ptrType->mElementType;
 								elementType = arrayType->mElementType;
-								byteOffset = ceIdx1.mImmediate * elementType->mSize;
+								byteOffset = ceIdx1.mImmediate * elementType->GetStride();
 							}
 							else if (ptrType->mElementType->mTypeCode == BeTypeCode_Vector)
 							{
 								auto arrayType = (BeVectorType*)ptrType->mElementType;
 								elementType = arrayType->mElementType;
-								byteOffset = ceIdx1.mImmediate * elementType->mSize;
+								byteOffset = ceIdx1.mImmediate * elementType->GetStride();
 							}
 							else
 							{
@@ -2099,7 +2096,7 @@ void CeBuilder::Build()
  						int relScale = 1;
  						if (ceIdx0.IsImmediate())
 						{
-							int byteOffset = ceIdx0.mImmediate * ptrType->mElementType->mSize;
+							int byteOffset = ceIdx0.mImmediate * ptrType->mElementType->GetStride();
 							if (byteOffset != 0)
 							{
 								result = FrameAlloc(ptrType);
@@ -2117,7 +2114,7 @@ void CeBuilder::Build()
 								auto mcElementSize = FrameAlloc(mIntPtrType);
 								Emit(CeOp_Const_32);
 								EmitFrameOffset(mcElementSize);
-								Emit((int32)ptrType->mElementType->mSize);
+								Emit((int32)ptrType->mElementType->GetStride());
 
 								auto ofsValue = FrameAlloc(mIntPtrType);
 								Emit(CeOp_Mul_I32);
@@ -2135,7 +2132,7 @@ void CeBuilder::Build()
 								auto mcElementSize = FrameAlloc(mIntPtrType);
 								Emit(CeOp_Const_64);
 								EmitFrameOffset(mcElementSize);
-								Emit((int64)ptrType->mElementType->mSize);
+								Emit((int64)ptrType->mElementType->GetStride());
 
 								auto ofsValue = FrameAlloc(mIntPtrType);
 								Emit(CeOp_Mul_I64);
@@ -2232,7 +2229,7 @@ void CeBuilder::Build()
 					{
 						auto sizedArray = (BeSizedArrayType*)aggType;
 						memberType = sizedArray->mElementType;
-						byteOffset = BF_ALIGN(memberType->mSize, memberType->mAlign) * castedInst->mIdx;
+						byteOffset = memberType->GetStride() * castedInst->mIdx;
 					}
 					else
 					{
@@ -3348,6 +3345,7 @@ BfIRValue CeContext::CreateConstant(BfModule* module, uint8* ptr, BfType* bfType
 {
 	auto ceModule = mCeMachine->mCeModule;
 	BfIRBuilder* irBuilder = module->mBfIRBuilder;
+	int32 ptrSize = module->mSystem->mPtrSize;
 
 	uint8* memStart = mMemory.mVals;
 	int memSize = mMemory.mSize;
@@ -3443,6 +3441,33 @@ BfIRValue CeContext::CreateConstant(BfModule* module, uint8* ptr, BfType* bfType
 			CE_CREATECONST_CHECKPTR(charPtr, lenVal);
 			String str(charPtr, lenVal);
 			return module->GetStringObjectValue(str);
+			
+		}
+
+		if (typeInst->IsInstanceOf(mCeMachine->mCompiler->mStringViewTypeDef))
+		{
+			char* charPtr = (char*)memStart + *(addr_ce*)(ptr);
+			int32 lenVal = *(int32*)(ptr + ptrSize);
+
+			CE_CREATECONST_CHECKPTR(charPtr, lenVal);
+			String str(charPtr, lenVal);
+
+			auto stringViewType = ceModule->ResolveTypeDef(mCeMachine->mCompiler->mStringViewTypeDef, BfPopulateType_Data)->ToTypeInstance();
+			auto spanType = stringViewType->mBaseType;
+			auto valueTypeType = spanType->mBaseType;
+
+			SizedArray<BfIRValue, 1> valueTypeValues;
+			BfIRValue valueTypeVal = irBuilder->CreateConstAgg(irBuilder->MapType(valueTypeType, BfIRPopulateType_Full), valueTypeValues);
+
+			SizedArray<BfIRValue, 3> spanValues;
+			spanValues.Add(valueTypeVal);
+			spanValues.Add(module->GetStringCharPtr(str));
+			spanValues.Add(irBuilder->CreateConst(BfTypeCode_IntPtr, lenVal));
+			BfIRValue spanVal = irBuilder->CreateConstAgg(irBuilder->MapType(spanType, BfIRPopulateType_Full), spanValues);
+
+			SizedArray<BfIRValue, 1> stringViewValues;
+			stringViewValues.Add(spanVal);
+			return irBuilder->CreateConstAgg(irBuilder->MapType(stringViewType, BfIRPopulateType_Full), stringViewValues);
 		}
 
 		SizedArray<BfIRValue, 8> fieldVals;
@@ -3499,13 +3524,7 @@ BfIRValue CeContext::CreateConstant(BfModule* module, uint8* ptr, BfType* bfType
 			Fail(StrFormat("Reference type '%s' return value not allowed", module->TypeToString(typeInst).c_str()));
 			return BfIRValue();
 		}
-
-		if (typeInst->IsPointer())
-		{
-			Fail(StrFormat("Pointer type '%s' return value not allowed", module->TypeToString(typeInst).c_str()));
-			return BfIRValue();
-		}
-
+		
 		if (typeInst->mBaseType != NULL)
 		{
 			auto result = CreateConstant(module, instData, typeInst->mBaseType);
@@ -3513,7 +3532,7 @@ BfIRValue CeContext::CreateConstant(BfModule* module, uint8* ptr, BfType* bfType
 				return BfIRValue();
 			fieldVals.Add(result);
 		}
-
+		
 		for (int fieldIdx = 0; fieldIdx < typeInst->mFieldInstances.size(); fieldIdx++)
 		{
 			auto& fieldInstance = typeInst->mFieldInstances[fieldIdx];
@@ -3526,7 +3545,7 @@ BfIRValue CeContext::CreateConstant(BfModule* module, uint8* ptr, BfType* bfType
 				if (fieldInstance.mResolvedType->IsInteger())
 					fieldVals.Add(irBuilder->CreatePtrToInt(vdataPtr, ((BfPrimitiveType*)fieldInstance.mResolvedType)->mTypeDef->mTypeCode));
 				else
-					fieldVals.Add(vdataPtr);
+					fieldVals.Add(vdataPtr);				
 				continue;
 			}
 
@@ -3535,19 +3554,48 @@ BfIRValue CeContext::CreateConstant(BfModule* module, uint8* ptr, BfType* bfType
 				return BfIRValue();
 
 			if (fieldInstance.mDataIdx == fieldVals.mSize)
-				fieldVals.Add(result);
+			{
+				fieldVals.Add(result);				
+			}
 			else
 			{
 				while (fieldInstance.mDataIdx >= fieldVals.mSize)
 					fieldVals.Add(BfIRValue());
-				fieldVals[fieldInstance.mDataIdx] = result;
+				fieldVals[fieldInstance.mDataIdx] = result;				
 			}
 		}
+				
+		for (auto& fieldVal : fieldVals)
+		{
+			if (!fieldVal)
+				fieldVal = irBuilder->CreateConstArrayZero(0);
+		}
 
 		auto instResult = irBuilder->CreateConstAgg(irBuilder->MapTypeInst(typeInst, BfIRPopulateType_Full), fieldVals);
 		return instResult;
 	}
 
+	if (bfType->IsPointer())
+	{
+		Fail(StrFormat("Pointer type '%s' return value not allowed", module->TypeToString(bfType).c_str()));
+		return BfIRValue();
+	}
+
+	if ((bfType->IsSizedArray()) && (!bfType->IsUnknownSizedArrayType()))
+	{
+		SizedArray<BfIRValue, 8> values;
+		auto sizedArrayType = (BfSizedArrayType*)bfType;
+		for (int i = 0; i < sizedArrayType->mElementCount; i++)
+		{
+			auto elemValue = CreateConstant(module, ptr + i * sizedArrayType->mElementType->GetStride(), sizedArrayType->mElementType);
+			if (!elemValue)
+				return BfIRValue();
+			values.Add(elemValue);
+		}		
+
+		return irBuilder->CreateConstAgg(irBuilder->MapType(sizedArrayType, BfIRPopulateType_Full), values);
+	}
+
 	return BfIRValue();
 }
 
@@ -6085,7 +6133,7 @@ CeErrorKind CeMachine::WriteConstant(CeConstStructData& data, BeConstant* constV
 			else if (globalVar->mType->mTypeCode == BeTypeCode_SizedArray)
 			{
 				auto arrayType = (BeSizedArrayType*)globalVar->mType;
-				dataOfs = arrayType->mElementType->mSize * constGep->mIdx1;
+				dataOfs = arrayType->mElementType->GetStride() * constGep->mIdx1;
 			}
 			else
 			{