# HG changeset patch # User Nobuyasu Oshiro # Date 1324374667 -32400 # Node ID 4a89a0a804dffc995038779b98f74034936f9d66 # Parent dbfc0d2dde362a251247c2c9bf6087d58a4b3e81 modify c-parser.c:RID_CbC_RET diff -r dbfc0d2dde36 -r 4a89a0a804df gcc/c-parser.c --- a/gcc/c-parser.c Sat Sep 24 02:43:04 2011 +0900 +++ b/gcc/c-parser.c Tue Dec 20 18:51:07 2011 +0900 @@ -2113,9 +2113,11 @@ attrs = build_tree_list(attrs, NULL_TREE); declspecs_add_attrs(specs, attrs); */ - attrs = build_tree_list (get_identifier("fastcall"), NULL_TREE); - /*attrs = build_tree_list (get_identifier("noreturn"), attrs);*/ - declspecs_add_attrs(specs, attrs); + if(!TARGET_64BIT) { + attrs = build_tree_list (get_identifier("fastcall"), NULL_TREE); + /*attrs = build_tree_list (get_identifier("noreturn"), attrs);*/ + declspecs_add_attrs(specs, attrs); + } c_parser_consume_token (parser); break; @@ -6158,20 +6160,54 @@ tree tlab; tree cond; + /* tree cstmt = c_begin_compound_stmt (true); - tlab = define_label (loc, label); gcc_assert (tlab); decl_attributes (&tlab, NULL_TREE, 0); add_stmt (build_stmt (loc, LABEL_EXPR, tlab)); - tree ret = c_finish_return (loc, retval, retval); /*tree ret = c_finish_return (retval);*/ + tree ret = c_finish_return (loc, retval, retval); //tree ret = c_finish_return (retval); TREE_USED(ret) = 1; - cond = integer_zero_node; + tree if_body = c_end_compound_stmt (loc, cstmt, true); TREE_SIDE_EFFECTS (cstmt) = 1; c_finish_if_stmt (loc, cond, if_body, NULL_TREE, false); + */ + + cond = integer_zero_node; + tree block_outside = c_begin_compound_stmt (false); + tree block_inside = c_begin_compound_stmt (false); + + tree stmt = c_begin_compound_stmt (true); + tlab = define_label (loc, label); + gcc_assert (tlab); + decl_attributes (&tlab, NULL_TREE, 0); + TREE_USED (tlab) = 1; + /* add_stmt (LABEL_EXPR) */ + add_stmt (build_stmt (loc, LABEL_EXPR, tlab)); + + /* add_stmt (RETURN_EXPR) */ + tree ret = c_finish_return (loc, retval, retval); + // TREE_USED(ret) = 1; + tree stmt_body = c_end_compound_stmt (loc, stmt, true); + + /* add_stmt (STATEMENT_LIST) : STATEMENT_LIST -> LABEL_EXPR -> RETURN_EXPR */ + add_stmt (stmt_body); + + tree body = c_end_compound_stmt (loc, block_inside, false); + + /* add_stmt (COND_EXPR) */ + c_finish_if_stmt (loc, cond, body, NULL_TREE, false); + + /* add_stmt (BIND_EXPR) : BIND_EXPR -> COND_EXPR -> STATEMENT_LIST */ + tree bind = c_end_compound_stmt (loc, block_outside, false); + TREE_SIDE_EFFECTS (bind) = 1; + add_stmt (bind); + + TREE_USED (retval) = 1; + } static tree @@ -6739,9 +6775,17 @@ tree decl_cond = build_decl (location, VAR_DECL, get_identifier ("retval"), TREE_TYPE (TREE_TYPE (current_function_decl))); - TREE_STATIC (decl_cond) = 1; - DECL_ARTIFICIAL (decl_cond) = 1; - pushdecl (decl_cond); + TREE_STATIC (decl_cond) = 1; + + /* use thread-local */ + //DECL_TLS_MODEL (decl_cond) = decl_default_tls_model (decl_cond); + // DECL_TLS_MODEL (decl_cond) = TLS_MODEL_REAL; + + /* Linux: TLS_MODEL_LOCAL_EXEC OS X: TlS_MODE_REAL */ + DECL_TLS_MODEL (decl_cond) = TLS_MODEL_LOCAL_EXEC; + //DECL_ARTIFICIAL (decl_cond) = 1; + // pushdecl (decl_cond); + add_stmt (build_stmt(location, DECL_EXPR, pushdecl (decl_cond))); /* define nested function. */ decl = @@ -6752,6 +6796,7 @@ /* 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); diff -r dbfc0d2dde36 -r 4a89a0a804df gcc/c-typeck.c --- a/gcc/c-typeck.c Sat Sep 24 02:43:04 2011 +0900 +++ b/gcc/c-typeck.c Tue Dec 20 18:51:07 2011 +0900 @@ -9325,6 +9325,7 @@ return stmt; } + /* Queue a cleanup. CLEANUP is an expression/statement to be executed when the current scope is exited. EH_ONLY is true when this is not meant to apply to normal control flow transfer. */ diff -r dbfc0d2dde36 -r 4a89a0a804df gcc/calls.c~ --- a/gcc/calls.c~ Sat Sep 24 02:43:04 2011 +0900 +++ b/gcc/calls.c~ Tue Dec 20 18:51:07 2011 +0900 @@ -99,6 +99,9 @@ word-sized pseudos we made. */ rtx *aligned_regs; int n_aligned_regs; +#ifndef noCbC +rtx exprs; +#endif }; /* A vector of one char per byte of stack space. A byte if nonzero if @@ -1893,6 +1896,10 @@ return true; } +#ifndef noCbC +#include "cbc-tree.h" +#endif + /* If X is a likely-spilled register value, copy it to a pseudo register and return that register. Return X otherwise. */ @@ -2296,8 +2303,13 @@ expanding a call, as that means we're an argument. Don't try if there's cleanups, as we know there's code to follow the call. */ + // -O2オプションがないときも末尾最適化が行われるように(Code Segmentのみ) if (currently_expanding_call++ != 0 +#ifndef noCbC + || ((!fndecl || !CbC_IS_CODE_SEGMENT (TREE_TYPE (fndecl))) && !flag_optimize_sibling_calls) +#else || !flag_optimize_sibling_calls +#endif || args_size.var || dbg_cnt (tail_call) == false) try_tail_call = 0; @@ -2388,6 +2400,67 @@ preferred_unit_stack_boundary = preferred_stack_boundary / BITS_PER_UNIT; +#ifndef noCbC + if ( fntype + && CbC_IS_CbC_GOTO (exp) // it's better? than CALL_EXPR_TAILCALL() + && CbC_IS_CODE_SEGMENT (TREE_TYPE (current_function_decl)) + ) + { + + args_size.constant = CbC_PRETENDED_STACK_SIZE; + // try_tail_callを矯正的に立たせて末尾最適化を必ずうように変更 + // -> expand_cbc_gotは不要に。 + /* return expand_cbc_goto(exp, target, fndecl, funtype, fntype, + * addr, ignore, flags, num_actuals, args, &args_size, + * args_so_far, + * old_stack_level, reg_parm_stack_space, old_pending_adj, + * preferred_stack_boundary, preferred_unit_stack_boundary, + * structure_value_addr, old_inhibit_defer_pop); */ + } + else if ( CbC_IS_CbC_GOTO (exp) ) + { + // TODO: 関数からコードセグメントへの遷移 + /* + if (fndecl) + { + char *name_callee = IDENTIFIER_POINTER(DECL_NAME(fndecl)); + warning(0, "no warning: code segment `%s' has been called from a function.", name_callee); + } + else + { + warning(0, "no warning: unnamed code segment has been called from a function."); + } + */ + args_size.constant = CbC_PRETENDED_STACK_SIZE; + } + else if ( fndecl && CbC_IS_CODE_SEGMENT (TREE_TYPE (fndecl)) ) + { + // 警告コードセグメントを関数呼び出し + //char *name= IDENTIFIER_POINTER(DECL_NAME(fndecl)); + //warning (0, "code segment `%s' has been \"called\" instead \"goto\".", name); + } + else if (CbC_IS_CODE_SEGMENT(TREE_TYPE (current_function_decl)) ) + { + // code segment内部からの関数呼び出し。なんも問題ない。 + //warning (0, "no warning: normal call from a code segment."); + } +#endif + + // when tail call optimization flag was down, warn about them. + // and flag it to force a tail call optimize. +#ifndef noCbC + if (fndecl && CbC_IS_CODE_SEGMENT (TREE_TYPE (fndecl)) + && CbC_IS_CODE_SEGMENT (TREE_TYPE (current_function_decl)) + && try_tail_call == 0) + { + location_t loc = EXPR_LOCATION (exp); + char *name_callee = IDENTIFIER_POINTER(DECL_NAME(fndecl)); + warning_at (loc, 0, "transition to code segment \"%s\" with CbC goto, but tail call optimization was cut.", + name_callee); + try_tail_call = 1; + } +#endif + /* We want to make two insn chains; one for a sibling call, the other for a normal call. We will select one of the two chains after initial RTL generation is complete. */ @@ -2454,16 +2527,31 @@ adjusted_args_size = args_size; /* Compute the actual size of the argument block required. The variable - and constant sizes must be combined, the size may have to be rounded, - and there may be a minimum required size. When generating a sibcall - pattern, do not round up, since we'll be re-using whatever space our - caller provided. */ + and constant sizes must be combined, the size may have to be rounded, + and there may be a minimum required size. When generating a sibcall + pattern, do not round up, since we'll be re-using whatever space our + caller provided. */ +#ifndef noCbC + if ( fntype && CbC_IS_CODE_SEGMENT(fntype) ) + { + unadjusted_args_size = args_size.constant; + adjusted_args_size.constant = CbC_PRETENDED_STACK_SIZE; + compute_argument_block_size (reg_parm_stack_space, + &adjusted_args_size, + fndecl, fntype, + (pass == 0 ? 0 + : preferred_stack_boundary)); + } + else +#endif + { unadjusted_args_size - = compute_argument_block_size (reg_parm_stack_space, - &adjusted_args_size, - fndecl, fntype, - (pass == 0 ? 0 - : preferred_stack_boundary)); + = compute_argument_block_size (reg_parm_stack_space, + &adjusted_args_size, + fndecl, fntype, + (pass == 0 ? 0 + : preferred_stack_boundary)); + } old_stack_allocated = stack_pointer_delta - pending_stack_adjust;