changeset 1:caeb520cebed

patch for CbC
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Fri, 17 Jul 2009 17:43:54 +0900
parents a06113de4d67
children 0b3575e68bac
files gcc/Makefile.in gcc/c-common.c gcc/c-common.h gcc/c-decl.c gcc/c-parser.c gcc/c-tree.h gcc/c-typeck.c gcc/calls.c gcc/cbc-tree.h gcc/function.c gcc/gcc.c gcc/gimplify.c gcc/passes.c gcc/tree-ssa-operands.c gcc/tree.c gcc/tree.h
diffstat 16 files changed, 655 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/gcc/Makefile.in	Fri Jul 17 14:47:48 2009 +0900
+++ b/gcc/Makefile.in	Fri Jul 17 17:43:54 2009 +0900
@@ -2521,7 +2521,7 @@
    hard-reg-set.h $(TOPLEV_H) hard-reg-set.h except.h $(TM_P_H) $(PREDICT_H) \
    libfuncs.h $(REAL_H) langhooks.h $(BASIC_BLOCK_H) tree-mudflap.h \
    $(BUILTINS_DEF) $(MACHMODE_H) $(DIAGNOSTIC_H) $(TREE_FLOW_H) value-prof.h
-calls.o : calls.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
+calls.o : calls.c $(CONFIG_H) $(SYSTEM_H) cbc-goto.h coretypes.h $(TM_H) $(RTL_H) \
    $(TREE_H) $(FLAGS_H) $(EXPR_H) $(OPTABS_H) langhooks.h $(TARGET_H) \
    libfuncs.h $(REGS_H) $(TOPLEV_H) output.h $(FUNCTION_H) $(TIMEVAR_H) $(TM_P_H) \
    $(CGRAPH_H) except.h sbitmap.h $(DBGCNT_H) $(TREE_FLOW_H)
--- a/gcc/c-common.c	Fri Jul 17 14:47:48 2009 +0900
+++ b/gcc/c-common.c	Fri Jul 17 17:43:54 2009 +0900
@@ -616,6 +616,10 @@
   { "__asm__",		RID_ASM,	0 },
   { "__attribute",	RID_ATTRIBUTE,	0 },
   { "__attribute__",	RID_ATTRIBUTE,	0 },
+#ifndef noCbC
+  /* CbC project */
+  { "__code",         RID_CbC_CODE,   0 },
+#endif
   { "__builtin_choose_expr", RID_CHOOSE_EXPR, D_CONLY },
   { "__builtin_offsetof", RID_OFFSETOF, 0 },
   { "__builtin_types_compatible_p", RID_TYPES_COMPATIBLE_P, D_CONLY },
@@ -624,6 +628,11 @@
   { "__complex__",	RID_COMPLEX,	0 },
   { "__const",		RID_CONST,	0 },
   { "__const__",	RID_CONST,	0 },
+#ifndef noCbC
+  /* CbC project */
+  { "__environment",  RID_CbC_ENV,    0 },
+  { "__return",       RID_CbC_RET,    0 },
+#endif
   { "__decltype",       RID_DECLTYPE,   D_CXXONLY },
   { "__extension__",	RID_EXTENSION,	0 },
   { "__func__",		RID_C99_FUNCTION_NAME, 0 },
--- a/gcc/c-common.h	Fri Jul 17 14:47:48 2009 +0900
+++ b/gcc/c-common.h	Fri Jul 17 17:43:54 2009 +0900
@@ -119,6 +119,11 @@
   RID_AT_INTERFACE,
   RID_AT_IMPLEMENTATION,
 
+#ifndef noCbC
+  /* Continuation based C */
+  RID_CbC_CODE, RID_CbC_ENV, RID_CbC_RET,
+#endif
+
   RID_MAX,
 
   RID_FIRST_MODIFIER = RID_STATIC,
--- a/gcc/c-decl.c	Fri Jul 17 14:47:48 2009 +0900
+++ b/gcc/c-decl.c	Fri Jul 17 17:43:54 2009 +0900
@@ -63,6 +63,13 @@
 #include "langhooks-def.h"
 #include "pointer-set.h"
 #include "gimple.h"
+#ifndef noCbC
+#include "cbc-tree.h"
+tree cbc_env;
+tree cbc_return_f;
+location_t cbc_return;
+#endif
+
 
 /* In grokdeclarator, distinguish syntactic contexts of declarators.  */
 enum decl_context
