changeset 87:4a89a0a804df

modify c-parser.c:RID_CbC_RET
author Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
date Tue, 20 Dec 2011 18:51:07 +0900
parents dbfc0d2dde36
children f214c1d5b862
files gcc/c-parser.c gcc/c-typeck.c gcc/calls.c~
diffstat 3 files changed, 152 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- 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);
 
--- 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.  */
--- 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;