OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / lto / lto-lang.c
index f7c0bfe..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.
@@ -34,6 +34,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple.h"
 #include "diagnostic-core.h"
 #include "toplev.h"
+#include "lto-streamer.h"
 
 static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
 static tree handle_leaf_attribute (tree *, tree, tree, int, bool *);
@@ -45,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
@@ -81,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
@@ -313,7 +328,7 @@ handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
      will have the correct types when we actually check them later.  */
   if (!args)
     {
-      gcc_assert (TYPE_ARG_TYPES (type));
+      gcc_assert (prototype_p (type));
       return NULL_TREE;
     }
 
@@ -370,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)
     {
@@ -396,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.  */
 
@@ -442,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;
 
@@ -453,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
@@ -507,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);
 }
 
 
@@ -611,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
@@ -639,14 +677,13 @@ lto_complain_wrong_lang_p (const struct cl_option *option ATTRIBUTE_UNUSED)
 }
 
 static void
-lto_init_options (unsigned int decoded_options_count ATTRIBUTE_UNUSED,
-                 struct cl_decoded_option *decoded_options ATTRIBUTE_UNUSED)
+lto_init_options_struct (struct gcc_options *opts)
 {
   /* By default, C99-like requirements for complex multiply and divide.
      ???  Until the complex method is encoded in the IL this is the only
      safe choice.  This will pessimize Fortran code with LTO unless
      people specify a complex method manually or use -ffast-math.  */
-  flag_complex_method = 2;
+  opts->x_flag_complex_method = 2;
 }
 
 /* Handle command-line option SCODE.  If the option takes an argument, it is
@@ -658,6 +695,7 @@ const char *resolution_file_name;
 static bool
 lto_handle_option (size_t scode, const char *arg,
                   int value ATTRIBUTE_UNUSED, int kind ATTRIBUTE_UNUSED,
+                  location_t loc ATTRIBUTE_UNUSED,
                   const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED)
 {
   enum opt_code code = (enum opt_code) scode;
@@ -707,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;
 }
@@ -951,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;
 }
@@ -990,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
@@ -1006,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;
 }
 
@@ -1064,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
@@ -1120,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);
 
@@ -1142,6 +1168,45 @@ lto_init (void)
   targetm.init_builtins ();
   build_common_builtin_nodes ();
 
+  /* Assign names to the builtin types, otherwise they'll end up
+     as __unknown__ in debug info.
+     ???  We simply need to stop pre-seeding the streamer cache.
+     Below is modeled after from c-common.c:c_common_nodes_and_builtins  */
+#define NAME_TYPE(t,n) \
+  if (t) \
+    TYPE_NAME (t) = build_decl (UNKNOWN_LOCATION, TYPE_DECL, \
+                               get_identifier (n), t)
+  NAME_TYPE (integer_type_node, "int");
+  NAME_TYPE (char_type_node, "char");
+  NAME_TYPE (long_integer_type_node, "long int");
+  NAME_TYPE (unsigned_type_node, "unsigned int");
+  NAME_TYPE (long_unsigned_type_node, "long unsigned int");
+  NAME_TYPE (long_long_integer_type_node, "long long int");
+  NAME_TYPE (long_long_unsigned_type_node, "long long unsigned int");
+  NAME_TYPE (short_integer_type_node, "short int");
+  NAME_TYPE (short_unsigned_type_node, "short unsigned int");
+  if (signed_char_type_node != char_type_node)
+    NAME_TYPE (signed_char_type_node, "signed char");
+  if (unsigned_char_type_node != char_type_node)
+    NAME_TYPE (unsigned_char_type_node, "unsigned char");
+  NAME_TYPE (float_type_node, "float");
+  NAME_TYPE (double_type_node, "double");
+  NAME_TYPE (long_double_type_node, "long double");
+  NAME_TYPE (void_type_node, "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;
@@ -1162,8 +1227,8 @@ static void lto_init_ts (void)
 #define LANG_HOOKS_OPTION_LANG_MASK lto_option_lang_mask
 #undef LANG_HOOKS_COMPLAIN_WRONG_LANG_P
 #define LANG_HOOKS_COMPLAIN_WRONG_LANG_P lto_complain_wrong_lang_p
-#undef LANG_HOOKS_INIT_OPTIONS
-#define LANG_HOOKS_INIT_OPTIONS lto_init_options
+#undef LANG_HOOKS_INIT_OPTIONS_STRUCT
+#define LANG_HOOKS_INIT_OPTIONS_STRUCT lto_init_options_struct
 #undef LANG_HOOKS_HANDLE_OPTION
 #define LANG_HOOKS_HANDLE_OPTION lto_handle_option
 #undef LANG_HOOKS_POST_OPTIONS