@@ -2339,8 +2346,13 @@
 /* Generate an implicit declaration for identifier FUNCTIONID as a
    function of type int ().  */
 
+#ifndef noCbC
+tree
+implicitly_declare (tree functionid, int fun)
+#else
 tree
 implicitly_declare (tree functionid)
+#endif
 {
   struct c_binding *b;
   tree decl = 0;
@@ -2415,7 +2427,12 @@
     }
 
   /* Not seen before.  */
+#ifndef noCbC
+  decl = build_decl (FUNCTION_DECL, functionid, 
+    fun==RID_CbC_CODE?build_function_type (void_type_node, NULL_TREE):default_function_type);
+#else
   decl = build_decl (FUNCTION_DECL, functionid, default_function_type);
+#endif
   DECL_EXTERNAL (decl) = 1;
   TREE_PUBLIC (decl) = 1;
   C_DECL_IMPLICIT (decl) = 1;
@@ -4560,7 +4577,17 @@
 	      }
 	    type_quals = TYPE_UNQUALIFIED;
 
-	    type = build_function_type (type, arg_types);
+#ifndef noCbC
+          if ( declspecs->typespec_word == cts_CbC_code )
+            {
+              type = build_code_segment_type (type, arg_types);
+            }
+          else
+#endif
+            {
+              type = build_function_type (type, arg_types);
+            }
+
 	    declarator = declarator->declarator;
 
 	    /* Set the TYPE_CONTEXTs for each tagged type which is local to
@@ -6072,6 +6099,68 @@
   return tree_cons (decl, value, NULL_TREE);
 }
 
+#ifndef noCbC
+#define CbC_STACK_SIZE (1024 * 8)
+static void cbc_set_codesegment(tree fndecl){
+  tree args;
+  tree *nextp;
+//  tree itype;
+//  tree icst;
+//  tree padding_array;
+//  tree list;
+  int padding_size = CbC_STACK_SIZE;
+
+  //CbC_IS_CODE_SEGMENT(TREE_TYPE(fndecl)) = 1;
+  //CbC_IS_CODE_SEGMENT(fndecl) = 1;
+
+  nextp = & TYPE_ARG_TYPES (TREE_TYPE (fndecl));
+  for (args = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); args;
+      args = TREE_CHAIN (args))
+    {
+      tree type = args ? TREE_VALUE (args) : 0;
+      tree type_size;
+      unsigned int size;
+
+      if (type == void_type_node)
+	break;
+
+      type_size = TYPE_SIZE (type);
+      size = TREE_INT_CST_LOW (type_size);
+      padding_size -= size;
+
+      nextp = & TREE_CHAIN(args);
+    }
+
+  /* error check.  */
+  if (padding_size<0)
+    {
+      error ("CbC: too many arguments on code segment %qE", fndecl);
+      return ;
+    }
+  else if (padding_size==0)
+    return ;
+
+#if 0
+  /* itype is integer_type that means last index.  */
+  icst  = build_int_cst (NULL_TREE, padding_size-1);
+  itype = build_index_type (icst);
+
+  /* create array_type node.  */
+  padding_array = build_array_type (integer_type_node, itype);
+
+  /* add array_type to this function's argument list
+     before void_type_node.  */
+  if (!args)
+    args = build_tree_list(NULL_TREE, void_type_node);
+  list = build_tree_list(NULL_TREE, padding_array);
+  TREE_CHAIN(list) = args;
+  *nextp = list;
+#endif
+
+  return ;
+}
+#endif
+
 
 /* Create the FUNCTION_DECL for a function definition.
    DECLSPECS, DECLARATOR and ATTRIBUTES are the parts of
@@ -6121,6 +6210,16 @@
   decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, true, NULL,
 			  &attributes, DEPRECATED_NORMAL);
 
+#ifndef noCbC
+  cbc_return_f = NULL_TREE;
+  cbc_env = NULL_TREE;
+  if ( declspecs->typespec_word == cts_CbC_code )
+    {
+	  cbc_set_codesegment(decl1);
+      //CbC_IS_CODE_SEGMENT(TREE_TYPE(decl1)) = 1;
+    }
+#endif
+
   /* If the declarator is not suitable for a function definition,
      cause a syntax error.  */
   if (decl1 == 0)
@@ -7249,6 +7348,11 @@
 	      else if (specs->typespec_word == cts_void)
 		error ("both %<long%> and %<void%> in "
 		       "declaration specifiers");
