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