From ae53196e74ae7a45635caf85b41d36663053a0c2 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Wed, 16 Feb 2022 08:28:05 -0500 Subject: [PATCH] Const lhs handling of ??, cond var assignment in CreateConditionalScope --- IDE/Tests/CompileFail001/src/LocalVars.bf | 18 +++++++++++++++ IDEHelper/Compiler/BfExprEvaluator.cpp | 27 ++++++++++++++++++----- IDEHelper/Compiler/BfModule.cpp | 27 ++++++++++++++++++++--- IDEHelper/Compiler/BfModule.h | 2 +- IDEHelper/Compiler/BfStmtEvaluator.cpp | 2 +- 5 files changed, 65 insertions(+), 11 deletions(-) diff --git a/IDE/Tests/CompileFail001/src/LocalVars.bf b/IDE/Tests/CompileFail001/src/LocalVars.bf index bd48b0bc..54361d2d 100644 --- a/IDE/Tests/CompileFail001/src/LocalVars.bf +++ b/IDE/Tests/CompileFail001/src/LocalVars.bf @@ -324,5 +324,23 @@ namespace IDETest } } + + public void Local7() + { + int a = 1; + int b; + int c; + int d; + + if ((a == 1) && ({b = 2; if (a == 1) {c = 1;} a == 1})) + { + int a2 = a; + int b2 = b; + int c2 = c; //FAIL + } + int a3 = a; + int b3 = b; //FAIL + int c3 = c; //FAIL + } } } diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 9a0819ca..5d8b0fc2 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -21360,13 +21360,10 @@ void BfExprEvaluator::PerformBinaryOperation(BfExpression* leftExpression, BfExp auto rhsBB = mModule->mBfIRBuilder->CreateBlock("land.rhs"); auto endBB = mModule->mBfIRBuilder->CreateBlock("land.end"); - // This makes any 'scope' allocs be dyn since we aren't sure if this will be short-circuited - SetAndRestoreValue prevIsConditional(mModule->mCurMethodState->mCurScope->mIsConditional, true); - mModule->mBfIRBuilder->CreateCondBr(leftValue.mValue, rhsBB, endBB); mModule->AddBasicBlock(rhsBB); - rightValue = mModule->CreateValueFromExpression(rightExpression, boolType, (BfEvalExprFlags)(mBfEvalExprFlags & BfEvalExprFlags_InheritFlags)); + rightValue = mModule->CreateValueFromExpression(rightExpression, boolType, (BfEvalExprFlags)((mBfEvalExprFlags & BfEvalExprFlags_InheritFlags) | BfEvalExprFlags_CreateConditionalScope)); mModule->mBfIRBuilder->CreateBr(endBB); auto endRhsBB = mModule->mBfIRBuilder->GetInsertBlock(); @@ -21472,6 +21469,22 @@ bool BfExprEvaluator::PerformBinaryOperation_NullCoalesce(BfTokenNode* opToken, { leftValue = mModule->LoadValue(leftValue); + if (leftValue.mValue.IsConst()) + { + auto constant = mModule->mBfIRBuilder->GetConstant(leftValue.mValue); + if (constant->IsNull()) + { + mResult = mModule->CreateValueFromExpression(rightExpression, wantType, (BfEvalExprFlags)(mBfEvalExprFlags & BfEvalExprFlags_InheritFlags)); + return true; + } + + // Already have a value, we don't need the right side + SetAndRestoreValue prevIgnoreWrites(mModule->mBfIRBuilder->mIgnoreWrites, true); + mModule->CreateValueFromExpression(rightExpression, wantType, (BfEvalExprFlags)((mBfEvalExprFlags & BfEvalExprFlags_InheritFlags) | BfEvalExprFlags_CreateConditionalScope)); + mResult = leftValue; + return true; + } + auto prevBB = mModule->mBfIRBuilder->GetInsertBlock(); auto rhsBB = mModule->mBfIRBuilder->CreateBlock("nullc.rhs"); auto endBB = mModule->mBfIRBuilder->CreateBlock("nullc.end"); @@ -21488,10 +21501,12 @@ bool BfExprEvaluator::PerformBinaryOperation_NullCoalesce(BfTokenNode* opToken, mModule->AddBasicBlock(rhsBB); BfTypedValue rightValue; + + if (assignTo != NULL) - rightValue = mModule->CreateValueFromExpression(rightExpression, wantType, (BfEvalExprFlags)((mBfEvalExprFlags & BfEvalExprFlags_InheritFlags))); + rightValue = mModule->CreateValueFromExpression(rightExpression, wantType, (BfEvalExprFlags)((mBfEvalExprFlags & BfEvalExprFlags_InheritFlags) | BfEvalExprFlags_CreateConditionalScope)); else - rightValue = mModule->CreateValueFromExpression(rightExpression, wantType, (BfEvalExprFlags)((mBfEvalExprFlags & BfEvalExprFlags_InheritFlags) | BfEvalExprFlags_NoCast)); + rightValue = mModule->CreateValueFromExpression(rightExpression, wantType, (BfEvalExprFlags)((mBfEvalExprFlags & BfEvalExprFlags_InheritFlags) | BfEvalExprFlags_NoCast | BfEvalExprFlags_CreateConditionalScope)); if (!rightValue) { diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 306d19ac..c78cc61b 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -8621,8 +8621,19 @@ BfTypedValue BfModule::FlushNullConditional(BfTypedValue result, bool ignoreNull return result; } -BF_NOINLINE void BfModule::EvaluateWithNewScope(BfExprEvaluator& exprEvaluator, BfExpression* expr, BfEvalExprFlags flags) +BF_NOINLINE void BfModule::EvaluateWithNewConditionalScope(BfExprEvaluator& exprEvaluator, BfExpression* expr, BfEvalExprFlags flags) { + BfDeferredLocalAssignData deferredLocalAssignData(mCurMethodState->mCurScope); + SetAndRestoreValue prevDLA(mCurMethodState->mDeferredLocalAssignData); + if (mCurMethodState != NULL) + { + deferredLocalAssignData.mIsIfCondition = true; + deferredLocalAssignData.mIfMayBeSkipped = true; + deferredLocalAssignData.ExtendFrom(mCurMethodState->mDeferredLocalAssignData, false); + deferredLocalAssignData.mVarIdBarrier = mCurMethodState->GetRootMethodState()->mCurLocalVarId; + mCurMethodState->mDeferredLocalAssignData = &deferredLocalAssignData; + } + BfScopeData newScope; newScope.mOuterIsConditional = true; newScope.mAllowTargeting = false; @@ -8630,9 +8641,11 @@ BF_NOINLINE void BfModule::EvaluateWithNewScope(BfExprEvaluator& exprEvaluator, { mCurMethodState->AddScope(&newScope); NewScopeState(true, false); - } + } + exprEvaluator.mBfEvalExprFlags = (BfEvalExprFlags)(exprEvaluator.mBfEvalExprFlags | flags); exprEvaluator.Evaluate(expr, (flags & BfEvalExprFlags_PropogateNullConditional) != 0, (flags & BfEvalExprFlags_IgnoreNullConditional) != 0, (flags & BfEvalExprFlags_AllowSplat) != 0); + if (mCurMethodState != NULL) RestoreScopeState(); } @@ -8669,7 +8682,15 @@ BfTypedValue BfModule::CreateValueFromExpression(BfExprEvaluator& exprEvaluator, if ((flags & BfEvalExprFlags_CreateConditionalScope) != 0) { - EvaluateWithNewScope(exprEvaluator, expr, flags); + if ((mCurMethodState == NULL) || (mCurMethodState->mCurScope->mScopeKind != BfScopeKind_StatementTarget_Conditional)) + { + EvaluateWithNewConditionalScope(exprEvaluator, expr, flags); + } + else + { + SetAndRestoreValue prevIsConditional(mCurMethodState->mCurScope->mIsConditional, true); + exprEvaluator.Evaluate(expr, (flags & BfEvalExprFlags_PropogateNullConditional) != 0, (flags & BfEvalExprFlags_IgnoreNullConditional) != 0, true); + } } else exprEvaluator.Evaluate(expr, (flags & BfEvalExprFlags_PropogateNullConditional) != 0, (flags & BfEvalExprFlags_IgnoreNullConditional) != 0, true); diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index 068b424e..28ab594f 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -1942,7 +1942,7 @@ public: BfIRFunction GetIntrinsic(BfMethodInstance* methodInstance, bool reportFailure = false); BfIRFunction GetBuiltInFunc(BfBuiltInFuncType funcType); BfIRValue CreateFunctionFrom(BfMethodInstance* methodInstance, bool tryExisting, bool isInlined); - void EvaluateWithNewScope(BfExprEvaluator& exprEvaluator, BfExpression* expr, BfEvalExprFlags flags); + void EvaluateWithNewConditionalScope(BfExprEvaluator& exprEvaluator, BfExpression* expr, BfEvalExprFlags flags); BfTypedValue CreateValueFromExpression(BfExprEvaluator& exprEvaluator, BfExpression* expr, BfType* wantTypeRef = NULL, BfEvalExprFlags flags = BfEvalExprFlags_None, BfType** outOrigType = NULL); BfTypedValue CreateValueFromExpression(BfExpression* expr, BfType* wantTypeRef = NULL, BfEvalExprFlags flags = BfEvalExprFlags_None, BfType** outOrigType = NULL); BfTypedValue GetOrCreateVarAddr(BfExpression* expr); diff --git a/IDEHelper/Compiler/BfStmtEvaluator.cpp b/IDEHelper/Compiler/BfStmtEvaluator.cpp index 738f6b67..2a47f177 100644 --- a/IDEHelper/Compiler/BfStmtEvaluator.cpp +++ b/IDEHelper/Compiler/BfStmtEvaluator.cpp @@ -3667,7 +3667,7 @@ void BfModule::DoIfStatement(BfIfStatement* ifStmt, bool includeTrueStmt, bool i UpdateSrcPos(ifStmt); BfScopeData newScope; - newScope.mOuterIsConditional = true; + newScope.mOuterIsConditional = true; newScope.mScopeKind = BfScopeKind_StatementTarget; if (ifStmt->mLabelNode != NULL) newScope.mLabelNode = ifStmt->mLabelNode->mLabel;