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.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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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))
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue