OSDN Git Service

2009-09-27 Sebastian Pop <sebastian.pop@amd.com>
[pf3gnuchains/gcc-fork.git] / gcc / lto-streamer-in.c
index a899f9d..751e704 100644 (file)
@@ -47,6 +47,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "output.h"
 #include "ipa-utils.h"
 #include "lto-streamer.h"
+#include "tree-pass.h"
 
 /* Data structure used to hash file names in the source_location field.  */
 struct string_slot
@@ -274,26 +275,31 @@ static location_t
 lto_input_location (struct lto_input_block *ib, struct data_in *data_in)
 {
   expanded_location xloc;
-  location_t loc;
 
   xloc.file = input_string (data_in, ib);
   if (xloc.file == NULL)
     return UNKNOWN_LOCATION;
 
+  xloc.file = canon_file_name (xloc.file);
   xloc.line = lto_input_sleb128 (ib);
   xloc.column = lto_input_sleb128 (ib);
+  xloc.sysp = lto_input_sleb128 (ib);
 
-  if (data_in->current_file)
-    linemap_add (line_table, LC_LEAVE, false, NULL, 0);
+  if (data_in->current_file != xloc.file)
+    {
+      if (data_in->current_file)
+       linemap_add (line_table, LC_LEAVE, false, NULL, 0);
+
+      linemap_add (line_table, LC_ENTER, xloc.sysp, xloc.file, xloc.line);
+    }
+  else if (data_in->current_line != xloc.line)
+    linemap_line_start (line_table, xloc.line, xloc.column);
 
-  data_in->current_file = canon_file_name (xloc.file);
+  data_in->current_file = xloc.file;
   data_in->current_line = xloc.line;
   data_in->current_col = xloc.column;
 
-  linemap_add (line_table, LC_ENTER, false, data_in->current_file, xloc.line);
-  LINEMAP_POSITION_FOR_COLUMN (loc, line_table, xloc.column);
-
-  return loc;
+  return linemap_position_for_column (line_table, xloc.column);
 }
 
 
@@ -868,6 +874,128 @@ input_ssa_names (struct lto_input_block *ib, struct data_in *data_in,
 }
 
 
