1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 11:38:21 +02:00

Reworked static append fields

This commit is contained in:
Brian Fiete 2025-01-24 06:14:46 -08:00
parent 9d8647cd84
commit ec34aa3d43
6 changed files with 147 additions and 85 deletions

View file

@ -5310,7 +5310,7 @@ BfTypedValue BfExprEvaluator::LoadField(BfAstNode* targetSrc, BfTypedValue targe
(mModule->mCurMethodInstance->mMethodDef->IsCtorOrInit()) &&
(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()))
{
auto intType = mModule->GetPrimitiveType(BfTypeCode_IntPtr);

View file

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

View file

@ -4227,7 +4227,7 @@ void BfModule::CreateStaticField(BfFieldInstance* fieldInstance, bool isThreadLo
{
BfIRType irType;
if (fieldInstance->IsAppendedObject())
if ((fieldInstance->IsAppendedObject()) && (!field->mIsStatic))
{
irType = mBfIRBuilder->MapTypeInst(fieldType->ToTypeInstance(), BfIRPopulateType_Eventually_Full);
initValue = mBfIRBuilder->CreateConstAggZero(irType);
@ -4743,6 +4743,99 @@ BfTypedValue BfModule::GetFieldInitializerValue(BfFieldInstance* fieldInstance,
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)
{
BfExprEvaluator exprEvaluator(this);
@ -4791,7 +4884,26 @@ void BfModule::AppendedObjectInit(BfFieldInstance* fieldInst)
BfIRValue fieldAddr;
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
fieldAddr = mBfIRBuilder->CreateInBoundsGEP(mCurMethodState->mLocals[0]->mValue, 0, fieldInst->mDataIdx);
@ -15501,9 +15613,6 @@ BfTypedValue BfModule::ReferenceStaticField(BfFieldInstance* fieldInstance)
{
BfIRType irType = mBfIRBuilder->MapType(typeType);
if (fieldInstance->IsAppendedObject())
irType = mBfIRBuilder->MapTypeInst(typeType->ToTypeInstance());
SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, mBfIRBuilder->mIgnoreWrites || staticVarName.StartsWith('#'));
globalValue = mBfIRBuilder->CreateGlobalVariable(
@ -15527,7 +15636,7 @@ BfTypedValue BfModule::ReferenceStaticField(BfFieldInstance* fieldInstance)
if (fieldDef->mIsVolatile)
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)
@ -17697,7 +17806,7 @@ void BfModule::EmitDtorBody()
localDef->mName = "_";
localDef->mResolvedType = fieldInst->mResolvedType;
if (fieldInst->IsAppendedObject())
if ((fieldInst->IsAppendedObject()) && (!fieldDef->mIsStatic))
{
localDef->mValue = mBfIRBuilder->CreateBitCast(value, mBfIRBuilder->MapType(fieldInst->mResolvedType));
}
@ -17722,7 +17831,7 @@ void BfModule::EmitDtorBody()
auto defLocalVar = AddLocalVariableDef(localDef, true);
if (!fieldInst->IsAppendedObject())
if ((!fieldInst->IsAppendedObject()) && (!fieldDef->mIsStatic))
{
// Put back so we actually modify the correct value*/
defLocalVar->mResolvedType = fieldInst->mResolvedType;
@ -17765,7 +17874,10 @@ void BfModule::EmitDtorBody()
BfTypedValue val;
if (fieldDef->mIsStatic)
{
val = ReferenceStaticField(fieldInst);
val = LoadValue(val);
}
else
{
auto fieldAddr = mBfIRBuilder->CreateInBoundsGEP(mCurMethodState->mLocals[0]->mValue, 0, fieldInst->mDataIdx);
@ -20357,7 +20469,7 @@ void BfModule::EmitGCMarkMembers()
if (markVal)
{
if (fieldInst.IsAppendedObject())
if ((fieldInst.IsAppendedObject()) && (!fieldDef->mIsStatic))
EmitGCMarkAppended(markVal);
else
EmitGCMarkValue(markVal, markFromGCThreadMethodInstance);

View file

@ -1887,6 +1887,7 @@ public:
void CreateStaticField(BfFieldInstance* fieldInstance, bool isThreadLocal = 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);
bool TryGetAppendedObjectInfo(BfFieldInstance* fieldInstance, int& dataSize, int& alignSize);
void AppendedObjectInit(BfFieldInstance* fieldInstance);
void MarkFieldInitialized(BfFieldInstance* fieldInstance);
bool IsThreadLocal(BfFieldInstance* fieldInstance);

View file

@ -5650,79 +5650,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
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)
{

View file

@ -83,6 +83,22 @@ namespace Tests
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)
{
int objSize = typeof(Object).InstanceSize;
@ -129,6 +145,11 @@ namespace Tests
Test.Assert(cf.mB.AllocSize == 1024);
Test.Assert(cf.mC == 234);
cf.mB.Append('!', 2048);
ClassG.Set("1234567890");
Test.Assert(ClassG.sFirst == "1234567890");
Test.Assert(ClassG.sSecond == "1234567890");
Test.Assert(ClassG.sThird == "1234567890");
}
#endif
}