/* 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.
#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);
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. */
static VEC(ld_plugin_symbol_resolution_t,heap) *
-lto_resolution_read (FILE *resolution, const char *file_name)
+lto_resolution_read (FILE *resolution, lto_file *file)
{
/* We require that objects in the resolution file are in the same
order as the lto1 command line. */
if (!resolution)
return NULL;
- name_len = strlen (file_name);
+ name_len = strlen (file->filename);
obj_name = XNEWVEC (char, name_len + 1);
fscanf (resolution, " "); /* Read white space. */
fread (obj_name, sizeof (char), name_len, resolution);
obj_name[name_len] = '\0';
- if (strcmp (obj_name, file_name) != 0)
+ if (strcmp (obj_name, file->filename) != 0)
internal_error ("unexpected file name %s in linker resolution file. "
- "Expected %s", obj_name, file_name);
+ "Expected %s", obj_name, file->filename);
+ if (file->offset != 0)
+ {
+ int t;
+ char offset_p[17];
+ int64_t offset;
+ t = fscanf (resolution, "@0x%16s", offset_p);
+ if (t != 1)
+ internal_error ("could not parse file offset");
+ offset = lto_parse_hex (offset_p);
+ if (offset != file->offset)
+ internal_error ("unexpected offset");
+ }
free (obj_name);
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);
}
size_t len;
VEC(ld_plugin_symbol_resolution_t,heap) *resolutions;
- resolutions = lto_resolution_read (resolution_file, file->filename);
+ resolutions = lto_resolution_read (resolution_file, file);
file_data = XCNEW (struct lto_file_decl_data);
file_data->file_name = file->filename;
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;
}
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
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);
++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";
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)
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)));
phase. */
if (flag_ltrans)
for (node = cgraph_nodes; node; node = node->next)
- if (!node->global.inlined_to
- && cgraph_decide_is_function_needed (node, node->decl))
- cgraph_mark_needed_node (node);
+ {
+ if (!node->global.inlined_to
+ && cgraph_decide_is_function_needed (node, node->decl))
+ cgraph_mark_needed_node (node);
+ /* FIXME: ipa_transforms_to_apply holds list of passes that have optimization
+ summaries computed and needs to apply changes. At the moment WHOPR only
+ supports inlining, so we can push it here by hand. In future we need to stream
+ this field into ltrans compilation. */
+ if (node->analyzed)
+ VEC_safe_push (ipa_opt_pass, heap,
+ node->ipa_transforms_to_apply,
+ (ipa_opt_pass)&pass_ipa_inline);
+ }
timevar_push (TV_IPA_LTO_DECL_IO);