Merge remote-tracking branch 'origin/GP-5915_ConditionalJoinFix' into

patch (Closes #8310)
This commit is contained in:
Ryan Kurtz 2025-08-07 12:13:37 -04:00
commit 8055da80b8
4 changed files with 83 additions and 17 deletions

View file

@ -638,6 +638,17 @@ JumpTable *FlowBlock::getJumptable(void) const
return jt;
}
/// Print a single unique identifier for \b this block
/// \param s is the output stream
void FlowBlock::printShortHeader(ostream &s) const
{
s << "Block_" << dec << index;
if (!getStart().isInvalid()) {
s << ':' << getStart();
}
}
/// Given a string describing a FlowBlock type, return the block_type.
/// This is currently only used by the decode() process.
/// TODO: Fill in the remaining names and types
@ -1293,8 +1304,24 @@ void BlockGraph::printRaw(ostream &s) const
printHeader(s);
s << endl;
for(iter=list.begin();iter!=list.end();++iter)
(*iter)->printRaw(s);
if (list.empty()) return;
iter = list.begin();
FlowBlock *lastBl = *iter;
++iter;
lastBl->printRaw(s);
for(;iter!=list.end();++iter) {
FlowBlock *curBl = *iter;
lastBl->printRawImpliedGoto(s, curBl);
curBl->printRaw(s);
lastBl = curBl;
}
}
void BlockGraph::printRawImpliedGoto(ostream &s,const FlowBlock *nextBlock) const
{
if (list.empty()) return;
list.back()->printRawImpliedGoto(s, nextBlock);
}
PcodeOp *BlockGraph::firstOp(void) const
@ -2658,6 +2685,24 @@ void BlockBasic::printRaw(ostream &s) const
}
}
void BlockBasic::printRawImpliedGoto(ostream &s,const FlowBlock *nextBlock) const
{
if (sizeOut() != 1) return;
const FlowBlock *outBlock = getOut(0);
if (nextBlock->getType() != t_basic) {
nextBlock = nextBlock->getFrontLeaf();
if (nextBlock == (const FlowBlock *)0) return;
nextBlock = nextBlock->subBlock(0);
}
if (getOut(0) == nextBlock) return;
if (!op.empty() && op.back()->isBranch()) return;
getStop().printRaw(s);
s << ": \t[ goto ";
outBlock->printShortHeader(s);
s << " ]" << endl;
}
/// \brief Check for values created in \b this block that flow outside the block.
///
/// The block can calculate a value for a BRANCHIND or CBRANCH and can copy values and this method will still

View file

