36 * We currently only do this for IL code. |
36 * We currently only do this for IL code. |
37 * This class will annotate the abstract syntax tree, by filling in the |
37 * This class will annotate the abstract syntax tree, by filling in the |
38 * prev_il_instruction variable in the il_instruction_c, so it points to |
38 * prev_il_instruction variable in the il_instruction_c, so it points to |
39 * the previous il_instruction_c object in the instruction list instruction_list_c. |
39 * the previous il_instruction_c object in the instruction list instruction_list_c. |
40 * |
40 * |
41 * The result will essentially be a linked list of il_instruction_c objects, each |
41 * Since IL code can contain jumps (JMP), the same il_instruction may effectively have |
|
42 * several previous il_instructions. In order to accommodate this, each il_instruction |
|
43 * will maintain a vector (i..e an array) of pointers to all the previous il_instructions. |
|
44 * We do however attempt to guarantee that the first element in the vector (array) will preferentially |
|
45 * point to the il instruction that is right before / imediately preceding the current il instructions, |
|
46 * i.e. the first element in the array will tend to point to the previous il_instruction |
|
47 * that is not a jump JMP IL instruction! |
|
48 * |
|
49 * The result will essentially be a graph of il_instruction_c objects, each |
42 * pointing to the previous il_instruction_c object. |
50 * pointing to the previous il_instruction_c object. |
43 * |
51 * |
44 * The reality is we will get several independent and isolated linked lists |
52 * The reality is we will get several independent and isolated linked lists |
45 * (actually, once we process labels correctly, this will become a graph): |
53 * (actually, since we now process labels correctly, this is really a graph): |
46 * one for each block of IL code (e.g. inside a Function, FB or Program). |
54 * one for each block of IL code (e.g. inside a Function, FB or Program). |
47 * Additionally, when the IL code has an expression (expression_c object), we will actually |
55 * Additionally, when the IL code has an expression (expression_c object), we will actually |
48 * have one more isolated linked list for the IL code inside that expression. |
56 * have one more isolated linked list for the IL code inside that expression. |
49 * |
57 * |
50 * e.g. |
58 * e.g. |
194 /* | label ':' [il_incomplete_instruction] eol_list */ |
202 /* | label ':' [il_incomplete_instruction] eol_list */ |
195 // SYM_REF2(il_instruction_c, label, il_instruction) |
203 // SYM_REF2(il_instruction_c, label, il_instruction) |
196 // void *visit(instruction_list_c *symbol); |
204 // void *visit(instruction_list_c *symbol); |
197 void *flow_control_analysis_c::visit(il_instruction_c *symbol) { |
205 void *flow_control_analysis_c::visit(il_instruction_c *symbol) { |
198 if ((NULL != prev_il_instruction) && (!prev_il_instruction_is_JMP_or_RET)) |
206 if ((NULL != prev_il_instruction) && (!prev_il_instruction_is_JMP_or_RET)) |
199 symbol->prev_il_instruction.push_back(prev_il_instruction); |
207 /* We try to guarantee that the previous il instruction that is in the previous line, will occupy the first element of the vector. |
|
208 * In order to do that, we use insert() instead of push_back() |
|
209 */ |
|
210 symbol->prev_il_instruction.insert(symbol->prev_il_instruction.begin() , prev_il_instruction); |
200 |
211 |
201 /* check if it is an il_expression_c, a JMP[C[N]], or a RET, and if so, handle it correctly */ |
212 /* check if it is an il_expression_c, a JMP[C[N]], or a RET, and if so, handle it correctly */ |
202 prev_il_instruction_is_JMP_or_RET = false; |
213 prev_il_instruction_is_JMP_or_RET = false; |
203 if (NULL != symbol->il_instruction) |
214 if (NULL != symbol->il_instruction) |
204 symbol->il_instruction->accept(*this); |
215 symbol->il_instruction->accept(*this); |
279 |
290 |
280 |
291 |
281 // SYM_REF1(il_simple_instruction_c, il_simple_instruction, symbol_c *prev_il_instruction;) |
292 // SYM_REF1(il_simple_instruction_c, il_simple_instruction, symbol_c *prev_il_instruction;) |
282 void *flow_control_analysis_c::visit(il_simple_instruction_c*symbol) { |
293 void *flow_control_analysis_c::visit(il_simple_instruction_c*symbol) { |
283 if (NULL != prev_il_instruction) |
294 if (NULL != prev_il_instruction) |
284 symbol->prev_il_instruction.push_back(prev_il_instruction); |
295 /* We try to guarantee that the previous il instruction that is in the previous line, will occupy the first element of the vector. |
|
296 * In order to do that, we use insert() instead of push_back() |
|
297 */ |
|
298 symbol->prev_il_instruction.insert(symbol->prev_il_instruction.begin() , prev_il_instruction); |
285 return NULL; |
299 return NULL; |
286 } |
300 } |
287 |
301 |
288 |
302 |
289 /* |
303 /* |