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; } |
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 |
__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型になっているが、実際には継続を行った関数と同じ戻値の型となる。
{ tree value, stmt, label, tlab, decl; c_parser_consume_token (parser); stmt = c_begin_stmt_expr (); cbc_return_f = c_parser_peek_token (parser)->value; location_t location = c_parser_peek_token (parser)->location; /* create label. (__label__ _cbc_exit0;) */ label = get_identifier ("_cbc_exit0"); tlab = declare_label (label); C_DECLARED_LABEL_FLAG (tlab) = 1; add_stmt (build_stmt (location, DECL_EXPR, tlab)); /* declare retval. (int retval;) */ tree decl_cond = build_decl (location, VAR_DECL, get_identifier ("retval"), TREE_TYPE (TREE_TYPE (current_function_decl))); TREE_STATIC (decl_cond) = 1; TREE_USED (decl_cond) = 1; /* Use thread-local */ DECL_TLS_MODEL (decl_cond) = decl_default_tls_model (decl_cond); DECL_NONLOCAL (decl_cond) = 1; add_stmt (build_stmt(location, DECL_EXPR, pushdecl (decl_cond))); /* define nested function. */ decl = cbc_finish_nested_function (location, label, decl_cond); TREE_USED(decl) = 1; /* define if-ed goto label and return statement. */ cbc_finish_labeled_goto (location, label, decl_cond); /* get pointer to nested function. */ value = build_addr (decl , current_function_decl); TREE_USED (current_function_decl) = 1; SET_EXPR_LOCATION (value, location); add_stmt (value); TREE_SIDE_EFFECTS (stmt) = 1; expr.value = c_finish_stmt_expr (location, stmt); expr.original_code = ERROR_MARK; }
void factorial(int n, int result, void(*print)()){ : (*print)(n,result,print,exit1, envp); }
void factorial(int n, int result, void *print){ : (*print)(n,result,print,exit1, envp); }
__code factorial(int n, int result, __rectype *print) { : (*print)(n,result,print,exit1, envp); }
typedef sturct node { selftype *left; selftype *right; int num; }*NODE
selftype は struct node を指す。