From f0c08ba7352b94da821f4493ddc305276f9b8494 Mon Sep 17 00:00:00 2001 From: Clark Coleman <clc@zephyr-software.com> Date: Fri, 23 Oct 2020 08:44:21 -0400 Subject: [PATCH] SPARK: Prep work for loops with multiple follow blocks. --- include/base/SMPFunction.h | 4 +- src/base/SMPBasicBlock.cpp | 14 ++--- src/base/SMPFunction.cpp | 108 +++++++++++++++++++++++++++---------- 3 files changed, 90 insertions(+), 36 deletions(-) diff --git a/include/base/SMPFunction.h b/include/base/SMPFunction.h index e1387ed1..dbfaf3c4 100644 --- a/include/base/SMPFunction.h +++ b/include/base/SMPFunction.h @@ -785,7 +785,7 @@ private: std::vector<int> LoopTypesByLoopNum; // indexed by loop number: top-testing, bottom-testing, middle-testing or infinite std::vector<int> LoopTestBlocksByLoopNum; // indexed by loop number; block number of header block for top-testing or tail block for bottom-testing, -1 for middle-testing std::vector<int> LoopHeadBlockNumbers; // indexed by loop number; block number of header block - std::vector<int> LoopFollowNodes; // indexed by loop number; block number of follow block + std::vector<std::set<int> > LoopFollowNodes; // indexed by loop number; block number of follow block std::vector<bool> LoopHasMultipleExits; std::vector<bool> LoopWritesMemory; // static, indirect or indexed writes std::vector<bool> LoopReadsMemory; // static, indirect or indexed reads @@ -1008,6 +1008,8 @@ private: bool AnalyzeMemWriteSafety(void); // Try to find safe indirect memory writes void UpdateLoopFollowBlockNum(int HeaderBlockNum, int FollowBlockNum); int FindFollowBlockNum(SMPBasicBlock *CurrBlock, bool StartAtLastInst = false); // Based on control flow structure of CurrBlock, find Ada follow block num; -1 if no structure besides fall-through + bool GetLoopFollowBlockNum(const std::size_t LoopNum, int &FirstFollowBlockNum) const; // return true if loop has multiple follow blocks + bool IsBlockLoopFollowBlock(const std::size_t LoopNum, const int BlockNum) const; // found in LoopFollowNodes[LoopNum] set? bool AnalyzeSwitchStatement(SMPBasicBlock *CurrBlock); // Analyze switch starting at indir jump at end of CurrBlock; return false if not well-structured void FindSwitchIDom(struct SwitchTableInfo &TableInfo); // Mark jumps to default case, find IDom of entire switch statement void BuildShadowCFG(void); // build skeleton CFG, then use in coalescing nodes to analyze expressions diff --git a/src/base/SMPBasicBlock.cpp b/src/base/SMPBasicBlock.cpp index ae218db6..dd7cbb25 100644 --- a/src/base/SMPBasicBlock.cpp +++ b/src/base/SMPBasicBlock.cpp @@ -567,14 +567,12 @@ void SMPBasicBlock::EmitSPARKAdaForFallThroughInsts(FILE *BodyFile) { STARS_ea_t InstAddr = CurrInst->GetAddr(); bool ControlFlowTerminator = ((InstAddr == LastID) && CurrInst->IsBasicBlockTerminator()); bool Untranslatable = CurrInst->IsMarkerInst() || (!CurrInst->IsAnalyzeable()); - if (!ControlFlowTerminator && (!Untranslatable)) { - CurrInst->EmitSPARKAda(BodyFile); - } - else { + if (Untranslatable) { // Set junk instructions to translated. - if (Untranslatable) { - CurrInst->SetSPARKTranslated(); - } + CurrInst->SetSPARKTranslated(); + } + else if (!ControlFlowTerminator) { + CurrInst->EmitSPARKAda(BodyFile); } } this->SetProcessed(true); @@ -2741,9 +2739,11 @@ void SMPBasicBlock::FreeReachingDefsMemory(void) { // Free SSA data structures that are no longer needed when all SSA numbers have // been recorded in DEFs and USEs. void SMPBasicBlock::FreeSSAMemory(void) { +#if 0 this->DomFrontier.clear(); #if SMP_SHRINK_TO_FIT std::set<int>(this->DomFrontier).swap(this->DomFrontier); +#endif #endif return; } // end of SMPBasicBlock::FreeSSAMemory() diff --git a/src/base/SMPFunction.cpp b/src/base/SMPFunction.cpp index 4d14ad5c..ab0f5dc9 100644 --- a/src/base/SMPFunction.cpp +++ b/src/base/SMPFunction.cpp @@ -6857,7 +6857,9 @@ void SMPFunction::FindLoopHeadsAndTails(SMPBasicBlock *CurrBlock) { } else { this->LoopHeadBlockNumbers.push_back(HeaderBlockNum); - this->LoopFollowNodes.push_back(FollowBlockNum); + set<int> DummySet; + DummySet.insert(FollowBlockNum); + this->LoopFollowNodes.push_back(DummySet); ++this->LoopCount; assert(this->LoopHeadBlockNumbers.size() == this->LoopCount); // If this is a double tail block, we need to arrange Loop N == inner, loop N-1 == outer. @@ -11819,7 +11821,11 @@ int SMPFunction::FindConditionalFollowNode(int HeadBlockNum) { if (this->IsBlockInAnyLoop(HeadBlockNum)) { int InnerMostLoopNum = this->GetInnermostLoopNum(HeadBlockNum); assert(0 <= InnerMostLoopNum); - int InnerMostFollowBlockNum = this->LoopFollowNodes[(size_t)InnerMostLoopNum]; + int InnerMostFollowBlockNum = SMP_BLOCKNUM_UNINIT; + bool MultiExitLoop = this->GetLoopFollowBlockNum((size_t)InnerMostLoopNum, InnerMostFollowBlockNum); + if (MultiExitLoop) { + InnerMostFollowBlockNum = SMP_BLOCKNUM_UNINIT; // error + } bool HitLoopFollowBlock = false; // If we did not find a FollowBlockNum, this will be a zero-trip loop. for (int BlockIndex = HeadBlockNum; BlockIndex < FollowBlockNum; ++BlockIndex) { @@ -12036,25 +12042,31 @@ int SMPFunction::FindConditionalFollowNode(int HeadBlockNum) { // If the ThenBlock is a loop header block, then the candidate ThenFollowBlock is just // the follow block for that loop. We will probably end up with -1 as our final // return value, as the ElseBlock will produce a different candidate. - int ThenFollowBlockNum; + int ThenFollowBlockNum = SMP_BLOCKNUM_UNINIT; SMPBasicBlock *ThenBlock = this->GetBlockByNum(ThenBlockNum); if (ThenBlock->IsLoopHeaderBlock()) { int ThenLoopNum = this->GetLoopNumFromHeaderBlockNum(ThenBlockNum); assert(0 <= ThenLoopNum); assert(((size_t) ThenLoopNum) < this->LoopFollowNodes.size()); - ThenFollowBlockNum = this->LoopFollowNodes[(size_t) ThenLoopNum]; + bool MultiExitThenLoop = this->GetLoopFollowBlockNum((size_t)ThenLoopNum, ThenFollowBlockNum); + if (MultiExitThenLoop) { + ThenFollowBlockNum = SMP_BLOCKNUM_UNINIT; // error + } } else { ThenFollowBlockNum = this->TrackConditionalBranchTerminus(HeadBlockNum, ThenBlockNum, ThenBlocksSeen, BlockAlreadySeenCounter); BlockAlreadySeenCounter = 0; } - int ElseFollowBlockNum; + int ElseFollowBlockNum = SMP_BLOCKNUM_UNINIT; SMPBasicBlock *ElseBlock = this->GetBlockByNum(ElseBlockNum); if (ElseBlock->IsLoopHeaderBlock()) { int ElseLoopNum = this->GetLoopNumFromHeaderBlockNum(ElseBlockNum); assert(0 <= ElseLoopNum); assert(((size_t) ElseLoopNum) < this->LoopFollowNodes.size()); - ElseFollowBlockNum = this->LoopFollowNodes[(size_t) ElseLoopNum]; + bool MultiExitElseLoop = this->GetLoopFollowBlockNum((size_t)ElseLoopNum, ElseFollowBlockNum); + if (MultiExitElseLoop) { + ElseFollowBlockNum = SMP_BLOCKNUM_UNINIT; // error + } } else { ElseFollowBlockNum = this->TrackConditionalBranchTerminus(HeadBlockNum, ElseBlockNum, ElseBlocksSeen, BlockAlreadySeenCounter); @@ -12329,8 +12341,8 @@ bool SMPFunction::FindMultiLoopContinue(const int BranchBlockNum) const { // Each successor of the COND_BRANCH at the end of BranchBlock // must be in one of the following three categories: // A) Inside the innermost loop containing BranchBlock. - // B) The follow block for the innermost loop containing BranchBlock. - // C) The header block for an outer loop that has the same follow block as the + // B) A follow block for the innermost loop containing BranchBlock. + // C) The header block for an outer loop that has the same (single) follow block as the // innermost loop. // // The SPARK Ada translations of these cases are straightforward: @@ -12348,19 +12360,23 @@ bool SMPFunction::FindMultiLoopContinue(const int BranchBlockNum) const { // An example that fails all three category tests, and is thus an unstructured multi-level // loop continue statement, is seen at basic block #8 in the func at 0x437bf3 in busybox.psexe. - int InnerLoopFollowBlockNum = this->LoopFollowNodes[(size_t)InnerMostLoopNum]; for (list<SMPBasicBlock *>::const_iterator SuccIter = BranchBlock->GetFirstConstSucc(); SuccIter != BranchBlock->GetLastConstSucc(); ++SuccIter) { SMPBasicBlock *SuccBlock = (*SuccIter); int SuccBlockNum = SuccBlock->GetNumber(); if (!this->IsBlockInLoop(SuccBlockNum, (size_t)InnerMostLoopNum)) { // Failed category A test. - if (SuccBlockNum != InnerLoopFollowBlockNum) { + if (!this->IsBlockLoopFollowBlock((size_t)InnerMostLoopNum, SuccBlockNum)) { // Failed category B test. Needs to be header block for outer loop. + int InnerLoopFollowBlockNum = SMP_BLOCKNUM_UNINIT; + bool MultiExitInnerLoop = this->GetLoopFollowBlockNum((size_t)InnerMostLoopNum, InnerLoopFollowBlockNum); int OuterLoopFollowBlockNum = SMP_BLOCKNUM_UNINIT; if (SuccBlock->IsLoopHeaderBlock()) { int OuterLoopNum = this->GetLoopNumFromHeaderBlockNum(SuccBlockNum); assert(0 <= OuterLoopNum); - OuterLoopFollowBlockNum = this->LoopFollowNodes[(size_t)OuterLoopNum]; + bool MultiExitOuterLoop = this->GetLoopFollowBlockNum((size_t)OuterLoopNum, OuterLoopFollowBlockNum); + if (MultiExitInnerLoop || MultiExitOuterLoop) { + Unstructured = true; + } } if (OuterLoopFollowBlockNum != InnerLoopFollowBlockNum) { // Failed category C test. @@ -14345,7 +14361,8 @@ void SMPFunction::AnalyzeLoopIterations(void) { bool CompareAgainstConst = false; // compare ExitUse1 against ExitConstUse2 if true, else ExitUse1 vs. ExitUse2 if ((SMP_BLOCKNUM_UNINIT != TestBlockNum) && ((LoopType == STARS_TOP_TESTING_LOOP) || (LoopType == STARS_BOTTOM_TESTING_LOOP))) { SMPBasicBlock *TestBlock = this->GetBlockByNum(TestBlockNum); - int FollowBlockNum = this->LoopFollowNodes[LoopIndex]; + int FollowBlockNum = SMP_BLOCKNUM_UNINIT; + bool MultiExitLoop = this->GetLoopFollowBlockNum(LoopIndex, FollowBlockNum); list<SMPBasicBlock *>::const_iterator TestTargBlockIter = TestBlock->GetCondNonFallThroughSucc(); if (TestTargBlockIter == TestBlock->GetLastConstSucc()) { SMP_msg("ERROR: LOOP: Could not find NonFallThroughSuccessor in test block %d loop %u in func at %llx\n", @@ -14356,7 +14373,7 @@ void SMPFunction::AnalyzeLoopIterations(void) { } int TestTargBlockNum = (*TestTargBlockIter)->GetNumber(); - bool BranchExitsLoop = (TestTargBlockNum == FollowBlockNum); + bool BranchExitsLoop = ((TestTargBlockNum == FollowBlockNum) || (!this->IsBlockInLoop(TestTargBlockNum, LoopIndex))); CurrentLoopComparisonExpr.ExitsLoop = BranchExitsLoop; SMPoperator BranchOperator = SMP_NULL_OPERATOR; STARS_ea_t DecrementAddr = STARS_BADADDR; @@ -16679,7 +16696,8 @@ bool SMPFunction::PropagateSignedness(void) { void SMPFunction::UpdateLoopFollowBlockNum(int LoopHeadBlockNum, int FollowBlockNum) { assert(SMP_BLOCKNUM_UNINIT != LoopHeadBlockNum); size_t LoopNum = this->FindLoopNumFromHeadBlockNum(LoopHeadBlockNum); - int OldFollowNum = this->LoopFollowNodes[LoopNum]; + int OldFollowNum = SMP_BLOCKNUM_UNINIT; + bool MultiExitLoop = this->GetLoopFollowBlockNum((size_t)LoopNum, OldFollowNum); bool VerboseOutput = global_stars_interface->VerboseSPARKMode(); // Safeguard against infinite loops. If our follow node is inside our loop, @@ -16695,11 +16713,14 @@ void SMPFunction::UpdateLoopFollowBlockNum(int LoopHeadBlockNum, int FollowBlock if (FollowInsideLoop) { SMP_msg("ERROR: SPARK: UpdateLoopFollowBlockNum() ignoring follow block %d inside loop with head block %d in func %s at %llx loop %zu\n", FollowBlockNum, LoopHeadBlockNum, this->GetFuncName(), (uint64_t) this->GetFirstFuncAddr(), LoopNum); + this->DumpDotCFG(); return; } if (OldFollowNum == SMP_BLOCKNUM_UNINIT) { - this->LoopFollowNodes[LoopNum] = FollowBlockNum; + assert(1 == this->LoopFollowNodes[LoopNum].size()); + this->LoopFollowNodes[LoopNum].clear(); + this->LoopFollowNodes[LoopNum].insert(FollowBlockNum); } else if (OldFollowNum != FollowBlockNum) { if (SMP_BLOCKNUM_UNINIT == FollowBlockNum) { @@ -18823,7 +18844,17 @@ void SMPFunction::Dump(void) { } } if (!this->LoopFollowNodes.empty()) { - SMP_msg(" Follow block number: %d", this->LoopFollowNodes[LoopNum]); + int FollowBlockNum = SMP_BLOCKNUM_UNINIT; + bool MultiExitLoop = (1 < this->LoopFollowNodes.size()); + if (!MultiExitLoop) { + SMP_msg(" Follow block number: %d", *(this->LoopFollowNodes[LoopNum].cbegin())); + } + else { + SMP_msg(" Follow block numbers: "); + for (int FollowBlockNum : this->LoopFollowNodes[LoopNum]) { + SMP_msg("%d ", FollowBlockNum); + } + } } SMP_msg("\n"); } @@ -22402,7 +22433,8 @@ void SMPFunction::EmitSPARKAdaForBlock(int CurrBlockNum, int FollowBlockNum, FIL assert(0 <= LoopNum); STARS_ea_t LoopAddr = CurrBlock->GetFirstNonMarkerAddr(); bool TranslatingGuardedLoop = (this->LoopToGuardMap.find(LoopAddr) != this->LoopToGuardMap.cend()); - int NextFollowBlockNum = this->LoopFollowNodes[LoopNum]; + int NextFollowBlockNum = SMP_BLOCKNUM_UNINIT; + bool MultiExitLoop = this->GetLoopFollowBlockNum((size_t)LoopNum, NextFollowBlockNum); // Could end with a loop if we call abort, etc., in which case no follow block. // Could be an infinite loop. Otherwise, we should have a follow block. bool FuncMightNotReturn = ((!this->FuncReturnsToCaller()) || this->HasCallToNonReturningFunc()); @@ -22595,7 +22627,8 @@ void SMPFunction::EmitSPARKAdaForBlock(int CurrBlockNum, int FollowBlockNum, FIL int NextBlockNum = NextBlock->GetNumber(); int LoopNum = this->GetLoopNumFromHeaderBlockNum(NextBlockNum); assert(0 <= LoopNum); - int NextFollowBlockNum = this->LoopFollowNodes[LoopNum]; + int NextFollowBlockNum = SMP_BLOCKNUM_UNINIT; + bool MultiExitLoop = this->GetLoopFollowBlockNum((size_t)LoopNum, NextFollowBlockNum); bool LoopMightBeInfinite = (STARS_INFINITE_OR_MIDDLE_TESTING_LOOP == this->LoopTypesByLoopNum[LoopNum]); // assert((SMP_BLOCKNUM_UNINIT != NextFollowBlockNum) || LoopMightBeInfinite); if (LoopToProc) { @@ -22640,14 +22673,14 @@ void SMPFunction::EmitSPARKAdaForBlock(int CurrBlockNum, int FollowBlockNum, FIL } } else if ((FlowType == CALL) || (FlowType == INDIR_CALL)) { - LastInst->EmitSPARKAda(SPARKBodyFile); + if (!LastInst->HasBeenTranslatedToSPARK()) { + LastInst->EmitSPARKAda(SPARKBodyFile); + } if (LastCFType == FALL_THROUGH) { // if ((FALL_THROUGH == LastCFType) && (ResumeBlockNum < 0)) { - if (FALL_THROUGH == LastCFType) { - list<SMPBasicBlock *>::const_iterator SuccIter = CurrBlock->GetFirstConstSucc(); - if (SuccIter != CurrBlock->GetLastConstSucc()) { - ResumeBlockNum = (*SuccIter)->GetNumber(); - } + list<SMPBasicBlock *>::const_iterator SuccIter = CurrBlock->GetFirstConstSucc(); + if (SuccIter != CurrBlock->GetLastConstSucc()) { + ResumeBlockNum = (*SuccIter)->GetNumber(); } } } @@ -22714,7 +22747,8 @@ void SMPFunction::EmitSPARKAdaForLoop(int HeaderBlockNum, int FollowBlockNum, FI // We have fallen through to an inner loop. Emit a call to the loop proc created later, and jump past inner loop. int LoopNum = this->GetLoopNumFromHeaderBlockNum(CurrBlockNum); assert(0 <= LoopNum); - int NextFollowBlockNum = this->LoopFollowNodes[LoopNum]; + int NextFollowBlockNum = SMP_BLOCKNUM_UNINIT; + bool MultiExitLoop = this->GetLoopFollowBlockNum((size_t)LoopNum, NextFollowBlockNum); bool LoopMightBeInfinite = (STARS_INFINITE_OR_MIDDLE_TESTING_LOOP == this->LoopTypesByLoopNum[LoopNum]); // assert((SMP_BLOCKNUM_UNINIT != NextFollowBlockNum) || LoopMightBeInfinite); this->EmitSPARKAdaLoopCall(CurrBlock->GetFirstAddr(), (size_t) LoopNum, SPARKBodyFile); @@ -22830,7 +22864,8 @@ void SMPFunction::EmitSPARKAdaForLoop(int HeaderBlockNum, int FollowBlockNum, FI int NextBlockNum = NextBlock->GetNumber(); int LoopNum = this->GetLoopNumFromHeaderBlockNum(NextBlockNum); assert(0 <= LoopNum); - int NextFollowBlockNum = this->LoopFollowNodes[LoopNum]; + int NextFollowBlockNum = SMP_BLOCKNUM_UNINIT; + bool MultiExitLoop = this->GetLoopFollowBlockNum((size_t)LoopNum, NextFollowBlockNum); bool LoopMightBeInfinite = (STARS_INFINITE_OR_MIDDLE_TESTING_LOOP == this->LoopTypesByLoopNum[LoopNum]); // assert((SMP_BLOCKNUM_UNINIT != NextFollowBlockNum) || LoopMightBeInfinite); this->EmitSPARKAdaLoopCall(NextBlock->GetFirstAddr(), (size_t) LoopNum, SPARKBodyFile); @@ -23061,7 +23096,8 @@ void SMPFunction::EmitSPARKAdaForConditional(int HeaderBlockNum, int FollowBlock assert(0 <= LoopNum); this->EmitSPARKAdaLoopCall(LoopAddr, (size_t) LoopNum, SPARKBodyFile); // Put the loop header and loop follow block numbers onto the work list - int LoopFollowBlockNum = this->LoopFollowNodes[(size_t)LoopNum]; + int LoopFollowBlockNum = SMP_BLOCKNUM_UNINIT; + bool MultiExitLoop = this->GetLoopFollowBlockNum((size_t)LoopNum, LoopFollowBlockNum); assert(0 < LoopFollowBlockNum); pair<int, int> BlockItem(CurrBlockNum, LoopFollowBlockNum); pair<int, pair<int, int> > WorkListItem(LoopNum, BlockItem); @@ -23298,7 +23334,7 @@ int SMPFunction::FindFollowBlockNum(SMPBasicBlock *CurrBlock, bool StartAtLastIn int LoopNum = this->GetLoopNumFromHeaderBlockNum(CurrBlock->GetNumber()); assert(0 <= LoopNum); bool LoopMightBeInfinite = (STARS_INFINITE_OR_MIDDLE_TESTING_LOOP == this->LoopTypesByLoopNum[LoopNum]); - FollowBlockNum = this->LoopFollowNodes[LoopNum]; + bool MultiExitLoop = this->GetLoopFollowBlockNum((size_t) LoopNum, FollowBlockNum); // assert((0 <= FollowBlockNum) || LoopMightBeInfinite); } else if (CurrBlock->IsSwitchDefaultCase()) { @@ -23352,6 +23388,22 @@ int SMPFunction::FindFollowBlockNum(SMPBasicBlock *CurrBlock, bool StartAtLastIn return FollowBlockNum; } // end of SMPFunction::FindFollowBlockNum() +// return true if loop has multiple follow blocks +bool SMPFunction::GetLoopFollowBlockNum(const size_t LoopNum, int &FirstFollowBlockNum) const { + assert(LoopNum < this->LoopFollowNodes.size()); + assert(!this->LoopFollowNodes[LoopNum].empty()); + bool MultiExitLoop = (1 < this->LoopFollowNodes[LoopNum].size()); + FirstFollowBlockNum = *(this->LoopFollowNodes[LoopNum].cbegin()); + return MultiExitLoop; +} // end of SMPFunction::GetLoopFollowBlockNum() + + +// found in LoopFollowNodes[LoopNum] set? +bool SMPFunction::IsBlockLoopFollowBlock(const std::size_t LoopNum, const int BlockNum) const { + assert(LoopNum < this->LoopFollowNodes.size()); + return (this->LoopFollowNodes[LoopNum].find(BlockNum) != this->LoopFollowNodes[LoopNum].cend()); +} // end of SMPFunction::IsBlockLoopFollowBlock() + // common code for different cases in EmitFuncPtrShadowingAnnotations2() void SMPFunction::EmitShadowingHelper(FILE *InfoAnnotFile, SMPInstr *CurrInst, bool FuncPtr, STARS_ea_t CallAddr) { STARS_ea_t ShadowCheckAddr = CurrInst->GetAddr(); -- GitLab