OSDN Git Service

2014-04-04 Richard Biener <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / gcc.c
index 0fd4edd..939dcc8 100644 (file)
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -1,7 +1,7 @@
 /* Compiler driver program that can handle many languages.
    Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
    1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
-   2010, 2011
+   2010, 2011, 2012
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -267,6 +267,7 @@ static const char *compare_debug_dump_opt_spec_function (int, const char **);
 static const char *compare_debug_self_opt_spec_function (int, const char **);
 static const char *compare_debug_auxbase_opt_spec_function (int, const char **);
 static const char *pass_through_libs_spec_func (int, const char **);
+static char *convert_white_space (char *);
 \f
 /* The Specs Language
 
@@ -675,6 +676,7 @@ proper position among the other output files.  */
     %{s} %{t} %{u*} %{z} %{Z} %{!nostdlib:%{!nostartfiles:%S}}\
     %{static:} %{L*} %(mfwrap) %(link_libgcc) %o\
     %{fopenmp|ftree-parallelize-loops=*:%:include(libgomp.spec)%(link_gomp)}\
+    %{fgnu-tm:%:include(libitm.spec)%(link_itm)}\
     %(mflib) " STACK_SPLIT_SPEC "\
     %{fprofile-arcs|fprofile-generate*|coverage:-lgcov}\
     %{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}\
@@ -839,9 +841,14 @@ static const char *const multilib_defaults_raw[] = MULTILIB_DEFAULTS;
 #define GOMP_SELF_SPECS "%{fopenmp|ftree-parallelize-loops=*: -pthread}"
 #endif
 
+/* Likewise for -fgnu-tm.  */
+#ifndef GTM_SELF_SPECS
+#define GTM_SELF_SPECS "%{fgnu-tm: -pthread}"
+#endif
+
 static const char *const driver_self_specs[] = {
   "%{fdump-final-insns:-fdump-final-insns=.} %<fdump-final-insns",
-  DRIVER_SELF_SPECS, CONFIGURE_SPECS, GOMP_SELF_SPECS
+  DRIVER_SELF_SPECS, CONFIGURE_SPECS, GOMP_SELF_SPECS, GTM_SELF_SPECS
 };
 
 #ifndef OPTION_DEFAULT_SPECS
@@ -1147,6 +1154,11 @@ static const char *multilib_dir;
    set_multilib_dir based on the compilation options.  */
 
 static const char *multilib_os_dir;
+
+/* Subdirectory to use for locating libraries in multiarch conventions.  Set by
+   set_multilib_dir based on the compilation options.  */
+
+static const char *multiarch_dir;
 \f
 /* Structure to keep track of the specs that have been defined so far.
    These are accessed using %(specname) in a compiler or link
@@ -2072,6 +2084,7 @@ for_each_path (const struct path_prefix *paths,
   struct prefix_list *pl;
   const char *multi_dir = NULL;
   const char *multi_os_dir = NULL;
+  const char *multiarch_suffix = NULL;
   const char *multi_suffix;
   const char *just_multi_suffix;
   char *path = NULL;
@@ -2089,11 +2102,14 @@ for_each_path (const struct path_prefix *paths,
     }
   if (do_multi && multilib_os_dir && strcmp (multilib_os_dir, ".") != 0)
     multi_os_dir = concat (multilib_os_dir, dir_separator_str, NULL);
+  if (multiarch_dir)
+    multiarch_suffix = concat (multiarch_dir, dir_separator_str, NULL);
 
   while (1)
     {
       size_t multi_dir_len = 0;
       size_t multi_os_dir_len = 0;
+      size_t multiarch_len = 0;
       size_t suffix_len;
       size_t just_suffix_len;
       size_t len;
@@ -2102,16 +2118,15 @@ for_each_path (const struct path_prefix *paths,
        multi_dir_len = strlen (multi_dir);
       if (multi_os_dir)
        multi_os_dir_len = strlen (multi_os_dir);
+      if (multiarch_suffix)
+       multiarch_len = strlen (multiarch_suffix);
       suffix_len = strlen (multi_suffix);
       just_suffix_len = strlen (just_multi_suffix);
 
       if (path == NULL)
        {
          len = paths->max_len + extra_space + 1;
-         if (suffix_len > multi_os_dir_len)
-           len += suffix_len;
-         else
-           len += multi_os_dir_len;
+         len += MAX (MAX (suffix_len, multi_os_dir_len), multiarch_len);
          path = XNEWVEC (char, len);
        }
 
@@ -2140,6 +2155,16 @@ for_each_path (const struct path_prefix *paths,
                break;
            }
 
+         /* Now try the multiarch path.  */
+         if (!skip_multi_dir
+             && !pl->require_machine_suffix && multiarch_dir)
+           {
+             memcpy (path + len, multiarch_suffix, multiarch_len + 1);
+             ret = callback (path, callback_info);
+             if (ret)
+               break;
+           }
+
          /* Now try the base path.  */
          if (!pl->require_machine_suffix
              && !(pl->os_multilib ? skip_multi_os_dir : skip_multi_dir))
