Cの関数呼び出し | CbCの継続> |
__code print_factorial(int prod) { printf("factorial = %d\n",prod); exit(0); } __code factorial0(int prod, int x) { if ( x >= 1) { goto factorial0(prod*x, x-1); }else{ goto print_factorial(prod); } } |
__code factorial(int x) { goto factorial0(1, x); } int main(int argc, char **argv) { int i; i = atoi(argv[1]); goto factorial(i); return 0; } |
Generic(ソースコード) | GIMPLE |
void factorial(int x) { int prod,i; for(i=1,prod=1; i <= x; i++){ prod = prod*i; } print_factorial(prod); } |
factorial (int x) { int prod; int i; i = 1; prod = 1; goto <D.2846>; <D.2845>: prod = prod * i; i = i + 1; <D.2846>: if (i <= x) goto <D.2845>; else goto <D.2847>; <D.2847>: print_factorial (prod); } |
SSA | RTL |
factorial (int x) { int i; int prod; <bb 2>: i_3 = 1; prod_4 = 1; goto <bb 4>; <bb 3>: prod_6 = prod_1 * i_2; i_7 = i_2 + 1; <bb 4>: # prod_1 = PHI <prod_4(2), prod_6(3)> # i_2 = PHI <i_3(2), i_7(3)> if (i_2 <= x_5(D)) goto <bb 3>; else goto <bb 5>; <bb 5>: print_factorial (prod_1); return; } |
(call (mem:QI (symbol_ref:DI ("print_factorial") [flags 0x403] <function_decl 0x146f6b200 print_factorial>) [0 S1 A8]) (const_int 0 [0])) |
値の代入:MODIFY_EXPR | 関数呼び出し:CALL_EXPR | |
命令 | b = a * 10 | func(a,10) |
Generic Tree |
Generic Treeでの表現
ソースコード | Generic Treeでの表現 |
int main() { int a, b; a = 3; b = func(a, 10); return b; } |
|
case RID_GOTO: c_parser_consume_token (parser); if ( c_parser_next_token_is (parser, CPP_NAME) && c_parser_peek_2nd_token (parser)->type == CPP_SEMICOLON ) { stmt = c_finish_goto_label (loc, c_parser_peek_token (parser)->value); c_parser_consume_token (parser); } else if (c_parser_next_token_is (parser, CPP_MULT)) { tree val; c_parser_consume_token (parser); val = c_parser_expression (parser).value; mark_exp_read (val); stmt = c_finish_goto_ptr (loc, val); } else expr = c_parser_expr_no_commas (parser, NULL); if (TREE_CODE(expr.value) == CALL_EXPR ) { location_t loc = c_parser_peek_token (parser)->location; cbc_replace_arguments (loc, expr.value); TREE_TYPE(expr.value) = void_type_node; CbC_IS_CbC_GOTO (expr.value) = 1; CALL_EXPR_TAILCALL (expr.value) = 1; add_stmt(expr.value); stmt = c_finish_return(loc, NULL_TREE, NULL_TREE); }
実際のコード | GCC 内で処理されるコード |
goto factorial0(1, x); |
factorial0(1, x); return; |
if(!TARGET_64BIT) { attrs = build_tree_list (get_identifier("fastcall"), NULL_TREE); declspecs_add_attrs(specs, attrs); }
Intel64 ではレジスタが増えている為、fastcallは標準でつくようになっている。
arch | int(整数型) | float(浮動小数点型) | double(浮動小数点型) |
i386 | 2 | 0 (stackを使用) |
0 (stackを使用) |
x86_64 | 6 | 8 | 8 |
int main() { int num = a(2); printf("main:num=%d\n",num); return 0; } int a(int num) { return b(num+5); } int b(int num) { printf("b:a = %d\n",num); return num+3; } |
|
|
if (currently_expanding_call++ != 0 || ((!fndecl || !CbC_IS_CODE_SEGMENT (TREE_TYPE (fndecl))) && !flag_optimize_sibling_calls) || args_size.var || dbg_cnt (tail_call) == false) try_tail_call = 0;
if ( #ifdef HAVE_sibcall_epilogue !HAVE_sibcall_epilogue #else 1 #endif || !try_tail_call || structure_value_addr != NULL_RTX #ifdef REG_PARM_STACK_SPACE || (OUTGOING_REG_PARM_STACK_SPACE (funtype) != OUTGOING_REG_PARM_STACK_SPACE (TREE_TYPE (current_function_decl))) || (reg_parm_stack_space != REG_PARM_STACK_SPACE (fndecl)) #endif || !targetm.function_ok_for_sibcall (fndecl, exp) || (flags & (ECF_RETURNS_TWICE | ECF_NORETURN)) || TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (addr))) || (fndecl && decl_function_context (fndecl) == current_function_decl) || args_size.constant > (crtl->args.size - crtl->args.pretend_args_size) || (targetm.calls.return_pops_args (fndecl, funtype, args_size.constant) != targetm.calls.return_pops_args (current_function_decl, TREE_TYPE (current_function_decl), crtl->args.size)) || !lang_hooks.decls.ok_for_sibcall (fndecl)) try_tail_call = 0; |
__code c1(__code ret(int,void *),void *env) { goto ret(1,env); } int main() { goto c1(__return, __environment); } |
__environmentキーワードは関数の環境を保持する。
goto c1(__return, __environment); goto c1(({ __label__ _cbc_exit0; static int retval; void _cbc_internal_return(int retval_, void *_envp) { retval = retval_; goto _cbc_exit0; } if (0) { _cbc_exit0: return retval; } _cbc_internal_return; }), __environment);
retval変数はint型になっているが、実際には継続を行った関数と同じ戻値の型となる。
void factorial(int n, int result, void(*print)()){ : (*print)(n,result,print,exit1, envp); }
void factorial(int n, int result, void *print){ : void(*print)(n,result,print,exit1, envp); }
__code factorial(int n, int result, __rectype *print) { : goto (*print)(n,result,print,exit1, envp); }
typedef sturct node { selftype *left; selftype *right; int num; }*NODE
selftype は struct node を指す。