@ -210,6 +210,14 @@ public:
/// \param s is the given stream to write to
virtual void printRaw(ostream &s) const {}
/// \brief If the \e out block of \b this is not the given next block, print an implied \b goto to the out block
///
/// In order to see where \b this block is flowing to, if there is no explicit branch op, and if the next block
/// being printed is \e not the fallthru branch, print the destination block as an implied \b goto op.
/// \param s is the output stream
/// \param nextBlock is the given nextBlock being printed
virtual void printRawImpliedGoto(ostream &s,const FlowBlock *nextBlock) const {}
virtual void emit(PrintLanguage *lng) const; ///<Emit the instructions in \b this FlowBlock as structured code
/// \brief Get the leaf block from which \b this block exits
@ -338,6 +346,7 @@ public:
bool isGotoIn(int4 i) const { return ((intothis[i].label & (f_irreducible|f_goto_edge))!=0); } ///< Is the i-th incoming edge unstructured
bool isGotoOut(int4 i) const { return ((outofthis[i].label & (f_irreducible|f_goto_edge))!=0); } ///< Is the i-th outgoing edge unstructured
JumpTable *getJumptable(void) const; ///< Get the JumpTable associated \b this block
void printShortHeader(ostream &s) const; ///< Print a short identifier for the block
static block_type nameToType(const string &name); ///< Get the block_type associated with a name string
static string typeToName(block_type bt); ///< Get the name string associated with a block_type
static bool compareBlockIndex(const FlowBlock *bl1,const FlowBlock *bl2); ///< Compare FlowBlock by index
@ -380,6 +389,7 @@ public:
virtual void scopeBreak(int4 curexit,int4 curloopexit);
virtual void printTree(ostream &s,int4 level) const;
virtual void printRaw(ostream &s) const;
void printRawImpliedGoto(ostream &s,const FlowBlock *nextBlock) const;
virtual void emit(PrintLanguage *lng) const { lng->emitBlockGraph(this); }
virtual PcodeOp *firstOp(void) const;
virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const;
@ -473,6 +483,7 @@ public:
virtual void decodeBody(Decoder &decoder);
virtual void printHeader(ostream &s) const;
virtual void printRaw(ostream &s) const;
virtual void printRawImpliedGoto(ostream &s,const FlowBlock *nextBlock) const;
virtual void emit(PrintLanguage *lng) const { lng->emitBlockBasic(this); }
virtual const FlowBlock *getExitLeaf(void) const { return this; }
virtual PcodeOp *firstOp(void) const;
@ -515,6 +526,7 @@ public:
virtual void printHeader(ostream &s) const;
virtual void printTree(ostream &s,int4 level) const;
virtual void printRaw(ostream &s) const { copy->printRaw(s); }
virtual void printRawImpliedGoto(ostream &s,const FlowBlock *nextBlock) const { copy->printRawImpliedGoto(s, nextBlock); }
virtual void emit(PrintLanguage *lng) const { lng->emitBlockCopy(this); }
virtual const FlowBlock *getExitLeaf(void) const { return this; }
virtual PcodeOp *firstOp(void) const { return copy->firstOp(); }

View file

@ -2074,18 +2074,10 @@ bool ConditionalJoin::match(BlockBasic *b1,BlockBasic *b2)
exita = (BlockBasic *)block1->getOut(0);
exitb = (BlockBasic *)block1->getOut(1);
if (exita == exitb) return false;
if (block2->getOut(0) == exita) {
if (block2->getOut(1) != exitb) return false;
if (block2->getOut(0) != exita) return false; // False exits must match
if (block2->getOut(1) != exitb) return false; // True exits must match
a_in2 = block2->getOutRevIndex(0);
b_in2 = block2->getOutRevIndex(1);
}
else if (block2->getOut(0) == exitb) {
if (block2->getOut(1) != exita) return false;
a_in2 = block2->getOutRevIndex(1);
b_in2 = block2->getOutRevIndex(0);
}
else
return false;
a_in1 = block1->getOutRevIndex(0);
b_in1 = block1->getOutRevIndex(1);

View file

@ -591,6 +591,11 @@ void TypeOpBranch::printRaw(ostream &s,const PcodeOp *op)
{
s << name << ' ';
const BlockBasic *parent = op->getParent();
if (parent != (const BlockBasic *)0 && parent->sizeOut() == 1) {
parent->getOut(0)->printShortHeader(s);
}
else
Varnode::printRaw(s,op->getIn(0));
}
@ -617,13 +622,25 @@ void TypeOpCbranch::printRaw(ostream &s,const PcodeOp *op)
{
s << name << ' ';
const BlockBasic *parent = op->getParent();
FlowBlock *falseOut = (FlowBlock *)0;
if (parent != (const BlockBasic *)0 && parent->sizeOut() == 2) {
FlowBlock *trueOut = parent->getTrueOut();
falseOut = parent->getFalseOut();
trueOut->printShortHeader(s);
}
else
Varnode::printRaw(s,op->getIn(0)); // Print the distant (non-fallthru) destination
s << " if (";
Varnode::printRaw(s,op->getIn(1));
if (op->isBooleanFlip()^op->isFallthruTrue())
if (op->isBooleanFlip())
s << " == 0)";
else
s << " != 0)";
if (falseOut != (FlowBlock *)0) {
s << " else ";
falseOut->printShortHeader(s);
}
}
TypeOpBranchind::TypeOpBranchind(TypeFactory *t) : TypeOp(t,CPUI_BRANCHIND,"switch")