+#ifndef noCbC
+	      else if (specs->typespec_word == cts_CbC_code)
+		error ("both %<long%> and %<void%> in "
+		       "declaration specifiers");
+#endif
 	      else if (specs->typespec_word == cts_bool)
 		error ("both %<long%> and %<_Bool%> in "
 		       "declaration specifiers");
@@ -7278,6 +7382,11 @@
 	      else if (specs->typespec_word == cts_void)
 		error ("both %<short%> and %<void%> in "
 		       "declaration specifiers");
+#ifndef noCbC
+	      else if (specs->typespec_word == cts_CbC_code)
+		error ("both %<short%> and %<void%> in "
+		       "declaration specifiers");
+#endif
 	      else if (specs->typespec_word == cts_bool)
 		error ("both %<short%> and %<_Bool%> in "
 		       "declaration specifiers");
@@ -7310,6 +7419,11 @@
 	      else if (specs->typespec_word == cts_void)
 		error ("both %<signed%> and %<void%> in "
 		       "declaration specifiers");
+#ifndef noCbC
+	      else if (specs->typespec_word == cts_CbC_code)
+		error ("both %<signed%> and %<void%> in "
+		       "declaration specifiers");
+#endif
 	      else if (specs->typespec_word == cts_bool)
 		error ("both %<signed%> and %<_Bool%> in "
 		       "declaration specifiers");
@@ -7339,6 +7453,11 @@
 	      else if (specs->typespec_word == cts_void)
 		error ("both %<unsigned%> and %<void%> in "
 		       "declaration specifiers");
+#ifndef noCbC
+	      else if (specs->typespec_word == cts_CbC_code)
+		error ("both %<unsigned%> and %<void%> in "
+		       "declaration specifiers");
+#endif
 	      else if (specs->typespec_word == cts_bool)
 		error ("both %<unsigned%> and %<_Bool%> in "
 		       "declaration specifiers");
@@ -7367,6 +7486,11 @@
 	      if (specs->typespec_word == cts_void)
 		error ("both %<complex%> and %<void%> in "
 		       "declaration specifiers");
+#ifndef noCbC
+	      else if (specs->typespec_word == cts_CbC_code)
+		error ("both %<complex%> and %<void%> in "
+		       "declaration specifiers");
+#endif
 	      else if (specs->typespec_word == cts_bool)
 		error ("both %<complex%> and %<_Bool%> in "
 		       "declaration specifiers");
@@ -7469,6 +7593,27 @@
 	      else
 		specs->typespec_word = cts_void;
 	      return specs;
+#ifndef noCbC
+	    case RID_CbC_CODE:
+	      if (specs->long_p)
+		error ("both %<long%> and %<void%> in "
+		       "declaration specifiers");
+	      else if (specs->short_p)
+		error ("both %<short%> and %<void%> in "
+		       "declaration specifiers");
+	      else if (specs->signed_p)
+		error ("both %<signed%> and %<void%> in "
+		       "declaration specifiers");
+	      else if (specs->unsigned_p)
+		error ("both %<unsigned%> and %<void%> in "
+		       "declaration specifiers");
+	      else if (specs->complex_p)
+		error ("both %<complex%> and %<void%> in "
+		       "declaration specifiers");
+	      else
+		specs->typespec_word = cts_CbC_code;
+	      return specs;
+#endif
 	    case RID_BOOL:
 	      if (specs->long_p)
 		error ("both %<long%> and %<_Bool%> in "
@@ -7823,6 +7968,9 @@
   switch (specs->typespec_word)
     {
     case cts_void:
+#ifndef noCbC
+    case cts_CbC_code:
+#endif
       gcc_assert (!specs->long_p && !specs->short_p
 		  && !specs->signed_p && !specs->unsigned_p
 		  && !specs->complex_p);
--- a/gcc/c-parser.c	Fri Jul 17 14:47:48 2009 +0900
+++ b/gcc/c-parser.c	Fri Jul 17 17:43:54 2009 +0900
@@ -57,6 +57,9 @@
 #include "vec.h"
 #include "target.h"
 #include "cgraph.h"
+#ifndef noCbC
+#include "cbc-tree.h"
+#endif
 
 
 /* Initialization routine for this file.  */
@@ -465,6 +468,12 @@
 	case RID_FRACT:
 	case RID_ACCUM:
 	case RID_SAT:
+#ifndef noCbC
+	case RID_CbC_CODE:
+#endif
+#ifndef noCbC
+	case RID_CbC_CODE:
+#endif
 	  return true;
 	default:
 	  return false;
@@ -1518,6 +1527,9 @@
 	case RID_FRACT:
 	case RID_ACCUM:
 	case RID_SAT:
+#ifndef noCbC
+	case RID_CbC_CODE:
+#endif
 	  if (!typespec_ok)
 	    goto out;
 	  attrs_ok = true;
@@ -3701,8 +3713,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
 	      stmt = c_finish_goto_label (c_parser_peek_token (parser)->value);
 	      c_parser_consume_token (parser);
 	    }
@@ -3712,7 +3730,79 @@
 	      stmt = c_finish_goto_ptr (c_parser_expression (parser).value);
 	    }
 	  else
