1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-10 12:32:20 +02:00

Support for marking append-allocated objects (mHasAppendWantMark)

This commit is contained in:
Brian Fiete 2025-01-28 14:49:15 -08:00
parent 9ae172c43f
commit 9baf0ead21
18 changed files with 475 additions and 103 deletions

View file

@ -1232,6 +1232,7 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild
typeInst->mHasPackingHoles = false;
typeInst->mWantsGCMarking = false;
typeInst->mHasDeclError = false;
typeInst->mHasAppendWantMark = false;
delete typeInst->mTypeInfoEx;
typeInst->mTypeInfoEx = NULL;

View file

@ -2067,6 +2067,15 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
BfMethodDef* strictEqualsMethod = NULL;
bool needsStaticInit = false;
if (mCurTypeDef->IsExtension())
needsDefaultCtor = false;
bool needsDtor = false;
bool needsStaticDtor = false;
bool hasStaticField = false;
bool hasNonStaticField = false;
bool hasThreadStatics = false;
for (int methodIdx = 0; methodIdx < (int)mCurTypeDef->mMethods.size(); methodIdx++)
{
auto method = mCurTypeDef->mMethods[methodIdx];
@ -2080,6 +2089,9 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
if (method->mMethodType == BfMethodType_Ctor)
{
if (method->HasAppend())
needsDtor = true;
if (method->mIsStatic)
{
if ((staticCtor != NULL) && (staticCtor->mMethodDeclaration != NULL))
@ -2239,15 +2251,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString)
if ((method->mImportKind == BfImportKind_Import_Dynamic) || (method->mImportKind == BfImportKind_Import_Unknown))
needsStaticInit = true;
}
if (mCurTypeDef->IsExtension())
needsDefaultCtor = false;
bool needsDtor = false;
bool needsStaticDtor = false;
bool hasStaticField = false;
bool hasNonStaticField = false;
bool hasThreadStatics = false;
for (auto field : mCurTypeDef->mFields)
{
if (field->mIsStatic)

View file

@ -7492,7 +7492,7 @@ void BfExprEvaluator::PushThis(BfAstNode* targetSrc, BfTypedValue argVal, BfMeth
else
allowThisSplatting = methodInstance->AllowsSplatting(-1);
if ((!allowThisSplatting) || (methodDef->mIsMutating))
if ((!allowThisSplatting) || (methodDef->mIsMutating) || (methodInstance->mCallingConvention == BfCallingConvention_Cdecl))
{
argVal = mModule->MakeAddressable(argVal);
irArgs.push_back(argVal.mValue);
@ -16569,7 +16569,8 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
int allocAlign = resolvedTypeRef->mAlign;
if (typeInstance != NULL)
allocAlign = typeInstance->mInstAlign;
int appendAllocAlign = 0;
int appendAllocAlign = 0;
BfAllocFlags allocFlags = BfAllocFlags_None;
if ((bindResult.mMethodInstance != NULL) && (bindResult.mMethodInstance->mMethodDef->HasAppend()))
{
@ -16605,6 +16606,9 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
appendSizeValue = appendSizeTypedValue.mValue;
allocAlign = BF_MAX(allocAlign, calcAppendMethodModule.mMethodInstance->mAppendAllocAlign);
appendAllocAlign = calcAppendMethodModule.mMethodInstance->mAppendAllocAlign;
if (calcAppendMethodModule.mMethodInstance->mHasAppendWantMark)
allocFlags = (BfAllocFlags)(allocFlags | BfAllocFlags_HasAppendWantMark);
}
if (appendAllocAlign != 0)
@ -16616,6 +16620,12 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
appendSizeValue = mModule->mBfIRBuilder->CreateAdd(appendSizeValue, mModule->GetConstValue(extraSize));
}
}
if ((allocFlags & BfAllocFlags_HasAppendWantMark) != 0)
{
int markInfoSize = sizeof(intptr) + sizeof(intptr) * 4; // Stack trace, MarkAppendEntry
appendSizeValue = mModule->mBfIRBuilder->CreateAdd(appendSizeValue, mModule->GetConstValue(markInfoSize));
}
}
// WTF? I'm not even sure this is correct - add more tests
@ -16635,7 +16645,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
}
else
{
allocValue = mModule->AllocFromType(resolvedTypeRef, allocTarget, appendSizeValue, BfIRValue(), 0, BfAllocFlags_None, allocAlign);
allocValue = mModule->AllocFromType(resolvedTypeRef, allocTarget, appendSizeValue, BfIRValue(), 0, allocFlags, allocAlign);
}
if (((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0) && (mModule->mCompiler->mCeMachine != NULL))
{
@ -16710,14 +16720,21 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
{
auto impMethodInstance = (BfMethodInstance*)vtableEntry.mImplementingMethod;
bool needsCall = false;
if (impMethodInstance != NULL)
{
needsCall = impMethodInstance->mMethodDef->mBody != NULL;
}
else
{
if (allocFlags & BfAllocFlags_HasAppendWantMark)
needsCall = true;
BF_ASSERT(vtableEntry.mImplementingMethod.mKind == BfMethodRefKind_AmbiguousRef);
if (!needsCall)
{
if (impMethodInstance != NULL)
{
needsCall = impMethodInstance->mMethodDef->mBody != NULL;
}
else
{
needsCall = true;
BF_ASSERT(vtableEntry.mImplementingMethod.mKind == BfMethodRefKind_AmbiguousRef);
}
}
if (!needsCall)

View file

@ -475,6 +475,7 @@ public:
BfTypedValue mConstAccum;
bool mFailed;
bool mIsFirstConstPass;
bool mHasAppendWantMark;
int mCurAppendAlign;
public:
@ -482,6 +483,7 @@ public:
{
mFailed = false;
mIsFirstConstPass = false;
mHasAppendWantMark = false;
mCurAppendAlign = 1;
}
@ -654,6 +656,9 @@ public:
return;
}
if (origResolvedTypeRef->WantsGCMarking())
mHasAppendWantMark = true;
bool isGenericParam = origResolvedTypeRef->IsGenericParam();
auto resolvedTypeRef = origResolvedTypeRef;
auto resultType = resolvedTypeRef;
@ -6272,6 +6277,8 @@ BfIRValue BfModule::GetTypeTypeData(BfType* type, BfCreateTypeDataContext& ctx,
typeFlags |= BfTypeFlags_Static;
if ((typeInstance != NULL) && (typeInstance->mTypeDef->mIsAbstract))
typeFlags |= BfTypeFlags_Abstract;
if ((typeInstance != NULL) && (typeInstance->mHasAppendWantMark))
typeFlags |= BfTypeFlags_HasAppendWantMark;
return typeTypeData;
}
@ -9534,7 +9541,7 @@ BfTypedValue BfModule::GetOrCreateVarAddr(BfExpression* expr)
}
// Clear memory, set classVData, call init. Actual ctor is called elsewhere.
void BfModule::InitTypeInst(BfTypedValue typedValue, BfScopeData* scopeData, bool zeroMemory, BfIRValue sizeValue)
void BfModule::InitTypeInst(BfTypedValue typedValue, BfScopeData* scopeData, bool zeroMemory, BfIRValue sizeValue, BfAllocFlags allocFlags)
{
auto typeInstance = typedValue.mType->ToTypeInstance();
if (zeroMemory)
@ -9581,6 +9588,8 @@ void BfModule::InitTypeInst(BfTypedValue typedValue, BfScopeData* scopeData, boo
SizedArray<BfIRValue, 4> llvmArgs;
llvmArgs.push_back(objectPtr);
llvmArgs.push_back(vDataRef);
llvmArgs.push_back(sizeValue);
llvmArgs.push_back(mBfIRBuilder->CreateConst(BfTypeCode_Int8, allocFlags));
auto objectStackInitMethod = GetInternalMethod("Dbg_ObjectStackInit");
if (objectStackInitMethod)
@ -10213,7 +10222,7 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget
doCondAlloca = !wasDynAlloc && isDynAlloc && mCurMethodState->mInConditionalBlock;
AddStackAlloc(typedVal, arraySize, NULL, scopeData, doCondAlloca, true);
}
InitTypeInst(typedVal, scopeData, zeroMemory, sizeValue);
InitTypeInst(typedVal, scopeData, zeroMemory, sizeValue, allocFlags);
return typedVal.mValue;
}
@ -10443,7 +10452,8 @@ BfIRValue BfModule::AllocFromType(BfType* type, const BfAllocTarget& allocTarget
llvmArgs.push_back(sizeValue);
llvmArgs.push_back(GetConstValue(typeInstance->mAlign));
llvmArgs.push_back(GetConstValue(stackCount));
auto moduleMethodInstance = GetInternalMethod("Dbg_ObjectAlloc", 4);
llvmArgs.push_back(GetConstValue(allocFlags, GetPrimitiveType(BfTypeCode_Int8)));
auto moduleMethodInstance = GetInternalMethod("Dbg_ObjectAlloc", 5);
BfIRValue objectVal = mBfIRBuilder->CreateCall(moduleMethodInstance.mFunc, llvmArgs);
result = mBfIRBuilder->CreateBitCast(objectVal, mBfIRBuilder->MapType(typeInstance));
}
@ -10647,6 +10657,9 @@ BfIRValue BfModule::AppendAllocFromType(BfType* type, BfIRValue appendSizeValue,
BfIRType toType;
if (typeInst != NULL)
{
mBfIRBuilder->PopulateType(typeInst);
if (typeInst->WantsGCMarking())
mCurTypeInstance->mHasAppendWantMark = true;
EmitAppendAlign(typeInst->mInstAlign, typeInst->mInstSize);
sizeValue = GetConstValue(typeInst->mInstSize);
toType = mBfIRBuilder->MapTypeInstPtr(typeInst);
@ -10665,6 +10678,35 @@ BfIRValue BfModule::AppendAllocFromType(BfType* type, BfIRValue appendSizeValue,
retTypeInstance = typeInst;
retValue = mBfIRBuilder->CreateIntToPtr(curIdxVal, toType);
if ((typeInst != NULL) && (typeInst->WantsGCMarking()) && (mCompiler->mOptions.mDebugAlloc))
{
auto curThis = GetThis();
auto thisObj = Cast(mCurMethodInstance->mMethodDef->GetRefNode(), curThis, mContext->mBfObjectType);
if (typeInst->IsObject())
{
auto appendedObj = Cast(mCurMethodInstance->mMethodDef->GetRefNode(), BfTypedValue(retValue, typeInst), mContext->mBfObjectType);
BfModuleMethodInstance allocMethod = GetInternalMethod("Dbg_ObjectAppended", 2);
SizedArray<BfIRValue, 2> llvmArgs;
llvmArgs.push_back(thisObj.mValue);
llvmArgs.push_back(appendedObj.mValue);
mBfIRBuilder->CreateCall(allocMethod.mFunc, llvmArgs);
}
else
{
// Raw
BfIRValue allocPtr = mBfIRBuilder->CreateBitCast(retValue, mBfIRBuilder->MapType(voidPtrType));
BfIRValue allocData = GetDbgRawAllocData(type);
BfModuleMethodInstance allocMethod = GetInternalMethod("Dbg_RawAppended", 3);
SizedArray<BfIRValue, 3> llvmArgs;
llvmArgs.push_back(thisObj.mValue);
llvmArgs.push_back(allocPtr);
llvmArgs.push_back(allocData);
mBfIRBuilder->CreateCall(allocMethod.mFunc, llvmArgs);
}
}
}
if ((retTypeInstance != NULL) && (retTypeInstance->IsObject()))
@ -15871,7 +15913,7 @@ BfTypedValue BfModule::GetThis(bool markUsing)
auto curMethodOwner = mCurMethodInstance->mMethodInstanceGroup->mOwner;
if ((curMethodOwner->IsStruct()) || (curMethodOwner->IsTypedPrimitive()))
{
if ((localDef->mResolvedType->IsTypedPrimitive()) && (!mCurMethodInstance->mMethodDef->mIsMutating))
if ((localDef->mResolvedType->IsTypedPrimitive()) && (!mCurMethodInstance->mMethodDef->mIsMutating) && (mCurMethodInstance->mCallingConvention != BfCallingConvention_Cdecl))
{
return BfTypedValue(thisValue, useMethodState->mLocals[0]->mResolvedType, BfTypedValueKind_ReadOnlyThisValue);
}
@ -17411,12 +17453,15 @@ BfTypedValue BfModule::TryConstCalcAppend(BfMethodInstance* methodInst, SizedArr
appendAllocVisitor.mFailed = true;
if (!appendAllocVisitor.mFailed)
constValue = appendAllocVisitor.mConstAccum;
if (appendAllocVisitor.mHasAppendWantMark)
methodInst->mHasAppendWantMark = true;
if (isFirstRun)
{
mCurMethodInstance->mEndingAppendAllocAlign = appendAllocVisitor.mCurAppendAlign;
if (mCurMethodInstance->mAppendAllocAlign <= 0)
mCurMethodInstance->mAppendAllocAlign = 1;
}
}
if (isFirstRun)
{
@ -18090,6 +18135,19 @@ void BfModule::EmitDtorBody()
}
}
}
// If there are appends then we just need the rootmost append type to do the Dbg_AppendDeleted
if ((!mIsComptimeModule) && (!methodDef->mIsStatic) && (mCompiler->mOptions.mDebugAlloc) &&
(mCurTypeInstance->HasAppendCtor()) && (!mCurTypeInstance->BaseHasAppendCtor()))
{
auto thisValue = GetThis();
auto appendedObj = mBfIRBuilder->CreateBitCast(thisValue.mValue, mBfIRBuilder->MapType(mContext->mBfObjectType));
BfModuleMethodInstance allocMethod = GetInternalMethod("Dbg_AppendDeleted", 1);
SizedArray<BfIRValue, 1> llvmArgs;
llvmArgs.push_back(appendedObj);
if (allocMethod)
mBfIRBuilder->CreateCall(allocMethod.mFunc, llvmArgs);
}
}
BfIRValue BfModule::CreateDllImportGlobalVar(BfMethodInstance* methodInstance, bool define)
@ -20534,6 +20592,19 @@ void BfModule::EmitGCMarkMembers()
CallChainedMethods(mCurMethodInstance, false);
}
}
// If there are appends then we just need the rootmost append type to do the Dbg_MarkAppended
if ((!mIsComptimeModule) && (!methodDef->mIsStatic) && (mCompiler->mOptions.mDebugAlloc) &&
(mCurTypeInstance->HasAppendCtor()) && (!mCurTypeInstance->BaseHasAppendCtor()))
{
auto thisValue = GetThis();
auto appendedObj = mBfIRBuilder->CreateBitCast(thisValue.mValue, mBfIRBuilder->MapType(mContext->mBfObjectType));
BfModuleMethodInstance allocMethod = GetInternalMethod("Dbg_MarkAppended", 1);
SizedArray<BfIRValue, 1> llvmArgs;
llvmArgs.push_back(appendedObj);
if (allocMethod)
mBfIRBuilder->CreateCall(allocMethod.mFunc, llvmArgs);
}
}
void BfModule::EmitGCFindTLSMembers()
@ -21452,7 +21523,8 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup,
else
{
bool wantPtr = (thisType->IsComposite()) && (!paramVar->mIsLowered);
if ((thisType->IsTypedPrimitive()) && (methodDef->HasNoThisSplat()))
if ((thisType->IsTypedPrimitive()) &&
((methodDef->HasNoThisSplat()) || (methodInstance->mCallingConvention == BfCallingConvention_Cdecl)))
wantPtr = true;
if (wantPtr)
@ -21582,7 +21654,8 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup,
{
diType = mBfIRBuilder->DbgGetType(paramVar->mResolvedType);
bool wantRef = paramVar->mResolvedType->IsComposite();
if ((paramVar->mResolvedType->IsTypedPrimitive()) && (methodDef->HasNoThisSplat()))
if ((paramVar->mResolvedType->IsTypedPrimitive()) &&
((methodDef->HasNoThisSplat()) || (methodInstance->mCallingConvention == BfCallingConvention_Cdecl)))
wantRef = true;
if (wantRef)
@ -23897,6 +23970,12 @@ void BfModule::GetMethodCustomAttributes(BfMethodInstance* methodInstance)
}
methodInstance->mCallingConvention = methodDef->mCallingConvention;
if ((typeInstance->IsValueType()) && (methodDef->mIsOverride) && (methodDef->mName == BF_METHODNAME_MARKMEMBERS))
{
// Make sure we we pass 'this' as a pointer into GCMarkMembers so it's compatible with the mark function pointer
methodInstance->mCallingConvention = BfCallingConvention_Cdecl;
}
if (customAttributes != NULL)
{
auto linkNameAttr = customAttributes->Get(mCompiler->mCallingConventionAttributeTypeDef);

View file

@ -128,10 +128,11 @@ enum BfCastResultFlags : int8
enum BfAllocFlags : int8
{
BfAllocFlags_None = 0,
BfAllocFlags_RawArray = 1,
BfAllocFlags_ZeroMemory = 2,
BfAllocFlags_NoDtorCall = 4,
BfAllocFlags_NoDefaultToMalloc = 8
BfAllocFlags_HasAppendWantMark = 1,
BfAllocFlags_RawArray = 2,
BfAllocFlags_ZeroMemory = 4,
BfAllocFlags_NoDtorCall = 8,
BfAllocFlags_NoDefaultToMalloc = 0x10,
};
enum BfProtectionCheckFlags : int8
@ -1736,7 +1737,7 @@ public:
void CleanupFileInstances();
void AssertErrorState();
void AssertParseErrorState();
void InitTypeInst(BfTypedValue typedValue, BfScopeData* scope, bool zeroMemory, BfIRValue dataSize);
void InitTypeInst(BfTypedValue typedValue, BfScopeData* scope, bool zeroMemory, BfIRValue dataSize, BfAllocFlags allocFlags = BfAllocFlags_None);
bool IsAllocatorAligned();
BfIRValue AllocBytes(BfAstNode* refNode, const BfAllocTarget& allocTarget, BfType* type, BfIRValue sizeValue, BfIRValue alignValue, BfAllocFlags allocFlags/*bool zeroMemory, bool defaultToMalloc*/);
BfIRValue GetMarkFuncPtr(BfType* type);

View file

@ -1381,11 +1381,6 @@ int BfMethodInstance::DbgGetVirtualMethodNum()
void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType, SizedArrayImpl<BfIRType>& paramTypes, bool forceStatic)
{
if (mMethodDef->mName == "Test4")
{
NOP;
}
BfModule* resolveModule = module->mContext->mUnreifiedModule;
resolveModule->PopulateType(mReturnType);
@ -1458,7 +1453,11 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
bool doSplat = false;
if (paramIdx == -1)
{
if ((!mMethodDef->mIsMutating) && (checkType->IsTypedPrimitive()))
if (mCallingConvention == BfCallingConvention_Cdecl)
{
// Pass by pointer even for typed primitives
}
else if ((!mMethodDef->mIsMutating) && (checkType->IsTypedPrimitive()))
{
checkType = checkType->GetUnderlyingType();
}
@ -2468,6 +2467,22 @@ bool BfTypeInstance::IsAnonymousInitializerType()
return (mTypeDef->mTypeDeclaration != NULL) && (mTypeDef->mTypeDeclaration->IsAnonymousInitializerType());
}
bool BfTypeInstance::HasAppendCtor()
{
return mTypeDef->mHasAppendCtor;
}
bool BfTypeInstance::BaseHasAppendCtor()
{
if (mBaseType != NULL)
{
if (mBaseType->HasAppendCtor())
return true;
return mBaseType->BaseHasAppendCtor();
}
return false;
}
void BfTypeInstance::ReportMemory(MemReporter* memReporter)
{
if (mGenericTypeInfo != NULL)

View file

@ -908,6 +908,7 @@ public:
bool mInCEMachine:1;
bool mCeCancelled:1;
bool mIsDisposed:1;
bool mHasAppendWantMark:1;
BfMethodChainType mChainType;
BfComptimeFlags mComptimeFlags;
BfCallingConvention mCallingConvention;
@ -951,6 +952,7 @@ public:
mInCEMachine = false;
mCeCancelled = false;
mIsDisposed = false;
mHasAppendWantMark = false;
mChainType = BfMethodChainType_None;
mComptimeFlags = BfComptimeFlag_None;
mCallingConvention = BfCallingConvention_Unspecified;
@ -2064,6 +2066,7 @@ public:
bool mHasPackingHoles;
bool mWantsGCMarking;
bool mHasDeclError;
bool mHasAppendWantMark;
public:
BfTypeInstance()
@ -2116,6 +2119,7 @@ public:
mWantsGCMarking = false;
mHasParameterizedBase = false;
mHasDeclError = false;
mHasAppendWantMark = false;
mMergedFieldDataCount = 0;
mConstHolder = NULL;
}
@ -2213,6 +2217,8 @@ public:
bool DefineStateAllowsStaticMethods() { return mDefineState >= BfTypeDefineState_HasInterfaces_Direct; }
bool IsAnonymous();
bool IsAnonymousInitializerType();
bool HasAppendCtor();
bool BaseHasAppendCtor();
virtual void ReportMemory(MemReporter* memReporter) override;
};

View file

@ -239,6 +239,7 @@ enum BfTypeFlags
BfTypeFlags_Static = 0x200000,
BfTypeFlags_Abstract = 0x400000,
BfTypeFlags_HasAppendWantMark = 0x800000,
};
enum BfMethodFlags