forked from cseagle/blc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
block.hh
793 lines (746 loc) · 49.7 KB
/
block.hh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
/* ###
* IP: GHIDRA
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/// \file block.hh
/// \brief Classes related to \e basic \e blocks and control-flow structuring
#ifndef __CPUI_BLOCK__
#define __CPUI_BLOCK__
#include "jumptable.hh"
class BlockBasic; // Forward declarations
class BlockList;
class BlockCopy;
class BlockGoto;
class BlockMultiGoto;
class BlockCondition;
class BlockIf;
class BlockWhileDo;
class BlockDoWhile;
class BlockInfLoop;
class BlockSwitch;
class PrintLanguage;
class BlockMap;
/// \brief A control-flow edge between blocks (FlowBlock)
///
/// The edge is owned by the source block and can have FlowBlock::edge_flags
/// labels applied to it. The \b point indicates the FlowBlock at the other end
/// from the source block. NOTE: The control-flow direction of the edge can
/// only be determined from context, whether the edge is in the incoming or outgoing edge list.
struct BlockEdge {
uint4 label; ///< Label of the edge
FlowBlock *point; ///< Other end of the edge
int4 reverse_index; ///< Index for edge coming other way
BlockEdge(void) {} ///< Constructor for use with restoreXml
BlockEdge(FlowBlock *pt,uint4 lab,int4 rev) { label=lab; point=pt; reverse_index = rev; } ///< Constructor
void saveXml(ostream &s) const; ///< Save the edge to an XML stream
void restoreXml(const Element *el,BlockMap &resolver); ///< Restore \b this edge from an XML stream
};
/// \brief Description of a control-flow block containing PcodeOps
///
/// This is the base class for basic blocks (BlockBasic) and the
/// hierarchical description of \e structured code. At all levels,
/// these can be viewed as a block of code (PcodeOp objects) with
/// other blocks flowing into and out of it.
class FlowBlock {
friend class BlockGraph;
public:
/// \brief The possible block types
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
};
/// \brief Boolean properties of blocks
///
/// The first four flags describe attributes of the blocks primary exiting edges
/// The f_interior_* flags do not necessarily apply to these edges. They are used
/// with the block structure and hierarchy algorithms where unstructured jumps
/// are removed from the list of primary edges. These flags keep track only of
/// the existence of unstructured edges, even though they aren't listed
enum block_flags {
f_goto_goto = 1, ///< (Block ends in) non-structured branch
f_break_goto = 2, ///< Block ends with a break;
f_continue_goto = 4, ///< Block ends with a continue;
f_switch_out = 0x10, ///< Output is decided by switch
f_unstructured_targ = 0x20, ///< Block is destination of unstructured goto
f_mark = 0x80, ///< Generic way to mark a block
f_mark2 = 0x100, ///< A secondary mark
f_entry_point = 0x200, ///< Official entry point of the function
f_interior_gotoout = 0x400, ///< The block has an unstructured jump out of interior
f_interior_gotoin = 0x800, ///< Block is target of unstructured jump to its interior
f_label_bumpup = 0x1000, ///< Any label printed higher up in hierarchy
f_donothing_loop = 0x2000, ///< Block does nothing in infinite loop (halt)
f_dead = 0x4000, ///< Block is in process of being deleted
f_whiledo_overflow = 0x8000,///< Set if the conditional block of a whiledo is too big to print as while(cond) { ...
f_flip_path = 0x10000, ///< If true, out edges have been flipped since last time path was traced
f_joined_block = 0x20000, ///< Block is a merged form of original basic blocks
f_duplicate_block = 0x40000 ///< Block is a duplicated version of an original basic block
};
/// \brief Boolean properties on edges
enum edge_flags {
f_goto_edge = 1, ///< Edge is unstructured
f_loop_edge = 2, ///< Edge completes a loop, removing these edges gives you a DAG
f_defaultswitch_edge = 4, ///< This is default edge from switchblock
f_irreducible = 8, ///< Edge which must be removed to make graph reducible
f_tree_edge = 0x10, ///< An edge in the spanning tree
f_forward_edge = 0x20, ///< An edge that jumps forward in the spanning tree
f_cross_edge = 0x40, ///< An edge that crosses subtrees in the spanning tree
f_back_edge = 0x80, ///< Within (reducible) graph, a back edge defining a loop
f_loop_exit_edge = 0x100 ///< Edge exits the body of a loop
};
private:
uint4 flags; ///< Collection of block_flags
FlowBlock *parent; ///< The parent block to which \b this belongs
FlowBlock *immed_dom; ///< Immediate dominating block
FlowBlock *copymap; ///< Back reference to a BlockCopy of \b this
int4 index; ///< Reference index for this block (reverse post order)
int4 visitcount; ///< A count of visits of this node for various algorithms
int4 numdesc; ///< Number of descendants of this block in spanning tree (+1)
vector<BlockEdge> intothis; ///< Blocks which (can) fall into this block
vector<BlockEdge> outofthis; ///< Blocks into which this block (can) fall
// If there are two possible outputs as the
// result of a conditional branch
// the first block in outofthis should be
// the result of the condition being false
static void replaceEdgeMap(vector<BlockEdge> &vec); ///< Update block references in edges with copy map
void addInEdge(FlowBlock *b,uint4 lab); ///< Add an edge coming into \b this
void restoreNextInEdge(const Element *el,BlockMap &resolver); ///< Restore the next input edge from XML
void halfDeleteInEdge(int4 slot); ///< Delete the \e in half of an edge, correcting indices
void halfDeleteOutEdge(int4 slot); ///< Delete the \e out half of an edge, correcting indices
void removeInEdge(int4 slot); ///< Remove an incoming edge
void removeOutEdge(int4 slot); ///< Remove an outgoing edge
void replaceInEdge(int4 num,FlowBlock *b); ///< Make an incoming edge flow from a given block
void replaceOutEdge(int4 num,FlowBlock *b); ///< Make an outgoing edge flow to a given block
void replaceEdgesThru(int4 in,int4 out); ///< Remove \b this from flow between two blocks
void swapEdges(void); ///< Swap the first and second \e out edges
void setOutEdgeFlag(int4 i,uint4 lab); ///< Apply an \e out edge label
void clearOutEdgeFlag(int4 i,uint4 lab); ///< Remove an \e out edge label
void eliminateInDups(FlowBlock *bl); ///< Eliminate duplicate \e in edges from given block
void eliminateOutDups(FlowBlock *bl); ///< Eliminate duplicate \e out edges to given block
static void findDups(const vector<BlockEdge> &ref,vector<FlowBlock *> &duplist);
void dedup(void); ///< Eliminate duplicate edges
void replaceUsingMap(void); ///< Update references to other blocks using getCopyMap()
#ifdef BLOCKCONSISTENT_DEBUG
void checkEdges(void); ///< Check the consistency of edge references
#endif
protected:
void setFlag(uint4 fl) { flags |= fl; } ///< Set a boolean property
void clearFlag(uint4 fl) { flags &= ~fl; } ///< Clear a boolean property
public:
FlowBlock(void); ///< Construct a block with no edges
virtual ~FlowBlock(void) {} ///< Destructor
int4 getIndex(void) const { return index; } ///< Get the index assigned to \b this block
FlowBlock *getParent(void) { return parent; } ///< Get the parent FlowBlock of \b this
FlowBlock *getImmedDom(void) const { return immed_dom; } ///< Get the immediate dominator FlowBlock
FlowBlock *getCopyMap(void) const { return copymap; } ///< Get the mapped FlowBlock
const FlowBlock *getParent(void) const { return (const FlowBlock *) parent; } ///< Get the parent FlowBlock of \b this
uint4 getFlags(void) const { return flags; } ///< Get the block_flags properties
virtual Address getStart(void) const { return Address(); } ///< Get the starting address of code in \b this FlowBlock
virtual Address getStop(void) const { return Address(); } ///< Get the ending address of code in \b this FlowBlock
virtual block_type getType(void) const { return t_plain; } ///< Get the FlowBlock type of \b this
virtual FlowBlock *subBlock(int4 i) const { return (FlowBlock *)0; } ///< Get the i-th component block
virtual void markUnstructured(void) {} ///< Mark target blocks of any unstructured edges
virtual void markLabelBumpUp(bool bump); ///< Let hierarchical blocks steal labels of their (first) components
virtual void scopeBreak(int4 curexit,int4 curloopexit) {} ///< Mark unstructured edges that should be \e breaks
virtual void printHeader(ostream &s) const; ///< Print a simple description of \b this to stream
virtual void printTree(ostream &s,int4 level) const; ///< Print tree structure of any blocks owned by \b this
virtual void printRaw(ostream &s) const {} ///< Print raw instructions contained in \b this FlowBlock
virtual void emit(PrintLanguage *lng) const; ///<Emit the instructions in \b this FlowBlock as structured code
virtual const FlowBlock *getExitLeaf(void) const { return (const FlowBlock *)0; } ///< Get the FlowBlock to which \b this block exits
virtual PcodeOp *lastOp(void) const { return (PcodeOp *)0; } ///< Get the last PcodeOp executed by \b this FlowBlock
virtual bool negateCondition(bool toporbottom); ///< Flip the condition computed by \b this
virtual bool preferComplement(Funcdata &data); ///< Rearrange \b this hierarchy to simplify boolean expressions
virtual FlowBlock *getSplitPoint(void); ///< Get the leaf splitting block
virtual int4 flipInPlaceTest(vector<PcodeOp *> &fliplist) const;
virtual void flipInPlaceExecute(void);
virtual bool isComplex(void) const { return true; } ///< Is \b this too complex to be a condition (BlockCondition)
virtual FlowBlock *nextFlowAfter(const FlowBlock *bl) const;
virtual void orderSwitchCases(void) const {} ///< Order \e case components of any contained BlockSwitch
virtual void saveXmlHeader(ostream &s) const; ///< Save basic information as XML attributes
virtual void restoreXmlHeader(const Element *el); ///< Restore basic information for XML attributes
virtual void saveXmlBody(ostream &s) const {} ///< Save detail about components to an XML stream
/// \brief Restore details about \b this FlowBlock from an XML stream
///
/// \param iter is an iterator to XML elements containing component tags etc.
/// \param enditer marks the end of the XML tags
/// \param resolver is used to recover FlowBlock objects based on XML references
virtual void restoreXmlBody(List::const_iterator &iter,List::const_iterator enditer,BlockMap &resolver) {}
void saveXmlEdges(ostream &s) const; ///< Save edge information to an XML stream
void restoreXmlEdges(List::const_iterator &iter,List::const_iterator enditer,BlockMap &resolver);
void saveXml(ostream &s) const; ///< Write out \b this to an XML stream
void restoreXml(const Element *el,BlockMap &resolver); ///< Restore \b this from an XML stream
const FlowBlock *nextInFlow(void) const; ///< Return next block to be executed in flow
void setVisitCount(int4 i) { visitcount = i; } ///< Set the number of times this block has been visited
int4 getVisitCount(void) const { return visitcount; } ///< Get the count of visits
void setGotoBranch(int4 i); ///< Mark a \e goto branch
void setDefaultSwitch(int4 i) { setOutEdgeFlag(i,f_defaultswitch_edge); } ///< Mark an edge as the switch default
bool isMark(void) const { return ((flags&f_mark)!=0); } ///< Return \b true if \b this block has been marked
void setMark(void) { flags |= f_mark; } ///< Mark \b this block
void clearMark(void) { flags &= ~f_mark; } ///< Clear any mark on \b this block
void setDonothingLoop(void) { flags |= f_donothing_loop; } ///< Label \b this as a \e do \e nothing loop
void setDead(void) { flags |= f_dead; } ///< Label \b this as dead
bool hasSpecialLabel(void) const { return ((flags&(f_joined_block|f_duplicate_block))!=0); } ///< Return \b true if \b this uses a different label
bool isJoined(void) const { return ((flags&f_joined_block)!=0); } ///< Return \b true if \b this is a \e joined basic block
bool isDuplicated(void) const { return ((flags&f_duplicate_block)!=0); } ///< Return \b true if \b this is a \e duplicated block
void setLoopExit(int4 i) { setOutEdgeFlag(i,f_loop_exit_edge); } ///< Label the edge exiting \b this as a loop
void clearLoopExit(int4 i) { clearOutEdgeFlag(i,f_loop_exit_edge); } ///< Clear the loop exit edge
void setBackEdge(int4 i) { setOutEdgeFlag(i,f_back_edge); } ///< Label the \e back edge of a loop
bool getFlipPath(void) const { return ((flags & f_flip_path)!=0); } ///< Have out edges been flipped
bool isJumpTarget(void) const; ///< Return \b true if non-fallthru jump flows into \b this
FlowBlock *getFalseOut(void) const { return outofthis[0].point; } ///< Get the \b false output FlowBlock
FlowBlock *getTrueOut(void) const { return outofthis[1].point; } ///< Get the \b true output FlowBlock
FlowBlock *getOut(int4 i) { return outofthis[i].point; } ///< Get the i-th output FlowBlock
const FlowBlock *getOut(int4 i) const { return (const FlowBlock *) outofthis[i].point; } ///< Get i-th output FlowBlock
int4 getOutRevIndex(int4 i) const { return outofthis[i].reverse_index; } ///< Get the input index of the i-th output FlowBlock
FlowBlock *getIn(int4 i) { return intothis[i].point; } ///< Get the i-th input FlowBlock
const FlowBlock *getIn(int4 i) const { return (const FlowBlock *) intothis[i].point; } ///< Get the i-th input FlowBlock
int4 getInRevIndex(int4 i) const { return intothis[i].reverse_index; } ///< Get the output index of the i-th input FlowBlock
const FlowBlock *getFrontLeaf(void) const; ///< Get the first leaf FlowBlock
FlowBlock *getFrontLeaf(void); ///< Get the first leaf FlowBlock
int4 calcDepth(const FlowBlock *leaf) const; ///< Get the depth of the given component FlowBlock
bool dominates(const FlowBlock *subBlock) const; ///< Does \b this block dominate the given block
bool restrictedByConditional(const FlowBlock *cond) const;
int4 sizeOut(void) const { return outofthis.size(); } ///< Get the number of out edges
int4 sizeIn(void) const { return intothis.size(); } ///< Get the number of in edges
bool hasLoopIn(void) const; ///< Is there a looping edge coming into \b this block
bool hasLoopOut(void) const; ///< Is there a looping edge going out of \b this block
bool isLoopIn(int4 i) const { return ((intothis[i].label & f_loop_edge)!=0); } ///< Is the i-th incoming edge a \e loop edge
bool isLoopOut(int4 i) const { return ((outofthis[i].label & f_loop_edge)!=0); } ///< Is the i-th outgoing edge a \e loop edge
int4 getInIndex(const FlowBlock *bl) const; ///< Get the incoming edge index for the given FlowBlock
int4 getOutIndex(const FlowBlock *bl) const; ///< Get the outgoing edge index for the given FlowBlock
bool isDefaultBranch(int4 i) const { return ((outofthis[i].label & f_defaultswitch_edge)!=0); } ///< Is the i-th out edge the switch default edge
bool isLabelBumpUp(void) const { return ((flags & f_label_bumpup)!=0); } ///< Are labels for \b this printed by the parent
bool isUnstructuredTarget(void) const { return ((flags & f_unstructured_targ)!=0); } ///< Is \b this the target of an unstructured goto
bool isInteriorGotoTarget(void) const { return ((flags & f_interior_gotoin)!=0); } ///< Is there an unstructured goto to \b this block's interior
bool hasInteriorGoto(void) const { return ((flags & f_interior_gotoout)!=0); } ///< Is there an unstructured goto out of \b this block's interior
bool isEntryPoint(void) const { return ((flags&f_entry_point)!=0); } ///< Is the entry point of the function
bool isSwitchOut(void) const { return ((flags&f_switch_out)!=0); } ///< Is \b this a switch block
bool isDonothingLoop(void) const { return ((flags&f_donothing_loop)!=0); } ///< Is \b this a \e do \e nothing block
bool isDead(void) const { return ((flags & f_dead)!=0); } ///< Is \b this block dead
bool isTreeEdgeIn(int4 i) const { return ((intothis[i].label & f_tree_edge)!=0); } ///< Is the i-th incoming edge part of the spanning tree
bool isBackEdgeIn(int4 i) const { return ((intothis[i].label & f_back_edge)!=0); } ///< Is the i-th incoming edge a \e back edge
bool isBackEdgeOut(int4 i) const { return ((outofthis[i].label & f_back_edge)!=0); } ///< Is the i-th outgoing edge a \e back edge
bool isIrreducibleOut(int4 i) const { return ((outofthis[i].label & f_irreducible)!=0); } ///< Is the i-th outgoing edge an irreducible edge
bool isIrreducibleIn(int4 i) const { return ((intothis[i].label & f_irreducible)!=0); } ///< Is the i-th incoming edge an irreducible edge
/// \brief Can \b this and the i-th output be merged into a BlockIf or BlockList
bool isDecisionOut(int4 i) const { return ((outofthis[i].label & (f_irreducible|f_back_edge|f_goto_edge))==0); }
/// \brief Can \b this and the i-th input be merged into a BlockIf or BlockList
bool isDecisionIn(int4 i) const { return ((intothis[i].label & (f_irreducible|f_back_edge|f_goto_edge))==0); }
/// \brief Is the i-th outgoing edge part of the DAG sub-graph
bool isLoopDAGOut(int4 i) const { return ((outofthis[i].label & (f_irreducible|f_back_edge|f_loop_exit_edge|f_goto_edge))==0); }
/// \brief Is the i-th incoming edge part of the DAG sub-graph
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); } ///< 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
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
static bool compareFinalOrder(const FlowBlock *bl1,const FlowBlock *bl2); ///< Final FlowBlock comparison
static FlowBlock *findCommonBlock(FlowBlock *bl1,FlowBlock *bl2); ///< Find the common dominator of two FlowBlocks
static FlowBlock *findCommonBlock(const vector<FlowBlock *> &blockSet); ///< Find common dominator of multiple FlowBlocks
};
/// \brief A control-flow block built out of sub-components
///
/// This is the core class for building a hierarchy of control-flow blocks.
/// A set of control-flow blocks can be grouped together and viewed as a single block,
/// with its own input and output blocks.
/// All the code structuring elements (BlockList, BlockIf, BlockWhileDo, etc.) derive from this.
class BlockGraph : public FlowBlock {
vector<FlowBlock *> list; ///< List of FlowBlock components within \b this super-block
void addBlock(FlowBlock *bl); ///< Add a component FlowBlock
void forceOutputNum(int4 i); ///< Force number of outputs
void selfIdentify(void); ///< Inherit our edges from the edges of our components
void identifyInternal(BlockGraph *ident,const vector<FlowBlock *> &nodes);
void clearEdgeFlags(uint4 flags); ///< Clear a set of properties from all edges in the graph
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); ///< Force the \e false out edge to go to the given FlowBlock
protected:
void swapBlocks(int4 i,int4 j); ///< Swap the positions two component FlowBlocks
static void markCopyBlock(FlowBlock *bl,uint4 fl); ///< Set properties on the first leaf FlowBlock
public:
void clear(void); ///< Clear all component FlowBlock objects
virtual ~BlockGraph(void) { clear(); } ///< Destructor
const vector<FlowBlock *> &getList(void) const { return list; } ///< Get the list of component FlowBlock objects
int4 getSize(void) const { return list.size(); } ///< Get the number of components
FlowBlock *getBlock(int4 i) const { return list[i]; } ///< Get the i-th component
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 orderSwitchCases(void) 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); ///< Restore \b this BlockGraph from an XML stream
void addEdge(FlowBlock *begin,FlowBlock *end); ///< Add a directed edge between component FlowBlocks
void addLoopEdge(FlowBlock *begin,int4 outindex); ///< Mark a given edge as a \e loop edge
void removeEdge(FlowBlock *begin,FlowBlock *end); ///< Remove an edge between component FlowBlocks
void switchEdge(FlowBlock *in,FlowBlock *outbefore,FlowBlock *outafter); ///< Move an edge from one out FlowBlock to another
void moveOutEdge(FlowBlock *blold,int4 slot,FlowBlock *blnew); ///< Move indicated \e out edge to a new FlowBlock
void removeBlock(FlowBlock *bl); ///< Remove a FlowBlock from \b this BlockGraph
void removeFromFlow(FlowBlock *bl); ///< Remove given FlowBlock preserving flow in \b this
void removeFromFlowSplit(FlowBlock *bl,bool flipflow); ///< Remove FlowBlock splitting flow between input and output edges
void spliceBlock(FlowBlock *bl); ///< Splice given FlowBlock together with its output
void setStartBlock(FlowBlock *bl); ///< Set the entry point FlowBlock for \b this graph
FlowBlock *getStartBlock(void) const; ///< Get the entry point FlowBlock
// Factory functions
FlowBlock *newBlock(void); ///< Build a new plain FlowBlock
BlockBasic *newBlockBasic(Funcdata *fd); ///< Build a new BlockBasic
// Factory (identify) routines
BlockCopy *newBlockCopy(FlowBlock *bl); ///< Build a new BlockCopy
BlockGoto *newBlockGoto(FlowBlock *bl); ///< Build a new BlockGoto
BlockMultiGoto *newBlockMultiGoto(FlowBlock *bl,int4 outedge); ///< Build a new BlockMultiGoto
BlockList *newBlockList(const vector<FlowBlock *> &nodes); ///< Build a new BlockList
BlockCondition *newBlockCondition(FlowBlock *b1,FlowBlock *b2); ///< Build a new BlockCondition
BlockIf *newBlockIfGoto(FlowBlock *cond); ///< Build a new BlockIfGoto
BlockIf *newBlockIf(FlowBlock *cond,FlowBlock *tc); ///< Build a new BlockIf
BlockIf *newBlockIfElse(FlowBlock *cond,FlowBlock *tc,FlowBlock *fc); ///< Build a new BlockIfElse
BlockWhileDo *newBlockWhileDo(FlowBlock *cond,FlowBlock *cl); ///< Build a new BlockWhileDo
BlockDoWhile *newBlockDoWhile(FlowBlock *condcl); ///< Build a new BlockDoWhile
BlockInfLoop *newBlockInfLoop(FlowBlock *body); ///< Build a new BlockInfLoop
BlockSwitch *newBlockSwitch(const vector<FlowBlock *> &cs,bool hasExit); ///< Build a new BlockSwitch
void orderBlocks(void) { ///< Sort blocks using the final ordering
if (list.size()!=1) sort(list.begin(),list.end(),compareFinalOrder); }
void buildCopy(const BlockGraph &graph); ///< Build a copy of a BlockGraph
void clearVisitCount(void); ///< Clear the visit count in all node FlowBlocks
void calcForwardDominator(const vector<FlowBlock *> &rootlist); ///< Calculate forward dominators
void buildDomTree(vector<vector<FlowBlock *> > &child) const; ///< Build the dominator tree
int4 buildDomDepth(vector<int4> &depth) const; ///< Calculate dominator depths
void buildDomSubTree(vector<FlowBlock *> &res,FlowBlock *root) const; ///< Collect nodes from a dominator sub-tree
void calcLoop(void); ///< Calculate loop edges
void collectReachable(vector<FlowBlock *> &res,FlowBlock *bl,bool un) const; ///< Collect reachable/unreachable FlowBlocks from a given start FlowBlock
void structureLoops(vector<FlowBlock *> &rootlist); ///< Label loop edges
#ifdef BLOCKCONSISTENT_DEBUG
bool isConsistent(void) const; ///< Check consistency of \b this BlockGraph
#endif
};
/// \brief A basic block for p-code operations.
///
/// A \b basic \b block is a maximal sequence of p-code operations (PcodeOp) that,
/// within the context of a function, always execute starting with the first
/// operation in sequence through in order to the last operation. Any decision points in the
/// control flow of a function manifest as branching operations (BRANCH, CBRANCH, BRANCHIND)
/// that necessarily occur as the last operation in a basic block.
///
/// Every Funcdata object implements the control-flow graph of the underlying function using
/// BlockBasic objects as the underlying nodes of the graph. The decompiler structures code
/// by making a copy of this graph and then overlaying a hierarchy of structured nodes on top of it.
///
/// The block also keeps track of the original range of addresses of instructions constituting the block.
/// As decompiler transformations progress, the set of addresses associated with the current set of
/// PcodeOps my migrate away from this original range.
class BlockBasic: public FlowBlock {
friend class Funcdata; // Only uses private functions
list<PcodeOp *> op; ///< The sequence of p-code operations
Funcdata *data; ///< The function of which this block is a part
RangeList cover; ///< Original range of addresses covered by this basic block
void insert(list<PcodeOp *>::iterator iter,PcodeOp *inst); ///< Insert p-code operation at a given position
void setInitialRange(const Address &beg,const Address &end); ///< Set the initial address range of the block
void copyRange(const BlockBasic *bb) { cover = bb->cover; } ///< Copy address ranges from another basic block
void mergeRange(const BlockBasic *bb) { cover.merge(bb->cover); } ///< Merge address ranges from another basic block
void setOrder(void); ///< Reset the \b SeqNum::order field for all PcodeOp objects in this block
void removeOp(PcodeOp *inst); ///< Remove PcodeOp from \b this basic block
public:
BlockBasic(Funcdata *fd) { data = fd; } ///< Construct given the underlying function
Funcdata *getFuncdata(void) { return data; } ///< Return the underlying Funcdata object
const Funcdata *getFuncdata(void) const { return (const Funcdata *)data; } ///< Return the underlying Funcdata object
bool contains(const Address &addr) const { return cover.inRange(addr, 1); } ///< Determine if the given address is contained in the original range
Address getEntryAddr(void) const; ///< Get the address of the (original) first operation to execute
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; ///< Check if \b this block can be removed without introducing inconsistencies
bool hasOnlyMarkers(void) const; ///< Does \b this block contain only MULTIEQUAL and INDIRECT ops
bool isDoNothing(void) const; ///< Should \b this block should be removed
list<PcodeOp *>::iterator beginOp(void) { return op.begin(); } ///< Return an iterator to the beginning of the PcodeOps
list<PcodeOp *>::iterator endOp(void) { return op.end(); } ///< Return an iterator to the end of the PcodeOps
list<PcodeOp *>::const_iterator beginOp(void) const { return op.begin(); } ///< Return an iterator to the beginning of the PcodeOps
list<PcodeOp *>::const_iterator endOp(void) const { return op.end(); } ///< Return an iterator to the end of the PcodeOps
bool emptyOp(void) const { return op.empty(); } ///< Return \b true if \b block contains no operations
static bool noInterveningStatement(PcodeOp *first,int4 path,PcodeOp *last);
};
/// \brief This class is used to mirror the BlockBasic objects in the fixed control-flow graph for a function
///
/// The decompiler does control-flow structuring by making an initial copy of the control-flow graph,
/// then iteratively collapsing nodes (in the copy) into \e structured nodes. So an instance of this
/// class acts as the mirror of an original basic block within the copy of the graph. During the
/// structuring process, an instance will start with an exact mirror of its underlying basic block's edges,
/// but as the algorithm proceeds, edges may get replaced as neighboring basic blocks get collapsed, and
/// eventually the instance will get collapsed itself and become a component of one of the \e structured
/// block objects (BlockIf, BlockDoWhile, etc). The block that incorporates the BlockCopy as a component
/// is accessible through getParent().
class BlockCopy : public FlowBlock {
FlowBlock *copy; ///< The block being mirrored by \b this (usually a BlockBasic)
public:
BlockCopy(FlowBlock *bl) { copy = bl; } ///< Construct given the block to copy
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;
};
/// \brief A block that terminates with an unstructured (goto) branch to another block
///
/// The \e goto must be an unconditional branch. The instance keeps track of the target block and
/// will emit the branch as some form of formal branch statement (goto, break, continue).
/// From the point of view of control-flow structuring, this block has \e no output edges. The
/// algorithm handles edges it can't structure by encapsulating it in the BlockGoto class and
/// otherwise removing the edge from the structured view of the graph.
class BlockGoto : public BlockGraph {
FlowBlock *gototarget; ///< The target block of the unstructured branch
uint4 gototype; ///< The type of unstructured branch (f_goto_goto, f_break_goto, etc.)
public:
BlockGoto(FlowBlock *bl) { gototarget = bl; gototype = f_goto_goto; } ///< Construct given target block
FlowBlock *getGotoTarget(void) const { return gototarget; } ///< Get the target block of the goto
uint4 getGotoType(void) const { return gototype; } ///< Get the type of unstructured branch
bool gotoPrints(void) const; ///< Should a formal goto statement be emitted
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;
};
/// \brief A block with multiple edges out, at least one of which is an unstructured (goto) branch.
///
/// An instance of this class is used to mirror a basic block with multiple out edges at the point
/// where one of the edges can't be structured. The instance keeps track of this edge but otherwise
/// presents a view to the structuring algorithm as if the edge didn't exist. If at a later point,
/// more edges can't be structured, the one instance can hold this information as well.
class BlockMultiGoto : public BlockGraph {
vector<FlowBlock *> gotoedges; ///< List of goto targets from this block
bool defaultswitch; ///< True if one of the unstructured edges is the formal switch \e default edge
public:
BlockMultiGoto(FlowBlock *bl) { defaultswitch = false; } ///< Construct given the underlying multi-exit block
void setDefaultGoto(void) { defaultswitch = true; } ///< Mark that this block holds an unstructured switch default
bool hasDefaultGoto(void) const { return defaultswitch; } ///< Does this block hold an unstructured switch default edge
void addEdge(FlowBlock *bl) { gotoedges.push_back(bl); } ///< Mark the edge from \b this to the given FlowBlock as unstructured
int4 numGotos(void) const { return gotoedges.size(); } ///< Get the number of unstructured edges
FlowBlock *getGoto(int4 i) const { return gotoedges[i]; } ///< Get the target FlowBlock along the i-th unstructured edge
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;
};
/// \brief A series of blocks that execute in sequence.
///
/// When structuring control-flow, an instance of this class represents blocks
/// that execute in sequence and fall-thru to each other. In general, the component
/// blocks may not be basic blocks and can have their own sub-structures.
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);
};
/// \brief Two conditional blocks combined into one conditional using BOOL_AND or BOOL_OR
///
/// This class is used to construct full conditional expressions. An instance glues together
/// two components, each with two outgoing edges. Of the four edges, 1 must go between the two
/// components, and 2 must go to the same exit block, so there will be exactly 2 distinct exit
/// blocks in total. The new condition can be interpreted as either:
/// - If condition one \b and condition two, goto exit 0, otherwise goto exit 1.
/// - If condition one \b or condition two, goto exit 1, otherwise goto exit 0.
///
/// depending on the boolean operation setting for the condition
class BlockCondition : public BlockGraph {
OpCode opc; ///< Type of boolean operation
public:
BlockCondition(OpCode c) { opc = c; } ///< Construct given the boolean operation
OpCode getOpcode(void) const { return opc; } ///< Get the boolean operation
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;
};
/// \brief A basic "if" block
///
/// This represents a formal "if" structure in code, with a expression for the condition, and
/// one or two bodies of the conditionally executed code. An instance has one, two, or three components.
/// One component is always the \e conditional block. If there is a second component, it is
/// the block of code executed when the condition is true. If there is a third component, it
/// is the "else" block, executed when the condition is false.
///
/// If there is only one component, this represents the case where the conditionally executed
/// branch is unstructured. This is generally emitted where the conditionally executed body
/// is the single \e goto statement.
///
/// A BlockIf will always have at most one (structured) exit edge. With one component, one of the edges of
/// the conditional component is unstructured. With two components, one of the conditional block
/// edges flows to the body block, and the body's out edge and the remaining conditional block out
/// edge flow to the same exit block. With three components, the one conditional edge flows to the
/// \e true body block, the other conditional edge flows to the \e false body block, and outgoing
/// edges from the body blocks, if they exist, flow to the same exit block.
class BlockIf : public BlockGraph {
uint4 gototype; ///< The type of unstructured edge (if present)
FlowBlock *gototarget; ///< The target FlowBlock of the unstructured edge (if present)
public:
BlockIf(void) { gototype = f_goto_goto; gototarget = (FlowBlock *)0; } ///< Constructor
void setGotoTarget(FlowBlock *bl) { gototarget = bl; } ///< Mark the target of the unstructured edge
FlowBlock *getGotoTarget(void) const { return gototarget; } ///< Get the target of the unstructured edge
uint4 getGotoType(void) const { return gototype; } ///< Get the type of unstructured edge
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;
};
/// \brief A loop structure where the condition is checked at the top.
///
/// This has exactly two components: one conditional block which evaluates when the
/// loop terminates, and one body block. The conditional block has two outgoing edges,
/// one to the body block and one to the exit block. The body block has one outgoing edge
/// back to the conditional block. The BlockWhileDo instance has exactly one outgoing edge.
///
/// Overflow syntax refers to the situation where there is a proper BlockWhileDo structure but
/// the conditional block is too long or complicated to emit as a single conditional expression.
/// An alternate `while(true) { }` form is used instead.
class BlockWhileDo : public BlockGraph {
public:
bool hasOverflowSyntax(void) const { return ((getFlags() & f_whiledo_overflow)!=0); } ///< Does \b this require overflow syntax
void setOverflowSyntax(void) { setFlag(f_whiledo_overflow); } ///< Set that \b this requires overflow syntax
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;
};
/// \brief A loop structure where the condition is checked at the bottom.
///
/// This has exactly one component with two outgoing edges: one edge flows to itself,
/// the other flows to the exit block. The BlockDoWhile instance has exactly one outgoing edge.
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;
};
/// \brief An infinite loop structure
///
/// This has exactly one component with one outgoing edge that flows into itself.
/// The BlockInfLoop instance has zero outgoing edges.
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;
};
/// \brief A structured \e switch construction
///
/// This always has at least one component, the first, that executes the \e switch statement
/// itself and has multiple outgoing edges. Each edge flows either to a formal exit block, or
/// to another \e case component. All additional components are \b case components, which have
/// either zero or one outgoing edge. If there is an edge, it flows either to another case
/// component or to the formal exit block. The BlockSwitch instance has zero or one outgoing edges.
class BlockSwitch : public BlockGraph {
JumpTable *jump; ///< Jump table associated with this switch
/// \brief A class for annotating and sorting the individual cases of the switch
struct CaseOrder {
FlowBlock *block; ///< The structured \e case block
const FlowBlock *basicblock; ///< The first basic-block to execute within the \e case block
uintb label; ///< The \e label for this case, as an untyped constant
int4 depth; ///< How deep in a fall-thru chain we are
int4 chain; ///< Who we immediately chain to, expressed as caseblocks index, -1 for no chaining
int4 outindex; ///< Index coming out of switch to this case
uint4 gototype; ///< (If non-zero) What type of unstructured \e case is this?
bool isexit; ///< Does this case flow to the \e exit block
bool isdefault; ///< True if this is formal \e default case for the switch
static bool compare(const CaseOrder &a,const CaseOrder &b); ///< Compare two cases
};
mutable vector<CaseOrder> caseblocks; ///< Blocks associated with switch cases
void addCase(FlowBlock *switchbl,FlowBlock *bl,uint4 gt); ///< Add a new \e case to this switch
public:
BlockSwitch(FlowBlock *ind); ///< Construct given the multi-exit root block
void grabCaseBasic(FlowBlock *switchbl,const vector<FlowBlock *> &cs); ///< Build annotated CaseOrder objects
FlowBlock *getSwitchBlock(void) const { return getBlock(0); } ///< Get the root switch component
int4 getNumCaseBlocks(void) const { return caseblocks.size(); } ///< Get the number of cases
FlowBlock *getCaseBlock(int4 i) const { return caseblocks[i].block; } ///< Get the i-th \e case FlowBlock
/// \brief Get the number of labels associated with one \e case block
///
/// \param i is the index of the \e case block
/// \return the number of labels put on the associated block
int4 getNumLabels(int4 i) const { return jump->numIndicesByBlock(caseblocks[i].basicblock); }
/// \brief Get a specific label associated with a \e case block
///
/// \param i is the index of the \e case block
/// \param j is the index of the specific label
/// \return the label as an untyped constant
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; } ///< Is the i-th \e case the \e default case
uint4 getGotoType(int4 i) const { return caseblocks[i].gototype; } ///< Get the edge type for the i-th \e case block
bool isExit(int4 i) const { return caseblocks[i].isexit; } ///< Does the i-th \e case block exit the switch?
const Datatype *getSwitchType(void) const; ///< Get the data-type of the switch variable
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 orderSwitchCases(void) const;
};
/// \brief Helper class for resolving cross-references while deserializing BlockGraph objects
///
/// FlowBlock objects are serialized with their associated \b index value and edges are serialized
/// with the indices of the FlowBlock end-points. During deserialization, this class maintains a
/// list of FlowBlock objects sorted by index and then looks up the FlowBlock matching a given
/// index as edges specify them.
class BlockMap {
const AddrSpaceManager *manage; ///< Address space manager used to restore FlowBlock address ranges
vector<FlowBlock *> sortlist; ///< The list of deserialized FlowBlock objects
FlowBlock *resolveBlock(FlowBlock::block_type bt); ///< Construct a FlowBlock of the given type
static FlowBlock *findBlock(const vector<FlowBlock *> &list,int4 ind); ///< Locate a FlowBlock with a given index
public:
BlockMap(const AddrSpaceManager *m) { manage = m; } ///< Construct given an address space manager
BlockMap(const BlockMap &op2); ///< Copy constructor
const AddrSpaceManager *getAddressManager(void) const { return manage; } ///< Get the address space manager
void sortList(void); ///< Sort the list of FlowBlock objects
/// \brief Find the FlowBlock matching the given index
///
/// \param index is the given index
/// \return the FlowBlock matching the index
FlowBlock *findLevelBlock(int4 index) const { return findBlock(sortlist,index); }
FlowBlock *createBlock(const string &name); ///< Create a FlowBlock of the named type
};
/// This is the main entry point, at the control-flow level, for printing structured code.
/// \param lng is the PrintLanguage that provides details of the high-level language being printed
inline void FlowBlock::emit(PrintLanguage *lng) const
{
}
/// For the instructions in this block, decide if the control-flow structure
/// can be rearranged so that boolean expressions come out more naturally.
/// \param data is the function to analyze
/// \return \b true if a change was made
inline bool FlowBlock::preferComplement(Funcdata &data)
{
return false;
}
/// If \b this block ends with a conditional branch, return the
/// deepest component block that performs the split. This component needs
/// to be able to perform flipInPlaceTest() and flipInPlaceExecute()
/// \return the component FlowBlock or NULL if this doesn't end in a conditional branch
inline FlowBlock *FlowBlock::getSplitPoint(void)
{
return (FlowBlock *)0;
}
/// \brief Test normalizing the conditional branch in \b this
///
/// Find the set of PcodeOp objects that need to be adjusted to flip
/// the condition \b this FlowBlock calculates.
///
/// Return:
/// - 0 if the flip would normalize the condition
/// - 1 if the flip doesn't affect normalization of the condition
/// - 2 if the flip produces an unnormalized condition
/// \param fliplist will contain the PcodeOps that need to be adjusted
/// \return 0 if the condition will be normalized, 1 or 2 otherwise
inline int4 FlowBlock::flipInPlaceTest(vector<PcodeOp *> &fliplist) const
{
return 2; // By default a block will not normalize
}
/// \brief Perform the flip to normalize conditional branch executed by \b this block
///
/// This reverses the outgoing edge order in the right basic blocks, but does not
/// modify the instructions directly.
inline void FlowBlock::flipInPlaceExecute(void)
{
}
/// \brief Get the leaf FlowBlock that will execute after the given FlowBlock
///
/// Within the hierarchy of \b this FlowBlock, assume the given FlowBlock
/// will fall-thru in its execution at some point. Return the first
/// leaf block (BlockBasic or BlockCopy) that will execute after the given
/// FlowBlock completes, assuming this is a unique block.
/// \param bl is the given FlowBlock
/// \return the next FlowBlock to execute or NULL
inline FlowBlock *FlowBlock::nextFlowAfter(const FlowBlock *bl) const
{
return (FlowBlock *)0;
}
/// \param bl1 is the first FlowBlock to compare
/// \param bl2 is the second FlowBlock to compare
/// \return true if the first comes before the second
inline bool FlowBlock::compareBlockIndex(const FlowBlock *bl1,const FlowBlock *bl2)
{
return (bl1->getIndex() < bl2->getIndex());
}
/// Cases are compared by their label
/// \param a is the first case to compare
/// \param b is the second
/// \return \b true if the first comes before the second
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