+#ifndef noCbC
+	    {
+	      struct c_expr expr;
+	      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);
+		}
+	      expr = c_parser_expr_no_commas (parser, NULL);
+	      if (TREE_CODE(expr.value) == CALL_EXPR )
+		{
+		  TREE_TYPE(expr.value) = void_type_node;
+		  if (c_parser_next_token_is (parser, CPP_COMMA)) 
+		    {
+		      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 (env_struct, "CbCenv->sp"), get_identifier("sp"));
+			argsp = build_component_ref (build_indirect_ref (env_struct, "CbCenv->sp"), get_identifier("argsp"));
+			//ebp = chainon (ebp, argsp);
+			tmp = build_tree_list (ebp, argsp);
+
+		      TREE_OPERAND (expr.value, 2) = tmp;
+
+
+		      /*
+		      c_parser_consume_token (parser);
+		      expr = default_function_array_conversion (expr);
+			ident = c_parser_peek_token (parser)->value;
+		      c_parser_consume_token (parser);
+		      expr.value = build_component_ref (build_indirect_ref (expr.value,
+			    "->"), ident);
+		      expr.original_code = ERROR_MARK;
+		      */
+
+
+		    }
+		  else
+		    TREE_OPERAND (expr.value, 2) = NULL_TREE;
+		  CbC_IS_CbC_GOTO (expr.value) = 1;
+		  CALL_EXPR_TAILCALL (expr.value) = 1;
+		  add_stmt(expr.value);
+		  CbC_HAVE_CbC_GOTO (current_function_decl) = 1;
+		  // should be match with function type?
+		  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);
@@ -5093,6 +5183,7 @@
 {
   struct c_expr expr, e1, e2, e3;
   struct c_type_name *t1, *t2;
+  static tree return_label1;
   location_t loc;
   switch (c_parser_peek_token (parser)->type)
     {
@@ -5490,6 +5581,239 @@
 	    expr.original_code = ERROR_MARK;
 	  }
 	  break;
+#ifndef noCbC
+	case RID_CbC_ENV:
+          {
+#if 0
+	    tree valuep_tree;
+	    tree value_tree;
+	    tree env_tree;
+
+	    tree exprstmt;
+	    tree stmt = c_begin_stmt_expr ();
+	    /*
+	     * __value = {
+	     *   void *ebp;
+	     *   char args[sizeof(arguments)];
+	     * };
+	     *
+	     *  __env = ({
+	     *    ebp = __builtin_frame_address(0);
+	     *    *__value=ebp;
+	     *    __value;
+	     *  })
+	     */
+
+	    /* get value of %ebp.  */
+	    env_tree = build_external_ref (
+		        get_identifier ("__builtin_frame_address"), 0,
+			c_parser_peek_token (parser)->location);
+	    env_tree = build_function_call(env_tree, 
+			   build_tree_list (NULL_TREE, build_int_cst (NULL_TREE,0)));
+
+	    /* ebp = __builtin_frame_address(0)  */
+	    valuep_tree = build_decl (VAR_DECL, get_identifier("__value"), intTI_type_node);
+	    TREE_STATIC (valuep_tree) = 1;
+	    lang_hooks.decls.pushdecl(valuep_tree);
+	    /* cast __value to pointer to pointer to void.  */
+	    valuep_tree = build_c_cast (build_pointer_type(ptr_type_node), valuep_tree);
+	    value_tree = build_indirect_ref (valuep_tree, "cbc: *__value");
+
+	    /* *__value = ebp;  */
+	    exprstmt = build_modify_expr (value_tree, NOP_EXPR, env_tree);
+	    add_stmt(exprstmt);
+
+	    /* __value;  */
+	    add_stmt(valuep_tree);
+#else
+
+	    //tree env;        // environment structure
+	    tree env_struct; // type of environment structure
+	    tree field;
+	    tree fields=NULL_TREE;
+	    tree comp, comp0;       // component of environment
+	    tree ebp;
+
+	    tree stmt = c_begin_stmt_expr ();
+
+	    /*
+	     * struct {
+	     *     void *sp;     <= %ebp
+	     *     void *argp;   <= &__environment.retval
+	     *     int retval;  // int? or return type of this function
+	     * } __CbCenv;
+	     *
+	     * __environment = &__CbCenv;
+	     *
+	     */
+
+	    if (!cbc_env)
+	      {
+		/* build type_node of environment structure  */
+		env_struct = 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);
+		//env_struct = make_node(RECORD_TYPE);
+		//TYPE_FIELDS (env_struct) = fields;
+		finish_struct (env_struct, fields, NULL_TREE);
+
+		/* declare __environment structure.  */
+		cbc_env = build_decl (VAR_DECL, get_identifier("__CbCenv"), env_struct);
+		TREE_STATIC (cbc_env) = 1;
+		lang_hooks.decls.pushdecl(cbc_env);
+	      }
+
+	    /* get value of %ebp.  */
+	    ebp = build_external_ref (
+		        get_identifier ("__builtin_frame_address"), 0,
+			c_parser_peek_token (parser)->location);
+	    ebp = build_function_call(ebp, 
+			   build_tree_list (NULL_TREE, build_int_cst (NULL_TREE,0)));
+
+	    /* assignment  void *sp = %ebp  */
+	    comp = build_component_ref (cbc_env, get_identifier("sp"));
+	    add_stmt (build_modify_expr (comp, NOP_EXPR, ebp));
+
+	    /* void *argsp = &__environment.retval  */
+	    comp = build_component_ref (cbc_env, get_identifier("argsp"));
+	    comp0 = build_component_ref (cbc_env, get_identifier("retval"));
+	    comp0 = build_unary_op (ADDR_EXPR, comp0, 0);
+	    add_stmt (build_modify_expr (comp, NOP_EXPR, comp0));
+
+
+	    /* &__environment for value of stmt_expr. */
+	    add_stmt (build_unary_op (ADDR_EXPR, cbc_env, 0));
+#endif
+	    //expr.value = valuep_tree;
+	    TREE_SIDE_EFFECTS (stmt) = 1;
+	    expr.value = c_finish_stmt_expr (stmt);
+	    //expr.value = build_unary_op (ADDR_EXPR, env, 0);
+	    c_parser_consume_token (parser);
+          }
+	  break;
+	case RID_CbC_RET:
+	case RID_RETURN:
+#if 1
+	  if (cbc_return_f==0) {
+	      tree retval;
+
+              /*
+                   Generates something like...
+
+                   __return = ({
+                       static volatile int __return;
+                       if (__return) {
+                       return_label:
+                            return value;
+                       }
+                       &&return_label;
+                   })
+               */
+
+	      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(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);
+		if (!cbc_env)
+		  {
+		      tree field,fields,env_struct;
+		    /* build type_node of environment structure  */
+		    env_struct = 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);
+		    //env_struct = make_node(RECORD_TYPE);
+		    //TYPE_FIELDS (env_struct) = fields;
+		    finish_struct (env_struct, fields, NULL_TREE);
+
+		    /* declare __environment structure.  */
+		    cbc_env = build_decl (VAR_DECL, get_identifier("__CbCenv"), env_struct);
+		    TREE_STATIC (cbc_env) = 1;
+		    lang_hooks.decls.pushdecl(cbc_env);
+		  }
+		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;
+
+	      // cbc_return_f =0;
+
+	  } 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);
+          }
+	  break;
+#endif
+#endif
 	default:
 	  c_parser_error (parser, "expected expression");
 	  expr.value = error_mark_node;