+/* Fixup the reference tree OP for replaced VAR_DECLs with mismatched
+   types.  */
+
+static void
+maybe_fixup_handled_component (tree op)
+{
+  tree decl_type;
+  tree wanted_type;
+
+  while (handled_component_p (TREE_OPERAND (op, 0)))
+    op = TREE_OPERAND (op, 0);
+  if (TREE_CODE (TREE_OPERAND (op, 0)) != VAR_DECL)
+    return;
+
+  decl_type = TREE_TYPE (TREE_OPERAND (op, 0));
+
+  switch (TREE_CODE (op))
+    {
+    case COMPONENT_REF:
+      /* The DECL_CONTEXT of the field-decl is the record type we look for.  */
+      wanted_type = DECL_CONTEXT (TREE_OPERAND (op, 1));
+      break;
+
+    case ARRAY_REF:
+      if (TREE_CODE (decl_type) == ARRAY_TYPE
+         && (TREE_TYPE (decl_type) == TREE_TYPE (op)
+             || useless_type_conversion_p (TREE_TYPE (op),
+                                           TREE_TYPE (decl_type))))
+       return;
+      /* An unknown size array type should be ok.  But we do not
+         lower the lower bound in all cases - ugh.  */
+      wanted_type = build_array_type (TREE_TYPE (op), NULL_TREE);
+      break;
+
+    case ARRAY_RANGE_REF:
+      if (TREE_CODE (decl_type) == ARRAY_TYPE
+         && (TREE_TYPE (decl_type) == TREE_TYPE (TREE_TYPE (op))
+             || useless_type_conversion_p (TREE_TYPE (TREE_TYPE (op)),
+                                           TREE_TYPE (decl_type))))
+       return;
+      /* An unknown size array type should be ok.  But we do not
+         lower the lower bound in all cases - ugh.  */
+      wanted_type = build_array_type (TREE_TYPE (TREE_TYPE (op)), NULL_TREE);
+      break;
+
+    case BIT_FIELD_REF:
+    case VIEW_CONVERT_EXPR:
+      /* Very nice - nothing to do.  */
+      return;
+
+    case REALPART_EXPR:
+    case IMAGPART_EXPR:
+      if (TREE_CODE (decl_type) == COMPLEX_TYPE
+         && (TREE_TYPE (decl_type) == TREE_TYPE (op)
+             || useless_type_conversion_p (TREE_TYPE (op),
+                                           TREE_TYPE (decl_type))))
+       return;
+      wanted_type = build_complex_type (TREE_TYPE (op));
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  if (!useless_type_conversion_p (wanted_type, decl_type))
+    TREE_OPERAND (op, 0) = build1 (VIEW_CONVERT_EXPR, wanted_type,
+                                  TREE_OPERAND (op, 0));
+}
+
+/* Fixup reference tree operands for substituted prevailing decls
+   with mismatched types in STMT.  */
+
+static void
+maybe_fixup_decls (gimple stmt)
+{
+  /* We have to fixup replaced decls here in case there were
+     inter-TU type mismatches.  Catch the most common cases
+     for now - this way we'll get testcases for the rest as
+     the type verifier will complain.  */
+  if (gimple_assign_single_p (stmt))
+    {
+      tree lhs = gimple_assign_lhs (stmt);
+      tree rhs = gimple_assign_rhs1 (stmt);
+
+      /* First catch loads and aggregate copies by adjusting the rhs.  */
+      if (TREE_CODE (rhs) == VAR_DECL)
+       {
+         if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
+           gimple_assign_set_rhs1 (stmt, build1 (VIEW_CONVERT_EXPR,
+                                                 TREE_TYPE (lhs), rhs));
+       }
+      else if (handled_component_p (rhs))
+       maybe_fixup_handled_component (rhs);
+      /* Then catch scalar stores.  */
+      else if (TREE_CODE (lhs) == VAR_DECL)
+       {
+         if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
+           gimple_assign_set_lhs (stmt, build1 (VIEW_CONVERT_EXPR,
+                                                TREE_TYPE (rhs), lhs));
+       }
+      else if (handled_component_p (lhs))
+       maybe_fixup_handled_component (lhs);
+    }
+  else if (is_gimple_call (stmt))
+    {
+      tree lhs = gimple_call_lhs (stmt);
+
+      if (lhs && TREE_CODE (lhs) == VAR_DECL)
+       {
+         if (!useless_type_conversion_p (TREE_TYPE (lhs),
+                                         gimple_call_return_type (stmt)))
+           gimple_call_set_lhs (stmt, build1 (VIEW_CONVERT_EXPR,
+                                              gimple_call_return_type (stmt),
+                                              lhs));
+       }
+      else if (lhs && handled_component_p (lhs))
+       maybe_fixup_handled_component (lhs);
+
+      /* Arguments, especially for varargs functions will be funny...  */
+    }
+}
+
 /* Read a statement with tag TAG in function FN from block IB using
    descriptors in DATA_IN.  */
 
@@ -939,6 +1067,40 @@ input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in,
        {
          tree op = lto_input_tree (ib, data_in);
          gimple_set_op (stmt, i, op);
+
+         /* Fixup FIELD_DECLs.  */
+         while (op && handled_component_p (op))
+           {
+             if (TREE_CODE (op) == COMPONENT_REF)
+               {
+                 tree field, type, tem;
+                 field = TREE_OPERAND (op, 1);
+                 type = DECL_CONTEXT (field);
+                 for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
+                   {
+                     if (tem == field
+                         || (TREE_TYPE (tem) == TREE_TYPE (field)
+                             && (DECL_FIELD_OFFSET (tem)
+                                 == DECL_FIELD_OFFSET (field))
+                             && (DECL_FIELD_BIT_OFFSET (tem)
+                                 == DECL_FIELD_BIT_OFFSET (field))
+                             && (DECL_OFFSET_ALIGN (tem)
+                                 == DECL_OFFSET_ALIGN (field))))
+                       break;
+                   }
+                 /* 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)
+                   TREE_OPERAND (op, 1) = tem;
+               }
+
+             op = TREE_OPERAND (op, 0);
+           }
        }
       break;
 
@@ -974,6 +1136,10 @@ input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in,
        }
     }
 
+  /* Fixup reference tree operands for substituted prevailing decls
+     with mismatched types.  */
+  maybe_fixup_decls (stmt);
+
   /* Mark the statement modified so its operand vectors can be filled in.  */
   gimple_set_modified (stmt, true);
 
@@ -1099,6 +1265,8 @@ input_function (tree fn_decl, struct data_in *data_in,
   gimple *stmts;
   basic_block bb;
   struct bitpack_d *bp;
+  struct cgraph_node *node;
+  tree args, narg, oarg;
 
   fn = DECL_STRUCT_FUNCTION (fn_decl);
   tag = input_record_start (ib);
@@ -1133,6 +1301,22 @@ input_function (tree fn_decl, struct data_in *data_in,
   /* Read all the local symbols.  */
   fn->local_decls = lto_input_tree (ib, data_in);
 
+  /* Read all function arguments.  We need to re-map them here to the
+     arguments of the merged function declaration.  */
+  args = lto_input_tree (ib, data_in); 
+  for (oarg = args, narg = DECL_ARGUMENTS (fn_decl);
+       oarg && narg;
+       oarg = TREE_CHAIN (oarg), narg = TREE_CHAIN (narg))
+    {
+      int ix;
+      bool res;
+      res = lto_streamer_cache_lookup (data_in->reader_cache, oarg, &ix);
+      gcc_assert (res);
+      /* Replace the argument in the streamer cache.  */
+      lto_streamer_cache_insert_at (data_in->reader_cache, narg, ix);
+    }
+  gcc_assert (!oarg && !narg);
+
   /* Read all the SSA names.  */
   input_ssa_names (ib, data_in, fn);
 
@@ -1144,9 +1328,6 @@ input_function (tree fn_decl, struct data_in *data_in,
   gcc_assert (DECL_INITIAL (fn_decl));
   DECL_SAVED_TREE (fn_decl) = NULL_TREE;
 
-  /* Read all function arguments.  */
-  DECL_ARGUMENTS (fn_decl) = lto_input_tree (ib, data_in); 
-
   /* Read all the basic blocks.  */
   tag = input_record_start (ib);
   while (tag)
@@ -1178,9 +1359,13 @@ input_function (tree fn_decl, struct data_in *data_in,
     gimple_set_body (fn_decl, bb_seq (ei_edge (ei)->dest));
   }
 
-  fixup_call_stmt_edges (cgraph_node (fn_decl), stmts);
+  node = cgraph_node (fn_decl);
+  fixup_call_stmt_edges (node, stmts);
+  execute_all_ipa_stmt_fixups (node, stmts);
 
   update_ssa (TODO_update_ssa_only_virtuals); 
+  free_dominance_info (CDI_DOMINATORS);
+  free_dominance_info (CDI_POST_DOMINATORS);
   free (stmts);
 }
 
@@ -1477,6 +1662,7 @@ unpack_ts_decl_common_value_fields (struct bitpack_d *bp, tree expr)
       if (TREE_CODE (expr) == VAR_DECL
          || TREE_CODE (expr) == PARM_DECL)
        DECL_HAS_VALUE_EXPR_P (expr) = (unsigned) bp_unpack_value (bp, 1);
+      DECL_RESTRICTED_P (expr) = (unsigned) bp_unpack_value (bp, 1);
     }
 }