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:
parent
3c74588e10
commit
d9725dda7c
6 changed files with 97 additions and 13 deletions
|
@ -2062,6 +2062,17 @@ void BeCOFFObject::Generate(BeModule* module)
|
|||
sect.mRelocs.push_back(reloc);
|
||||
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
|
||||
{
|
||||
MarkSectionUsed(mBSSSect);
|
||||
|
|
|
@ -4161,7 +4161,7 @@ BfTypedValue BfExprEvaluator::LookupIdentifier(BfAstNode* refNode, const StringI
|
|||
}
|
||||
}
|
||||
|
||||
BfTypedValue thisValue = mModule->GetThis();
|
||||
BfTypedValue thisValue = mModule->GetThis(false);
|
||||
|
||||
bool forcedIFaceLookup = false;
|
||||
if ((mModule->mCurMethodInstance != NULL) && (mModule->mCurMethodInstance->mIsForeignMethodDef))
|
||||
|
@ -4173,7 +4173,10 @@ BfTypedValue BfExprEvaluator::LookupIdentifier(BfAstNode* refNode, const StringI
|
|||
if (thisValue)
|
||||
{
|
||||
if (findName == "this")
|
||||
{
|
||||
mModule->MarkUsingThis();
|
||||
return thisValue;
|
||||
}
|
||||
if (findName == "base")
|
||||
{
|
||||
auto baseValue = thisValue;
|
||||
|
@ -4184,6 +4187,7 @@ BfTypedValue BfExprEvaluator::LookupIdentifier(BfAstNode* refNode, const StringI
|
|||
{
|
||||
MakeBaseConcrete(baseValue);
|
||||
}
|
||||
mModule->MarkUsingThis();
|
||||
return baseValue;
|
||||
}
|
||||
|
||||
|
@ -4654,6 +4658,9 @@ BfTypedValue BfExprEvaluator::LookupField(BfAstNode* targetSrc, BfTypedValue tar
|
|||
return BfTypedValue();
|
||||
}
|
||||
|
||||
if ((!field->mIsStatic) && ((flags & BfLookupFieldFlag_IsImplicitThis) != 0))
|
||||
mModule->MarkUsingThis();
|
||||
|
||||
mResultFieldInstance = fieldInstance;
|
||||
|
||||
// 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);
|
||||
|
||||
if ((!prop->mIsStatic) && ((flags & BfLookupFieldFlag_IsImplicitThis) != 0))
|
||||
mModule->MarkUsingThis();
|
||||
|
||||
mPropSrc = targetSrc;
|
||||
mPropDef = prop;
|
||||
mPropCheckedKind = checkedKind;
|
||||
|
|
|
@ -14371,7 +14371,23 @@ int BfModule::GetFieldDataIdx(BfTypeInstance* typeInst, int fieldIdx, const char
|
|||
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;
|
||||
while ((useMethodState != NULL) && (useMethodState->mClosureState != NULL) && (useMethodState->mClosureState->mCapturing))
|
||||
|
@ -14465,6 +14481,7 @@ BfTypedValue BfModule::GetThis()
|
|||
thisValue = thisLocal->mAddr;
|
||||
else
|
||||
thisValue = mBfIRBuilder->CreateLoad(thisLocal->mAddr);
|
||||
if (markUsing)
|
||||
useMethodState->mLocals[0]->mReadFromId = useMethodState->GetRootMethodState()->mCurAccessId++;
|
||||
|
||||
if (useMethodState->mClosureState != NULL)
|
||||
|
@ -21462,6 +21479,8 @@ BfModuleMethodInstance BfModule::GetLocalMethodInstance(BfLocalMethod* localMeth
|
|||
wantsVisitBody = false;
|
||||
if (methodInstance->IsOrInUnspecializedVariation())
|
||||
wantsVisitBody = false;
|
||||
if ((methodDeclaration != NULL) && (methodDeclaration->mStaticSpecifier != NULL))
|
||||
wantsVisitBody = false;
|
||||
|
||||
if (wantsVisitBody)
|
||||
{
|
||||
|
|
|
@ -175,6 +175,7 @@ public:
|
|||
BfLocalVarAssignKind mAssignedKind;
|
||||
bool mHadExitBeforeAssign;
|
||||
bool mIsReadOnly;
|
||||
bool mIsStatic;
|
||||
bool mIsSplat;
|
||||
bool mIsLowered;
|
||||
bool mAllowAddr;
|
||||
|
@ -204,6 +205,7 @@ public:
|
|||
mWrittenToId = -1;
|
||||
mReadFromId = -1;
|
||||
mIsReadOnly = false;
|
||||
mIsStatic = false;
|
||||
mIsSplat = false;
|
||||
mIsLowered = false;
|
||||
mAllowAddr = false;
|
||||
|
@ -1678,7 +1680,8 @@ public:
|
|||
BfTypedValue GetCompilerFieldValue(const StringImpl& str);
|
||||
BfTypedValue ReferenceStaticField(BfFieldInstance* fieldInstance);
|
||||
int GetFieldDataIdx(BfTypeInstance* typeInst, int fieldIdx, const char* fieldName = NULL);
|
||||
BfTypedValue GetThis();
|
||||
BfTypedValue GetThis(bool markUsing = true);
|
||||
void MarkUsingThis();
|
||||
BfLocalVariable* GetThisVariable();
|
||||
bool IsInGeneric();
|
||||
bool InDefinitionSection();
|
||||
|
|
|
@ -4068,9 +4068,12 @@ BfAstNode* BfReducer::DoCreateStatement(BfAstNode* node, CreateStmtFlags createS
|
|||
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 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);
|
||||
}
|
||||
MEMBER_SET(variableDecl, mModSpecifier, tokenNode);
|
||||
exprStmt->SetSrcStart(variableDecl->mSrcStart);
|
||||
exprStmt->SetSrcStart(tokenNode->mSrcStart);
|
||||
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);
|
||||
return stmt;
|
||||
|
|
|
@ -1335,6 +1335,7 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD
|
|||
|
||||
bool isConst = (varDecl->mModSpecifier != NULL) && (varDecl->mModSpecifier->GetToken() == BfToken_Const);
|
||||
bool isReadOnly = (varDecl->mModSpecifier != NULL) && (varDecl->mModSpecifier->GetToken() == BfToken_ReadOnly);
|
||||
bool isStatic = (varDecl->mModSpecifier != NULL) && (varDecl->mModSpecifier->GetToken() == BfToken_Static);
|
||||
|
||||
BfLocalVariable* localDef = new BfLocalVariable();
|
||||
if (varDecl->mNameNode != NULL)
|
||||
|
@ -1346,6 +1347,7 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD
|
|||
{
|
||||
localDef->mName = "val";
|
||||
}
|
||||
localDef->mIsStatic = isStatic;
|
||||
|
||||
bool handledExprBoolResult = false;
|
||||
bool handledVarInit = false;
|
||||
|
@ -1679,7 +1681,7 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD
|
|||
|
||||
if ((!initValue) && (!initHandled))
|
||||
{
|
||||
if (isConst)
|
||||
if ((isConst) || (isStatic))
|
||||
{
|
||||
BfConstResolver constResolver(this);
|
||||
initValue = constResolver.Resolve(varDecl->mInitializer, resolvedType, BfConstResolveFlag_ActualizeValues);
|
||||
|
@ -1763,6 +1765,11 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD
|
|||
|
||||
_CheckConst();
|
||||
|
||||
if (isStatic)
|
||||
{
|
||||
NOP;
|
||||
}
|
||||
|
||||
if ((initValue.mKind == BfTypedValueKind_TempAddr) && (!initHandled))
|
||||
{
|
||||
BF_ASSERT(initValue.IsAddr());
|
||||
|
@ -1781,7 +1788,7 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD
|
|||
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))
|
||||
{
|
||||
|
@ -1794,6 +1801,27 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD
|
|||
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;
|
||||
if ((initValue) && (!handledVarStore) && (!isConst) && (!initHandled))
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue