OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / lto / lto-lang.c
index 5f157d6..d255e65 100644 (file)
@@ -1,5 +1,5 @@
 /* Language-dependent hooks for LTO.
-   Copyright 2009, 2010 Free Software Foundation, Inc.
+   Copyright 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
    Contributed by CodeSourcery, Inc.
 
 This file is part of GCC.
@@ -46,35 +46,48 @@ static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
 static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
 static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
 static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
+static tree handle_transaction_pure_attribute (tree *, tree, tree, int, bool *);
+static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
+static tree ignore_attribute (tree *, tree, tree, int, bool *);
+
 static tree handle_format_attribute (tree *, tree, tree, int, bool *);
 static tree handle_format_arg_attribute (tree *, tree, tree, int, bool *);
 
 /* Table of machine-independent attributes supported in GIMPLE.  */
 const struct attribute_spec lto_attribute_table[] =
 {
-  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
+  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
+       do_diagnostic } */
   { "noreturn",               0, 0, true,  false, false,
-                             handle_noreturn_attribute },
+                             handle_noreturn_attribute, false },
   { "leaf",                  0, 0, true,  false, false,
-                             handle_leaf_attribute },
+                             handle_leaf_attribute, false },
   /* The same comments as for noreturn attributes apply to const ones.  */
   { "const",                  0, 0, true,  false, false,
-                             handle_const_attribute },
+                             handle_const_attribute, false },
   { "malloc",                 0, 0, true,  false, false,
-                             handle_malloc_attribute },
+                             handle_malloc_attribute, false },
   { "pure",                   0, 0, true,  false, false,
-                             handle_pure_attribute },
+                             handle_pure_attribute, false },
   { "no vops",                0, 0, true,  false, false,
-                             handle_novops_attribute },
+                             handle_novops_attribute, false },
   { "nonnull",                0, -1, false, true, true,
-                             handle_nonnull_attribute },
+                             handle_nonnull_attribute, false },
   { "nothrow",                0, 0, true,  false, false,
-                             handle_nothrow_attribute },
+                             handle_nothrow_attribute, false },
+  { "returns_twice",          0, 0, true,  false, false,
+                             handle_returns_twice_attribute, false },
   { "sentinel",               0, 1, false, true, true,
-                             handle_sentinel_attribute },
+                             handle_sentinel_attribute, false },
   { "type generic",           0, 0, false, true, true,
-                             handle_type_generic_attribute },
-  { NULL,                     0, 0, false, false, false, NULL }
+                             handle_type_generic_attribute, false },
+  { "transaction_pure",              0, 0, false, true, true,
+                             handle_transaction_pure_attribute, false },
+  /* For internal use only.  The leading '*' both prevents its usage in
+     source code and signals that it may be overridden by machine tables.  */
+  { "*tm regparm",            0, 0, false, true, true,
+                             ignore_attribute, false },
+  { NULL,                     0, 0, false, false, false, NULL, false }
 };
 
 /* Give the specifications for the format attributes, used by C and all
@@ -82,12 +95,13 @@ const struct attribute_spec lto_attribute_table[] =
 
 const struct attribute_spec lto_format_attribute_table[] =
 {
-  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
+  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
+       affects_type_identity } */
   { "format",                 3, 3, false, true,  true,
-                             handle_format_attribute },
+                             handle_format_attribute, false },
   { "format_arg",             1, 1, false, true,  true,
-                             handle_format_arg_attribute },
-  { NULL,                     0, 0, false, false, false, NULL }
+                             handle_format_arg_attribute, false },
+  { NULL,                     0, 0, false, false, false, NULL, false }
 };
 
 enum built_in_attribute
@@ -371,13 +385,7 @@ handle_sentinel_attribute (tree *node, tree ARG_UNUSED (name), tree args,
                           int ARG_UNUSED (flags),
                           bool * ARG_UNUSED (no_add_attrs))
 {
-  tree params = TYPE_ARG_TYPES (*node);
-  gcc_assert (params);
-
-  while (TREE_CHAIN (params))
-    params = TREE_CHAIN (params);
-
-  gcc_assert (!VOID_TYPE_P (TREE_VALUE (params)));
+  gcc_assert (stdarg_p (*node));
 
   if (args)
     {
@@ -397,21 +405,56 @@ handle_type_generic_attribute (tree *node, tree ARG_UNUSED (name),
                               tree ARG_UNUSED (args), int ARG_UNUSED (flags),
                               bool * ARG_UNUSED (no_add_attrs))
 {
-  tree params;
-  
   /* Ensure we have a function type.  */
   gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
   
-  params = TYPE_ARG_TYPES (*node);
-  while (params && ! VOID_TYPE_P (TREE_VALUE (params)))
-    params = TREE_CHAIN (params);
-
   /* Ensure we have a variadic function.  */
-  gcc_assert (!params);
+  gcc_assert (!prototype_p (*node) || stdarg_p (*node));
+
+  return NULL_TREE;
+}
+
+/* Handle a "transaction_pure" attribute.  */
+
+static tree
+handle_transaction_pure_attribute (tree *node, tree ARG_UNUSED (name),
+                                  tree ARG_UNUSED (args),
+                                  int ARG_UNUSED (flags),
+                                  bool * ARG_UNUSED (no_add_attrs))
+{
+  /* Ensure we have a function type.  */
+  gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
+
+  return NULL_TREE;
+}
+
+/* Handle a "returns_twice" attribute.  */
+
+static tree
+handle_returns_twice_attribute (tree *node, tree ARG_UNUSED (name),
+                               tree ARG_UNUSED (args),
+                               int ARG_UNUSED (flags),
+                               bool * ARG_UNUSED (no_add_attrs))
+{
+  gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
+
+  DECL_IS_RETURNS_TWICE (*node) = 1;
 
   return NULL_TREE;
 }
 
+/* Ignore the given attribute.  Used when this attribute may be usefully
+   overridden by the target, but is not used generically.  */
+
+static tree
+ignore_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name),
+                 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
+                 bool *no_add_attrs)
+{
+  *no_add_attrs = true;
+  return NULL_TREE;
+}
+
 /* Handle a "format" attribute; arguments as in
    struct attribute_spec.handler.  */
 
@@ -443,7 +486,8 @@ handle_format_arg_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name),
 static void
 def_fn_type (builtin_type def, builtin_type ret, bool var, int n, ...)
 {
-  tree args = NULL, t;
+  tree t;
+  tree *args = XALLOCAVEC (tree, n);
   va_list list;
   int i;
 
@@ -454,21 +498,21 @@ def_fn_type (builtin_type def, builtin_type ret, bool var, int n, ...)
       t = builtin_types[a];
       if (t == error_mark_node)
        goto egress;
-      args = tree_cons (NULL_TREE, t, args);
+      args[i] = t;
     }
   va_end (list);
 
-  args = nreverse (args);
-  if (!var)
-    args = chainon (args, void_list_node);
-
   t = builtin_types[ret];
   if (t == error_mark_node)
     goto egress;
-  t = build_function_type (t, args);
+  if (var)
+    t = build_varargs_function_type_array (t, n, args);
+  else
+    t = build_function_type_array (t, n, args);
 
  egress:
   builtin_types[def] = t;
+  va_end (list);
 }
 
 /* Used to help initialize the builtin-types.def table.  When a type of
@@ -508,9 +552,7 @@ def_builtin_1 (enum built_in_function fncode, const char *name,
     add_builtin_function (libname, libtype, fncode, fnclass,
                          NULL, fnattrs);
 
-  built_in_decls[(int) fncode] = decl;
-  if (implicit_p)
-    implicit_built_in_decls[(int) fncode] = decl;
+  set_builtin_decl (fncode, decl, implicit_p);
 }
 
 
@@ -612,11 +654,6 @@ lto_define_builtins (tree va_list_ref_type_node ATTRIBUTE_UNUSED,
 
 static GTY(()) tree registered_builtin_types;
 
-/* A chain of builtin functions that we need to recognize.  We will
-   assume that all other function names we see will be defined by the
-   user's program.  */
-static GTY(()) tree registered_builtin_fndecls;
-
 /* Language hooks.  */
 
 static unsigned int
@@ -708,8 +745,6 @@ lto_post_options (const char **pfilename ATTRIBUTE_UNUSED)
      support.  */
   flag_excess_precision_cmdline = EXCESS_PRECISION_FAST;
 
-  lto_read_all_file_options ();
-
   /* Initialize the compiler back end.  */
   return false;
 }
@@ -952,8 +987,10 @@ lto_type_for_mode (enum machine_mode mode, int unsigned_p)
   return NULL_TREE;
 }
 
-static int
-lto_global_bindings_p (void) 
+/* Return true if we are in the global binding level.  */
+
+static bool
+lto_global_bindings_p (void)
 {
   return cfun == NULL;
 }
@@ -991,7 +1028,10 @@ lto_pushdecl (tree t ATTRIBUTE_UNUSED)
 static tree
 lto_getdecls (void)
 {
-  return registered_builtin_fndecls;
+  /* We have our own write_globals langhook, hence the getdecls
+     langhook shouldn't be used, except by dbxout.c, so we can't
+     just abort here.  */
+  return NULL_TREE;
 }
 
 static void
