GP-6610 Add count of jumptable recover stages

This commit is contained in:
caheckman
2026-04-24 15:49:42 +00:00
parent 2d416f1071
commit 4bec0d1809
5 changed files with 16 additions and 33 deletions
@@ -768,25 +768,10 @@ void FlowInfo::truncateIndirectJump(PcodeOp *op,JumpTable::RecoveryMode mode)
}
}
/// \brief Test if the given p-code op is a member of an array
///
/// \param array is the array of p-code ops to search
/// \param op is the given p-code op to search for
/// \return \b true if the op is a member of the array
bool FlowInfo::isInArray(vector<PcodeOp *> &array,PcodeOp *op)
{
for(int4 i=0;i<array.size();++i) {
if (array[i] == op) return true;
}
return false;
}
void FlowInfo::generateOps(void)
{
vector<PcodeOp *> notreached; // indirect ops that are not reachable
int4 notreachcnt = 0;
clearProperties();
addrlist.push_back(data.getAddress());
while(!addrlist.empty()) // Recovering as much as possible except jumptables
@@ -812,10 +797,9 @@ void FlowInfo::generateOps(void)
checkContainedCall(); // Check for PIC constructions
checkMultistageJumptables();
while(notreachcnt < notreached.size()) {
tablelist.push_back(notreached[notreachcnt]);
notreachcnt += 1;
}
for(int4 i=0;i<notreached.size();++i)
tablelist.push_back(notreached[i]);
notreached.clear();
if (hasInject())
injectPcode();
} while(!tablelist.empty()); // Inlining or multistage may have added new indirect branches
@@ -1445,7 +1429,7 @@ void FlowInfo::recoverJumpTables(vector<JumpTable *> &newTables,vector<PcodeOp *
truncateIndirectJump(op,mode); // Treat the indirect jump as a call
}
else if (jt->isPartial()) {
if (tablelist.size() > 1 && !isInArray(notreached,op)) {
if (tablelist.size() > 1 && jt->getRecoverCount() <= 1) {
// If the recovery is incomplete with current flow AND there is more flow to generate,
// AND we haven't tried to recover this table before
notreached.push_back(op); // Save this op so we can try to recover the table again later
@@ -138,7 +138,6 @@ private:
void recoverJumpTables(vector<JumpTable *> &newTables,vector<PcodeOp *> &notreached);
void deleteCallSpec(FuncCallSpecs *fc); ///< Remove the given call site from the list for \b this function
void truncateIndirectJump(PcodeOp *op,JumpTable::RecoveryMode mode); ///< Treat indirect jump as CALLIND/RETURN
static bool isInArray(vector<PcodeOp *> &array,PcodeOp *op);
public:
FlowInfo(Funcdata &d,PcodeOpBank &o,BlockGraph &b,vector<FuncCallSpecs *> &q); ///< Constructor
FlowInfo(Funcdata &d,PcodeOpBank &o,BlockGraph &b,vector<FuncCallSpecs *> &q,const FlowInfo *op2); ///< Cloning constructor
@@ -491,6 +491,7 @@ JumpTable *Funcdata::installJumpTable(const Address &addr)
JumpTable::RecoveryMode Funcdata::stageJumpTable(Funcdata &partial,JumpTable *jt,PcodeOp *op,FlowInfo *flow)
{
jt->incrementRecoveryCount();
if (!partial.isJumptableRecoveryOn()) {
// Do full analysis on the table if we haven't before
partial.flags |= jumptablerecovery_on; // Mark that this Funcdata object is dedicated to jumptable recovery
@@ -2403,9 +2403,7 @@ JumpTable::JumpTable(Address ad)
switchVarConsume = ~((uintb)0);
defaultBlock = -1;
lastBlock = -1;
maxaddsub = 1;
maxleftright = 1;
maxext = 1;
recoverCount = 0;
displayFormat = 0;
partialTable = false;
collectloads = false;
@@ -2424,9 +2422,7 @@ JumpTable::JumpTable(const JumpTable *op2)
switchVarConsume = ~((uintb)0);
defaultBlock = -1;
lastBlock = op2->lastBlock;
maxaddsub = op2->maxaddsub;
maxleftright = op2->maxleftright;
maxext = op2->maxext;
recoverCount = op2->recoverCount;
displayFormat = op2->displayFormat;
partialTable = op2->partialTable;
collectloads = op2->collectloads;
@@ -2771,8 +2767,9 @@ void JumpTable::clear(void)
indirect = (PcodeOp *)0;
switchVarConsume = ~((uintb)0);
defaultBlock = -1;
recoverCount = 0;
partialTable = false;
// -opaddress- -maxtablesize- -maxaddsub- -maxleftright- -maxext- -collectloads- are permanent
// -opaddress- -maxtablesize- -collectloads- are permanent
}
/// The recovered addresses and case labels are encode to the stream.
@@ -2871,6 +2868,7 @@ bool JumpTable::checkForMultistage(Funcdata *fd)
if (addresstable.size()!=1) return false;
if (partialTable) return false;
if (indirect == (PcodeOp *)0) return false;
if (recoverCount > 1) return false;
if (fd->getOverride().queryMultistageJumptable(indirect->getAddr())) {
partialTable = true; // Mark that we need additional recovery
@@ -549,6 +549,9 @@ public:
fail_callother = 4 ///< Address formed by CALLOTHER
};
private:
static constexpr uint4 maxaddsub = 1; ///< Maximum ADDs or SUBs to normalize
static constexpr uint4 maxleftright = 1; ///< Maximum shifts to normalize
static constexpr uint4 maxext = 1; ///< Maximum extensions to normalize
/// \brief An address table index and its corresponding out-edge
struct IndexPair {
int4 blockPosition; ///< Out-edge index for the basic-block
@@ -568,9 +571,7 @@ private:
uintb switchVarConsume; ///< Bits of the switch variable being consumed
int4 defaultBlock; ///< The out-edge corresponding to the \e default switch destination (-1 = undefined)
int4 lastBlock; ///< Block out-edge corresponding to last entry in the address table
uint4 maxaddsub; ///< Maximum ADDs or SUBs to normalize
uint4 maxleftright; ///< Maximum shifts to normalize
uint4 maxext; ///< Maximum extensions to normalize
int4 recoverCount; ///< Number of times recovery attempted on \b this table
uint4 displayFormat; ///< Display format for integer \e case values
bool partialTable; ///< Set to \b true if \b this table is incomplete and needs additional recovery steps
bool collectloads; ///< Set to \b true if information about in-memory model data is/should be collected
@@ -598,14 +599,14 @@ public:
const Address &getOpAddress(void) const { return opaddress; } ///< Get the address of the BRANCHIND for the switch
PcodeOp *getIndirectOp(void) const { return indirect; } ///< Get the BRANCHIND PcodeOp
void setIndirectOp(PcodeOp *ind) { opaddress = ind->getAddr(); indirect = ind; } ///< Set the BRANCHIND PcodeOp
void setNormMax(uint4 maddsub,uint4 mleftright,uint4 mext) {
maxaddsub = maddsub; maxleftright = mleftright; maxext = mext; } ///< Set the switch variable normalization model restrictions
uint4 getDisplayFormat(void) const { return displayFormat; } ///< Get the display format for integer cases
void setDisplayFormat(uint4 format) { displayFormat = format; } ///< Set the display format to use for integer case values
void setOverride(const vector<Address> &addrtable,const Address &naddr,uintb h,uintb sv);
int4 numIndicesByBlock(const FlowBlock *bl) const;
int4 getIndexByBlock(const FlowBlock *bl,int4 i) const;
Address getAddressByIndex(int4 i) const { return addresstable[i]; } ///< Get the i-th address table entry
int4 getRecoverCount(void) const { return recoverCount; } ///< Get number of times a recovery has been attempted
void incrementRecoveryCount(void) { recoverCount += 1; } ///< Record that another round of recovery is being attempted
void setLastAsDefault(void); ///< Set the \e default jump-table target to be the last address in the table
void setDefaultBlock(int4 bl) { defaultBlock = bl; } ///< Set out-edge of the switch destination considered to be \e default
void setLoadCollect(bool val) { collectloads = val; } ///< Set whether LOAD records should be collected