--- a/gcc/c-tree.h	Fri Jul 17 14:47:48 2009 +0900
+++ b/gcc/c-tree.h	Fri Jul 17 17:43:54 2009 +0900
@@ -213,6 +213,9 @@
   cts_int,
   cts_float,
   cts_double,
+#ifndef noCbC
+  cts_CbC_code,
+#endif
   cts_dfloat32,
   cts_dfloat64,
   cts_dfloat128,
@@ -480,7 +483,11 @@
 		       struct c_declspecs *, tree, tree *);
 extern tree groktypename (struct c_type_name *);
 extern tree grokparm (const struct c_parm *);
+#ifndef noCbC
+extern tree implicitly_declare (tree,int);
+#else
 extern tree implicitly_declare (tree);
+#endif
 extern void keep_next_level (void);
 extern void pending_xref_error (void);
 extern void c_push_function_context (void);
--- a/gcc/c-typeck.c	Fri Jul 17 14:47:48 2009 +0900
+++ b/gcc/c-typeck.c	Fri Jul 17 17:43:54 2009 +0900
@@ -44,6 +44,9 @@
 #include "tree-iterator.h"
 #include "gimple.h"
 #include "tree-flow.h"
+#ifndef noCbC
+  #include "cbc-tree.h"
+#endif
 
 /* Possible cases of implicit bad conversions.  Used to select
    diagnostic messages in convert_for_assignment.  */
