1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-09 03:52:19 +02:00

Static local methods and variables, fixed erroneous 'this' capture

This commit is contained in:
Brian Fiete 2022-02-11 10:38:57 -05:00
parent 3c74588e10
commit d9725dda7c
6 changed files with 97 additions and 13 deletions

View file

@ -2062,6 +2062,17 @@ void BeCOFFObject::Generate(BeModule* module)
sect.mRelocs.push_back(reloc); sect.mRelocs.push_back(reloc);
sect.mData.Write((int64)0); sect.mData.Write((int64)0);
} }
else if (auto constVal = BeValueDynCast<BeConstant>(globalVar->mInitializer))
{
MarkSectionUsed(mDataSect);
sym->mSectionNum = mDataSect.mSectionIdx + 1;
mDataSect.mData.Align(globalVar->mAlign);
mDataSect.mAlign = BF_MAX(mDataSect.mAlign, globalVar->mAlign);
AlignConst(mDataSect, constVal);
sym->mValue = mDataSect.mData.GetSize();
WriteConst(mDataSect, constVal);
}
else else
{ {
MarkSectionUsed(mBSSSect); MarkSectionUsed(mBSSSect);

View file

@ -4161,7 +4161,7 @@ BfTypedValue BfExprEvaluator::LookupIdentifier(BfAstNode* refNode, const StringI
} }
} }
BfTypedValue thisValue = mModule->GetThis(); BfTypedValue thisValue = mModule->GetThis(false);
bool forcedIFaceLookup = false; bool forcedIFaceLookup = false;
if ((mModule->mCurMethodInstance != NULL) && (mModule->mCurMethodInstance->mIsForeignMethodDef)) if ((mModule->mCurMethodInstance != NULL) && (mModule->mCurMethodInstance->mIsForeignMethodDef))
@ -4173,7 +4173,10 @@ BfTypedValue BfExprEvaluator::LookupIdentifier(BfAstNode* refNode, const StringI
if (thisValue) if (thisValue)
{ {
if (findName == "this") if (findName == "this")
{
mModule->MarkUsingThis();
return thisValue; return thisValue;
}
if (findName == "base") if (findName == "base")
{ {
auto baseValue = thisValue; auto baseValue = thisValue;
@ -4184,6 +4187,7 @@ BfTypedValue BfExprEvaluator::LookupIdentifier(BfAstNode* refNode, const StringI
{ {
MakeBaseConcrete(baseValue); MakeBaseConcrete(baseValue);
} }
mModule->MarkUsingThis();
return baseValue; return baseValue;
} }
@ -4654,6 +4658,9 @@ BfTypedValue BfExprEvaluator::LookupField(BfAstNode* targetSrc, BfTypedValue tar
return BfTypedValue(); return BfTypedValue();
} }
if ((!field->mIsStatic) && ((flags & BfLookupFieldFlag_IsImplicitThis) != 0))
mModule->MarkUsingThis();
mResultFieldInstance = fieldInstance; mResultFieldInstance = fieldInstance;
// Are we accessing a 'var' field that has not yet been resolved? // Are we accessing a 'var' field that has not yet been resolved?
@ -5043,6 +5050,9 @@ BfTypedValue BfExprEvaluator::LookupField(BfAstNode* targetSrc, BfTypedValue tar
mModule->SetElementType(targetSrc, BfSourceElementType_Method); mModule->SetElementType(targetSrc, BfSourceElementType_Method);
if ((!prop->mIsStatic) && ((flags & BfLookupFieldFlag_IsImplicitThis) != 0))
mModule->MarkUsingThis();
mPropSrc = targetSrc; mPropSrc = targetSrc;
mPropDef = prop; mPropDef = prop;
mPropCheckedKind = checkedKind; mPropCheckedKind = checkedKind;

View file

@ -14371,7 +14371,23 @@ int BfModule::GetFieldDataIdx(BfTypeInstance* typeInst, int fieldIdx, const char
return fieldInstance.mDataIdx; return fieldInstance.mDataIdx;
} }
BfTypedValue BfModule::GetThis() void BfModule::MarkUsingThis()
{
auto useMethodState = mCurMethodState;
while ((useMethodState != NULL) && (useMethodState->mClosureState != NULL) && (useMethodState->mClosureState->mCapturing))
{
useMethodState = useMethodState->mPrevMethodState;
}
if ((useMethodState != NULL) && (!useMethodState->mLocals.IsEmpty()))
{
auto localVar = useMethodState->mLocals[0];
if (localVar->mIsThis)
localVar->mReadFromId = useMethodState->GetRootMethodState()->mCurAccessId++;
}
}
BfTypedValue BfModule::GetThis(bool markUsing)
{ {
auto useMethodState = mCurMethodState; auto useMethodState = mCurMethodState;
while ((useMethodState != NULL) && (useMethodState->mClosureState != NULL) && (useMethodState->mClosureState->mCapturing)) while ((useMethodState != NULL) && (useMethodState->mClosureState != NULL) && (useMethodState->mClosureState->mCapturing))
@ -14465,6 +14481,7 @@ BfTypedValue BfModule::GetThis()
thisValue = thisLocal->mAddr; thisValue = thisLocal->mAddr;
else else
thisValue = mBfIRBuilder->CreateLoad(thisLocal->mAddr); thisValue = mBfIRBuilder->CreateLoad(thisLocal->mAddr);
if (markUsing)
useMethodState->mLocals[0]->mReadFromId = useMethodState->GetRootMethodState()->mCurAccessId++; useMethodState->mLocals[0]->mReadFromId = useMethodState->GetRootMethodState()->mCurAccessId++;
if (useMethodState->mClosureState != NULL) if (useMethodState->mClosureState != NULL)
@ -21462,6 +21479,8 @@ BfModuleMethodInstance BfModule::GetLocalMethodInstance(BfLocalMethod* localMeth
wantsVisitBody = false; wantsVisitBody = false;
if (methodInstance->IsOrInUnspecializedVariation()) if (methodInstance->IsOrInUnspecializedVariation())
wantsVisitBody = false; wantsVisitBody = false;
if ((methodDeclaration != NULL) && (methodDeclaration->mStaticSpecifier != NULL))
wantsVisitBody = false;
if (wantsVisitBody) if (wantsVisitBody)
{ {

View file

@ -175,6 +175,7 @@ public:
BfLocalVarAssignKind mAssignedKind; BfLocalVarAssignKind mAssignedKind;
bool mHadExitBeforeAssign; bool mHadExitBeforeAssign;
bool mIsReadOnly; bool mIsReadOnly;
bool mIsStatic;
bool mIsSplat; bool mIsSplat;
bool mIsLowered; bool mIsLowered;
bool mAllowAddr; bool mAllowAddr;
@ -204,6 +205,7 @@ public:
mWrittenToId = -1; mWrittenToId = -1;
mReadFromId = -1; mReadFromId = -1;
mIsReadOnly = false; mIsReadOnly = false;
mIsStatic = false;
mIsSplat = false; mIsSplat = false;
mIsLowered = false; mIsLowered = false;
mAllowAddr = false; mAllowAddr = false;
@ -1678,7 +1680,8 @@ public:
BfTypedValue GetCompilerFieldValue(const StringImpl& str); BfTypedValue GetCompilerFieldValue(const StringImpl& str);
BfTypedValue ReferenceStaticField(BfFieldInstance* fieldInstance); BfTypedValue ReferenceStaticField(BfFieldInstance* fieldInstance);
int GetFieldDataIdx(BfTypeInstance* typeInst, int fieldIdx, const char* fieldName = NULL); int GetFieldDataIdx(BfTypeInstance* typeInst, int fieldIdx, const char* fieldName = NULL);
BfTypedValue GetThis(); BfTypedValue GetThis(bool markUsing = true);
void MarkUsingThis();
BfLocalVariable* GetThisVariable(); BfLocalVariable* GetThisVariable();
bool IsInGeneric(); bool IsInGeneric();
bool InDefinitionSection(); bool InDefinitionSection();

View file

@ -4068,9 +4068,12 @@ BfAstNode* BfReducer::DoCreateStatement(BfAstNode* node, CreateStmtFlags createS
continuingVariable = BfNodeDynCast<BfVariableDeclaration>(exprStmt->mExpression); continuingVariable = BfNodeDynCast<BfVariableDeclaration>(exprStmt->mExpression);
} }
} }
else if ((token == BfToken_Const) || (token == BfToken_ReadOnly)) else if ((token == BfToken_Const) || (token == BfToken_ReadOnly) || (token == BfToken_Static))
{ {
auto stmt = CreateStatementAfter(tokenNode, (CreateStmtFlags)(CreateStmtFlags_FindTrailingSemicolon | CreateStmtFlags_ForceVariableDecl)); auto flags = (CreateStmtFlags)(CreateStmtFlags_FindTrailingSemicolon | CreateStmtFlags_ForceVariableDecl);
if (token == BfToken_Static)
flags = (CreateStmtFlags)(flags | CreateStmtFlags_AllowLocalFunction);
auto stmt = CreateStatementAfter(tokenNode, flags);
if (auto exprStmt = BfNodeDynCast<BfExpressionStatement>(stmt)) if (auto exprStmt = BfNodeDynCast<BfExpressionStatement>(stmt))
{ {
if (auto variableDecl = BfNodeDynCast<BfVariableDeclaration>(exprStmt->mExpression)) if (auto variableDecl = BfNodeDynCast<BfVariableDeclaration>(exprStmt->mExpression))
@ -4080,10 +4083,20 @@ BfAstNode* BfReducer::DoCreateStatement(BfAstNode* node, CreateStmtFlags createS
Fail(StrFormat("'%s' already specified", BfTokenToString(variableDecl->mModSpecifier->GetToken())), variableDecl->mModSpecifier); Fail(StrFormat("'%s' already specified", BfTokenToString(variableDecl->mModSpecifier->GetToken())), variableDecl->mModSpecifier);
} }
MEMBER_SET(variableDecl, mModSpecifier, tokenNode); MEMBER_SET(variableDecl, mModSpecifier, tokenNode);
exprStmt->SetSrcStart(variableDecl->mSrcStart); exprStmt->SetSrcStart(tokenNode->mSrcStart);
return stmt; return stmt;
} }
} }
if (auto localMethod = BfNodeDynCast<BfLocalMethodDeclaration>(stmt))
{
if (localMethod->mMethodDeclaration->mStaticSpecifier != NULL)
{
Fail(StrFormat("'%s' already specified", BfTokenToString(localMethod->mMethodDeclaration->mStaticSpecifier->GetToken())), localMethod->mMethodDeclaration->mStaticSpecifier);
}
MEMBER_SET(localMethod->mMethodDeclaration, mStaticSpecifier, tokenNode);
localMethod->SetSrcStart(tokenNode->mSrcStart);
return localMethod;
}
Fail(StrFormat("Unexpected '%s' specifier", BfTokenToString(tokenNode->GetToken())), tokenNode); Fail(StrFormat("Unexpected '%s' specifier", BfTokenToString(tokenNode->GetToken())), tokenNode);
return stmt; return stmt;

View file

@ -1335,6 +1335,7 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD
bool isConst = (varDecl->mModSpecifier != NULL) && (varDecl->mModSpecifier->GetToken() == BfToken_Const); bool isConst = (varDecl->mModSpecifier != NULL) && (varDecl->mModSpecifier->GetToken() == BfToken_Const);
bool isReadOnly = (varDecl->mModSpecifier != NULL) && (varDecl->mModSpecifier->GetToken() == BfToken_ReadOnly); bool isReadOnly = (varDecl->mModSpecifier != NULL) && (varDecl->mModSpecifier->GetToken() == BfToken_ReadOnly);
bool isStatic = (varDecl->mModSpecifier != NULL) && (varDecl->mModSpecifier->GetToken() == BfToken_Static);
BfLocalVariable* localDef = new BfLocalVariable(); BfLocalVariable* localDef = new BfLocalVariable();
if (varDecl->mNameNode != NULL) if (varDecl->mNameNode != NULL)
@ -1346,6 +1347,7 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD
{ {
localDef->mName = "val"; localDef->mName = "val";
} }
localDef->mIsStatic = isStatic;
bool handledExprBoolResult = false; bool handledExprBoolResult = false;
bool handledVarInit = false; bool handledVarInit = false;
@ -1679,7 +1681,7 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD
if ((!initValue) && (!initHandled)) if ((!initValue) && (!initHandled))
{ {
if (isConst) if ((isConst) || (isStatic))
{ {
BfConstResolver constResolver(this); BfConstResolver constResolver(this);
initValue = constResolver.Resolve(varDecl->mInitializer, resolvedType, BfConstResolveFlag_ActualizeValues); initValue = constResolver.Resolve(varDecl->mInitializer, resolvedType, BfConstResolveFlag_ActualizeValues);
@ -1763,6 +1765,11 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD
_CheckConst(); _CheckConst();
if (isStatic)
{
NOP;
}
if ((initValue.mKind == BfTypedValueKind_TempAddr) && (!initHandled)) if ((initValue.mKind == BfTypedValueKind_TempAddr) && (!initHandled))
{ {
BF_ASSERT(initValue.IsAddr()); BF_ASSERT(initValue.IsAddr());
@ -1781,7 +1788,7 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD
mCurMethodState->mCurScope->mDeferredLifetimeEnds.push_back(localDef->mAddr); mCurMethodState->mCurScope->mDeferredLifetimeEnds.push_back(localDef->mAddr);
} }
if ((!localDef->mAddr) && (!isConst) && ((!localDef->mIsReadOnly) || (localNeedsAddr))) if ((!localDef->mAddr) && (!isConst) && (!isStatic) && ((!localDef->mIsReadOnly) || (localNeedsAddr)))
{ {
if ((exprEvaluator != NULL) && (exprEvaluator->mResultIsTempComposite)) if ((exprEvaluator != NULL) && (exprEvaluator->mResultIsTempComposite))
{ {
@ -1794,6 +1801,27 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD
localDef->mAddr = AllocLocalVariable(resolvedType, localDef->mName); localDef->mAddr = AllocLocalVariable(resolvedType, localDef->mName);
} }
if (isStatic)
{
String name = mModuleName + "_" + mCurMethodInstance->mMethodDef->mName + "_" + localDef->mName;
HashContext closureHashCtx;
closureHashCtx.Mixin(varDecl->mSrcStart);
uint64 closureHash = closureHashCtx.Finish64();
name += "$";
name += BfTypeUtils::HashEncode64(closureHash);
initValue = LoadValue(initValue);
if ((initValue) && (!initValue.mValue.IsConst()))
{
Fail("Static local variables can only be initialized with a const value", varDecl->mInitializer);
initValue = BfTypedValue();
}
localDef->mAddr = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapType(localDef->mResolvedType), false, BfIRLinkageType_Internal, initValue.mValue, name);;
initHandled = true;
}
bool wantsStore = false; bool wantsStore = false;
if ((initValue) && (!handledVarStore) && (!isConst) && (!initHandled)) if ((initValue) && (!handledVarStore) && (!isConst) && (!initHandled))
{ {