From 63eb0fec03610229d90e0c184bf4503d61cf3c64 Mon Sep 17 00:00:00 2001 From: Clark Coleman <clc@zephyr-software.com> Date: Fri, 28 Aug 2020 23:49:57 -0400 Subject: [PATCH] SPARK crash fixes for sks and mplayer binaries. --- src/base/SMPFunction.cpp | 41 ++++++++++++++++++++++++++++++++-------- src/base/SMPInstr.cpp | 5 +++++ 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/src/base/SMPFunction.cpp b/src/base/SMPFunction.cpp index 50649601..f74d212f 100644 --- a/src/base/SMPFunction.cpp +++ b/src/base/SMPFunction.cpp @@ -11123,14 +11123,24 @@ bool SMPFunction::FindSwitchStatementFollowBlock(struct SwitchTableInfo &TableIn return ConsistentFollowBlock; } // end of SMPFunction::FindSwitchStatementFollowBlock() -// Start at CaseBlockNum, return followblocknum with IncomingEdgeCount +// Start at CaseBlockNum, return followblocknum with >=IncomingEdgeCount predecessors int SMPFunction::FindCaseFollowBlock(int CaseBlockNum, int HeaderBlockNum, std::size_t IncomingEdgeCount) const { int FollowBlockNum = SMP_BLOCKNUM_UNINIT; // We define a well-structured switch statement suh that it is forbidden to have one case fall through to another. // Our algorithm would need to be modified to handle fall-throughs, which would require special translation to SPARK Ada // as such case fall-throughs are not permitted in SPARK Ada. - // Algorithm: Traverse CFG from CaseBlockNum until we find a block with IncomingEdgeCount that is dominated by HeaderBlockNum. + // What blocks have already been processed (i.e. follow block determinations from other cases)? + STARSBitSet ProcessedOutsideThisCase; + ProcessedOutsideThisCase.AllocateBits(this->GetNumBlocks()); + for (size_t BlockIndex = 0; BlockIndex < this->GetNumBlocks(); ++BlockIndex) + if (this->GetBlockByNum(BlockIndex)->IsProcessed()) + ProcessedOutsideThisCase.SetBit(BlockIndex); + // Using this bitset, we can differentiate between hitting a follow block multiple times from within this case + // (e.g. short-circuit branches out to it) and hitting it across different cases. + + // Algorithm: Traverse CFG from CaseBlockNum until we find a block with IncomingEdgeCount that is dominated by HeaderBlockNum + // but is NOT dominated by CaseBlockNum. // If we encounter an already processed block, stop and return -2 as the block number to signal this condition. // If one of our successors finds a follow block and the others all return -2, return the follow block number. // If we reach a block not dominated by HeaderBlockNum before finding a follow block or a visited block, return -1. @@ -11140,22 +11150,32 @@ int SMPFunction::FindCaseFollowBlock(int CaseBlockNum, int HeaderBlockNum, std:: for (list<SMPBasicBlock *>::iterator SuccIter = CaseBlock->GetFirstSucc(); SuccIter != CaseBlock->GetLastSucc(); ++SuccIter) { SMPBasicBlock *SuccBlock = (*SuccIter); int SuccBlockNum = SuccBlock->GetNumber(); + + // Screen out back edges. + if (this->DoesBlockDominateBlock(SuccBlockNum, CaseBlockNum)) + continue; + // NOTE: We have to screen out nested switch statements' follow blocks. STARS_ea_t LastBlockAddr = SuccBlock->GetLastAddr(); ControlFlowType SuccBranchType = this->GetControlFlowType(LastBlockAddr); + + // NOTE: Need more precise determination of nested switches? bool NestedSwitch = (SuccBranchType == CASE_BREAK_TO_FOLLOW_NODE); // avoid being deceived by nested follow nodes - // Possibilities: already visited; not dominated by HeaderBlockNum; has IncomingEdgeCount; or needs recursion + + // Possibilities: already visited; not dominated by HeaderBlockNum; has >=IncomingEdgeCount; or needs recursion if (this->DoesBlockDominateBlock(HeaderBlockNum, SuccBlockNum)) { - if (SuccBlock->IsProcessed()) { + bool DomWithinCase = this->DoesBlockDominateBlock(CaseBlockNum, SuccBlockNum); + + if (SuccBlock->IsProcessed() && ProcessedOutsideThisCase.GetBit((size_t) SuccBlockNum)) { if (FollowBlockNum == SMP_BLOCKNUM_UNINIT) - FollowBlockNum = -2; // record first already-visited block + FollowBlockNum = -2; // record first already-visited follow block } - else if (!NestedSwitch && (SuccBlock->GetNumPreds() == IncomingEdgeCount)) { + else if (!NestedSwitch && (SuccBlock->GetNumPreds() >= IncomingEdgeCount) && (!DomWithinCase)) { // follow block found. SuccBlock->SetProcessed(true); FollowBlockNum = SuccBlockNum; } - else { // need to recurse into successor block + else if (DomWithinCase) { // need to recurse into successor block int SuccFollowBlockNum = this->FindCaseFollowBlock(SuccBlockNum, HeaderBlockNum, IncomingEdgeCount); // Meet function for existing FollowBlockNum and SuccFollowBlockNum if ((FollowBlockNum == SMP_BLOCKNUM_UNINIT) || (FollowBlockNum == -2)) { @@ -11177,6 +11197,11 @@ int SMPFunction::FindCaseFollowBlock(int CaseBlockNum, int HeaderBlockNum, std:: } } } + else { + // Wandered out of our case without finding follow block; unstructured. + FollowBlockNum = SMP_BLOCKNUM_UNINIT; + break; + } } else { // cannot be structured switch statement; wandered out of switch without finding good follow block. FollowBlockNum = SMP_BLOCKNUM_UNINIT; @@ -13697,7 +13722,7 @@ void SMPFunction::BuildDominatorTree(void) { bool SMPFunction::DoesBlockDominateBlock(int HeadBlockNum, int TailBlockNum) const { if (HeadBlockNum == TailBlockNum) return true; - else if ((HeadBlockNum == SMP_BLOCKNUM_UNINIT) || (TailBlockNum == SMP_BLOCKNUM_UNINIT)) { + else if ((HeadBlockNum < 0) || (TailBlockNum < 0)) { return false; } else { diff --git a/src/base/SMPInstr.cpp b/src/base/SMPInstr.cpp index 0e98b8d4..3b9cf6db 100644 --- a/src/base/SMPInstr.cpp +++ b/src/base/SMPInstr.cpp @@ -2047,6 +2047,11 @@ void SMPRegTransfer::EmitSPARKAda(FILE *OutFile) { } SMPoperator CurrOper = this->GetOperator(); + if ((SMP_INPUT == CurrOper) || (SMP_OUTPUT == CurrOper)) { + SMP_fprintf(OutFile, "\nERROR\n"); + SMP_msg("ERROR: SPARK: Cannot translate operator SMP_INPUT or SMP_OUTPUT at %llx\n", (uint64_t) this->GetParentInst()->GetAddr()); + return; + } assert(CurrOper == SMP_ASSIGN); bool X86ProcCall = this->GetParentInst()->MDIsArithmeticUsingCarryFlag(); uint16_t LeftByteWidth = LeftOp->GetByteWidth(); -- GitLab