Mercurial > cospy
comparison src/cospy.c @ 15:cf0d24827624
Tree traveling and manipulation functions
author | Thinker K.F. Li <thinker@codemud.net> |
---|---|
date | Fri, 10 Sep 2010 11:43:43 +0800 |
parents | 566b62a49462 |
children | 3808a6ffc881 |
comparison
equal
deleted
inserted
replaced
14:566b62a49462 | 15:cf0d24827624 |
---|---|
108 | 108 |
109 edge = edge->next_callee; | 109 edge = edge->next_callee; |
110 } | 110 } |
111 } | 111 } |
112 | 112 |
113 /*! \defgroup tree_travel Tree traveling and manipulation tools. | |
114 * @{ | |
115 */ | |
116 typedef struct _stmt_link { | |
117 tree stmt; | |
118 struct _stmt_link *parent; | |
119 } stmt_link; | |
120 | |
113 /*! \brief Trival tree of GIMPLE code with a callback. | 121 /*! \brief Trival tree of GIMPLE code with a callback. |
114 * | 122 * |
115 * walk_code_free() would call the function given by cb with | 123 * walk_code_free() would call the function given by cb with |
116 * expression and data as arguments. The cb is called only for the | 124 * expression and data as arguments. The cb is called only for the |
117 * node with tree code value given by accept_code. | 125 * node with tree code value given by accept_code. |
118 */ | 126 * |
119 static void | 127 * \param accept_code is tree code of nodes that calling cb for or -1 |
120 walk_code_tree(tree expr, int accept_code, | 128 * to call cb for every node. |
121 void (*cb)(tree, void *), void *data) { | 129 * \param visit is true for traveling and false for cleaning. |
130 */ | |
131 static void | |
132 _walk_code_tree(tree expr, int accept_code, | |
133 void (*cb)(tree, void *, stmt_link *), void *data, | |
134 stmt_link *parent, bool visit) { | |
135 stmt_link me = {expr, parent}; | |
122 int code; | 136 int code; |
123 tree child; | 137 tree child; |
124 int i, sz; | 138 int i, sz; |
125 tree_stmt_iterator stmt_itr; | 139 tree_stmt_iterator stmt_itr; |
126 | 140 |
127 if(expr == NULL) | 141 if(expr == NULL) |
128 return; | 142 return; |
129 | 143 |
144 TREE_VISITED(expr) = visit; | |
145 | |
146 if(TREE_VISITED(expr)) | |
147 return; | |
148 | |
130 code = TREE_CODE(expr); | 149 code = TREE_CODE(expr); |
131 | 150 |
132 if(accept_code && code == accept_code) | 151 if(cb && (accept_code == -1 || code == accept_code)) |
133 cb(expr, data); | 152 cb(expr, data, parent); |
134 | 153 |
135 switch(code) { | 154 switch(code) { |
136 case ERROR_MARK: /* 0 */ | 155 case ERROR_MARK: /* 0 */ |
137 case IDENTIFIER_NODE: | 156 case IDENTIFIER_NODE: |
138 case TREE_LIST: | 157 case TREE_LIST: |
192 case COND_EXPR: | 211 case COND_EXPR: |
193 case VEC_COND_EXPR: | 212 case VEC_COND_EXPR: |
194 sz = TREE_OPERAND_LENGTH(expr); | 213 sz = TREE_OPERAND_LENGTH(expr); |
195 for(i = 0; i < sz; i++) { | 214 for(i = 0; i < sz; i++) { |
196 child = TREE_OPERAND(expr, i); | 215 child = TREE_OPERAND(expr, i); |
197 walk_code_tree(child, accept_code, cb, data); | 216 _walk_code_tree(child, accept_code, cb, data, &me, visit); |
198 } | 217 } |
199 break; | 218 break; |
200 | 219 |
201 case BIND_EXPR: | 220 case BIND_EXPR: |
202 /* See BIND_EXPR in tree.def */ | 221 /* See BIND_EXPR in tree.def */ |
203 child = BIND_EXPR_BODY(expr); | 222 child = BIND_EXPR_BODY(expr); |
204 walk_code_tree(child, accept_code, cb, data); | 223 _walk_code_tree(child, accept_code, cb, data, &me, visit); |
205 break; | 224 break; |
206 | 225 |
207 case CALL_EXPR: | 226 case CALL_EXPR: |
208 case WITH_CLEANUP_EXPR: | 227 case WITH_CLEANUP_EXPR: |
209 case CLEANUP_POINT_EXPR: | 228 case CLEANUP_POINT_EXPR: |
293 case SCEV_NOT_KNOWN: | 312 case SCEV_NOT_KNOWN: |
294 case POLYNOMIAL_CHREC: | 313 case POLYNOMIAL_CHREC: |
295 sz = TREE_OPERAND_LENGTH(expr); | 314 sz = TREE_OPERAND_LENGTH(expr); |
296 for(i = 0; i < sz; i++) { | 315 for(i = 0; i < sz; i++) { |
297 child = TREE_OPERAND(expr, i); | 316 child = TREE_OPERAND(expr, i); |
298 walk_code_tree(child, accept_code, cb, data); | 317 _walk_code_tree(child, accept_code, cb, data, &me, visit); |
299 } | 318 } |
300 break; | 319 break; |
301 | 320 |
302 case STATEMENT_LIST: | 321 case STATEMENT_LIST: |
303 /* See STATEMENT_LIST in tree.def of GCC */ | 322 /* See STATEMENT_LIST in tree.def of GCC */ |
304 for(stmt_itr = tsi_start(expr); | 323 for(stmt_itr = tsi_start(expr); |
305 !tsi_end_p(stmt_itr); | 324 !tsi_end_p(stmt_itr); |
306 tsi_next(&stmt_itr)) { | 325 tsi_next(&stmt_itr)) { |
307 child = tsi_stmt(stmt_itr); | 326 child = tsi_stmt(stmt_itr); |
308 walk_code_tree(child, accept_code, cb, data); | 327 _walk_code_tree(child, accept_code, cb, data, &me, visit); |
309 } | 328 } |
310 break; | 329 break; |
311 | 330 |
312 case ASSERT_EXPR: | 331 case ASSERT_EXPR: |
313 case TREE_BINFO: | 332 case TREE_BINFO: |
350 case OPTIMIZATION_NODE: | 369 case OPTIMIZATION_NODE: |
351 case TARGET_OPTION_NODE: | 370 case TARGET_OPTION_NODE: |
352 sz = TREE_OPERAND_LENGTH(expr); | 371 sz = TREE_OPERAND_LENGTH(expr); |
353 for(i = 0; i < sz; i++) { | 372 for(i = 0; i < sz; i++) { |
354 child = TREE_OPERAND(expr, i); | 373 child = TREE_OPERAND(expr, i); |
355 walk_code_tree(child, accept_code, cb, data); | 374 _walk_code_tree(child, accept_code, cb, data, &me, visit); |
356 } | 375 } |
357 break; | 376 break; |
358 } | 377 } |
359 } | 378 } |
360 | 379 |
361 static void | 380 static void |
362 found_call(tree expr, void *data) { | 381 walk_code_tree(tree expr, int accept_code, |
382 void (*cb)(tree, void *, stmt_link *), void *data) { | |
383 _walk_code_tree(expr, accept_code, cb, data, NULL, true); | |
384 | |
385 /* cleaning visited flag for every node */ | |
386 _walk_code_tree(expr, -1, NULL, NULL, NULL, false); | |
387 } | |
388 | |
389 static void | |
390 tree_insert_before_stmt(tree new_node, tree old_node, tree parent) { | |
391 tree_stmt_iterator itr; | |
392 tree visit; | |
393 | |
394 for(itr = tsi_start(parent); !tsi_end_p(itr); tsi_next(&itr)) { | |
395 visit = tsi_stmt(itr); | |
396 if(visit == old_node) { | |
397 tsi_link_before(&itr, new_node, TSI_SAME_STMT); | |
398 TREE_VISITED(new_node) = true; | |
399 break; | |
400 } | |
401 } | |
402 } | |
403 | |
404 static void | |
405 tree_insert_before_arg(tree new_node, tree old_node, tree parent) { | |
406 tree visit; | |
407 tree compound; | |
408 int len; | |
409 int i; | |
410 | |
411 len = TREE_OPERAND_LENGTH(parent); | |
412 for(i = 0; i < len; i++) { | |
413 visit = TREE_OPERAND(parent, i); | |
414 if(visit == old_node) { | |
415 compound = build2(COMPOUND_EXPR, TREE_TYPE(old_node), | |
416 new_node, old_node); | |
417 TREE_VISITED(compound) = true; | |
418 TREE_OPERAND(parent, i) = compound; | |
419 break; | |
420 } | |
421 } | |
422 } | |
423 | |
424 /*! \brief Insert a new node before an old node under a parent. | |
425 * | |
426 * \param new_node is the node to be inserted. | |
427 * \param old_node is the node where the new one being inserted before. | |
428 * \param parent is the parent node of old_node. | |
429 */ | |
430 static void | |
431 tree_insert_before(tree new_node, tree old_node, tree parent) { | |
432 int pcode; | |
433 | |
434 pcode = TREE_CODE(parent); | |
435 if(pcode == STATEMENT_LIST) | |
436 tree_insert_before_stmt(new_node, old_node, parent); | |
437 else | |
438 tree_insert_before_arg(new_node, old_node, parent); | |
439 } | |
440 | |
441 /* @} */ | |
442 | |
443 /*! \brief Called for found CALL_EXPR in a tree when trevaling. | |
444 */ | |
445 static void | |
446 found_call(tree expr, void *data, stmt_link *parent_link) { | |
363 tree addr; | 447 tree addr; |
364 tree fn, fn_name; | 448 tree fn, fn_name; |
449 tree parent = parent_link->stmt; | |
365 | 450 |
366 addr = TREE_OPERAND(expr, 1); | 451 addr = TREE_OPERAND(expr, 1); |
367 fn = TREE_OPERAND(addr, 0); | 452 fn = TREE_OPERAND(addr, 0); |
368 fn_name = DECL_NAME(fn); | 453 fn_name = DECL_NAME(fn); |
369 | 454 |
370 printf(" CALL %s:%s:%d\n", IDENTIFIER_POINTER(fn_name), | 455 printf(" CALL %s:%s:%d from a %d\n", |
456 IDENTIFIER_POINTER(fn_name), | |
371 EXPR_FILENAME(expr), | 457 EXPR_FILENAME(expr), |
372 EXPR_LINENO(expr)); | 458 EXPR_LINENO(expr), |
459 TREE_CODE(parent)); | |
373 } | 460 } |
374 | 461 |
375 /*! \brief Find all call expression in a code block. | 462 /*! \brief Find all call expression in a code block. |
376 * | 463 * |
377 * This function find CALL_EXPR in body of a function that represented | 464 * This function find CALL_EXPR in body of a function that represented |