@@ -2445,9 +2470,17 @@ add_sysrooted_prefix (struct path_prefix *pprefix, const char *prefix,
 
   if (target_system_root)
     {
+      char *sysroot_no_trailing_dir_separator = xstrdup (target_system_root);
+      size_t sysroot_len = strlen (target_system_root);
+
+      if (sysroot_len > 0
+         && target_system_root[sysroot_len - 1] == DIR_SEPARATOR)
+       sysroot_no_trailing_dir_separator[sysroot_len - 1] = '\0';
+
       if (target_sysroot_suffix)
          prefix = concat (target_sysroot_suffix, prefix, NULL);
-      prefix = concat (target_system_root, prefix, NULL);
+      prefix = concat (sysroot_no_trailing_dir_separator, prefix, NULL);
+      free (sysroot_no_trailing_dir_separator);
 
       /* We have to override this because GCC's notion of sysroot
         moves along with GCC.  */
@@ -2944,7 +2977,7 @@ display_help (void)
   fputs (_("  -pass-exit-codes         Exit with highest error code from a phase\n"), stdout);
   fputs (_("  --help                   Display this information\n"), stdout);
   fputs (_("  --target-help            Display target specific command line options\n"), stdout);
-  fputs (_("  --help={target|optimizers|warnings|params|[^]{joined|separate|undocumented}}[,...]\n"), stdout);
+  fputs (_("  --help={common|optimizers|params|target|warnings|[^]{joined|separate|undocumented}}[,...]\n"), stdout);
   fputs (_("                           Display specific types of command line options\n"), stdout);
   if (! verbose_flag)
     fputs (_("  (Use '-v --help' to display command line options of sub-processes)\n"), stdout);
@@ -2956,6 +2989,9 @@ display_help (void)
   fputs (_("  -print-libgcc-file-name  Display the name of the compiler's companion library\n"), stdout);
   fputs (_("  -print-file-name=<lib>   Display the full path to library <lib>\n"), stdout);
   fputs (_("  -print-prog-name=<prog>  Display the full path to compiler component <prog>\n"), stdout);
+  fputs (_("\
+  -print-multiarch         Display the target's normalized GNU triplet, used as\n\
+                           a component in the library path\n"), stdout);
   fputs (_("  -print-multi-directory   Display the root directory for versions of libgcc\n"), stdout);
   fputs (_("\
   -print-multi-lib         Display the mapping between command line options and\n\
@@ -2988,6 +3024,8 @@ display_help (void)
   fputs (_("  -S                       Compile only; do not assemble or link\n"), stdout);
   fputs (_("  -c                       Compile and assemble, but do not link\n"), stdout);
   fputs (_("  -o <file>                Place the output into <file>\n"), stdout);
+  fputs (_("  -pie                     Create a position independent executable\n"), stdout);
+  fputs (_("  -shared                  Create a shared library\n"), stdout);
   fputs (_("\
   -x <language>            Specify the language of the following input files\n\
                            Permissible languages include: c c++ assembler none\n\
@@ -3137,16 +3175,6 @@ driver_wrong_lang_callback (const struct cl_decoded_option *decoded,
                 &decoded->canonical_option[1], false);
 }
 
-/* Note that an option (index OPT_INDEX, argument ARG, value VALUE)
-   has been successfully handled with a handler for mask MASK.  */
-
-static void
-driver_post_handling_callback (const struct cl_decoded_option *decoded ATTRIBUTE_UNUSED,
-                              unsigned int mask ATTRIBUTE_UNUSED)
-{
-  /* Nothing to do here.  */
-}
-
 static const char *spec_lang = 0;
 static int last_language_n_infiles;
 
@@ -3238,6 +3266,7 @@ driver_handle_option (struct gcc_options *opts,
     case OPT_print_multi_directory:
     case OPT_print_sysroot:
     case OPT_print_multi_os_directory:
+    case OPT_print_multiarch:
     case OPT_print_sysroot_headers_suffix:
     case OPT_time:
     case OPT_wrapper:
@@ -3533,7 +3562,6 @@ set_option_handlers (struct cl_option_handlers *handlers)
 {
   handlers->unknown_option_callback = driver_unknown_option_callback;
   handlers->wrong_lang_callback = driver_wrong_lang_callback;
-  handlers->post_handling_callback = driver_post_handling_callback;
   handlers->num_handlers = 3;
   handlers->handlers[0].handler = driver_handle_option;
   handlers->handlers[0].mask = CL_DRIVER;
@@ -4891,6 +4919,15 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
                  do_spec_1 (" ", 0, NULL);
                }
 
+             if (multiarch_dir)
+               {
+                 do_spec_1 ("-imultiarch", 1, NULL);
+                 /* Make this a separate argument.  */
+                 do_spec_1 (" ", 0, NULL);
+                 do_spec_1 (multiarch_dir, 1, NULL);
+                 do_spec_1 (" ", 0, NULL);
+               }
+
              if (gcc_exec_prefix)
                {
                  do_spec_1 ("-iprefix", 1, NULL);
@@ -5456,6 +5493,21 @@ switch_matches (const char *atom, const char *end_atom, int starred)
        && check_live_switch (i, plen))
       return true;
 
+    /* Check if a switch with separated form matching the atom.
+       We check -D and -U switches. */
+    else if (switches[i].args != 0)
+      {
+       if ((*switches[i].part1 == 'D' || *switches[i].part1 == 'U')
+           && *switches[i].part1 == atom[0])
+         {
+           if (!strncmp (switches[i].args[0], &atom[1], len - 1)
+               && (starred || (switches[i].part1[1] == '\0'
+                               && switches[i].args[0][len - 1] == '\0'))
+               && check_live_switch (i, (starred ? 1 : -1)))
+             return true;
+         }
+      }
+
   return false;
 }
 
@@ -6448,9 +6500,14 @@ main (int argc, char **argv)
 
   /* Set up to remember the pathname of the lto wrapper. */
 
-  lto_wrapper_file = find_a_file (&exec_prefixes, "lto-wrapper", X_OK, false);
+  if (have_c)
+    lto_wrapper_file = NULL;
+  else
+    lto_wrapper_file = find_a_file (&exec_prefixes, "lto-wrapper",
+                                   X_OK, false);
   if (lto_wrapper_file)
     {
+      lto_wrapper_file = convert_white_space (lto_wrapper_file);
       lto_wrapper_spec = lto_wrapper_file;
       obstack_init (&collect_obstack);
       obstack_grow (&collect_obstack, "COLLECT_LTO_WRAPPER=",
@@ -6508,6 +6565,15 @@ main (int argc, char **argv)
       return (0);
     }
 
+  if (print_multiarch)
+    {
+      if (multiarch_dir == NULL)
+       printf ("\n");
+      else
+       printf ("%s\n", multiarch_dir);
+      return (0);
+    }
+
   if (print_sysroot)
     {
       if (target_system_root)
@@ -6568,7 +6634,7 @@ main (int argc, char **argv)
     {
       printf (_("%s %s%s\n"), progname, pkgversion_string,
              version_string);
-      printf ("Copyright %s 2011 Free Software Foundation, Inc.\n",
+      printf ("Copyright %s 2012 Free Software Foundation, Inc.\n",
              _("(C)"));
       fputs (_("This is free software; see the source for copying conditions.  There is NO\n\
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"),
@@ -6822,39 +6888,47 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"
   if (num_linker_inputs > 0 && !seen_error () && print_subprocess_help < 2)
     {
       int tmp = execution_count;
+
+      if (! have_c)
+       {
 #if HAVE_LTO_PLUGIN > 0
 #if HAVE_LTO_PLUGIN == 2
-      const char *fno_use_linker_plugin = "fno-use-linker-plugin";
+         const char *fno_use_linker_plugin = "fno-use-linker-plugin";
 #else
-      const char *fuse_linker_plugin = "fuse-linker-plugin";
+         const char *fuse_linker_plugin = "fuse-linker-plugin";
 #endif
 #endif
 
-      /* We'll use ld if we can't find collect2.  */
-      if (! strcmp (linker_name_spec, "collect2"))
-       {
-         char *s = find_a_file (&exec_prefixes, "collect2", X_OK, false);
-         if (s == NULL)
-           linker_name_spec = "ld";
-       }
+         /* We'll use ld if we can't find collect2.  */
+         if (! strcmp (linker_name_spec, "collect2"))
+           {
+             char *s = find_a_file (&exec_prefixes, "collect2", X_OK, false);
+             if (s == NULL)
+               linker_name_spec = "ld";
+           }
 
 #if HAVE_LTO_PLUGIN > 0
 #if HAVE_LTO_PLUGIN == 2
-      if (!switch_matches (fno_use_linker_plugin,
-                          fno_use_linker_plugin + strlen (fno_use_linker_plugin), 0))
+         if (!switch_matches (fno_use_linker_plugin,
+                              fno_use_linker_plugin
+                              + strlen (fno_use_linker_plugin), 0))
 #else
-      if (switch_matches (fuse_linker_plugin,
-                         fuse_linker_plugin + strlen (fuse_linker_plugin), 0))
+         if (switch_matches (fuse_linker_plugin,
+                             fuse_linker_plugin
+                             + strlen (fuse_linker_plugin), 0))
 #endif
-       {
-         linker_plugin_file_spec = find_a_file (&exec_prefixes,
-                                                LTOPLUGINSONAME, R_OK,
-                                                false);
-         if (!linker_plugin_file_spec)
-           fatal_error ("-fuse-linker-plugin, but %s not found", LTOPLUGINSONAME);
-       }
+           {
+             char *temp_spec = find_a_file (&exec_prefixes,
+                                            LTOPLUGINSONAME, R_OK,
+                                            false);
+             if (!temp_spec)
+               fatal_error ("-fuse-linker-plugin, but %s not found",
+                            LTOPLUGINSONAME);
+             linker_plugin_file_spec = convert_white_space (temp_spec);
+           }
 #endif
-      lto_gcc_spec = argv[0];
+         lto_gcc_spec = argv[0];
+       }
 
       /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
         for collect.  */
@@ -7271,7 +7345,9 @@ default_arg (const char *p, int len)
    options are present, then we will ignore this completely. Passing
    that, gcc will consider each multilib_select in turn using the same
    rules for matching the options. If a match is found, that subdirectory
-   will be used.  */
+   will be used.
+   A subdirectory name is optionally followed by a colon and the corresponding
+   multiarch name.  */
 
 static void
 set_multilib_dir (void)
@@ -7483,10 +7559,25 @@ set_multilib_dir (void)
            q++;
          if (q < end)
            {
-             char *new_multilib_os_dir = XNEWVEC (char, end - q);
-             memcpy (new_multilib_os_dir, q + 1, end - q - 1);
-             new_multilib_os_dir[end - q - 1] = '\0';
-             multilib_os_dir = new_multilib_os_dir;
+             const char *q2 = q + 1, *ml_end = end;
+             char *new_multilib_os_dir;
+
+             while (q2 < end && *q2 != ':')
+               q2++;
+             if (*q2 == ':')
+               ml_end = q2;
+             new_multilib_os_dir = XNEWVEC (char, ml_end - q);
+             memcpy (new_multilib_os_dir, q + 1, ml_end - q - 1);
+             new_multilib_os_dir[ml_end - q - 1] = '\0';
+             multilib_os_dir = *new_multilib_os_dir ? new_multilib_os_dir : ".";
+
+             if (q2 < end && *q2 == ':')
+               {
+                 char *new_multiarch_dir = XNEWVEC (char, end - q2);
+                 memcpy (new_multiarch_dir, q2 + 1, end - q2 - 1);
+                 new_multiarch_dir[end - q2 - 1] = '\0';
+                 multiarch_dir = new_multiarch_dir;
+               }
              break;
            }
        }
@@ -7546,9 +7637,10 @@ print_multilib_info (void)
        }
 
       /* When --disable-multilib was used but target defines
-        MULTILIB_OSDIRNAMES, entries starting with .: are there just
-        to find multilib_os_dir, so skip them from output.  */
-      if (this_path[0] == '.' && this_path[1] == ':')
+        MULTILIB_OSDIRNAMES, entries starting with .: (and not starting
+         with .:: for multiarch configurations) are there just to find
+         multilib_os_dir, so skip them from output.  */
+      if (this_path[0] == '.' && this_path[1] == ':' && this_path[2] != ':')
        skip = 1;
 
       /* Check for matches with the multilib_exclusions. We don't bother
@@ -8287,3 +8379,51 @@ pass_through_libs_spec_func (int argc, const char **argv)
     }
   return prepended;
 }
+
+/* Insert backslash before spaces in ORIG (usually a file path), to 
+   avoid being broken by spec parser.
+
+   This function is needed as do_spec_1 treats white space (' ' and '\t')
+   as the end of an argument. But in case of -plugin /usr/gcc install/xxx.so,
+   the file name should be treated as a single argument rather than being
+   broken into multiple. Solution is to insert '\\' before the space in a 
+   file name.
+   
+   This function converts and only converts all occurrence of ' ' 
+   to '\\' + ' ' and '\t' to '\\' + '\t'.  For example:
+   "a b"  -> "a\\ b"
+   "a  b" -> "a\\ \\ b"
+   "a\tb" -> "a\\\tb"
+   "a\\ b" -> "a\\\\ b"
+
+   orig: input null-terminating string that was allocated by xalloc. The
+   memory it points to might be freed in this function. Behavior undefined
+   if ORIG wasn't xalloced or was freed already at entry.
+
+   Return: ORIG if no conversion needed. Otherwise a newly allocated string
+   that was converted from ORIG.  */
+
+static char *
+convert_white_space (char *orig)
+{
+  int len, number_of_space = 0;
+
+  for (len = 0; orig[len]; len++)
+    if (orig[len] == ' ' || orig[len] == '\t') number_of_space++;
+
+  if (number_of_space)
+    {
+      char *new_spec = (char *) xmalloc (len + number_of_space + 1);
+      int j, k;
+      for (j = 0, k = 0; j <= len; j++, k++)
+       {
+         if (orig[j] == ' ' || orig[j] == '\t')
+           new_spec[k++] = '\\';
+         new_spec[k] = orig[j];
+       }
+      free (orig);
+      return new_spec;
+  }
+  else
+    return orig;
+}