OSDN Git Service

2010-02-10 Joost VandeVondele <jv244@cam.ac.uk>
[pf3gnuchains/gcc-fork.git] / gcc / lto / lto.c
index 9cb7d65..de53a09 100644 (file)
@@ -1,5 +1,5 @@
 /* Top-level LTO routines.
-   Copyright 2009 Free Software Foundation, Inc.
+   Copyright 2009, 2010 Free Software Foundation, Inc.
    Contributed by CodeSourcery, Inc.
 
 This file is part of GCC.
@@ -50,6 +50,14 @@ along with GCC; see the file COPYING3.  If not see
 #include <sys/mman.h>
 #endif
 
+/* Handle opening elf files on hosts, such as Windows, that may use 
+   text file handling that will break binary access.  */
+
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
+
+
 DEF_VEC_P(bitmap);
 DEF_VEC_ALLOC_P(bitmap,heap);
 
@@ -249,6 +257,28 @@ lto_read_decls (struct lto_file_decl_data *decl_data, const void *data,
   lto_data_in_delete (data_in);
 }
 
+/* strtoll is not portable. */
+int64_t
+lto_parse_hex (const char *p) {
+  uint64_t ret = 0;
+  for (; *p != '\0'; ++p)
+    {
+      char c = *p;
+      unsigned char part;
+      ret <<= 4;
+      if (c >= '0' && c <= '9')
+        part = c - '0';
+      else if (c >= 'a' && c <= 'f')
+        part = c - 'a' + 10;
+      else if (c >= 'A' && c <= 'F')
+        part = c - 'A' + 10;
+      else
+        internal_error ("could not parse hex number");
+      ret |= part;
+    }
+  return ret;
+}
+
 /* Read resolution for file named FILE_NAME. The resolution is read from
    RESOLUTION. An array with the symbol resolution is returned. The array
    size is written to SIZE. */
@@ -280,15 +310,12 @@ lto_resolution_read (FILE *resolution, lto_file *file)
   if (file->offset != 0)
     {
       int t;
-      char offset_p[21];
-      long long offset;
-      t = fscanf (resolution, "@%20s", offset_p);
+      char offset_p[17];
+      int64_t offset;
+      t = fscanf (resolution, "@0x%16s", offset_p);
       if (t != 1)
         internal_error ("could not parse file offset");
-      errno = 0;
-      offset = strtoll(offset_p, NULL, 10);
-      if (errno != 0)
-        internal_error ("could not parse file offset");
+      offset = lto_parse_hex (offset_p);
       if (offset != file->offset)
         internal_error ("unexpected offset");
     }
@@ -325,7 +352,7 @@ lto_resolution_read (FILE *resolution, lto_file *file)
        internal_error ("Invalid resolution in the resolution file.");
 
       VEC_safe_grow_cleared (ld_plugin_symbol_resolution_t, heap, ret,
-                            index + 1);
+                            max_index + 1);
       VEC_replace (ld_plugin_symbol_resolution_t, ret, index, r);
     }
 
@@ -402,7 +429,7 @@ lto_read_section_data (struct lto_file_decl_data *file_data,
   if (fd == -1)
     {
       fd_name = xstrdup (file_data->file_name);
-      fd = open (file_data->file_name, O_RDONLY);
+      fd = open (file_data->file_name, O_RDONLY|O_BINARY);
       if (fd == -1)
        return NULL;
     }
@@ -1050,6 +1077,8 @@ lto_wpa_write_files (void)
   return output_files;
 }
 
+/* Template of LTRANS dumpbase suffix.  */
+#define DUMPBASE_SUFFIX        ".ltrans18446744073709551615"
 
 /* Perform local transformations (LTRANS) on the files in the NULL-terminated
    FILES array.  These should have been written previously by
@@ -1069,6 +1098,8 @@ lto_execute_ltrans (char *const *files)
   int err;
   int status;
   FILE *ltrans_output_list_stream = NULL;
+  bool seen_dumpbase = false;
+  char *dumpbase_suffix = NULL;
 
   timevar_push (TV_WHOPR_WPA_LTRANS_EXEC);
 
@@ -1107,13 +1138,26 @@ lto_execute_ltrans (char *const *files)
          ++j;
        obstack_init (&env_obstack);
        obstack_grow (&env_obstack, &collect_gcc_options[i], j - i);
-       obstack_1grow (&env_obstack, 0);
+       if (seen_dumpbase)
+         obstack_grow (&env_obstack, DUMPBASE_SUFFIX,
+                       sizeof (DUMPBASE_SUFFIX));
+       else
+         obstack_1grow (&env_obstack, 0);
        option = XOBFINISH (&env_obstack, char *);
+       if (seen_dumpbase)
+         {
+           dumpbase_suffix = option + 7 + j - i;
+           seen_dumpbase = false;
+         }
 
        /* LTRANS does not need -fwpa nor -fltrans-*.  */
        if (strncmp (option, "-fwpa", 5) != 0
            && strncmp (option, "-fltrans-", 9) != 0)
-         *argv_ptr++ = option;
+         {
+           if (strncmp (option, "-dumpbase", 9) == 0)
+             seen_dumpbase = true;
+           *argv_ptr++ = option;
+         }
       }
   *argv_ptr++ = "-fltrans";
 
@@ -1171,6 +1215,11 @@ lto_execute_ltrans (char *const *files)
          argv_ptr[2] = files[i];
          argv_ptr[3] = NULL;
 
+         /* Append a sequence number to -dumpbase for LTRANS.  */
+         if (dumpbase_suffix)
+           snprintf (dumpbase_suffix, sizeof (DUMPBASE_SUFFIX) - 7,
+                     "%lu", (unsigned long) i);
+
          /* Execute the driver.  */
          pex = pex_init (0, "lto1", NULL);
          if (pex == NULL)
@@ -1357,7 +1406,7 @@ static void
 lto_fixup_field_decl (tree t, void *data)
 {
   lto_fixup_decl_common (t, data);
-  gcc_assert (no_fixup_p (DECL_FIELD_OFFSET (t)));
+  LTO_FIXUP_SUBTREE (DECL_FIELD_OFFSET (t));
   LTO_FIXUP_SUBTREE (DECL_BIT_FIELD_TYPE (t));
   LTO_FIXUP_SUBTREE (DECL_QUALIFIER (t));
   gcc_assert (no_fixup_p (DECL_FIELD_BIT_OFFSET (t)));