@@ -403,6 +406,9 @@
       /* Function types: prefer the one that specified arg types.
 	 If both do, merge the arg types.  Also merge the return types.  */
       {
+#ifndef noCbC
+	int is_code_segment = CbC_IS_CODE_SEGMENT(t1);
+#endif
 	tree valtype = composite_type (TREE_TYPE (t1), TREE_TYPE (t2));
 	tree p1 = TYPE_ARG_TYPES (t1);
 	tree p2 = TYPE_ARG_TYPES (t2);
@@ -419,12 +425,20 @@
 	/* Simple way if one arg fails to specify argument types.  */
 	if (TYPE_ARG_TYPES (t1) == 0)
 	 {
+#ifndef noCbC
+	   if (is_code_segment) t1 = build_code_segment_type (valtype, TYPE_ARG_TYPES (t2));
+	   else
+#endif
 	    t1 = build_function_type (valtype, TYPE_ARG_TYPES (t2));
 	    t1 = build_type_attribute_variant (t1, attributes);
 	    return qualify_type (t1, t2);
 	 }
 	if (TYPE_ARG_TYPES (t2) == 0)
 	 {
+#ifndef noCbC
+	   if (is_code_segment) t1 = build_code_segment_type (valtype, TYPE_ARG_TYPES (t1));
+	   else
+#endif
 	   t1 = build_function_type (valtype, TYPE_ARG_TYPES (t1));
 	   t1 = build_type_attribute_variant (t1, attributes);
 	   return qualify_type (t1, t2);
@@ -518,6 +532,11 @@
 	  }
 
 	c_override_global_bindings_to_false = false;
+
+#ifndef noCbC
+	if (is_code_segment) t1 = build_code_segment_type (valtype, newargs);
+	else
+#endif
 	t1 = build_function_type (valtype, newargs);
 	t1 = qualify_type (t1, t2);
 	/* ... falls through ...  */
@@ -2199,7 +2218,11 @@
     ref = decl;
   else if (fun)
     /* Implicit function declaration.  */
+#ifndef noCbC
+    ref = implicitly_declare (id, fun);
+#else
     ref = implicitly_declare (id);
+#endif
   else if (decl == error_mark_node)
     /* Don't complain about something that's already been
        complained about.  */
@@ -2743,7 +2766,13 @@
 
   gcc_assert (parmnum == nargs);
 
+#ifndef noCbC
+  if (typetail != 0 && TREE_VALUE (typetail) != void_type_node
+	  //&& !CbC_IS_CODE_SEGMENT(TREE_TYPE(fundecl)) )
+	  && !(fundecl&&CbC_IS_CODE_SEGMENT(fundecl)) )
+#else
   if (typetail != 0 && TREE_VALUE (typetail) != void_type_node)
+#endif
     {
       error ("too few arguments to function %qE", function);
       return -1;
--- a/gcc/calls.c	Fri Jul 17 14:47:48 2009 +0900
+++ b/gcc/calls.c	Fri Jul 17 17:43:54 2009 +0900
@@ -98,6 +98,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
@@ -1879,6 +1882,11 @@
   return true;
 }
 
+#ifndef noCbC
+#include "cbc-tree.h"
+#include "cbc-goto.h"
+#endif
+
 /* If X is a likely-spilled register value, copy it to a pseudo
    register and return that register.  Return X otherwise.  */
 
@@ -1904,7 +1912,7 @@
   return x;
 }
 