@@ -1007,10 +1047,6 @@ lto_write_globals (void)
 static tree
 lto_builtin_function (tree decl)
 {
-  /* Record it.  */
-  TREE_CHAIN (decl) = registered_builtin_fndecls;
-  registered_builtin_fndecls = decl;
-
   return decl;
 }
 
@@ -1065,49 +1101,39 @@ lto_build_c_type_nodes (void)
   pid_type_node = integer_type_node;
 }
 
+/* Re-compute TYPE_CANONICAL for NODE and related types.  */
+
+static void
+lto_register_canonical_types (tree node)
+{
+  if (!node
+      || !TYPE_P (node))
+    return;
+
+  TYPE_CANONICAL (node) = NULL_TREE;
+  TYPE_CANONICAL (node) = gimple_register_canonical_type (node);
+
+  if (POINTER_TYPE_P (node)
+      || TREE_CODE (node) == COMPLEX_TYPE
+      || TREE_CODE (node) == ARRAY_TYPE)
+    lto_register_canonical_types (TREE_TYPE (node));
+}
 
 /* Perform LTO-specific initialization.  */
 
 static bool
 lto_init (void)
 {
+  unsigned i;
+
   /* We need to generate LTO if running in WPA mode.  */
   flag_generate_lto = flag_wpa;
 
   /* Initialize libcpp line maps for gcc_assert to work.  */
-  linemap_add (line_table, LC_RENAME, 0, NULL, 0);
-  linemap_add (line_table, LC_RENAME, 0, NULL, 0);
+  linemap_add (line_table, LC_ENTER, 0, NULL, 0);
 
   /* Create the basic integer types.  */
-  build_common_tree_nodes (flag_signed_char);
-
-  /* Share char_type_node with whatever would be the default for the target.
-     char_type_node will be used for internal types such as
-     va_list_type_node but will not be present in the lto stream.  */
-  /* ???  This breaks the more common case of consistent but non-standard
-     setting of flag_signed_char, so share according to flag_signed_char.
-     See PR42528.  */
-  char_type_node
-    = flag_signed_char ? signed_char_type_node : unsigned_char_type_node;
-
-  /* Tell the middle end what type to use for the size of objects.  */
-  if (strcmp (SIZE_TYPE, "unsigned int") == 0)
-    {
-      set_sizetype (unsigned_type_node);
-      size_type_node = unsigned_type_node;
-    }
-  else if (strcmp (SIZE_TYPE, "long unsigned int") == 0)
-    {
-      set_sizetype (long_unsigned_type_node);
-      size_type_node = long_unsigned_type_node;
-    }
-  else if (strcmp (SIZE_TYPE, "long long unsigned int") == 0)
-    {
-      set_sizetype (long_long_unsigned_type_node);
-      size_type_node = long_long_unsigned_type_node;
-    }
-  else
-    gcc_unreachable ();
+  build_common_tree_nodes (flag_signed_char, /*short_double=*/false);
 
   /* The global tree for the main identifier is filled in by
      language-specific front-end initialization that is not run in the
@@ -1121,11 +1147,10 @@ lto_init (void)
      distinction should only be relevant to the front-end, so we
      always use the C definition here in lto1.  */
   gcc_assert (fileptr_type_node == ptr_type_node);
+  gcc_assert (TYPE_MAIN_VARIANT (fileptr_type_node) == ptr_type_node);
 
   ptrdiff_type_node = integer_type_node;
 
-  /* Create other basic types.  */
-  build_common_tree_nodes_2 (/*short_double=*/false);
   lto_build_c_type_nodes ();
   gcc_assert (va_list_type_node);
 
@@ -1171,6 +1196,17 @@ lto_init (void)
   NAME_TYPE (boolean_type_node, "bool");
 #undef NAME_TYPE
 
+  /* Register the common node types with the canonical type machinery so
+     we properly share alias-sets across languages and TUs.  Do not
+     expose the common nodes as type merge target - those that should be
+     are already exposed so by pre-loading the LTO streamer caches.  */
+  for (i = 0; i < itk_none; ++i)
+    lto_register_canonical_types (integer_types[i]);
+  /* The sizetypes are not used to access data so we do not need to
+     do anything about them.  */
+  for (i = 0; i < TI_MAX; ++i)
+    lto_register_canonical_types (global_trees[i]);
+
   /* Initialize LTO-specific data structures.  */
   lto_global_var_decls = VEC_alloc (tree, gc, 256);
   in_lto_p = true;