#ifndef __CPUI_BLOCK__
#define __CPUI_BLOCK__
#include "jumptable.hh"
class BlockBasic; class BlockList;
class BlockCopy;
class BlockGoto;
class BlockMultiGoto;
class BlockCondition;
class BlockIf;
class BlockWhileDo;
class BlockDoWhile;
class BlockInfLoop;
class BlockSwitch;
class PrintLanguage;
class BlockMap;
struct BlockEdge {
uint4 label; FlowBlock *point; int4 reverse_index; BlockEdge(void) {} BlockEdge(FlowBlock *pt,uint4 lab,int4 rev) { label=lab; point=pt; reverse_index = rev; } void saveXml(ostream &s) const; void restoreXml(const Element *el,BlockMap &resolver); };
class FlowBlock {
friend class BlockGraph;
public:
enum block_type {
t_plain, t_basic, t_graph, t_copy, t_goto, t_multigoto, t_ls,
t_condition, t_if, t_whiledo, t_dowhile, t_switch, t_infloop
};
enum block_flags {
f_goto_goto = 1, f_break_goto = 2, f_continue_goto = 4, f_switch_out = 0x10, f_unstructured_targ = 0x20, f_mark = 0x80, f_mark2 = 0x100, f_entry_point = 0x200, f_interior_gotoout = 0x400, f_interior_gotoin = 0x800, f_label_bumpup = 0x1000, f_donothing_loop = 0x2000, f_dead = 0x4000, f_whiledo_overflow = 0x8000, f_flip_path = 0x10000, f_joined_block = 0x20000, f_duplicate_block = 0x40000 };
enum edge_flags {
f_goto_edge = 1, f_loop_edge = 2, f_defaultswitch_edge = 4, f_irreducible = 8, f_tree_edge = 0x10, f_forward_edge = 0x20, f_cross_edge = 0x40, f_back_edge = 0x80, f_loop_exit_edge = 0x100 };
private:
uint4 flags; FlowBlock *parent; FlowBlock *immed_dom; FlowBlock *copymap; int4 index; int4 visitcount; int4 numdesc; vector<BlockEdge> intothis; vector<BlockEdge> outofthis; static void replaceEdgeMap(vector<BlockEdge> &vec); void addInEdge(FlowBlock *b,uint4 lab); void restoreNextInEdge(const Element *el,BlockMap &resolver); void halfDeleteInEdge(int4 slot); void halfDeleteOutEdge(int4 slot); void removeInEdge(int4 slot); void removeOutEdge(int4 slot); void replaceInEdge(int4 num,FlowBlock *b); void replaceOutEdge(int4 num,FlowBlock *b); void replaceEdgesThru(int4 in,int4 out); void swapEdges(void); void setOutEdgeFlag(int4 i,uint4 lab); void clearOutEdgeFlag(int4 i,uint4 lab); void eliminateInDups(FlowBlock *bl); void eliminateOutDups(FlowBlock *bl); static void findDups(const vector<BlockEdge> &ref,vector<FlowBlock *> &duplist);
void dedup(void); void replaceUsingMap(void); #ifdef BLOCKCONSISTENT_DEBUG
void checkEdges(void); #endif
protected:
void setFlag(uint4 fl) { flags |= fl; } void clearFlag(uint4 fl) { flags &= ~fl; } public:
FlowBlock(void); virtual ~FlowBlock(void) {} int4 getIndex(void) const { return index; } FlowBlock *getParent(void) { return parent; } FlowBlock *getImmedDom(void) const { return immed_dom; } FlowBlock *getCopyMap(void) const { return copymap; } const FlowBlock *getParent(void) const { return (const FlowBlock *) parent; } uint4 getFlags(void) const { return flags; } virtual Address getStart(void) const { return Address(); } virtual Address getStop(void) const { return Address(); } virtual block_type getType(void) const { return t_plain; } virtual FlowBlock *subBlock(int4 i) const { return (FlowBlock *)0; } virtual void markUnstructured(void) {} virtual void markLabelBumpUp(bool bump); virtual void scopeBreak(int4 curexit,int4 curloopexit) {} virtual void printHeader(ostream &s) const; virtual void printTree(ostream &s,int4 level) const; virtual void printRaw(ostream &s) const {} virtual void emit(PrintLanguage *lng) const; virtual const FlowBlock *getExitLeaf(void) const { return (const FlowBlock *)0; } virtual PcodeOp *lastOp(void) const { return (PcodeOp *)0; } virtual bool negateCondition(bool toporbottom); virtual bool preferComplement(Funcdata &data); virtual FlowBlock *getSplitPoint(void); virtual int4 flipInPlaceTest(vector<PcodeOp *> &fliplist) const;
virtual void flipInPlaceExecute(void);
virtual bool isComplex(void) const { return true; } virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const;
virtual void finalTransform(Funcdata &data) {} virtual void finalizePrinting(Funcdata &data) const {} virtual void saveXmlHeader(ostream &s) const; virtual void restoreXmlHeader(const Element *el); virtual void saveXmlBody(ostream &s) const {}
virtual void restoreXmlBody(List::const_iterator &iter,List::const_iterator enditer,BlockMap &resolver) {}
void saveXmlEdges(ostream &s) const; void restoreXmlEdges(List::const_iterator &iter,List::const_iterator enditer,BlockMap &resolver);
void saveXml(ostream &s) const; void restoreXml(const Element *el,BlockMap &resolver); const FlowBlock *nextInFlow(void) const; void setVisitCount(int4 i) { visitcount = i; } int4 getVisitCount(void) const { return visitcount; } void setGotoBranch(int4 i); void setDefaultSwitch(int4 i) { setOutEdgeFlag(i,f_defaultswitch_edge); } bool isMark(void) const { return ((flags&f_mark)!=0); } void setMark(void) { flags |= f_mark; } void clearMark(void) { flags &= ~f_mark; } void setDonothingLoop(void) { flags |= f_donothing_loop; } void setDead(void) { flags |= f_dead; } bool hasSpecialLabel(void) const { return ((flags&(f_joined_block|f_duplicate_block))!=0); } bool isJoined(void) const { return ((flags&f_joined_block)!=0); } bool isDuplicated(void) const { return ((flags&f_duplicate_block)!=0); } void setLoopExit(int4 i) { setOutEdgeFlag(i,f_loop_exit_edge); } void clearLoopExit(int4 i) { clearOutEdgeFlag(i,f_loop_exit_edge); } void setBackEdge(int4 i) { setOutEdgeFlag(i,f_back_edge); } bool getFlipPath(void) const { return ((flags & f_flip_path)!=0); } bool isJumpTarget(void) const; FlowBlock *getFalseOut(void) const { return outofthis[0].point; } FlowBlock *getTrueOut(void) const { return outofthis[1].point; } FlowBlock *getOut(int4 i) { return outofthis[i].point; } const FlowBlock *getOut(int4 i) const { return (const FlowBlock *) outofthis[i].point; } int4 getOutRevIndex(int4 i) const { return outofthis[i].reverse_index; } FlowBlock *getIn(int4 i) { return intothis[i].point; } const FlowBlock *getIn(int4 i) const { return (const FlowBlock *) intothis[i].point; } int4 getInRevIndex(int4 i) const { return intothis[i].reverse_index; } const FlowBlock *getFrontLeaf(void) const; FlowBlock *getFrontLeaf(void); int4 calcDepth(const FlowBlock *leaf) const; bool dominates(const FlowBlock *subBlock) const; bool restrictedByConditional(const FlowBlock *cond) const;
int4 sizeOut(void) const { return outofthis.size(); } int4 sizeIn(void) const { return intothis.size(); } bool hasLoopIn(void) const; bool hasLoopOut(void) const; bool isLoopIn(int4 i) const { return ((intothis[i].label & f_loop_edge)!=0); } bool isLoopOut(int4 i) const { return ((outofthis[i].label & f_loop_edge)!=0); } int4 getInIndex(const FlowBlock *bl) const; int4 getOutIndex(const FlowBlock *bl) const; bool isDefaultBranch(int4 i) const { return ((outofthis[i].label & f_defaultswitch_edge)!=0); } bool isLabelBumpUp(void) const { return ((flags & f_label_bumpup)!=0); } bool isUnstructuredTarget(void) const { return ((flags & f_unstructured_targ)!=0); } bool isInteriorGotoTarget(void) const { return ((flags & f_interior_gotoin)!=0); } bool hasInteriorGoto(void) const { return ((flags & f_interior_gotoout)!=0); } bool isEntryPoint(void) const { return ((flags&f_entry_point)!=0); } bool isSwitchOut(void) const { return ((flags&f_switch_out)!=0); } bool isDonothingLoop(void) const { return ((flags&f_donothing_loop)!=0); } bool isDead(void) const { return ((flags & f_dead)!=0); } bool isTreeEdgeIn(int4 i) const { return ((intothis[i].label & f_tree_edge)!=0); } bool isBackEdgeIn(int4 i) const { return ((intothis[i].label & f_back_edge)!=0); } bool isBackEdgeOut(int4 i) const { return ((outofthis[i].label & f_back_edge)!=0); } bool isIrreducibleOut(int4 i) const { return ((outofthis[i].label & f_irreducible)!=0); } bool isIrreducibleIn(int4 i) const { return ((intothis[i].label & f_irreducible)!=0); }
bool isDecisionOut(int4 i) const { return ((outofthis[i].label & (f_irreducible|f_back_edge|f_goto_edge))==0); }
bool isDecisionIn(int4 i) const { return ((intothis[i].label & (f_irreducible|f_back_edge|f_goto_edge))==0); }
bool isLoopDAGOut(int4 i) const { return ((outofthis[i].label & (f_irreducible|f_back_edge|f_loop_exit_edge|f_goto_edge))==0); }
bool isLoopDAGIn(int4 i) const { return ((intothis[i].label & (f_irreducible|f_back_edge|f_loop_exit_edge|f_goto_edge))==0); }
bool isGotoIn(int4 i) const { return ((intothis[i].label & (f_irreducible|f_goto_edge))!=0); } bool isGotoOut(int4 i) const { return ((outofthis[i].label & (f_irreducible|f_goto_edge))!=0); } JumpTable *getJumptable(void) const; static block_type nameToType(const string &name); static string typeToName(block_type bt); static bool compareBlockIndex(const FlowBlock *bl1,const FlowBlock *bl2); static bool compareFinalOrder(const FlowBlock *bl1,const FlowBlock *bl2); static FlowBlock *findCommonBlock(FlowBlock *bl1,FlowBlock *bl2); static FlowBlock *findCommonBlock(const vector<FlowBlock *> &blockSet); };
class BlockGraph : public FlowBlock {
vector<FlowBlock *> list; void addBlock(FlowBlock *bl); void forceOutputNum(int4 i); void selfIdentify(void); void identifyInternal(BlockGraph *ident,const vector<FlowBlock *> &nodes);
void clearEdgeFlags(uint4 fl); static FlowBlock *createVirtualRoot(const vector<FlowBlock *> &rootlist);
void findSpanningTree(vector<FlowBlock *> &preorder,vector<FlowBlock *> &rootlist);
bool findIrreducible(const vector<FlowBlock *> &preorder,int4 &irreduciblecount);
void forceFalseEdge(const FlowBlock *out0); protected:
void swapBlocks(int4 i,int4 j); static void markCopyBlock(FlowBlock *bl,uint4 fl); public:
void clear(void); virtual ~BlockGraph(void) { clear(); } const vector<FlowBlock *> &getList(void) const { return list; } int4 getSize(void) const { return list.size(); } FlowBlock *getBlock(int4 i) const { return list[i]; } virtual block_type getType(void) const { return t_graph; }
virtual FlowBlock *subBlock(int4 i) const { return list[i]; }
virtual void markUnstructured(void);
virtual void markLabelBumpUp(bool bump);
virtual void scopeBreak(int4 curexit,int4 curloopexit);
virtual void printTree(ostream &s,int4 level) const;
virtual void printRaw(ostream &s) const;
virtual void emit(PrintLanguage *lng) const { lng->emitBlockGraph(this); }
virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const;
virtual void finalTransform(Funcdata &data);
virtual void finalizePrinting(Funcdata &data) const;
virtual void saveXmlBody(ostream &s) const;
virtual void restoreXmlBody(List::const_iterator &iter,List::const_iterator enditer,BlockMap &resolver);
void restoreXml(const Element *el,const AddrSpaceManager *m); void addEdge(FlowBlock *begin,FlowBlock *end); void addLoopEdge(FlowBlock *begin,int4 outindex); void removeEdge(FlowBlock *begin,FlowBlock *end); void switchEdge(FlowBlock *in,FlowBlock *outbefore,FlowBlock *outafter); void moveOutEdge(FlowBlock *blold,int4 slot,FlowBlock *blnew); void removeBlock(FlowBlock *bl); void removeFromFlow(FlowBlock *bl); void removeFromFlowSplit(FlowBlock *bl,bool flipflow); void spliceBlock(FlowBlock *bl); void setStartBlock(FlowBlock *bl); FlowBlock *getStartBlock(void) const; FlowBlock *newBlock(void); BlockBasic *newBlockBasic(Funcdata *fd);
BlockCopy *newBlockCopy(FlowBlock *bl); BlockGoto *newBlockGoto(FlowBlock *bl); BlockMultiGoto *newBlockMultiGoto(FlowBlock *bl,int4 outedge); BlockList *newBlockList(const vector<FlowBlock *> &nodes); BlockCondition *newBlockCondition(FlowBlock *b1,FlowBlock *b2); BlockIf *newBlockIfGoto(FlowBlock *cond); BlockIf *newBlockIf(FlowBlock *cond,FlowBlock *tc); BlockIf *newBlockIfElse(FlowBlock *cond,FlowBlock *tc,FlowBlock *fc); BlockWhileDo *newBlockWhileDo(FlowBlock *cond,FlowBlock *cl); BlockDoWhile *newBlockDoWhile(FlowBlock *condcl); BlockInfLoop *newBlockInfLoop(FlowBlock *body); BlockSwitch *newBlockSwitch(const vector<FlowBlock *> &cs,bool hasExit);
void orderBlocks(void) { if (list.size()!=1) sort(list.begin(),list.end(),compareFinalOrder); }
void buildCopy(const BlockGraph &graph); void clearVisitCount(void); void calcForwardDominator(const vector<FlowBlock *> &rootlist); void buildDomTree(vector<vector<FlowBlock *> > &child) const; int4 buildDomDepth(vector<int4> &depth) const; void buildDomSubTree(vector<FlowBlock *> &res,FlowBlock *root) const; void calcLoop(void); void collectReachable(vector<FlowBlock *> &res,FlowBlock *bl,bool un) const; void structureLoops(vector<FlowBlock *> &rootlist); #ifdef BLOCKCONSISTENT_DEBUG
bool isConsistent(void) const; #endif
};
class BlockBasic: public FlowBlock {
friend class Funcdata; list<PcodeOp *> op; Funcdata *data; RangeList cover; void insert(list<PcodeOp *>::iterator iter,PcodeOp *inst); void setInitialRange(const Address &beg,const Address &end); void copyRange(const BlockBasic *bb) { cover = bb->cover; } void mergeRange(const BlockBasic *bb) { cover.merge(bb->cover); } void setOrder(void); void removeOp(PcodeOp *inst); public:
BlockBasic(Funcdata *fd) { data = fd; } Funcdata *getFuncdata(void) { return data; } const Funcdata *getFuncdata(void) const { return (const Funcdata *)data; } bool contains(const Address &addr) const { return cover.inRange(addr, 1); } Address getEntryAddr(void) const; virtual Address getStart(void) const;
virtual Address getStop(void) const;
virtual block_type getType(void) const { return t_basic; }
virtual FlowBlock *subBlock(int4 i) const { return (FlowBlock *)0; }
virtual void saveXmlBody(ostream &s) const;
virtual void restoreXmlBody(List::const_iterator &iter,List::const_iterator enditer,BlockMap &resolver);
virtual void printHeader(ostream &s) const;
virtual void printRaw(ostream &s) const;
virtual void emit(PrintLanguage *lng) const { lng->emitBlockBasic(this); }
virtual const FlowBlock *getExitLeaf(void) const { return this; }
virtual PcodeOp *lastOp(void) const;
virtual bool negateCondition(bool toporbottom);
virtual FlowBlock *getSplitPoint(void);
virtual int4 flipInPlaceTest(vector<PcodeOp *> &fliplist) const;
virtual void flipInPlaceExecute(void);
virtual bool isComplex(void) const;
bool unblockedMulti(int4 outslot) const; bool hasOnlyMarkers(void) const; bool isDoNothing(void) const; list<PcodeOp *>::iterator beginOp(void) { return op.begin(); } list<PcodeOp *>::iterator endOp(void) { return op.end(); } list<PcodeOp *>::const_iterator beginOp(void) const { return op.begin(); } list<PcodeOp *>::const_iterator endOp(void) const { return op.end(); } bool emptyOp(void) const { return op.empty(); } static bool noInterveningStatement(PcodeOp *first,int4 path,PcodeOp *last);
};
class BlockCopy : public FlowBlock {
FlowBlock *copy; public:
BlockCopy(FlowBlock *bl) { copy = bl; } virtual FlowBlock *subBlock(int4 i) const { return copy; }
virtual block_type getType(void) const { return t_copy; }
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 emit(PrintLanguage *lng) const { lng->emitBlockCopy(this); }
virtual const FlowBlock *getExitLeaf(void) const { return this; }
virtual PcodeOp *lastOp(void) const { return copy->lastOp(); }
virtual bool negateCondition(bool toporbottom) { bool res = copy->negateCondition(true); FlowBlock::negateCondition(toporbottom); return res; }
virtual FlowBlock *getSplitPoint(void) { return copy->getSplitPoint(); }
virtual bool isComplex(void) const { return copy->isComplex(); }
virtual void saveXmlHeader(ostream &s) const;
};
class BlockGoto : public BlockGraph {
FlowBlock *gototarget; uint4 gototype; public:
BlockGoto(FlowBlock *bl) { gototarget = bl; gototype = f_goto_goto; } FlowBlock *getGotoTarget(void) const { return gototarget; } uint4 getGotoType(void) const { return gototype; } bool gotoPrints(void) const; virtual block_type getType(void) const { return t_goto; }
virtual void markUnstructured(void);
virtual void scopeBreak(int4 curexit,int4 curloopexit);
virtual void printHeader(ostream &s) const;
virtual void printRaw(ostream &s) const { getBlock(0)->printRaw(s); }
virtual void emit(PrintLanguage *lng) const { lng->emitBlockGoto(this); }
virtual const FlowBlock *getExitLeaf(void) const { return getBlock(0)->getExitLeaf(); }
virtual PcodeOp *lastOp(void) const { return getBlock(0)->lastOp(); }
virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const;
virtual void saveXmlBody(ostream &s) const;
};
class BlockMultiGoto : public BlockGraph {
vector<FlowBlock *> gotoedges; bool defaultswitch; public:
BlockMultiGoto(FlowBlock *bl) { defaultswitch = false; } void setDefaultGoto(void) { defaultswitch = true; } bool hasDefaultGoto(void) const { return defaultswitch; } void addEdge(FlowBlock *bl) { gotoedges.push_back(bl); } int4 numGotos(void) const { return gotoedges.size(); } FlowBlock *getGoto(int4 i) const { return gotoedges[i]; }
virtual block_type getType(void) const { return t_multigoto; }
virtual void scopeBreak(int4 curexit,int4 curloopexit);
virtual void printHeader(ostream &s) const;
virtual void printRaw(ostream &s) const { getBlock(0)->printRaw(s); }
virtual void emit(PrintLanguage *lng) const { getBlock(0)->emit(lng); }
virtual const FlowBlock *getExitLeaf(void) const { return getBlock(0)->getExitLeaf(); }
virtual PcodeOp *lastOp(void) const { return getBlock(0)->lastOp(); }
virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const;
virtual void saveXmlBody(ostream &s) const;
};
class BlockList : public BlockGraph {
public:
virtual block_type getType(void) const { return t_ls; }
virtual void printHeader(ostream &s) const;
virtual void emit(PrintLanguage *lng) const { lng->emitBlockLs(this); }
virtual const FlowBlock *getExitLeaf(void) const;
virtual PcodeOp *lastOp(void) const;
virtual bool negateCondition(bool toporbottom);
virtual FlowBlock *getSplitPoint(void);
};
class BlockCondition : public BlockGraph {
OpCode opc; public:
BlockCondition(OpCode c) { opc = c; } OpCode getOpcode(void) const { return opc; } virtual block_type getType(void) const { return t_condition; }
virtual void scopeBreak(int4 curexit,int4 curloopexit);
virtual void printHeader(ostream &s) const;
virtual void emit(PrintLanguage *lng) const { lng->emitBlockCondition(this); }
virtual bool negateCondition(bool toporbottom);
virtual FlowBlock *getSplitPoint(void) { return this; }
virtual int4 flipInPlaceTest(vector<PcodeOp *> &fliplist) const;
virtual void flipInPlaceExecute(void);
virtual PcodeOp *lastOp(void) const;
virtual bool isComplex(void) const { return getBlock(0)->isComplex(); }
virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const;
virtual void saveXmlHeader(ostream &s) const;
};
class BlockIf : public BlockGraph {
uint4 gototype; FlowBlock *gototarget; public:
BlockIf(void) { gototype = f_goto_goto; gototarget = (FlowBlock *)0; } void setGotoTarget(FlowBlock *bl) { gototarget = bl; } FlowBlock *getGotoTarget(void) const { return gototarget; } uint4 getGotoType(void) const { return gototype; } virtual block_type getType(void) const { return t_if; }
virtual void markUnstructured(void);
virtual void scopeBreak(int4 curexit,int4 curloopexit);
virtual void printHeader(ostream &s) const;
virtual void emit(PrintLanguage *lng) const { lng->emitBlockIf(this); }
virtual bool preferComplement(Funcdata &data);
virtual const FlowBlock *getExitLeaf(void) const;
virtual PcodeOp *lastOp(void) const;
virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const;
virtual void saveXmlBody(ostream &s) const;
};
class BlockWhileDo : public BlockGraph {
mutable PcodeOp *initializeOp; mutable PcodeOp *iterateOp; mutable PcodeOp *loopDef; void findLoopVariable(PcodeOp *cbranch,BlockBasic *head,BlockBasic *tail,PcodeOp *lastOp); PcodeOp *findInitializer(BlockBasic *head,int4 slot) const; PcodeOp *testTerminal(Funcdata &data,int4 slot) const; bool testIterateForm(void) const; public:
BlockWhileDo(void) { initializeOp = (PcodeOp *)0; iterateOp = (PcodeOp *)0; loopDef = (PcodeOp *)0; } PcodeOp *getInitializeOp(void) const { return initializeOp; } PcodeOp *getIterateOp(void) const { return iterateOp; } bool hasOverflowSyntax(void) const { return ((getFlags() & f_whiledo_overflow)!=0); } void setOverflowSyntax(void) { setFlag(f_whiledo_overflow); } virtual block_type getType(void) const { return t_whiledo; }
virtual void markLabelBumpUp(bool bump);
virtual void scopeBreak(int4 curexit,int4 curloopexit);
virtual void printHeader(ostream &s) const;
virtual void emit(PrintLanguage *lng) const { lng->emitBlockWhileDo(this); }
virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const;
virtual void finalTransform(Funcdata &data);
virtual void finalizePrinting(Funcdata &data) const;
};
class BlockDoWhile : public BlockGraph {
public:
virtual block_type getType(void) const { return t_dowhile; }
virtual void markLabelBumpUp(bool bump);
virtual void scopeBreak(int4 curexit,int4 curloopexit);
virtual void printHeader(ostream &s) const;
virtual void emit(PrintLanguage *lng) const { lng->emitBlockDoWhile(this); }
virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const;
};
class BlockInfLoop : public BlockGraph {
public:
virtual block_type getType(void) const { return t_infloop; }
virtual void markLabelBumpUp(bool bump);
virtual void scopeBreak(int4 curexit,int4 curloopexit);
virtual void printHeader(ostream &s) const;
virtual void emit(PrintLanguage *lng) const { lng->emitBlockInfLoop(this); }
virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const;
};
class BlockSwitch : public BlockGraph {
JumpTable *jump; struct CaseOrder {
FlowBlock *block; const FlowBlock *basicblock; uintb label; int4 depth; int4 chain; int4 outindex; uint4 gototype; bool isexit; bool isdefault; static bool compare(const CaseOrder &a,const CaseOrder &b); };
mutable vector<CaseOrder> caseblocks; void addCase(FlowBlock *switchbl,FlowBlock *bl,uint4 gt); public:
BlockSwitch(FlowBlock *ind); void grabCaseBasic(FlowBlock *switchbl,const vector<FlowBlock *> &cs); FlowBlock *getSwitchBlock(void) const { return getBlock(0); } int4 getNumCaseBlocks(void) const { return caseblocks.size(); } FlowBlock *getCaseBlock(int4 i) const { return caseblocks[i].block; }
int4 getNumLabels(int4 i) const { return jump->numIndicesByBlock(caseblocks[i].basicblock); }
uintb getLabel(int4 i,int4 j) const { return jump->getLabelByIndex(jump->getIndexByBlock(caseblocks[i].basicblock,j)); }
bool isDefaultCase(int4 i) const { return caseblocks[i].isdefault; } uint4 getGotoType(int4 i) const { return caseblocks[i].gototype; } bool isExit(int4 i) const { return caseblocks[i].isexit; } const Datatype *getSwitchType(void) const; virtual block_type getType(void) const { return t_switch; }
virtual void markUnstructured(void);
virtual void scopeBreak(int4 curexit,int4 curloopexit);
virtual void printHeader(ostream &s) const;
virtual void emit(PrintLanguage *lng) const { lng->emitBlockSwitch(this); }
virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const;
virtual void finalizePrinting(Funcdata &data) const;
};
class BlockMap {
const AddrSpaceManager *manage; vector<FlowBlock *> sortlist; FlowBlock *resolveBlock(FlowBlock::block_type bt); static FlowBlock *findBlock(const vector<FlowBlock *> &list,int4 ind); public:
BlockMap(const AddrSpaceManager *m) { manage = m; } BlockMap(const BlockMap &op2); const AddrSpaceManager *getAddressManager(void) const { return manage; } void sortList(void);
FlowBlock *findLevelBlock(int4 index) const { return findBlock(sortlist,index); }
FlowBlock *createBlock(const string &name); };
inline void FlowBlock::emit(PrintLanguage *lng) const
{
}
inline bool FlowBlock::preferComplement(Funcdata &data)
{
return false;
}
inline FlowBlock *FlowBlock::getSplitPoint(void)
{
return (FlowBlock *)0;
}
inline int4 FlowBlock::flipInPlaceTest(vector<PcodeOp *> &fliplist) const
{
return 2; }
inline void FlowBlock::flipInPlaceExecute(void)
{
}
inline FlowBlock *FlowBlock::nextFlowAfter(const FlowBlock *bl) const
{
return (FlowBlock *)0;
}
inline bool FlowBlock::compareBlockIndex(const FlowBlock *bl1,const FlowBlock *bl2)
{
return (bl1->getIndex() < bl2->getIndex());
}
inline bool BlockSwitch::CaseOrder::compare(const CaseOrder &a,const CaseOrder &b)
{
if (a.label != b.label)
return (a.label < b.label);
return (a.depth < b.depth);
}
#endif