Explorar el Código

Reworked static append fields

Brian Fiete hace 8 meses
padre
commit
ec34aa3d43

+ 1 - 1
IDEHelper/Compiler/BfExprEvaluator.cpp

@@ -5310,7 +5310,7 @@ BfTypedValue BfExprEvaluator::LoadField(BfAstNode* targetSrc, BfTypedValue targe
 			(mModule->mCurMethodInstance->mMethodDef->IsCtorOrInit()) &&
 			(mModule->mCurMethodInstance->mMethodDef->IsCtorOrInit()) &&
 			(mModule->mCurMethodInstance->mMethodDef->mIsStatic);
 			(mModule->mCurMethodInstance->mMethodDef->mIsStatic);
 
 
-		if ((mModule->mCompiler->mOptions.mRuntimeChecks) && (fieldInstance->IsAppendedObject()) && (!mModule->mBfIRBuilder->mIgnoreWrites) &&
+		if ((mModule->mCompiler->mOptions.mRuntimeChecks) && (fieldInstance->IsAppendedObject()) && (!fieldDef->mIsStatic) && (!mModule->mBfIRBuilder->mIgnoreWrites) &&
 			(!mModule->IsSkippingExtraResolveChecks()))
 			(!mModule->IsSkippingExtraResolveChecks()))
 		{
 		{
 			auto intType = mModule->GetPrimitiveType(BfTypeCode_IntPtr);
 			auto intType = mModule->GetPrimitiveType(BfTypeCode_IntPtr);

+ 1 - 1
IDEHelper/Compiler/BfIRBuilder.cpp

@@ -3287,7 +3287,7 @@ void BfIRBuilder::CreateDbgTypeDefinition(BfType* type)
 				PopulateType(resolvedFieldType, BfIRPopulateType_Eventually_Full);
 				PopulateType(resolvedFieldType, BfIRPopulateType_Eventually_Full);
 			resolvedFieldDIType = DbgGetType(resolvedFieldType);
 			resolvedFieldDIType = DbgGetType(resolvedFieldType);
 
 
-			if (fieldInstance->IsAppendedObject())
+			if ((fieldInstance->IsAppendedObject()) && (!fieldDef->mIsStatic))
 				resolvedFieldDIType = DbgGetTypeInst(resolvedFieldType->ToTypeInstance());
 				resolvedFieldDIType = DbgGetTypeInst(resolvedFieldType->ToTypeInstance());
 
 
 			if ((fieldDef == NULL) && (typeInstance->IsPayloadEnum()))
 			if ((fieldDef == NULL) && (typeInstance->IsPayloadEnum()))

+ 122 - 10
IDEHelper/Compiler/BfModule.cpp

@@ -4227,7 +4227,7 @@ void BfModule::CreateStaticField(BfFieldInstance* fieldInstance, bool isThreadLo
 		{
 		{
 			BfIRType irType;
 			BfIRType irType;
 
 
-			if (fieldInstance->IsAppendedObject())
+			if ((fieldInstance->IsAppendedObject()) && (!field->mIsStatic))
 			{
 			{
 				irType = mBfIRBuilder->MapTypeInst(fieldType->ToTypeInstance(), BfIRPopulateType_Eventually_Full);
 				irType = mBfIRBuilder->MapTypeInst(fieldType->ToTypeInstance(), BfIRPopulateType_Eventually_Full);
 				initValue = mBfIRBuilder->CreateConstAggZero(irType);
 				initValue = mBfIRBuilder->CreateConstAggZero(irType);
@@ -4743,6 +4743,99 @@ BfTypedValue BfModule::GetFieldInitializerValue(BfFieldInstance* fieldInstance,
 	return result;
 	return result;
 }
 }
 
 
+bool BfModule::TryGetAppendedObjectInfo(BfFieldInstance* fieldInstance, int& dataSize, int& alignSize)
+{	
+	auto resolvedFieldType = fieldInstance->GetResolvedType();
+	auto fieldDef = fieldInstance->GetFieldDef();
+
+	BfAstNode* nameRefNode = NULL;
+	if (auto fieldDecl = fieldDef->GetFieldDeclaration())
+		nameRefNode = fieldDecl->mNameNode;
+	else if (auto paramDecl = fieldDef->GetParamDeclaration())
+		nameRefNode = paramDecl->mNameNode;
+	if (nameRefNode == NULL)
+		nameRefNode = fieldDef->mTypeRef;
+
+	dataSize = resolvedFieldType->mSize;
+	alignSize = resolvedFieldType->mAlign;
+
+	SetAndRestoreValue<BfFieldDef*> prevTypeRef(mContext->mCurTypeState->mCurFieldDef, fieldDef);
+	SetAndRestoreValue<BfTypeState::ResolveKind> prevResolveKind(mContext->mCurTypeState->mResolveKind, BfTypeState::ResolveKind_FieldType);
+
+	PopulateType(resolvedFieldType, BfPopulateType_Data);
+
+	auto fieldTypeInst = resolvedFieldType->ToTypeInstance();
+	dataSize = BF_MAX(fieldTypeInst->mInstSize, 0);
+	alignSize = BF_MAX(fieldTypeInst->mInstAlign, 1);
+
+	if (fieldTypeInst->mTypeFailed)
+	{
+		TypeFailed(fieldTypeInst);
+		fieldInstance->mResolvedType = GetPrimitiveType(BfTypeCode_Var);
+		return false;
+	}
+
+	if ((fieldTypeInst != NULL) && (fieldTypeInst->mTypeDef->mIsAbstract))
+	{
+		Fail("Cannot create an instance of an abstract class", nameRefNode);
+	}
+
+	SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true);
+	BfMethodState methodState;
+	SetAndRestoreValue<BfMethodState*> prevMethodState(mCurMethodState, &methodState);
+	methodState.mTempKind = BfMethodState::TempKind_NonStatic;
+
+	BfTypedValue appendIndexValue;
+	BfExprEvaluator exprEvaluator(this);
+
+	BfResolvedArgs resolvedArgs;
+
+	auto fieldDecl = fieldDef->GetFieldDeclaration();
+	if (auto invocationExpr = BfNodeDynCast<BfInvocationExpression>(fieldDecl->mInitializer))
+	{
+		resolvedArgs.Init(invocationExpr->mOpenParen, &invocationExpr->mArguments, &invocationExpr->mCommas, invocationExpr->mCloseParen);
+		exprEvaluator.ResolveArgValues(resolvedArgs, BfResolveArgsFlag_DeferParamEval);
+	}
+
+	BfFunctionBindResult bindResult;
+	bindResult.mSkipThis = true;
+	bindResult.mWantsArgs = true;
+	SetAndRestoreValue<BfFunctionBindResult*> prevBindResult(exprEvaluator.mFunctionBindResult, &bindResult);
+
+	BfTypedValue emptyThis(mBfIRBuilder->GetFakeVal(), mCurTypeInstance, mCurTypeInstance->IsStruct());
+
+	exprEvaluator.mBfEvalExprFlags = BfEvalExprFlags_Comptime;
+	auto ctorResult = exprEvaluator.MatchConstructor(nameRefNode, NULL, emptyThis, fieldTypeInst, resolvedArgs, false, BfMethodGenericArguments(), true);
+
+	if ((bindResult.mMethodInstance != NULL) && (bindResult.mMethodInstance->mMethodDef->mHasAppend))
+	{
+		auto calcAppendMethodModule = GetMethodInstanceAtIdx(bindResult.mMethodInstance->GetOwner(), bindResult.mMethodInstance->mMethodDef->mIdx + 1, BF_METHODNAME_CALCAPPEND);
+
+		SizedArray<BfIRValue, 2> irArgs;
+		if (bindResult.mIRArgs.size() > 1)
+			irArgs.Insert(0, &bindResult.mIRArgs[1], bindResult.mIRArgs.size() - 1);
+		BfTypedValue appendSizeTypedValue = TryConstCalcAppend(calcAppendMethodModule.mMethodInstance, irArgs, true);
+		if (appendSizeTypedValue)
+		{
+			int appendAlign = calcAppendMethodModule.mMethodInstance->mAppendAllocAlign;
+			dataSize = BF_ALIGN(dataSize, appendAlign);
+			alignSize = BF_MAX(alignSize, appendAlign);
+
+			auto constant = mBfIRBuilder->GetConstant(appendSizeTypedValue.mValue);
+			if (constant != NULL)
+			{
+				dataSize += constant->mInt32;
+			}
+		}
+		else
+		{
+			Fail(StrFormat("Append constructor '%s' does not result in a constant size", MethodToString(bindResult.mMethodInstance).c_str()), nameRefNode);
+		}
+	}	
+
+	return true;
+}
+
 void BfModule::AppendedObjectInit(BfFieldInstance* fieldInst)
 void BfModule::AppendedObjectInit(BfFieldInstance* fieldInst)
 {
 {
 	BfExprEvaluator exprEvaluator(this);
 	BfExprEvaluator exprEvaluator(this);
@@ -4791,7 +4884,26 @@ void BfModule::AppendedObjectInit(BfFieldInstance* fieldInst)
 	BfIRValue fieldAddr;
 	BfIRValue fieldAddr;
 	if (fieldDef->mIsStatic)
 	if (fieldDef->mIsStatic)
 	{
 	{
-		fieldAddr = ReferenceStaticField(fieldInst).mValue;
+		auto fieldTypedValue = ReferenceStaticField(fieldInst);		
+
+		int dataSize = 1;
+		int alignSize = 1;
+		TryGetAppendedObjectInfo(fieldInst, dataSize, alignSize);
+
+		String dataName;
+		BfMangler::MangleStaticFieldName(dataName, mCompiler->GetMangleKind(), mCurTypeInstance, fieldDef->mName, fieldInst->mResolvedType);
+		dataName += "__DATA";
+
+		auto arrayType = mBfIRBuilder->GetSizedArrayType(mBfIRBuilder->GetPrimitiveType(BfTypeCode_Int8), dataSize);
+		auto globalVar = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->GetSizedArrayType(mBfIRBuilder->GetPrimitiveType(BfTypeCode_Int8), dataSize), false,
+			BfIRLinkageType_Internal, mBfIRBuilder->CreateConstArrayZero(dataSize), dataName);
+		mBfIRBuilder->GlobalVar_SetAlignment(globalVar, alignSize);
+
+		auto castedVal = mBfIRBuilder->CreateBitCast(globalVar, mBfIRBuilder->MapType(fieldInst->mResolvedType));
+		mBfIRBuilder->CreateStore(castedVal, fieldTypedValue.mValue);
+
+		fieldTypedValue = LoadValue(fieldTypedValue);
+		fieldAddr = fieldTypedValue.mValue;
 	}
 	}
 	else
 	else
 		fieldAddr = mBfIRBuilder->CreateInBoundsGEP(mCurMethodState->mLocals[0]->mValue, 0, fieldInst->mDataIdx);
 		fieldAddr = mBfIRBuilder->CreateInBoundsGEP(mCurMethodState->mLocals[0]->mValue, 0, fieldInst->mDataIdx);
@@ -15500,10 +15612,7 @@ BfTypedValue BfModule::ReferenceStaticField(BfFieldInstance* fieldInstance)
 		if ((typeType != NULL) && (!typeType->IsValuelessType()))
 		if ((typeType != NULL) && (!typeType->IsValuelessType()))
 		{
 		{
 			BfIRType irType = mBfIRBuilder->MapType(typeType);
 			BfIRType irType = mBfIRBuilder->MapType(typeType);
-
-			if (fieldInstance->IsAppendedObject())
-				irType = mBfIRBuilder->MapTypeInst(typeType->ToTypeInstance());
-
+			
 			SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, mBfIRBuilder->mIgnoreWrites || staticVarName.StartsWith('#'));
 			SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, mBfIRBuilder->mIgnoreWrites || staticVarName.StartsWith('#'));
 
 
 			globalValue = mBfIRBuilder->CreateGlobalVariable(
 			globalValue = mBfIRBuilder->CreateGlobalVariable(
@@ -15527,7 +15636,7 @@ BfTypedValue BfModule::ReferenceStaticField(BfFieldInstance* fieldInstance)
 
 
 	if (fieldDef->mIsVolatile)
 	if (fieldDef->mIsVolatile)
 		return BfTypedValue(globalValue, type, BfTypedValueKind_VolatileAddr);
 		return BfTypedValue(globalValue, type, BfTypedValueKind_VolatileAddr);
-	return BfTypedValue(globalValue, type, !fieldDef->mIsConst && !fieldInstance->IsAppendedObject());
+	return BfTypedValue(globalValue, type, !fieldDef->mIsConst);
 }
 }
 
 
 BfFieldInstance* BfModule::GetFieldInstance(BfTypeInstance* typeInst, int fieldIdx, const char* fieldName)
 BfFieldInstance* BfModule::GetFieldInstance(BfTypeInstance* typeInst, int fieldIdx, const char* fieldName)
@@ -17697,7 +17806,7 @@ void BfModule::EmitDtorBody()
 					localDef->mName = "_";
 					localDef->mName = "_";
 					localDef->mResolvedType = fieldInst->mResolvedType;
 					localDef->mResolvedType = fieldInst->mResolvedType;
 
 
-					if (fieldInst->IsAppendedObject())
+					if ((fieldInst->IsAppendedObject()) && (!fieldDef->mIsStatic))
 					{
 					{
 						localDef->mValue = mBfIRBuilder->CreateBitCast(value, mBfIRBuilder->MapType(fieldInst->mResolvedType));
 						localDef->mValue = mBfIRBuilder->CreateBitCast(value, mBfIRBuilder->MapType(fieldInst->mResolvedType));
 					}
 					}
@@ -17722,7 +17831,7 @@ void BfModule::EmitDtorBody()
 
 
 					auto defLocalVar = AddLocalVariableDef(localDef, true);
 					auto defLocalVar = AddLocalVariableDef(localDef, true);
 
 
-					if (!fieldInst->IsAppendedObject())
+					if ((!fieldInst->IsAppendedObject()) && (!fieldDef->mIsStatic))
 					{
 					{
 						// Put back so we actually modify the correct value*/
 						// Put back so we actually modify the correct value*/
 						defLocalVar->mResolvedType = fieldInst->mResolvedType;
 						defLocalVar->mResolvedType = fieldInst->mResolvedType;
@@ -17765,7 +17874,10 @@ void BfModule::EmitDtorBody()
 
 
 				BfTypedValue val;
 				BfTypedValue val;
 				if (fieldDef->mIsStatic)
 				if (fieldDef->mIsStatic)
+				{
 					val = ReferenceStaticField(fieldInst);
 					val = ReferenceStaticField(fieldInst);
+					val = LoadValue(val);
+				}
 				else
 				else
 				{
 				{
 					auto fieldAddr = mBfIRBuilder->CreateInBoundsGEP(mCurMethodState->mLocals[0]->mValue, 0, fieldInst->mDataIdx);
 					auto fieldAddr = mBfIRBuilder->CreateInBoundsGEP(mCurMethodState->mLocals[0]->mValue, 0, fieldInst->mDataIdx);
@@ -20357,7 +20469,7 @@ void BfModule::EmitGCMarkMembers()
 
 
 						if (markVal)
 						if (markVal)
 						{
 						{
-							if (fieldInst.IsAppendedObject())
+							if ((fieldInst.IsAppendedObject()) && (!fieldDef->mIsStatic))
 								EmitGCMarkAppended(markVal);
 								EmitGCMarkAppended(markVal);
 							else
 							else
 								EmitGCMarkValue(markVal, markFromGCThreadMethodInstance);
 								EmitGCMarkValue(markVal, markFromGCThreadMethodInstance);

+ 1 - 0
IDEHelper/Compiler/BfModule.h

@@ -1887,6 +1887,7 @@ public:
 	void CreateStaticField(BfFieldInstance* fieldInstance, bool isThreadLocal = false);
 	void CreateStaticField(BfFieldInstance* fieldInstance, bool isThreadLocal = false);
 	void ResolveConstField(BfTypeInstance* typeInst, BfFieldInstance* fieldInstance, BfFieldDef* field, bool forceResolve = false);
 	void ResolveConstField(BfTypeInstance* typeInst, BfFieldInstance* fieldInstance, BfFieldDef* field, bool forceResolve = false);
 	BfTypedValue GetFieldInitializerValue(BfFieldInstance* fieldInstance, BfExpression* initializer = NULL, BfFieldDef* fieldDef = NULL, BfType* fieldType = NULL, bool doStore = false);
 	BfTypedValue GetFieldInitializerValue(BfFieldInstance* fieldInstance, BfExpression* initializer = NULL, BfFieldDef* fieldDef = NULL, BfType* fieldType = NULL, bool doStore = false);
+	bool TryGetAppendedObjectInfo(BfFieldInstance* fieldInstance, int& dataSize, int& alignSize);
 	void AppendedObjectInit(BfFieldInstance* fieldInstance);
 	void AppendedObjectInit(BfFieldInstance* fieldInstance);
 	void MarkFieldInitialized(BfFieldInstance* fieldInstance);
 	void MarkFieldInitialized(BfFieldInstance* fieldInstance);
 	bool IsThreadLocal(BfFieldInstance* fieldInstance);
 	bool IsThreadLocal(BfFieldInstance* fieldInstance);

+ 1 - 73
IDEHelper/Compiler/BfModuleTypeUtils.cpp

@@ -5650,79 +5650,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
 
 
 						if (fieldInstance->IsAppendedObject())
 						if (fieldInstance->IsAppendedObject())
 						{
 						{
-							SetAndRestoreValue<BfFieldDef*> prevTypeRef(mContext->mCurTypeState->mCurFieldDef, fieldDef);
-							SetAndRestoreValue<BfTypeState::ResolveKind> prevResolveKind(mContext->mCurTypeState->mResolveKind, BfTypeState::ResolveKind_FieldType);
-
-							PopulateType(resolvedFieldType, BfPopulateType_Data);
-
-							auto fieldTypeInst = resolvedFieldType->ToTypeInstance();
-							dataSize = BF_MAX(fieldTypeInst->mInstSize, 0);
-							alignSize = BF_MAX(fieldTypeInst->mInstAlign, 1);
-
-							if (fieldTypeInst->mTypeFailed)
-							{
-								TypeFailed(fieldTypeInst);
-								fieldInstance->mResolvedType = GetPrimitiveType(BfTypeCode_Var);
-								continue;
-							}
-
-							if ((typeInstance != NULL) && (fieldTypeInst->mTypeDef->mIsAbstract))
-							{
-								Fail("Cannot create an instance of an abstract class", nameRefNode);
-							}
-
-							SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true);
-							BfMethodState methodState;
-							SetAndRestoreValue<BfMethodState*> prevMethodState(mCurMethodState, &methodState);
-							methodState.mTempKind = BfMethodState::TempKind_NonStatic;
-
-							BfTypedValue appendIndexValue;
-							BfExprEvaluator exprEvaluator(this);
-
-							BfResolvedArgs resolvedArgs;
-
-							auto fieldDecl = fieldDef->GetFieldDeclaration();
-							if (auto invocationExpr = BfNodeDynCast<BfInvocationExpression>(fieldDecl->mInitializer))
-							{
-								resolvedArgs.Init(invocationExpr->mOpenParen, &invocationExpr->mArguments, &invocationExpr->mCommas, invocationExpr->mCloseParen);
-								exprEvaluator.ResolveArgValues(resolvedArgs, BfResolveArgsFlag_DeferParamEval);
-							}
-
-							BfFunctionBindResult bindResult;
-							bindResult.mSkipThis = true;
-							bindResult.mWantsArgs = true;
-							SetAndRestoreValue<BfFunctionBindResult*> prevBindResult(exprEvaluator.mFunctionBindResult, &bindResult);
-
-							BfTypedValue emptyThis(mBfIRBuilder->GetFakeVal(), resolvedTypeRef, resolvedTypeRef->IsStruct());
-
-							exprEvaluator.mBfEvalExprFlags = BfEvalExprFlags_Comptime;
-							auto ctorResult = exprEvaluator.MatchConstructor(nameRefNode, NULL, emptyThis, fieldTypeInst, resolvedArgs, false, BfMethodGenericArguments(), true);
-
-							if ((bindResult.mMethodInstance != NULL) && (bindResult.mMethodInstance->mMethodDef->mHasAppend))
-							{
-								auto calcAppendMethodModule = GetMethodInstanceAtIdx(bindResult.mMethodInstance->GetOwner(), bindResult.mMethodInstance->mMethodDef->mIdx + 1, BF_METHODNAME_CALCAPPEND);
-
-								SizedArray<BfIRValue, 2> irArgs;
-								if (bindResult.mIRArgs.size() > 1)
-									irArgs.Insert(0, &bindResult.mIRArgs[1], bindResult.mIRArgs.size() - 1);
-								BfTypedValue appendSizeTypedValue = TryConstCalcAppend(calcAppendMethodModule.mMethodInstance, irArgs, true);
-								if (appendSizeTypedValue)
-								{
-									int appendAlign = calcAppendMethodModule.mMethodInstance->mAppendAllocAlign;
-									dataSize = BF_ALIGN(dataSize, appendAlign);
-									alignSize = BF_MAX(alignSize, appendAlign);
-
-									auto constant = mBfIRBuilder->GetConstant(appendSizeTypedValue.mValue);
-									if (constant != NULL)
-									{
-										dataSize += constant->mInt32;
-									}
-								}
-								else
-								{
-									Fail(StrFormat("Append constructor '%s' does not result in a constant size", MethodToString(bindResult.mMethodInstance).c_str()), nameRefNode);
-								}
-							}
+							TryGetAppendedObjectInfo(fieldInstance, dataSize, alignSize);
 						}
 						}
 						else if (fieldDef->mIsAppend)
 						else if (fieldDef->mIsAppend)
 						{
 						{

+ 21 - 0
IDEHelper/Tests/src/Append.bf

@@ -83,6 +83,22 @@ namespace Tests
 			public int mC = 234;
 			public int mC = 234;
 		}
 		}
 
 
+		static class ClassG
+		{
+			public static append String sFirst;
+			public static append String sSecond;
+			public static append String sThird;
+
+			static public StringView sValue => Self.sFirst;
+
+			static public void Set(StringView value)
+			{
+				Self.sThird.Set(value);
+				Self.sSecond.Set(value);
+				Self.sFirst.Set(value);
+			}
+		}
+
 		static void CheckData(Object obj, int lastAllocSize, uint8[] data)
 		static void CheckData(Object obj, int lastAllocSize, uint8[] data)
 		{
 		{
 			int objSize = typeof(Object).InstanceSize;
 			int objSize = typeof(Object).InstanceSize;
@@ -129,6 +145,11 @@ namespace Tests
 			Test.Assert(cf.mB.AllocSize == 1024);
 			Test.Assert(cf.mB.AllocSize == 1024);
 			Test.Assert(cf.mC == 234);
 			Test.Assert(cf.mC == 234);
 			cf.mB.Append('!', 2048);
 			cf.mB.Append('!', 2048);
+
+			ClassG.Set("1234567890");
+			Test.Assert(ClassG.sFirst == "1234567890");
+			Test.Assert(ClassG.sSecond == "1234567890");
+			Test.Assert(ClassG.sThird == "1234567890");
 		}
 		}
 #endif
 #endif
 	}
 	}