OSDN Git Service

2010-12-09 Yao Qi <yao@codesourcery.com>
[pf3gnuchains/gcc-fork.git] / gcc / lto-streamer-in.c
index 8061fe3..4fe9cdb 100644 (file)
@@ -719,7 +719,8 @@ make_new_block (struct function *fn, unsigned int index)
 /* Read the CFG for function FN from input block IB.  */
 
 static void
-input_cfg (struct lto_input_block *ib, struct function *fn)
+input_cfg (struct lto_input_block *ib, struct function *fn,
+          int count_materialization_scale)
 {
   unsigned int bb_count;
   basic_block p_bb;
@@ -766,7 +767,8 @@ input_cfg (struct lto_input_block *ib, struct function *fn)
 
          dest_index = lto_input_uleb128 (ib);
          probability = (int) lto_input_sleb128 (ib);
-         count = (gcov_type) lto_input_sleb128 (ib);
+         count = ((gcov_type) lto_input_sleb128 (ib) * count_materialization_scale
+                  + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;
          edge_flags = lto_input_uleb128 (ib);
 
          dest = BASIC_BLOCK_FOR_FUNCTION (fn, dest_index);
@@ -956,27 +958,60 @@ input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in,
              if (TREE_CODE (op) == COMPONENT_REF)
                {
                  tree field, type, tem;
+                 tree closest_match = NULL_TREE;
                  field = TREE_OPERAND (op, 1);
                  type = DECL_CONTEXT (field);
                  for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
                    {
-                     if (tem == field
-                         || (gimple_types_compatible_p (TREE_TYPE (tem),
-                                                        TREE_TYPE (field),
-                                                        GTC_DIAG)
-                             && DECL_NONADDRESSABLE_P (tem)
-                                == DECL_NONADDRESSABLE_P (field)
-                             && gimple_compare_field_offset (tem, field)))
+                     if (tem == field)
                        break;
+                     if (DECL_NONADDRESSABLE_P (tem)
+                         == DECL_NONADDRESSABLE_P (field)
+                         && gimple_compare_field_offset (tem, field))
+                       {
+                         if (types_compatible_p (TREE_TYPE (tem),
+                                                 TREE_TYPE (field)))
+                           break;
+                         else
+                           closest_match = tem;
+                       }
                    }
                  /* In case of type mismatches across units we can fail
                     to unify some types and thus not find a proper
-                    field-decl here.  So only assert here if checking
-                    is enabled.  */
-#ifdef ENABLE_CHECKING
-                 gcc_assert (tem != NULL_TREE);
-#endif
-                 if (tem != NULL_TREE)
+                    field-decl here.  */
+                 if (tem == NULL_TREE)
+                   {
+                     /* Thus, emit a ODR violation warning.  */
+                     if (warning_at (gimple_location (stmt), 0,
+                                     "use of type %<%E%> with two mismatching "
+                                     "declarations at field %<%E%>",
+                                     type, TREE_OPERAND (op, 1)))
+                       {
+                         if (TYPE_FIELDS (type))
+                           inform (DECL_SOURCE_LOCATION (TYPE_FIELDS (type)),
+                                   "original type declared here");
+                         inform (DECL_SOURCE_LOCATION (TREE_OPERAND (op, 1)),
+                                 "field in mismatching type declared here");
+                         if (TYPE_NAME (TREE_TYPE (field))
+                             && (TREE_CODE (TYPE_NAME (TREE_TYPE (field)))
+                                 == TYPE_DECL))
+                           inform (DECL_SOURCE_LOCATION
+                                     (TYPE_NAME (TREE_TYPE (field))),
+                                   "type of field declared here");
+                         if (closest_match
+                             && TYPE_NAME (TREE_TYPE (closest_match))
+                             && (TREE_CODE (TYPE_NAME
+                                  (TREE_TYPE (closest_match))) == TYPE_DECL))
+                           inform (DECL_SOURCE_LOCATION
+                                     (TYPE_NAME (TREE_TYPE (closest_match))),
+                                   "type of mismatching field declared here");
+                       }
+                     /* And finally fixup the types.  */
+                     TREE_OPERAND (op, 0)
+                       = build1 (VIEW_CONVERT_EXPR, type,
+                                 TREE_OPERAND (op, 0));
+                   }
+                 else
                    TREE_OPERAND (op, 1) = tem;
                }
 
@@ -1033,7 +1068,8 @@ input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in,
 
 static void
 input_bb (struct lto_input_block *ib, enum LTO_tags tag,
-         struct data_in *data_in, struct function *fn)
+         struct data_in *data_in, struct function *fn,
+         int count_materialization_scale)
 {
   unsigned int index;
   basic_block bb;
@@ -1046,7 +1082,8 @@ input_bb (struct lto_input_block *ib, enum LTO_tags tag,
   index = lto_input_uleb128 (ib);
   bb = BASIC_BLOCK_FOR_FUNCTION (fn, index);
 
-  bb->count = lto_input_sleb128 (ib);
+  bb->count = (lto_input_sleb128 (ib) * count_materialization_scale
+              + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;
   bb->loop_depth = lto_input_sleb128 (ib);
   bb->frequency = lto_input_sleb128 (ib);
   bb->flags = lto_input_sleb128 (ib);
@@ -1220,12 +1257,14 @@ input_function (tree fn_decl, struct data_in *data_in,
   DECL_INITIAL (fn_decl) = lto_input_tree (ib, data_in);
   gcc_assert (DECL_INITIAL (fn_decl));
   DECL_SAVED_TREE (fn_decl) = NULL_TREE;
+  node = cgraph_node (fn_decl);
 
   /* Read all the basic blocks.  */
   tag = input_record_start (ib);
   while (tag)
     {
-      input_bb (ib, tag, data_in, fn);
+      input_bb (ib, tag, data_in, fn,
+               node->count_materialization_scale);
       tag = input_record_start (ib);
     }
 
@@ -1267,7 +1306,6 @@ input_function (tree fn_decl, struct data_in *data_in,
     gimple_set_body (fn_decl, bb_seq (ei_edge (ei)->dest));
   }
 
-  node = cgraph_node (fn_decl);
   fixup_call_stmt_edges (node, stmts);
   execute_all_ipa_stmt_fixups (node, stmts);
 
@@ -1360,6 +1398,7 @@ lto_read_body (struct lto_file_decl_data *file_data, tree fn_decl,
     {
       struct function *fn = DECL_STRUCT_FUNCTION (fn_decl);
       struct lto_in_decl_state *decl_state;
+      struct cgraph_node *node = cgraph_node (fn_decl);
 
       push_cfun (fn);
       init_tree_ssa (fn);
@@ -1369,7 +1408,7 @@ lto_read_body (struct lto_file_decl_data *file_data, tree fn_decl,
       gcc_assert (decl_state);
       file_data->current_decl_state = decl_state;
 
-      input_cfg (&ib_cfg, fn);
+      input_cfg (&ib_cfg, fn, node->count_materialization_scale);
 
       /* Set up the struct function.  */
       input_function (fn_decl, data_in, &ib_main);
@@ -1876,7 +1915,8 @@ static void
 lto_input_ts_common_tree_pointers (struct lto_input_block *ib,
                                   struct data_in *data_in, tree expr)
 {
-  TREE_TYPE (expr) = lto_input_tree (ib, data_in);
+  if (TREE_CODE (expr) != IDENTIFIER_NODE)
+    TREE_TYPE (expr) = lto_input_tree (ib, data_in);
 }
 
 
@@ -1915,6 +1955,13 @@ lto_input_ts_decl_minimal_tree_pointers (struct lto_input_block *ib,
 {
   DECL_NAME (expr) = lto_input_tree (ib, data_in);
   DECL_CONTEXT (expr) = lto_input_tree (ib, data_in);
+  /* We do not stream BLOCK_VARS but lazily construct it here.  */
+  if (DECL_CONTEXT (expr)
+      && TREE_CODE (DECL_CONTEXT (expr)) == BLOCK)
+    {
+      TREE_CHAIN (expr) = BLOCK_VARS (DECL_CONTEXT (expr));
+      BLOCK_VARS (DECL_CONTEXT (expr)) = expr;
+    }
   DECL_SOURCE_LOCATION (expr) = lto_input_location (ib, data_in);
 }
 
@@ -2136,7 +2183,8 @@ lto_input_ts_block_tree_pointers (struct lto_input_block *ib,
   unsigned i, len;
 
   BLOCK_SOURCE_LOCATION (expr) = lto_input_location (ib, data_in);
-  BLOCK_VARS (expr) = lto_input_chain (ib, data_in);
+  /* We do not stream BLOCK_VARS but lazily construct it when reading
+     in decls.  */
 
   len = lto_input_uleb128 (ib);
   if (len > 0)
@@ -2359,27 +2407,26 @@ lto_input_tree_pointers (struct lto_input_block *ib, struct data_in *data_in,
 static void
 lto_register_var_decl_in_symtab (struct data_in *data_in, tree decl)
 {
-  /* Register symbols with file or global scope to mark what input
-     file has their definition.  */
-  if (decl_function_context (decl) == NULL_TREE)
-    {
-      /* Variable has file scope, not local. Need to ensure static variables
-        between different files don't clash unexpectedly.  */
-      if (!TREE_PUBLIC (decl))
-        {
-         /* ??? We normally pre-mangle names before we serialize them
-            out.  Here, in lto1, we do not know the language, and
-            thus cannot do the mangling again. Instead, we just
-            append a suffix to the mangled name.  The resulting name,
-            however, is not a properly-formed mangled name, and will
-            confuse any attempt to unmangle it.  */
-         const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
-         char *label;
-
-         ASM_FORMAT_PRIVATE_NAME (label, name, DECL_UID (decl));
-         SET_DECL_ASSEMBLER_NAME (decl, get_identifier (label));
-          rest_of_decl_compilation (decl, 1, 0);
-        }
+  tree context;
+
+  /* Variable has file scope, not local. Need to ensure static variables
+     between different files don't clash unexpectedly.  */
+  if (!TREE_PUBLIC (decl)
+      && !((context = decl_function_context (decl))
+          && auto_var_in_fn_p (decl, context)))
+    {
+      /* ??? We normally pre-mangle names before we serialize them
+        out.  Here, in lto1, we do not know the language, and
+        thus cannot do the mangling again. Instead, we just
+        append a suffix to the mangled name.  The resulting name,
+        however, is not a properly-formed mangled name, and will
+        confuse any attempt to unmangle it.  */
+      const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+      char *label;
+
+      ASM_FORMAT_PRIVATE_NAME (label, name, DECL_UID (decl));
+      SET_DECL_ASSEMBLER_NAME (decl, get_identifier (label));
+      rest_of_decl_compilation (decl, 1, 0);
     }
 
   /* If this variable has already been declared, queue the