diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 7389cfc5..3c426813 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -7750,12 +7750,9 @@ void BfExprEvaluator::FinishDeferredEvals(BfResolvedArgs& argValues) localVar->Init(); mModule->AddLocalVariableDef(localVar, true); - auto curScope = mModule->mCurMethodState->mCurScope; + auto curScope = mModule->mCurMethodState->mCurScope; if (curScope->mScopeKind == BfScopeKind_StatementTarget) - { - // Move this variable into the parent scope - curScope->mLocalVarStart = (int)mModule->mCurMethodState->mLocals.size(); - } + mModule->MoveLocalToParentScope(localVar); } } } @@ -9331,47 +9328,7 @@ BfTypedValue BfExprEvaluator::ResolveArgValue(BfResolvedArg& resolvedArg, BfType mModule->CreateValueFromExpression(variableDeclaration->mInitializer, variableType, BfEvalExprFlags_NoCast); } - BfLocalVariable* localVar = new BfLocalVariable(); - if ((variableDeclaration != NULL) && (variableDeclaration->mNameNode != NULL)) - { - localVar->mName = variableDeclaration->mNameNode->ToString(); - localVar->mNameNode = BfNodeDynCast(variableDeclaration->mNameNode); - } - else - { - if (paramNameNode != NULL) - { - localVar->mName = "__"; - paramNameNode->ToString(localVar->mName); - localVar->mName += "_"; - localVar->mName += StrFormat("%d", mModule->mCurMethodState->GetRootMethodState()->mCurLocalVarId); - } - else - localVar->mName = "__" + StrFormat("%d", mModule->mCurMethodState->GetRootMethodState()->mCurLocalVarId); - } - - localVar->mResolvedType = variableType; - mModule->PopulateType(variableType); - if (!variableType->IsValuelessType()) - localVar->mAddr = mModule->CreateAlloca(variableType); - localVar->mIsReadOnly = isLet; - localVar->mReadFromId = 0; - localVar->mWrittenToId = 0; - localVar->mAssignedKind = BfLocalVarAssignKind_Unconditional; - mModule->CheckVariableDef(localVar); - localVar->Init(); - mModule->AddLocalVariableDef(localVar, true); - - CheckVariableDeclaration(resolvedArg.mExpression, false, false, false); - - argValue = BfTypedValue(localVar->mAddr, mModule->CreateRefType(variableType, BfRefType::RefKind_Out)); - - auto curScope = mModule->mCurMethodState->mCurScope; - if (curScope->mScopeKind == BfScopeKind_StatementTarget) - { - // Move this variable into the parent scope - curScope->mLocalVarStart = (int)mModule->mCurMethodState->mLocals.size(); - } + argValue = mModule->CreateOutVariable(resolvedArg.mExpression, variableDeclaration, paramNameNode, variableType, BfTypedValue()); } return argValue; } diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 223e12e5..3a0acf6b 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -16039,6 +16039,74 @@ BfIRValue BfModule::AllocLocalVariable(BfType* type, const StringImpl& name, boo return allocaInst; } +BfTypedValue BfModule::CreateOutVariable(BfAstNode* refNode, BfVariableDeclaration* variableDeclaration, BfAstNode* paramNameNode, BfType* variableType, BfTypedValue initValue) +{ + bool isLet = (variableDeclaration != NULL) && (variableDeclaration->mTypeRef->IsExact()); + bool isVar = (variableDeclaration == NULL) || (variableDeclaration->mTypeRef->IsExact()); + + BfLocalVariable* localVar = new BfLocalVariable(); + if ((variableDeclaration != NULL) && (variableDeclaration->mNameNode != NULL)) + { + localVar->mName = variableDeclaration->mNameNode->ToString(); + localVar->mNameNode = BfNodeDynCast(variableDeclaration->mNameNode); + } + else + { + if (paramNameNode != NULL) + { + localVar->mName = "__"; + paramNameNode->ToString(localVar->mName); + localVar->mName += "_"; + localVar->mName += StrFormat("%d", mCurMethodState->GetRootMethodState()->mCurLocalVarId); + } + else + localVar->mName = "__" + StrFormat("%d", mCurMethodState->GetRootMethodState()->mCurLocalVarId); + } + + localVar->mResolvedType = variableType; + PopulateType(variableType); + if (!variableType->IsValuelessType()) + localVar->mAddr = CreateAlloca(variableType); + localVar->mIsReadOnly = isLet; + localVar->mReadFromId = 0; + localVar->mWrittenToId = 0; + localVar->mAssignedKind = BfLocalVarAssignKind_Unconditional; + CheckVariableDef(localVar); + localVar->Init(); + AddLocalVariableDef(localVar, true); + + BfExprEvaluator exprEvaluator(this); + exprEvaluator.CheckVariableDeclaration(refNode, false, false, false); + + auto argValue = BfTypedValue(localVar->mAddr, CreateRefType(variableType, BfRefType::RefKind_Out)); + + initValue = LoadOrAggregateValue(initValue); + + if ((initValue) && (!initValue.mType->IsValuelessType())) + mBfIRBuilder->CreateStore(initValue.mValue, localVar->mAddr); + + auto curScope = mCurMethodState->mCurScope; + if (curScope->mScopeKind == BfScopeKind_StatementTarget) + MoveLocalToParentScope(localVar); + + return argValue; +} + +void BfModule::MoveLocalToParentScope(BfLocalVariable* localVar) +{ + auto curScope = mCurMethodState->mCurScope; + if (mCurMethodState->mLocals.back() != localVar) + return; + + curScope->mLocalVarStart = (int)mCurMethodState->mLocals.size(); + if ((!curScope->mDeferredLifetimeEnds.IsEmpty()) && (curScope->mDeferredLifetimeEnds.back() == localVar->mAddr)) + { + curScope->mDeferredLifetimeEnds.pop_back(); + if (curScope->mPrevScope != NULL) + curScope->mPrevScope->mDeferredLifetimeEnds.push_back(localVar->mAddr); + } +} + void BfModule::DoAddLocalVariable(BfLocalVariable* localVar) { BF_ASSERT(localVar->mResolvedType != NULL); diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index 0f6b4aba..5a8788df 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -1928,6 +1928,8 @@ public: String GenericParamSourceToString(const BfGenericParamSource& genericParamSource); bool CheckGenericConstraints(const BfGenericParamSource& genericParamSource, BfType* checkArgType, BfAstNode* checkArgTypeRef, BfGenericParamInstance* genericParamInst, BfTypeVector* methodGenericArgs = NULL, BfError** errorOut = NULL); BfIRValue AllocLocalVariable(BfType* type, const StringImpl& name, bool doLifetimeEnd = true); + BfTypedValue CreateOutVariable(BfAstNode* refNode, BfVariableDeclaration* variableDeclaration, BfAstNode* paramNameNode, BfType* variableType, BfTypedValue initValue); + void MoveLocalToParentScope(BfLocalVariable* localVar); void DoAddLocalVariable(BfLocalVariable* localVar); void FixLocalVariable(BfLocalVariable* localVar); void DoLocalVariableDebugInfo(BfLocalVariable* localVar, bool doAliasValue = false, BfIRValue declareBefore = BfIRValue(), BfIRInitType initType = BfIRInitType_NotSet); diff --git a/IDEHelper/Compiler/BfStmtEvaluator.cpp b/IDEHelper/Compiler/BfStmtEvaluator.cpp index b318ac2a..8f0ee998 100644 --- a/IDEHelper/Compiler/BfStmtEvaluator.cpp +++ b/IDEHelper/Compiler/BfStmtEvaluator.cpp @@ -2438,16 +2438,9 @@ void BfModule::HandleCaseEnumMatch_Tuple(BfTypedValue tupleVal, const BfSizedArr if (prevHadFallthrough) Fail("Destructuring cannot be used when the previous case contains a fallthrough", expr); + + CreateOutVariable(expr, varDecl, NULL, tupleElement.mType, tupleElement); - auto localVar = HandleVariableDeclaration(varDecl, tupleElement, false, true); - localVar->mReadFromId = 0; // Don't give usage errors for binds - - auto curScope = mCurMethodState->mCurScope; - if (curScope->mScopeKind == BfScopeKind_StatementTarget) - { - // Move this variable into the parent scope - curScope->mLocalVarStart = localVar->mLocalVarIdx + 1; - } continue; } @@ -2473,10 +2466,7 @@ void BfModule::HandleCaseEnumMatch_Tuple(BfTypedValue tupleVal, const BfSizedArr localVar->mReadFromId = 0; // Don't give usage errors for binds auto curScope = mCurMethodState->mCurScope; if (curScope->mScopeKind == BfScopeKind_StatementTarget) - { - // Move this variable into the parent scope - curScope->mLocalVarStart = localVar->mLocalVarIdx + 1; - } + MoveLocalToParentScope(localVar); continue; } }