Fix liveness analysis.
[smatch.git] / linearize.h
blobb31af9530165b68860dc6071b1ad4c4706d333ff
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 struct instruction;
10 DECLARE_PTR_LIST(pseudo_ptr_list, pseudo_t);
12 enum pseudo_type {
13 PSEUDO_VOID,
14 PSEUDO_REG,
15 PSEUDO_SYM,
16 PSEUDO_VAL,
17 PSEUDO_ARG,
18 PSEUDO_PHI,
21 struct pseudo {
22 int nr;
23 enum pseudo_type type;
24 struct pseudo_ptr_list *users;
25 struct ident *ident;
26 union {
27 struct symbol *sym;
28 struct instruction *def;
29 long long value;
33 extern struct pseudo void_pseudo;
35 #define VOID (&void_pseudo)
37 struct multijmp {
38 struct basic_block *target;
39 int begin, end;
42 struct instruction {
43 unsigned opcode:8,
44 size:24;
45 struct basic_block *bb;
46 union {
47 pseudo_t target;
48 pseudo_t cond; /* for branch and switch */
50 union {
51 struct /* branch */ {
52 struct basic_block *bb_true, *bb_false;
54 struct /* switch */ {
55 struct multijmp_list *multijmp_list;
57 struct /* phi_node */ {
58 struct pseudo_list *phi_list;
60 struct /* phi source */ {
61 pseudo_t phi_src;
62 struct instruction_list *phi_users;
64 struct /* unops */ {
65 pseudo_t src;
66 struct symbol *orig_type; /* casts */
67 unsigned int offset; /* memops */
69 struct /* binops and sel */ {
70 pseudo_t src1, src2, src3;
72 struct /* slice */ {
73 pseudo_t base;
74 unsigned from, len;
76 struct /* multijump */ {
77 int begin, end;
79 struct /* setval */ {
80 pseudo_t symbol; /* Subtle: same offset as "src" !! */
81 struct expression *val;
83 struct /* call */ {
84 pseudo_t func;
85 struct pseudo_list *arguments;
87 struct /* context */ {
88 int increment;
90 struct /* asm */ {
91 const char *string;
92 struct pseudo_list *outputs;
93 struct pseudo_list *inputs;
98 enum opcode {
99 OP_BADOP,
101 /* Entry */
102 OP_ENTRY,
104 /* Terminator */
105 OP_TERMINATOR,
106 OP_RET = OP_TERMINATOR,
107 OP_BR,
108 OP_SWITCH,
109 OP_INVOKE,
110 OP_COMPUTEDGOTO,
111 OP_UNWIND,
112 OP_TERMINATOR_END = OP_UNWIND,
114 /* Binary */
115 OP_BINARY,
116 OP_ADD = OP_BINARY,
117 OP_SUB,
118 OP_MUL,
119 OP_DIV,
120 OP_MOD,
121 OP_SHL,
122 OP_SHR,
124 /* Logical */
125 OP_AND,
126 OP_OR,
127 OP_XOR,
128 OP_AND_BOOL,
129 OP_OR_BOOL,
130 OP_BINARY_END = OP_OR_BOOL,
132 /* Binary comparison */
133 OP_BINCMP,
134 OP_SET_EQ = OP_BINCMP,
135 OP_SET_NE,
136 OP_SET_LE,
137 OP_SET_GE,
138 OP_SET_LT,
139 OP_SET_GT,
140 OP_SET_B,
141 OP_SET_A,
142 OP_SET_BE,
143 OP_SET_AE,
144 OP_BINCMP_END = OP_SET_AE,
146 /* Uni */
147 OP_NOT,
148 OP_NEG,
150 /* Select - three input values */
151 OP_SEL,
153 /* Memory */
154 OP_MALLOC,
155 OP_FREE,
156 OP_ALLOCA,
157 OP_LOAD,
158 OP_STORE,
159 OP_SETVAL,
160 OP_GET_ELEMENT_PTR,
162 /* Other */
163 OP_PHI,
164 OP_PHISOURCE,
165 OP_CAST,
166 OP_PTRCAST,
167 OP_CALL,
168 OP_VANEXT,
169 OP_VAARG,
170 OP_SLICE,
171 OP_SNOP,
172 OP_LNOP,
173 OP_NOP,
174 OP_DEATHNOTE,
175 OP_ASM,
177 /* Sparse tagging (line numbers, context, whatever) */
178 OP_CONTEXT,
181 struct basic_block_list;
182 struct instruction_list;
184 struct basic_block {
185 struct position pos;
186 unsigned long generation;
187 int context;
188 struct entrypoint *ep;
189 struct basic_block_list *parents; /* sources */
190 struct basic_block_list *children; /* destinations */
191 struct instruction_list *insns; /* Linear list of instructions */
192 struct pseudo_list *needs, *defines;
195 static inline int is_branch_goto(struct instruction *br)
197 return br && br->opcode==OP_BR && (!br->bb_true || !br->bb_false);
200 static inline void add_bb(struct basic_block_list **list, struct basic_block *bb)
202 add_ptr_list(list, bb);
205 static inline void add_instruction(struct instruction_list **list, struct instruction *insn)
207 add_ptr_list(list, insn);
210 static inline void add_multijmp(struct multijmp_list **list, struct multijmp *multijmp)
212 add_ptr_list(list, multijmp);
215 static inline void *add_pseudo(struct pseudo_list **list, struct pseudo *pseudo)
217 return add_ptr_list(list, pseudo);
221 static inline int bb_terminated(struct basic_block *bb)
223 struct instruction *insn;
224 if (!bb)
225 return 0;
226 insn = last_instruction(bb->insns);
227 return insn && insn->opcode >= OP_RET && insn->opcode <= OP_UNWIND;
230 static inline int bb_reachable(struct basic_block *bb)
232 return bb != NULL;
235 static inline void add_pseudo_ptr(pseudo_t *ptr, struct pseudo_ptr_list **list)
237 add_ptr_list(list, ptr);
240 static inline int has_use_list(pseudo_t p)
242 return (p && p->type != PSEUDO_VOID && p->type != PSEUDO_VAL);
245 static inline void use_pseudo(pseudo_t p, pseudo_t *pp)
247 *pp = p;
248 if (has_use_list(p))
249 add_pseudo_ptr(pp, &p->users);
252 static inline void remove_bb_from_list(struct basic_block_list **list, struct basic_block *entry, int count)
254 delete_ptr_list_entry((struct ptr_list **)list, entry, count);
257 static inline void replace_bb_in_list(struct basic_block_list **list,
258 struct basic_block *old, struct basic_block *new, int count)
260 replace_ptr_list_entry((struct ptr_list **)list, old, new, count);
263 struct entrypoint {
264 struct symbol *name;
265 struct symbol_list *syms;
266 struct symbol_list *accesses;
267 struct basic_block_list *bbs;
268 struct basic_block *active;
269 struct instruction *entry;
272 extern void insert_select(struct basic_block *bb, struct instruction *br, struct instruction *phi, pseudo_t true, pseudo_t false);
273 extern void insert_branch(struct basic_block *bb, struct instruction *br, struct basic_block *target);
275 pseudo_t alloc_phi(struct basic_block *source, pseudo_t pseudo, int size);
276 pseudo_t alloc_pseudo(struct instruction *def);
277 pseudo_t value_pseudo(long long val);
279 struct entrypoint *linearize_symbol(struct symbol *sym);
280 void show_entry(struct entrypoint *ep);
281 const char *show_pseudo(pseudo_t pseudo);
282 void show_bb(struct basic_block *bb);
283 void show_instruction(struct instruction *insn);
285 #endif /* LINEARIZE_H */