validation: delete obsolete dev_hold() check
[smatch.git] / linearize.h
bloba77e4b3e5f6f448f0aefbda1802a33f70a6bc92b
1 #ifndef LINEARIZE_H
2 #define LINEARIZE_H
4 #include "lib.h"
5 #include "allocate.h"
6 #include "token.h"
7 #include "opcode.h"
8 #include "parse.h"
9 #include "symbol.h"
10 #include "ptrmap.h"
12 struct instruction;
14 struct pseudo_user {
15 struct instruction *insn;
16 pseudo_t *userp;
19 DECLARE_ALLOCATOR(pseudo_user);
20 DECLARE_PTR_LIST(pseudo_user_list, struct pseudo_user);
21 DECLARE_PTRMAP(phi_map, struct symbol *, pseudo_t);
24 enum pseudo_type {
25 PSEUDO_VOID,
26 PSEUDO_UNDEF,
27 PSEUDO_PHI,
28 PSEUDO_REG,
29 PSEUDO_ARG,
30 PSEUDO_SYM,
31 PSEUDO_VAL,
34 struct pseudo {
35 int nr;
36 enum pseudo_type type;
37 struct pseudo_user_list *users;
38 struct ident *ident;
39 union {
40 struct symbol *sym;
41 struct instruction *def;
42 long long value;
44 void *priv;
47 extern struct pseudo void_pseudo;
49 #define VOID (&void_pseudo)
51 static inline bool is_zero(pseudo_t pseudo)
53 return pseudo->type == PSEUDO_VAL && pseudo->value == 0;
56 static inline bool is_nonzero(pseudo_t pseudo)
58 return pseudo->type == PSEUDO_VAL && pseudo->value != 0;
62 struct multijmp {
63 struct basic_block *target;
64 long long begin, end;
67 struct asm_constraint {
68 pseudo_t pseudo;
69 const char *constraint;
70 const struct ident *ident;
71 unsigned int is_memory:1;
74 DECLARE_ALLOCATOR(asm_constraint);
75 DECLARE_PTR_LIST(asm_constraint_list, struct asm_constraint);
77 struct asm_rules {
78 struct asm_constraint_list *inputs;
79 struct asm_constraint_list *outputs;
80 struct asm_constraint_list *clobbers;
83 DECLARE_ALLOCATOR(asm_rules);
85 struct instruction {
86 unsigned opcode:7,
87 tainted:1,
88 size:24;
89 struct basic_block *bb;
90 struct position pos;
91 struct symbol *type;
92 pseudo_t target;
93 union {
94 struct /* entrypoint */ {
95 struct pseudo_list *arg_list;
97 struct /* branch */ {
98 pseudo_t cond;
99 struct basic_block *bb_true, *bb_false;
101 struct /* switch */ {
102 pseudo_t _cond;
103 struct multijmp_list *multijmp_list;
105 struct /* phi_node */ {
106 pseudo_t phi_var; // used for SSA conversion
107 struct pseudo_list *phi_list;
108 unsigned int used:1;
110 struct /* phi source */ {
111 pseudo_t phi_src;
112 struct instruction_list *phi_users;
114 struct /* unops */ {
115 pseudo_t src;
116 struct symbol *orig_type; /* casts */
118 struct /* memops */ {
119 pseudo_t addr; /* alias .src */
120 long long offset;
121 unsigned int is_volatile:1;
123 struct /* binops and sel */ {
124 pseudo_t src1, src2, src3;
126 struct /* compare */ {
127 pseudo_t _src1, _src2; // alias .src[12]
128 struct symbol *itype; // input operands' type
130 struct /* slice */ {
131 pseudo_t base;
132 unsigned from, len;
134 struct /* setval */ {
135 struct expression *val;
137 struct /* setfval */ {
138 long double fvalue;
140 struct /* call */ {
141 pseudo_t func;
142 struct pseudo_list *arguments;
143 struct symbol_list *fntypes;
145 struct /* context */ {
146 int increment;
147 int check;
148 struct expression *context_expr;
150 struct /* asm */ {
151 const char *string;
152 struct asm_rules *asm_rules;
157 struct basic_block_list;
158 struct instruction_list;
160 struct basic_block {
161 struct position pos;
162 unsigned long generation;
163 struct entrypoint *ep;
164 struct basic_block_list *parents; /* sources */
165 struct basic_block_list *children; /* destinations */
166 struct instruction_list *insns; /* Linear list of instructions */
167 struct basic_block *idom; /* link to the immediate dominator */
168 unsigned int nr; /* unique id for label's names */
169 int dom_level; /* level in the dominance tree */
170 struct basic_block_list *doms; /* list of BB idominated by this one */
171 struct pseudo_list *needs, *defines;
172 union {
173 struct phi_map *phi_map;/* needed during SSA conversion */
174 int postorder_nr; /* postorder number */
175 int context; /* needed during context checking */
176 void *priv;
182 // return the opcode of the instruction defining ``SRC`` if existing
183 // and OP_BADOP if not. It also assigns the defining instruction
184 // to ``DEF``.
185 #define DEF_OPCODE(DEF, SRC) \
186 (((SRC)->type == PSEUDO_REG && (DEF = (SRC)->def)) ? DEF->opcode : OP_BADOP)
189 static inline void add_bb(struct basic_block_list **list, struct basic_block *bb)
191 add_ptr_list(list, bb);
194 static inline void add_instruction(struct instruction_list **list, struct instruction *insn)
196 add_ptr_list(list, insn);
199 static inline void add_multijmp(struct multijmp_list **list, struct multijmp *multijmp)
201 add_ptr_list(list, multijmp);
204 static inline pseudo_t *add_pseudo(struct pseudo_list **list, pseudo_t pseudo)
206 return add_ptr_list(list, pseudo);
209 static inline int remove_pseudo(struct pseudo_list **list, pseudo_t pseudo)
211 return delete_ptr_list_entry((struct ptr_list **)list, pseudo, 0) != 0;
214 static inline int pseudo_in_list(struct pseudo_list *list, pseudo_t pseudo)
216 return lookup_ptr_list_entry((struct ptr_list *)list, pseudo);
219 static inline int bb_terminated(struct basic_block *bb)
221 struct instruction *insn;
222 if (!bb)
223 return 0;
224 insn = last_instruction(bb->insns);
225 return insn && insn->opcode >= OP_TERMINATOR
226 && insn->opcode <= OP_TERMINATOR_END;
229 static inline int bb_reachable(struct basic_block *bb)
231 return bb != NULL;
234 static inline int lookup_bb(struct basic_block_list *list, struct basic_block *bb)
236 return lookup_ptr_list_entry((struct ptr_list *)list, bb);
240 static inline void add_pseudo_user_ptr(struct pseudo_user *user, struct pseudo_user_list **list)
242 add_ptr_list(list, user);
245 static inline int has_use_list(pseudo_t p)
247 return (p && p->type != PSEUDO_VOID && p->type != PSEUDO_UNDEF && p->type != PSEUDO_VAL);
250 static inline bool has_definition(pseudo_t p)
252 return p->type == PSEUDO_REG || p->type == PSEUDO_PHI;
255 static inline int pseudo_user_list_size(struct pseudo_user_list *list)
257 return ptr_list_size((struct ptr_list *)list);
260 static inline bool pseudo_user_list_empty(struct pseudo_user_list *list)
262 return ptr_list_empty((struct ptr_list *)list);
265 static inline int has_users(pseudo_t p)
267 return !pseudo_user_list_empty(p->users);
270 static inline bool one_use(pseudo_t p)
272 return !ptr_list_multiple((struct ptr_list *)(p->users));
275 static inline int nbr_users(pseudo_t p)
277 return pseudo_user_list_size(p->users);
280 static inline struct pseudo_user *alloc_pseudo_user(struct instruction *insn, pseudo_t *pp)
282 struct pseudo_user *user = __alloc_pseudo_user(0);
283 user->userp = pp;
284 user->insn = insn;
285 return user;
288 static inline void use_pseudo(struct instruction *insn, pseudo_t p, pseudo_t *pp)
290 *pp = p;
291 if (has_use_list(p))
292 add_pseudo_user_ptr(alloc_pseudo_user(insn, pp), &p->users);
295 static inline void remove_bb_from_list(struct basic_block_list **list, struct basic_block *entry, int count)
297 delete_ptr_list_entry((struct ptr_list **)list, entry, count);
300 static inline void replace_bb_in_list(struct basic_block_list **list,
301 struct basic_block *old, struct basic_block *new, int count)
303 replace_ptr_list_entry((struct ptr_list **)list, old, new, count);
306 struct entrypoint {
307 struct symbol *name;
308 struct symbol_list *syms;
309 struct pseudo_list *accesses;
310 struct basic_block_list *bbs;
311 struct basic_block *active;
312 struct instruction *entry;
313 unsigned int dom_levels; /* max levels in the dom tree */
316 extern void insert_select(struct basic_block *bb, struct instruction *br, struct instruction *phi, pseudo_t if_true, pseudo_t if_false);
317 extern void insert_branch(struct basic_block *bb, struct instruction *br, struct basic_block *target);
319 struct instruction *alloc_phisrc(pseudo_t pseudo, struct symbol *type);
320 struct instruction *alloc_phi_node(struct basic_block *bb, struct symbol *type, struct ident *ident);
321 struct instruction *insert_phi_node(struct basic_block *bb, struct symbol *var);
322 void add_phi_node(struct basic_block *bb, struct instruction *phi_node);
324 pseudo_t alloc_phi(struct basic_block *source, pseudo_t pseudo, struct symbol *type);
325 pseudo_t alloc_pseudo(struct instruction *def);
326 pseudo_t value_pseudo(long long val);
327 pseudo_t undef_pseudo(void);
329 struct entrypoint *linearize_symbol(struct symbol *sym);
330 int unssa(struct entrypoint *ep);
331 void show_entry(struct entrypoint *ep);
332 void show_insn_entry(struct instruction *insn);
333 const char *show_pseudo(pseudo_t pseudo);
334 void show_bb(struct basic_block *bb);
335 void show_insn_bb(struct instruction *insn);
336 const char *show_instruction(struct instruction *insn);
337 const char *show_label(struct basic_block *bb);
339 #endif /* LINEARIZE_H */