# HG changeset patch # User Nobuyasu Oshiro # Date 1313905819 -32400 # Node ID e334828451cba4237d786f7c9a6fb0dfcc942203 # Parent b81903832de20364465d400616930ad649ff934c modify gcc/c-parser.c diff -r b81903832de2 -r e334828451cb gcc/c-parser.c --- a/gcc/c-parser.c Sun Aug 21 09:24:16 2011 +0900 +++ b/gcc/c-parser.c Sun Aug 21 14:50:19 2011 +0900 @@ -56,6 +56,9 @@ #include "vec.h" #include "target.h" #include "cgraph.h" +#ifndef noCbC +#include "cbc-tree.h" +#endif #include "plugin.h" @@ -650,6 +653,9 @@ case RID_FRACT: case RID_ACCUM: case RID_SAT: +#ifndef noCbC + case RID_CbC_CODE: +#endif return true; default: return false; @@ -2090,6 +2096,30 @@ declspecs_add_type (loc, specs, t); c_parser_consume_token (parser); break; +#ifndef noCbC + case RID_CbC_CODE: + if (!typespec_ok) + goto out; + attrs_ok = true; + seen_type = true; + if (c_dialect_objc ()) + parser->objc_need_raw_identifier = true; + t.kind = ctsk_resword; + t.spec = c_parser_peek_token (parser)->value; + declspecs_add_type (loc, specs, t); + + /* + attrs = get_identifier("fastcall"); + 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); + + c_parser_consume_token (parser); + break; +#endif case RID_ENUM: if (!typespec_ok) goto out; @@ -4306,6 +4336,79 @@ c_parser_statement_after_labels (parser); } +#if 0 +static tree +c_parser_cbc_make_env(c_parser *parser) +{ + struct c_expr env; + tree field, fields=NULL_TREE; + tree env_struct, env_struct_type; + tree ebp, argsp; + tree tmp; + + c_parser_consume_token (parser); + env = c_parser_expr_no_commas (parser, NULL); + env = default_function_array_conversion (env); + + /* build type_node of environment structure */ + env_struct_type = start_struct (RECORD_TYPE, NULL_TREE); + field = build_decl (FIELD_DECL, get_identifier("sp"), ptr_type_node); + fields = chainon (field, fields); + field = build_decl (FIELD_DECL, get_identifier("argsp"), ptr_type_node); + fields = chainon (field, fields); + //field = build_decl (FIELD_DECL, get_identifier("retval"), intSI_type_node); + //fields = chainon (field, fields); + fields = nreverse(fields); + finish_struct (env_struct_type, fields, NULL_TREE); + + env_struct = build_c_cast (build_pointer_type(env_struct_type), env.value); + //build_component_ref (cbc_env, get_identifier("argsp")); + ebp = build_component_ref (build_indirect_ref (loc,env_struct, "CbCenv->sp"), get_identifier("sp")); + argsp = build_component_ref (build_indirect_ref (loc, env_struct, "CbCenv->sp"), get_identifier("argsp")); + //ebp = chainon (ebp, argsp); + tmp = build_tree_list (ebp, argsp); + + return tmp; +} +#endif + +static tree +cbc_replace_arguments (location_t loc, tree call) +{ + tree args; + tree fn; + tree tmp_decl; + int i=0; + + fn = CALL_EXPR_FN (call); + if ( TREE_CODE (fn)==PARM_DECL || !TREE_CONSTANT (fn) ) + { + tmp_decl = build_decl (loc, VAR_DECL, NULL_TREE, TREE_TYPE(fn)); + pushdecl (tmp_decl); + + add_stmt (build_modify_expr (loc, tmp_decl, NULL_TREE, NOP_EXPR, loc, fn, NULL_TREE)); + CALL_EXPR_FN (call) = tmp_decl; + } + + args = CALL_EXPR_ARGS (call); + for ( ;args; args = TREE_CHAIN (args), i++) + { + tree arg = TREE_VALUE (args); + + //if ( !CONSTANT_CLASS_P (arg) && !VAR_OR_FUNCTION_DECL_P (arg) ) + if ( TREE_CODE (arg)==PARM_DECL || !TREE_CONSTANT (arg) ) + { + tmp_decl = build_decl (loc, VAR_DECL, NULL_TREE, TREE_TYPE(arg)); + pushdecl (tmp_decl); + + add_stmt (build_modify_expr (loc, tmp_decl, NULL_TREE, NOP_EXPR, loc, arg, NULL_TREE)); + CALL_EXPR_ARG (call, i) = tmp_decl; + } + } + + return call; +} + /* Parse a statement, other than a labeled statement. */ static void @@ -4340,6 +4443,14 @@ break; case RID_GOTO: c_parser_consume_token (parser); +#ifndef noCbC + if ( c_parser_next_token_is (parser, CPP_NAME) + && c_parser_peek_2nd_token (parser)->type == CPP_SEMICOLON ) + { +#else + if (c_parser_next_token_is (parser, CPP_NAME)) + { +#endif if (c_parser_next_token_is (parser, CPP_NAME)) { stmt = c_finish_goto_label (loc, @@ -4356,7 +4467,34 @@ stmt = c_finish_goto_ptr (loc, val); } else +#ifndef noCbC + { + if (c_parser_next_token_is (parser, CPP_NAME)) + { + tree id = c_parser_peek_token (parser)->value; + location_t loc = c_parser_peek_token (parser)->location; + /** build_external_ref (id,RID_CbC_CODE , loc); **/ + build_external_ref (loc, id, RID_CbC_CODE, &expr.original_type); + } + 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; + /*tree env = NULL_TREE;**/ + 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); /* stmt = c_finish_return (0); */ + } + else + c_parser_error (parser, "expected code segment jump or %<*%>"); + } +#else c_parser_error (parser, "expected identifier or %<*%>"); +#endif goto expect_semicolon; case RID_CONTINUE: c_parser_consume_token (parser); @@ -6009,11 +6147,127 @@ Classname . identifier */ +static void +cbc_finish_labeled_goto (location_t loc, tree label, tree retval) +{ + /* add statement below. + * + * if (0) { + * _cbc_exit0: + * return retval; + * } + */ + 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_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); +} + +static tree +cbc_finish_nested_function (location_t loc, tree label, tree retval_decl) +{ + + /* add statement below. + * void __return_func(int _retval, void *_envp){ + * retval = _retval; + * goto exit0; + * } + */ + /* TODO: + * retval(lhs)のTREE_DECLを引数から取得するように + * int _retvalパラメータのタイプはretvalに合わせる + */ + + tree fnbody; + tree _retval_decl, _envp_decl; + struct c_declarator *declarator; + //tree ident; + struct c_arg_info *args; + struct c_declspecs *specs; + struct c_typespec t; + { + push_scope (); + declare_parm_level (); + /*tree retval_type = TREE_TYPE(retval_decl);*/ + + _retval_decl = build_decl (loc, PARM_DECL, get_identifier ("_retval"), TREE_TYPE(retval_decl)); + DECL_SOURCE_LOCATION (_retval_decl) = loc; + DECL_ARTIFICIAL (_retval_decl) = 1; + DECL_ARG_TYPE (_retval_decl) = TREE_TYPE(retval_decl); + pushdecl (_retval_decl); + finish_decl (_retval_decl, loc, NULL_TREE, NULL_TREE, NULL_TREE); + + _envp_decl = build_decl (loc, PARM_DECL, get_identifier ("_envp"), ptr_type_node); + DECL_SOURCE_LOCATION (_envp_decl) = loc; + DECL_ARTIFICIAL (_envp_decl) = 1; + DECL_ARG_TYPE (_envp_decl) = ptr_type_node; + pushdecl (_envp_decl); + finish_decl (_envp_decl, loc, NULL_TREE, NULL_TREE, NULL_TREE); + + args = get_parm_info(false); + pop_scope(); + } + + t.kind = ctsk_resword; + t.spec = get_identifier("void"); + specs = build_null_declspecs(); + declspecs_add_type (loc, specs, t); + finish_declspecs (specs); + + /* make nested function. */ + declarator = build_id_declarator (get_identifier ("_cbc_internal_return")); + declarator = build_function_declarator (args, declarator); + + c_push_function_context (); + + if (!start_function (specs, declarator, NULL_TREE)) + { + c_pop_function_context(); + gcc_assert (0); + } + store_parm_decls (); + + + /* start compound statement. */ + tree cstmt = c_begin_compound_stmt (true); + + add_stmt (build_modify_expr (loc, retval_decl, NULL_TREE, NOP_EXPR, loc, _retval_decl, NULL_TREE)); + //tree stmt = c_finish_goto_label (loc, label); + + /* end compound statement. */ + fnbody = c_end_compound_stmt (loc, cstmt, true); + TREE_SIDE_EFFECTS (cstmt) = 1; + + /* finish declaration of nested function. */ + tree decl = current_function_decl; + add_stmt (fnbody); + finish_function (); + c_pop_function_context (); + + add_stmt (build_stmt (loc, DECL_EXPR, decl)); + return decl; + +} + static struct c_expr c_parser_postfix_expression (c_parser *parser) { struct c_expr expr, e1, e2, e3; struct c_type_name *t1, *t2; + //cbc? static tree return_label1; location_t loc = c_parser_peek_token (parser)->location;; expr.original_code = ERROR_MARK; expr.original_type = NULL; @@ -6435,6 +6689,190 @@ expr.value = objc_build_encode_expr (type); } break; +#ifndef noCbC + case RID_CbC_ENV: + { + c_parser_consume_token (parser); + /* get value of %ebp. */ + /*tree env_tree = build_external_ref ( + get_identifier ("__builtin_frame_address"), 0, + c_parser_peek_token (parser)->location);*/ + loc = c_parser_peek_token (parser)->location; + tree env_tree = build_external_ref (loc, + get_identifier ("__builtin_frame_address"), 0, &expr.original_type); + expr.value = build_function_call(loc, env_tree, + build_tree_list (NULL_TREE, build_int_cst (NULL_TREE,0))); + expr.original_code = ERROR_MARK; + + } + break; + case RID_CbC_RET: + case RID_RETURN: + +#if 0 + if (cbc_return_f==0) + { tree retval; + + /* + Generates something like... + + int retval = 1; + void (*ret)(int retval_,void *fp) ; + + ret = ({ + __label__ exit0; + volatile static flag = 0; + void __return_func(int retval_,void *fp) { + retval = retval_; + goto exit0; + } + if (flag) { + exit0: + printf("f1: fp = 0x%x\n",__builtin_frame_address(0)); + return retval; + } + __return_func; + }); + + */ + + tree stmt = c_begin_stmt_expr (); + cbc_return_f = c_parser_peek_token (parser)->value; + cbc_return = c_parser_peek_token (parser)->location; + c_parser_consume_token (parser); + location_t next = c_parser_peek_token (parser)->location; + + // dummy variable for hidden condition + struct c_expr cexpr; + tree cond; + location_t loc; + loc = next; + tree decl_cond = + build_decl (VAR_DECL, get_identifier ("__return"), + intHI_type_node); + TREE_STATIC (decl_cond) = 1; + cexpr.value = lang_hooks.decls.pushdecl(decl_cond); + + cexpr.original_code = ERROR_MARK; + cond = c_objc_common_truthvalue_conversion(loc, cexpr.value); + if (EXPR_P (cond)) + SET_EXPR_LOCATION (cond, loc); + + + + + tree fwlabel = create_artificial_label (); + //TREE_USED(fwlabel) = 1; + + //add_stmt (build1 (GOTO_EXPR, void_type_node, fwlabel)); + tree block = c_begin_compound_stmt (flag_isoc99); + + tree tlab = lookup_label(cbc_return_f); + + tree decl= build_stmt (LABEL_EXPR, tlab); + //TREE_USED(decl) = 1; + add_stmt(decl); + + //tree hoge = build_int_cst(NULL_TREE,55); + retval = build_component_ref (cbc_env, get_identifier("retval")); + tree ret = c_finish_return (retval); + TREE_USED(ret) = 1; + tree first_body = c_end_compound_stmt (block, flag_isoc99); + + c_finish_if_stmt (loc, cond, first_body, NULL_TREE, false); + + // define_label(EXPR_LOCATION(decl) ,cbc_return_f); + return_label1 = + define_label(cbc_return ,cbc_return_f); + tree fwdef= build_stmt (LABEL_EXPR, fwlabel); + + //TREE_USED(fwdef) = 1; + add_stmt(fwdef); + TREE_SIDE_EFFECTS (block) = 1; + + // tree label = lookup_label(c_parser_peek_token (parser)->value); + //TREE_USED(label) = 1; + + tree value = build1(ADDR_EXPR, ptr_type_node, return_label1); + SET_EXPR_LOCATION (value, next); + TREE_SIDE_EFFECTS (value) = 1; + add_stmt(value); + + TREE_SIDE_EFFECTS (stmt) = 1; + expr.value = c_finish_stmt_expr (stmt); + expr.original_code = ERROR_MARK; + + + } + else + { + //tree label = lookup_label(c_parser_peek_token (parser)->value); + //TREE_USED(label) = 1; + //expr.value = build1(ADDR_EXPR, ptr_type_node, label); + expr.value = build1(ADDR_EXPR, ptr_type_node, return_label1); + c_parser_consume_token (parser); + } +#else //by KENT. + { + /* + ({ + __label__ _cbc_exit0; + void __return_func(int retval_, void *_envp){ + retval = retval_; + goto exit0; + } + if (0) { + _cbc_exit0: + return retval; + } + __return_func; + }); + */ + 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; + DECL_ARTIFICIAL (decl_cond) = 1; + pushdecl (decl_cond); + + /* define nested function. */ + decl = + cbc_finish_nested_function (location, label, decl_cond); + + /* 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); + SET_EXPR_LOCATION (value, location); + add_stmt (value); + /*value = build_external_ref (get_identifier("_cbc_internal_return"), false, location);*/ + /*value = build_unary_op (location, ADDR_EXPR, value, 0);*/ + /*add_stmt (value);*/ + + TREE_SIDE_EFFECTS (stmt) = 1; + expr.value = c_finish_stmt_expr (location, stmt); + expr.original_code = ERROR_MARK; + } + +#endif //0 + break; +#endif //noCbC + default: c_parser_error (parser, "expected expression"); expr.value = error_mark_node;