-/* Generate all the code for a CALL_EXPR exp
+/* Generate all the code for a function call
    and return an rtx for its value.
    Store the value in TARGET (specified as an rtx) if convenient.
    If the value is stored in TARGET then TARGET is returned.
@@ -2374,6 +2382,39 @@
 
   preferred_unit_stack_boundary = preferred_stack_boundary / BITS_PER_UNIT;
 
+#ifndef noCbC
+  if ( fntype
+       //&& CbC_IS_CODE_SEGMENT (fntype)
+       //&& fndecl
+       //&& CbC_IS_CODE_SEGMENT (fndecl)
+       //&& CbC_IS_CODE_SEGMENT(TREE_TYPE(fndecl))
+       //&& CALL_EXPR_TAILCALL (exp)
+       && CbC_IS_CbC_GOTO (exp) // it's better? than CALL_EXPR_TAILCALL()
+     )
+    {
+
+      // fprintf(stderr, "\n\tgoto code segment.\n");
+      args_size.constant = CbC_ARGS_SIZE;
+      return expand_cbc_goto(exp, target, fndecl, funtype,
+	      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 ( fndecl&&CbC_HAVE_CbC_GOTO(fndecl) )
+    {
+      char *name = IDENTIFIER_POINTER(DECL_NAME(fndecl));
+      fprintf(stderr, "\nCbC: function %s having CbCgoto statement has been `CALLED'.\n", name);
+      //args_size.constant = CbC_ARGS_SIZE;
+    }
+  else if ( fntype&&CbC_IS_CODE_SEGMENT(fntype) )
+    {
+      char *name = IDENTIFIER_POINTER(DECL_NAME(fndecl));
+      fprintf(stderr, "\nCbC error: codesegment %s has been `CALLED!'.\n", name);
+    }
+#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.  */
@@ -2444,12 +2485,27 @@
 	 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) )
+         || ( fndecl && CbC_HAVE_CbC_GOTO(fndecl) ) )
+        {
+        unadjusted_args_size = args_size.constant;
+        adjusted_args_size.constant = CbC_ARGS_SIZE;
+        compute_argument_block_size (reg_parm_stack_space,
+                                     &adjusted_args_size,
+                                     (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));
+      }
 
       old_stack_allocated = stack_pointer_delta - pending_stack_adjust;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gcc/cbc-tree.h	Fri Jul 17 17:43:54 2009 +0900
@@ -0,0 +1,16 @@
+/* Set if the fntype is code segment on CbC language.  */
+// flag3,5,6 has been used by c-tree.h
+#define CbC_IS_CODE_SEGMENT(TYPE) TYPE_LANG_FLAG_5 ( FUNCTION_TYPE_CHECK(TYPE))
+#define CbC_HAVE_CbC_GOTO(EXP) DECL_LANG_FLAG_4 (FUNCTION_DECL_CHECK (EXP))
+
+/* Set if the CALL_EXPR NODE is goto statement on CbC language.  */
+//#define CbC_IS_CbC_GOTO(NODE) (CALL_EXPR_CHECK(NODE)->common.lang_flag_5)
+
+// old difinition
+//#define CbC_IS_CODE_SEGMENT(EXP) DECL_LANG_FLAG_7 (FUNCTION_DECL_CHECK (EXP))
+//#define CbC_IS_CODE_SEGMENT(NODE) (TYPE_CHECK (NODE)->type.lang_flag_5)
+#define CbC_IS_CbC_GOTO(NODE) TREE_LANG_FLAG_5 (CALL_EXPR_CHECK(NODE))
+
+extern tree cbc_return_f;
+extern tree cbc_env;
+extern location_t cbc_return;
--- a/gcc/function.c	Fri Jul 17 14:47:48 2009 +0900
+++ b/gcc/function.c	Fri Jul 17 17:43:54 2009 +0900
@@ -3228,6 +3228,11 @@
       SET_DECL_RTL (result, x);
     }
 
+#ifndef noCbC
+  //if (CbC_IS_CODE_SEGMENT(TREE_TYPE(fndecl)) )
+    //all.stack_args_size.constant = CbC_STACK_SIZE;
+#endif
+
   /* We have aligned all the args, so add space for the pretend args.  */
   crtl->args.pretend_args_size = all.pretend_args_size;
   all.stack_args_size.constant += all.extra_pretend_bytes;
--- a/gcc/gcc.c	Fri Jul 17 14:47:48 2009 +0900
+++ b/gcc/gcc.c	Fri Jul 17 17:43:54 2009 +0900
@@ -988,6 +988,9 @@
   {".zip", "#Java", 0, 0, 0}, {".jar", "#Java", 0, 0, 0},
   /* Next come the entries for C.  */
   {".c", "@c", 0, 1, 1},
