[PATCH] Fix "return" target handling
[smatch.git] / linearize.h
blob8c6a800f8d33c96c76c527b9b8228efb622fa29f
1 #ifndef LINEARIZE_H
2 #define LINEARIZE_H
4 #include "lib.h"
5 #include "token.h"
6 #include "parse.h"
7 #include "symbol.h"
9 /* Silly pseudo define. Do this right some day */
10 struct pseudo {
11 int nr;
14 typedef struct pseudo *pseudo_t;
16 extern struct pseudo void_pseudo;
18 #define VOID (&void_pseudo)
20 struct multijmp {
21 struct basic_block *target;
22 int begin, end;
25 struct phi {
26 struct basic_block *source;
27 pseudo_t pseudo;
30 struct instruction {
31 struct symbol *type;
32 int opcode;
33 union {
34 pseudo_t target;
35 pseudo_t cond; /* for branch and switch */
37 union {
38 struct /* branch */ {
39 struct basic_block *bb_true, *bb_false;
41 struct /* switch */ {
42 struct multijmp_list *multijmp_list;
44 struct /* phi_node */ {
45 struct phi_list *phi_list;
47 struct /* unops */ {
48 struct symbol *orig_type; /* casts */
49 pseudo_t src;
51 struct /* binops */ {
52 pseudo_t src1, src2;
54 struct /* multijump */ {
55 int begin, end;
57 struct /* setval */ {
58 struct expression *val;
60 struct /* call */ {
61 pseudo_t func;
62 struct pseudo_list *arguments;
67 enum opcode {
68 OP_BADOP,
69 /* Terminator */
70 OP_TERMINATOR,
71 OP_RET = OP_TERMINATOR,
72 OP_BR,
73 OP_SWITCH,
74 OP_INVOKE,
75 OP_UNWIND,
76 OP_TERMINATOR_END = OP_UNWIND,
78 /* Binary */
79 OP_BINARY,
80 OP_ADD = OP_BINARY,
81 OP_SUB,
82 OP_MUL,
83 OP_DIV,
84 OP_MOD,
85 OP_SHL,
86 OP_SHR,
87 OP_BINARY_END = OP_SHR,
89 /* Logical */
90 OP_LOGICAL,
91 OP_AND = OP_LOGICAL,
92 OP_OR,
93 OP_XOR,
94 OP_LOGICAL_END = OP_XOR,
96 /* Binary comparison */
97 OP_BINCMP,
98 OP_SET_EQ = OP_BINCMP,
99 OP_SET_NE,
100 OP_SET_LE,
101 OP_SET_GE,
102 OP_SET_LT,
103 OP_SET_GT,
104 OP_BINCMP_END = OP_SET_GT,
106 /* Uni */
107 OP_NOT,
108 OP_NEG,
110 /* Memory */
111 OP_MALLOC,
112 OP_FREE,
113 OP_ALLOCA,
114 OP_LOAD,
115 OP_STORE,
116 OP_SETVAL,
117 OP_GET_ELEMENT_PTR,
119 /* Other */
120 OP_PHI,
121 OP_CAST,
122 OP_CALL,
123 OP_VANEXT,
124 OP_VAARG,
127 struct basic_block_list;
128 struct instruction_list;
131 * Basic block flags. Right now we only have one, which keeps
132 * track (at build time) whether the basic block has been branched
133 * out of yet.
135 #define BB_REACHABLE 0x00000001
137 struct basic_block {
138 unsigned long flags; /* BB status flags */
139 struct basic_block_list *parents; /* sources */
140 struct instruction_list *insns; /* Linear list of instructions */
143 static inline int is_branch_goto(struct instruction *br)
145 return br && br->opcode==OP_BR && (!br->bb_true || !br->bb_false);
148 static inline void add_bb(struct basic_block_list **list, struct basic_block *bb)
150 add_ptr_list((struct ptr_list **)list, bb);
153 static inline void add_instruction(struct instruction_list **list, struct instruction *insn)
155 add_ptr_list((struct ptr_list **)list, insn);
158 static inline void add_multijmp(struct multijmp_list **list, struct multijmp *multijmp)
160 add_ptr_list((struct ptr_list **)list, multijmp);
163 static inline void add_phi(struct phi_list **list, struct phi *phi)
165 add_ptr_list((struct ptr_list **)list, phi);
168 static inline void add_pseudo(struct pseudo_list **list, struct pseudo *pseudo)
170 add_ptr_list((struct ptr_list **)list, pseudo);
174 static inline int bb_terminated(struct basic_block *bb)
176 struct instruction *insn;
177 if (!bb)
178 return 0;
179 insn = last_instruction(bb->insns);
180 return insn && insn->opcode >= OP_RET && insn->opcode <= OP_UNWIND;
183 static inline int bb_reachable(struct basic_block *bb)
185 return bb && (bb->parents || (bb->flags & BB_REACHABLE));
188 struct entrypoint {
189 struct symbol *name;
190 struct symbol_list *syms;
191 struct basic_block_list *bbs;
192 struct basic_block *active;
195 void linearize_symbol(struct symbol *sym);
197 #endif /* LINEARIZE_H */