changeset 71:e334828451cb

modify gcc/c-parser.c
author Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
date Sun, 21 Aug 2011 14:50:19 +0900
parents b81903832de2
children 20c18990c3e4
files gcc/c-parser.c
diffstat 1 files changed, 438 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- 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;