From c107a332684a81e545f925982a3993fcd96aa8a5 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Mon, 15 Nov 2021 16:44:28 -0800 Subject: [PATCH] Handle block splitting in tuple match --- IDEHelper/Compiler/BfIRCodeGen.cpp | 4 + IDEHelper/Compiler/BfIRCodeGen.h | 1 + IDEHelper/Compiler/BfModule.h | 2 +- IDEHelper/Compiler/BfStmtEvaluator.cpp | 148 +++++++++++++------------ 4 files changed, 84 insertions(+), 71 deletions(-) diff --git a/IDEHelper/Compiler/BfIRCodeGen.cpp b/IDEHelper/Compiler/BfIRCodeGen.cpp index 94ec1b69..ea4ebd87 100644 --- a/IDEHelper/Compiler/BfIRCodeGen.cpp +++ b/IDEHelper/Compiler/BfIRCodeGen.cpp @@ -2519,6 +2519,8 @@ void BfIRCodeGen::HandleNextCmd() case BfIRCmd_SetInsertPoint: { CMD_PARAM(llvm::BasicBlock*, block); + if (mLockedBlocks.Contains(block)) + Fail("Attempt to modify locked block"); mIRBuilder->SetInsertPoint(block); } break; @@ -3861,6 +3863,8 @@ void BfIRCodeGen::HandleNextCmd() if (!useAsm) { + mLockedBlocks.Add(irBuilder->GetInsertBlock()); + // This is generates slower code than the inline asm in debug mode, but can optimize well in release auto int8Ty = llvm::Type::getInt8Ty(*mLLVMContext); auto int8Ptr = irBuilder->CreateBitCast(val, int8Ty->getPointerTo()); diff --git a/IDEHelper/Compiler/BfIRCodeGen.h b/IDEHelper/Compiler/BfIRCodeGen.h index 719a9f6b..30285c51 100644 --- a/IDEHelper/Compiler/BfIRCodeGen.h +++ b/IDEHelper/Compiler/BfIRCodeGen.h @@ -117,6 +117,7 @@ public: Dictionary mReflectDataMap; Dictionary mAlignedTypeToNormalType; Dictionary mTypeToTypeIdMap; + HashSet mLockedBlocks; public: void InitTarget(); diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index e306457b..2b1acfcb 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -1800,7 +1800,7 @@ public: void CheckTupleVariableDeclaration(BfTupleExpression* tupleExpr, BfType* initType); void HandleTupleVariableDeclaration(BfVariableDeclaration* varDecl, BfTupleExpression* tupleExpr, BfTypedValue initTupleValue, bool isReadOnly, bool isConst, bool forceAddr, BfIRBlock* declBlock = NULL); void HandleTupleVariableDeclaration(BfVariableDeclaration* varDecl); - void HandleCaseEnumMatch_Tuple(BfTypedValue tupleVal, const BfSizedArray& arguments, BfAstNode* tooFewRef, BfIRValue phiVal, BfIRBlock& matchedBlock, BfIRBlock falseBlock, bool& hadConditional, bool clearOutOnMismatch); + void HandleCaseEnumMatch_Tuple(BfTypedValue tupleVal, const BfSizedArray& arguments, BfAstNode* tooFewRef, BfIRValue phiVal, BfIRBlock& matchedBlockStart, BfIRBlock& matchedBlockEnd, BfIRBlock& falseBlockStart, BfIRBlock& falseBlockEnd, bool& hadConditional, bool clearOutOnMismatch); BfTypedValue TryCaseTupleMatch(BfTypedValue tupleVal, BfTupleExpression* tupleExpr, BfIRBlock* eqBlock, BfIRBlock* notEqBlock, BfIRBlock* matchBlock, bool& hadConditional, bool clearOutOnMismatch); BfTypedValue TryCaseEnumMatch(BfTypedValue enumVal, BfTypedValue tagVal, BfExpression* expr, BfIRBlock* eqBlock, BfIRBlock* notEqBlock, BfIRBlock* matchBlock, int& uncondTagId, bool& hadConditional, bool clearOutOnMismatch); BfTypedValue HandleCaseBind(BfTypedValue enumVal, const BfTypedValue& tagVal, BfEnumCaseBindExpression* bindExpr, BfIRBlock* eqBlock = NULL, BfIRBlock* notEqBlock = NULL, BfIRBlock* matchBlock = NULL, int* outEnumIdx = NULL); diff --git a/IDEHelper/Compiler/BfStmtEvaluator.cpp b/IDEHelper/Compiler/BfStmtEvaluator.cpp index de932d27..e2a8a117 100644 --- a/IDEHelper/Compiler/BfStmtEvaluator.cpp +++ b/IDEHelper/Compiler/BfStmtEvaluator.cpp @@ -2216,7 +2216,7 @@ void BfModule::HandleTupleVariableDeclaration(BfVariableDeclaration* varDecl) AssertErrorState(); } -void BfModule::HandleCaseEnumMatch_Tuple(BfTypedValue tupleVal, const BfSizedArray& arguments, BfAstNode* tooFewRef, BfIRValue phiVal, BfIRBlock& matchedBlock, BfIRBlock falseBlock, bool& hadConditional, bool clearOutOnMismatch) +void BfModule::HandleCaseEnumMatch_Tuple(BfTypedValue tupleVal, const BfSizedArray& arguments, BfAstNode* tooFewRef, BfIRValue phiVal, BfIRBlock& matchedBlockStart, BfIRBlock& matchedBlockEnd, BfIRBlock& falseBlockStart, BfIRBlock& falseBlockEnd, bool& hadConditional, bool clearOutOnMismatch) { SetAndRestoreValue prevInCondBlock(mCurMethodState->mInConditionalBlock); @@ -2297,7 +2297,7 @@ void BfModule::HandleCaseEnumMatch_Tuple(BfTypedValue tupleVal, const BfSizedArr tooFewRef = tupleExpr->mValues[tupleExpr->mValues.size() - 1]; if (tooFewRef == NULL) tooFewRef = tupleExpr->mOpenParen; - HandleCaseEnumMatch_Tuple(tupleElement, tupleExpr->mValues, tooFewRef, phiVal, matchedBlock, falseBlock, hadConditional, clearOutOnMismatch); + HandleCaseEnumMatch_Tuple(tupleElement, tupleExpr->mValues, tooFewRef, phiVal, matchedBlockStart, matchedBlockEnd, falseBlockStart, falseBlockEnd, hadConditional, clearOutOnMismatch); continue; } } @@ -2345,10 +2345,17 @@ void BfModule::HandleCaseEnumMatch_Tuple(BfTypedValue tupleVal, const BfSizedArr { tupleElement = LoadValue(tupleElement); + bool isMatchedBlockEnd = matchedBlockEnd == mBfIRBuilder->GetInsertBlock(); + bool isFalseBlockEnd = falseBlockEnd == mBfIRBuilder->GetInsertBlock(); + BfExprEvaluator exprEvaluator(this); exprEvaluator.mExpectingType = tupleFieldInstance->GetResolvedType(); exprEvaluator.mBfEvalExprFlags = BfEvalExprFlags_AllowOutExpr; exprEvaluator.Evaluate(expr); + if (isMatchedBlockEnd) + matchedBlockEnd = mBfIRBuilder->GetInsertBlock(); + if (isFalseBlockEnd) + falseBlockEnd = mBfIRBuilder->GetInsertBlock(); auto argValue = exprEvaluator.mResult; if (!argValue) continue; @@ -2388,17 +2395,18 @@ void BfModule::HandleCaseEnumMatch_Tuple(BfTypedValue tupleVal, const BfSizedArr auto insertBlock = mBfIRBuilder->GetInsertBlock(); mBfIRBuilder->AddPhiIncoming(phiVal, mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 0), insertBlock); } - matchedBlock = mBfIRBuilder->CreateBlock("match", false); - mBfIRBuilder->CreateCondBr(exprResult.mValue, matchedBlock, falseBlock); - mBfIRBuilder->AddBlock(matchedBlock); - mBfIRBuilder->SetInsertPoint(matchedBlock); + matchedBlockStart = matchedBlockEnd = mBfIRBuilder->CreateBlock("match", false); + + mBfIRBuilder->CreateCondBr(exprResult.mValue, matchedBlockStart, falseBlockStart); + mBfIRBuilder->AddBlock(matchedBlockStart); + mBfIRBuilder->SetInsertPoint(matchedBlockStart); } } } if (!deferredAssigns.empty()) - mBfIRBuilder->SetInsertPoint(matchedBlock); + mBfIRBuilder->SetInsertPoint(matchedBlockEnd); // We assign these only after the value checks succeed for (auto& deferredAssign : deferredAssigns) @@ -2413,7 +2421,7 @@ void BfModule::HandleCaseEnumMatch_Tuple(BfTypedValue tupleVal, const BfSizedArr if ((clearOutOnMismatch) && (!deferredAssigns.IsEmpty())) { auto curInsertPoint = mBfIRBuilder->GetInsertBlock(); - mBfIRBuilder->SetInsertPoint(falseBlock); + mBfIRBuilder->SetInsertPoint(falseBlockEnd); for (auto& deferredAssign : deferredAssigns) { auto tupleFieldInstance = &tupleType->mFieldInstances[deferredAssign.mFieldIdx]; @@ -2428,6 +2436,7 @@ void BfModule::HandleCaseEnumMatch_Tuple(BfTypedValue tupleVal, const BfSizedArr continue; mBfIRBuilder->CreateMemSet(argValue.mValue, GetConstValue8(0), GetConstValue(argValue.mType->mSize), GetConstValue(argValue.mType->mAlign)); } + falseBlockEnd = mBfIRBuilder->GetInsertBlock(); mBfIRBuilder->SetInsertPoint(curInsertPoint); } @@ -2544,63 +2553,61 @@ BfTypedValue BfModule::TryCaseTupleMatch(BfTypedValue tupleVal, BfTupleExpressio //auto dscrType = enumType->GetDiscriminatorType(); //BfIRValue eqResult = mBfIRBuilder->CreateCmpEQ(tagVal.mValue, mBfIRBuilder->CreateConst(dscrType->mTypeDef->mTypeCode, tagId)); - BfIRBlock falseBlock; - BfIRBlock doneBlock; + BfIRBlock falseBlockStart; + BfIRBlock falseBlockEnd; + BfIRBlock doneBlockStart; if (notEqBlock != NULL) - doneBlock = *notEqBlock; + doneBlockStart = *notEqBlock; else - doneBlock = mBfIRBuilder->CreateBlock("caseDone", false); + doneBlockStart = mBfIRBuilder->CreateBlock("caseDone", false); + BfIRBlock doneBlockEnd = doneBlockStart; if (clearOutOnMismatch) { - falseBlock = mBfIRBuilder->CreateBlock("caseNotEq", false); - mBfIRBuilder->AddBlock(falseBlock); + falseBlockStart = falseBlockEnd = mBfIRBuilder->CreateBlock("caseNotEq", false); + mBfIRBuilder->AddBlock(falseBlockStart); } - BfIRBlock matchedBlock = mBfIRBuilder->CreateBlock("caseMatch", false); + BfIRBlock matchedBlockStart = mBfIRBuilder->CreateBlock("caseMatch", false); if (matchBlock != NULL) - *matchBlock = matchedBlock; - mBfIRBuilder->CreateBr(matchedBlock); - mBfIRBuilder->AddBlock(matchedBlock); + *matchBlock = matchedBlockStart; + mBfIRBuilder->CreateBr(matchedBlockStart); + mBfIRBuilder->AddBlock(matchedBlockStart); - mBfIRBuilder->SetInsertPoint(doneBlock); + mBfIRBuilder->SetInsertPoint(doneBlockEnd); BfIRValue phiVal; if (eqBlock == NULL) phiVal = mBfIRBuilder->CreatePhi(mBfIRBuilder->MapType(boolType), 2); - if (phiVal) - { - auto falseVal = mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 0); - - if (falseBlock) - mBfIRBuilder->AddPhiIncoming(phiVal, falseVal, falseBlock); -// else -// mBfIRBuilder->AddPhiIncoming(phiVal, falseVal, startBlock); - } - - mBfIRBuilder->SetInsertPoint(matchedBlock); - - HandleCaseEnumMatch_Tuple(tupleVal, tupleExpr->mValues, tooFewRef, falseBlock ? BfIRValue() : phiVal, matchedBlock, falseBlock ? falseBlock : doneBlock, hadConditional, clearOutOnMismatch); + + mBfIRBuilder->SetInsertPoint(matchedBlockStart); + BfIRBlock matchedBlockEnd = matchedBlockStart; + HandleCaseEnumMatch_Tuple(tupleVal, tupleExpr->mValues, tooFewRef, falseBlockStart ? BfIRValue() : phiVal, matchedBlockStart, matchedBlockEnd, + falseBlockStart ? falseBlockStart : doneBlockStart, falseBlockEnd ? falseBlockEnd : doneBlockEnd, hadConditional, clearOutOnMismatch); if (phiVal) { + auto falseVal = mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 0); + if (falseBlockEnd) + mBfIRBuilder->AddPhiIncoming(phiVal, falseVal, falseBlockEnd); + auto trueVal = mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 1); - mBfIRBuilder->AddPhiIncoming(phiVal, trueVal, matchedBlock); + mBfIRBuilder->AddPhiIncoming(phiVal, trueVal, matchedBlockEnd); } if (eqBlock != NULL) mBfIRBuilder->CreateBr(*eqBlock); else - mBfIRBuilder->CreateBr(doneBlock); + mBfIRBuilder->CreateBr(doneBlockStart); - if (falseBlock) + if (falseBlockEnd) { - mBfIRBuilder->SetInsertPoint(falseBlock); - mBfIRBuilder->CreateBr(doneBlock); + mBfIRBuilder->SetInsertPoint(falseBlockEnd); + mBfIRBuilder->CreateBr(doneBlockStart); //mBfIRBuilder->AddPhiIncoming(phiVal, mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 0), falseBlock); } - mBfIRBuilder->AddBlock(doneBlock); - mBfIRBuilder->SetInsertPoint(doneBlock); + mBfIRBuilder->AddBlock(doneBlockStart); + mBfIRBuilder->SetInsertPoint(doneBlockEnd); if (phiVal) return BfTypedValue(phiVal, boolType); @@ -2709,41 +2716,35 @@ BfTypedValue BfModule::TryCaseEnumMatch(BfTypedValue enumVal, BfTypedValue tagVa auto dscrType = enumType->GetDiscriminatorType(); BfIRValue eqResult = mBfIRBuilder->CreateCmpEQ(tagVal.mValue, mBfIRBuilder->CreateConst(dscrType->mTypeDef->mTypeCode, tagId)); - BfIRBlock falseBlock; - BfIRBlock doneBlock; + BfIRBlock falseBlockStart; + BfIRBlock falseBlockEnd; + BfIRBlock doneBlockStart; + BfIRBlock doneBlockEnd; if (notEqBlock != NULL) - doneBlock = *notEqBlock; + doneBlockStart = doneBlockEnd = *notEqBlock; else - doneBlock = mBfIRBuilder->CreateBlock("caseDone", false); + doneBlockStart = doneBlockEnd = mBfIRBuilder->CreateBlock("caseDone", false); if (clearOutOnMismatch) { - falseBlock = mBfIRBuilder->CreateBlock("caseNotEq", false); - mBfIRBuilder->AddBlock(falseBlock); + falseBlockStart = falseBlockEnd = mBfIRBuilder->CreateBlock("caseNotEq", false); + mBfIRBuilder->AddBlock(falseBlockStart); } - BfIRBlock matchedBlock = mBfIRBuilder->CreateBlock("caseMatch", false); + BfIRBlock matchedBlockStart = mBfIRBuilder->CreateBlock("caseMatch", false); + BfIRBlock matchedBlockEnd = matchedBlockStart; if (matchBlock != NULL) - *matchBlock = matchedBlock; - mBfIRBuilder->CreateCondBr(eqResult, matchedBlock, falseBlock ? falseBlock : doneBlock); + *matchBlock = matchedBlockStart; + mBfIRBuilder->CreateCondBr(eqResult, matchedBlockStart, falseBlockStart ? falseBlockStart : doneBlockStart); - mBfIRBuilder->AddBlock(matchedBlock); + mBfIRBuilder->AddBlock(matchedBlockStart); - mBfIRBuilder->SetInsertPoint(doneBlock); + mBfIRBuilder->SetInsertPoint(doneBlockEnd); BfIRValue phiVal; if (eqBlock == NULL) phiVal = mBfIRBuilder->CreatePhi(mBfIRBuilder->MapType(boolType), 1 + (int)tupleType->mFieldInstances.size()); - if (phiVal) - { - auto falseVal = mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 0); - - if (falseBlock) - mBfIRBuilder->AddPhiIncoming(phiVal, falseVal, falseBlock); - else - mBfIRBuilder->AddPhiIncoming(phiVal, falseVal, startBlock); - } - - mBfIRBuilder->SetInsertPoint(matchedBlock); + + mBfIRBuilder->SetInsertPoint(matchedBlockEnd); BfTypedValue tupleVal; if (!enumVal.IsAddr()) @@ -2848,30 +2849,37 @@ BfTypedValue BfModule::TryCaseEnumMatch(BfTypedValue enumVal, BfTypedValue tagVa /// - HandleCaseEnumMatch_Tuple(tupleVal, invocationExpr->mArguments, tooFewRef, falseBlock ? BfIRValue() : phiVal, matchedBlock, falseBlock ? falseBlock : doneBlock, hadConditional, clearOutOnMismatch); + HandleCaseEnumMatch_Tuple(tupleVal, invocationExpr->mArguments, tooFewRef, falseBlockStart ? BfIRValue() : phiVal, matchedBlockStart, matchedBlockEnd, + falseBlockStart ? falseBlockStart : doneBlockStart, falseBlockEnd ? falseBlockEnd : doneBlockEnd, + hadConditional, clearOutOnMismatch); /////// if (phiVal) { + auto falseVal = mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 0); + if (falseBlockEnd) + mBfIRBuilder->AddPhiIncoming(phiVal, falseVal, falseBlockEnd); + else + mBfIRBuilder->AddPhiIncoming(phiVal, falseVal, startBlock); auto trueVal = mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 1); - mBfIRBuilder->AddPhiIncoming(phiVal, trueVal, matchedBlock); + mBfIRBuilder->AddPhiIncoming(phiVal, trueVal, matchedBlockEnd); } if (eqBlock != NULL) mBfIRBuilder->CreateBr(*eqBlock); else - mBfIRBuilder->CreateBr(doneBlock); + mBfIRBuilder->CreateBr(doneBlockStart); - if (falseBlock) + if (falseBlockEnd) { - mBfIRBuilder->SetInsertPoint(falseBlock); - mBfIRBuilder->CreateBr(doneBlock); + mBfIRBuilder->SetInsertPoint(falseBlockEnd); + mBfIRBuilder->CreateBr(doneBlockStart); //mBfIRBuilder->AddPhiIncoming(phiVal, mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 0), falseBlock); } - mBfIRBuilder->AddBlock(doneBlock); - mBfIRBuilder->SetInsertPoint(doneBlock); + mBfIRBuilder->AddBlock(doneBlockStart); + mBfIRBuilder->SetInsertPoint(doneBlockEnd); if (phiVal) return BfTypedValue(phiVal, boolType); @@ -5775,7 +5783,7 @@ void BfModule::Visit(BfForStatement* forStmt) } void BfModule::DoForLess(BfForEachStatement* forEachStmt) -{ +{ UpdateSrcPos(forEachStmt); auto startBB = mBfIRBuilder->GetInsertBlock();