+#ifndef noCbC
+  {".cbc", "@c", 0, 1, 1},
+#endif
   {"@c",
    /* cc1 has an integrated ISO C preprocessor.  We should invoke the
       external preprocessor if -save-temps is given.  */
--- a/gcc/gimplify.c	Fri Jul 17 14:47:48 2009 +0900
+++ b/gcc/gimplify.c	Fri Jul 17 17:43:54 2009 +0900
@@ -52,6 +52,10 @@
 #include "splay-tree.h"
 #include "vec.h"
 #include "gimple.h"
+#ifndef noCbC
+#include "cbc-tree.h"
+#endif
+
 
 
 enum gimplify_omp_var_data
@@ -1329,7 +1333,16 @@
       return GS_ALL_DONE;
     }
 
-  if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl))))
+  if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (current_function_decl))) 
+#ifndef noCbC
+      || ( ret_expr
+           && TREE_CODE(ret_expr)==CALL_EXPR
+	   && CbC_IS_CbC_GOTO(ret_expr) 
+	   //&& !CbC_IS_CODE_SEGMENT(TREE_TYPE(current_function_decl)))
+	   && !(current_function_decl&&CbC_IS_CODE_SEGMENT(TREE_TYPE(current_function_decl))))
+	   //&& !(current_function_decl&&CbC_IS_CODE_SEGMENT(current_function_decl)))
+#endif
+     )
     result_decl = NULL_TREE;
   else
     {
--- a/gcc/passes.c	Fri Jul 17 14:47:48 2009 +0900
+++ b/gcc/passes.c	Fri Jul 17 17:43:54 2009 +0900
@@ -518,7 +518,11 @@
   NEXT_PASS (pass_build_cfg);
   NEXT_PASS (pass_lower_complex_O0);
   NEXT_PASS (pass_lower_vector);
+#ifndef noCbC
+  //NEXT_PASS (pass_warn_function_return);
+#else
   NEXT_PASS (pass_warn_function_return);
+#endif
   NEXT_PASS (pass_build_cgraph_edges);
   NEXT_PASS (pass_inline_parameters);
   *p = NULL;
--- a/gcc/tree-ssa-operands.c	Fri Jul 17 14:47:48 2009 +0900
+++ b/gcc/tree-ssa-operands.c	Fri Jul 17 17:43:54 2009 +0900
@@ -34,6 +34,9 @@
 #include "toplev.h"
 #include "langhooks.h"
 #include "ipa-reference.h"
+#ifndef noCbC
+  #include "cbc-tree.h"
+#endif
 
 /* This file contains the code required to manage the operands cache of the 
    SSA optimizer.  For every stmt, we maintain an operand cache in the stmt 
--- a/gcc/tree.c	Fri Jul 17 14:47:48 2009 +0900
+++ b/gcc/tree.c	Fri Jul 17 17:43:54 2009 +0900
@@ -90,6 +90,10 @@
 #undef DEFTREECODE
 #undef END_OF_BASE_TREE_CODES
 
+#ifndef noCbC
+#include "cbc-tree.h"
+#endif
+
 /* Each tree code class has an associated string representation.
    These must correspond to the tree_code_class entries.  */
 
@@ -5808,6 +5812,28 @@
   return type;
 }
 
+#ifndef noCbC
+tree
+build_code_segment_type (tree value_type, tree arg_types)
+{
+  tree t;
+  hashval_t hashcode = 0;
+
+  gcc_assert (TREE_CODE (value_type) == VOID_TYPE);
+
+  /* Make a node of the sort we want.  */
+  t = make_node (FUNCTION_TYPE);
+  TREE_TYPE (t) = value_type;
+  TYPE_ARG_TYPES (t) = arg_types;
+
+  CbC_IS_CODE_SEGMENT (t) = 1;
+
+  if (!COMPLETE_TYPE_P (t))
+    layout_type (t);
+  return t;
+}
+#endif
+
 /* Computes the canonical argument types from the argument type list
    ARGTYPES. 
 
--- a/gcc/tree.h	Fri Jul 17 14:47:48 2009 +0900
+++ b/gcc/tree.h	Fri Jul 17 17:43:54 2009 +0900
@@ -4017,6 +4017,9 @@
 extern tree value_member (tree, tree);
 extern tree purpose_member (const_tree, tree);
 
+#ifndef noCbC
+extern tree build_code_segment_type (tree, tree);
+#endif
 extern int attribute_list_equal (const_tree, const_tree);
 extern int attribute_list_contained (const_tree, const_tree);
 extern int tree_int_cst_equal (const_tree, const_tree);