This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[lto plugin][patch] call gcc


This patch makes the plugin actually call gcc. Now we can compile some
simple examples passing by the plugin, but it has some problems. I am
not sure if I should commit it.

The code is mostly copied from collect2 and there is a lot more to
copy. Right now the plugin only supports local compilation and uses a
hardcoded temp file name.

I think we need another wrapper to share some code among the plugin
and collect2. In particular, the wrapper should

*) be called with the gcc to use and its arguments
*) figure out if we should use wpa or local lto
*) process the arguments (add -x flto for example)
*) run gcc
*) print a list of output files

Using this wrapper collect2 and the plugin would share a lot more
code. The diff to trunk's collect2 should also be reduced. Any
objections?

Yet another option that I haven't tested is for the plugin to call
collect2. For this to work collect2 would have to accept things like a
function being defined in two of its input files, since the plugin
could have extracted them from archives.

Cheers,
-- 
Rafael Avila de Espindola

Google | Gordon House | Barrow Street | Dublin 4 | Ireland
Registered in Dublin, Ireland | Registration Number: 368047
diff --git a/lto-plugin/lto-plugin.c b/lto-plugin/lto-plugin.c
index 9c0a640..8893352 100644
--- a/lto-plugin/lto-plugin.c
+++ b/lto-plugin/lto-plugin.c
@@ -36,6 +36,9 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
 #include <sys/stat.h>
 #include <unistd.h>
 #include <fcntl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <errno.h>
 
 #ifdef HAVE_GELF_H
 # include <gelf.h>
@@ -85,6 +88,10 @@ static ld_plugin_add_input_file add_input_file;
 static struct plugin_file_info *claimed_files = NULL;
 static unsigned int num_claimed_files = 0;
 
+static char *lto_gcc;
+static char **lto_gcc_argv;
+static int lto_gcc_num_args;
+
 /* Parse an entry of the IL symbol table. The data to be parsed is pointed
    by P and the result is written in ENTRY. The slot number is stored in SLOT.
    Returns the address of the next entry. */
@@ -288,23 +295,64 @@ write_resolution(void)
   fclose (f);
 }
 
+static void
+exec_gcc (const char *path, char *const argv[])
+{
+  int pid = fork ();
+  assert (pid >= 0);
+  if (pid == 0)
+    {
+      execv (path, argv);
+      perror ("error: ");
+      exit (1);
+    }
+  else
+    {
+      int status;
+      int p = wait (&status);
+      assert (p == pid);
+      assert (WIFEXITED (status) && WEXITSTATUS (status) == 0);
+    }
+}
+
 /* Called by the linker once all symbols have been read. */
 
 static enum ld_plugin_status
 all_symbols_read_handler (void)
 {
   unsigned i;
+  unsigned num_lto_args = num_claimed_files + lto_gcc_num_args + 7;
+  char **lto_argv = (char **) calloc (sizeof (char *), num_lto_args);
+  const char **lto_arg_ptr = (const char **) lto_argv;
+  assert (lto_gcc);
+
   free_1 ();
 
   write_resolution ();
 
+
+  *lto_arg_ptr++ = lto_gcc;
+  *lto_arg_ptr++ = "-combine";
+  *lto_arg_ptr++ = "-x";
+  *lto_arg_ptr++ = "lto";
+  *lto_arg_ptr++ = "-c";
+  *lto_arg_ptr++ = "-o";
+  *lto_arg_ptr++ = "temp.o"; /* FIXME: should use a temp file */
+
+  for (i = 0; i < lto_gcc_num_args; i++)
+    *lto_arg_ptr++ = lto_gcc_argv[i];
+
   for (i = 0; i < num_claimed_files; i++)
     {
       struct plugin_file_info *info = &claimed_files[i];
 
-      /* FIXME: actually run wpa :-) */
-      add_input_file (info->name);
+      *lto_arg_ptr++ = info->name;
     }
+
+  *lto_arg_ptr++ = NULL;
+  exec_gcc (lto_gcc, lto_argv);
+
+  add_input_file ("temp.o"); /* FIXME: should use a temp file */
   return LDPS_OK;
 }
 
@@ -420,6 +468,33 @@ claim_file_handler (const struct ld_plugin_input_file *file, int *claimed)
   return LDPS_OK;
 }
 
+static void
+process_option (const char *p)
+{
+  unsigned i;
+
+  assert (!lto_gcc);
+  assert (strncmp("gcc=", p, 4) == 0);
+  lto_gcc = strdup(p + 4);
+
+  for (i = 0; lto_gcc[i] != '\0'; i++)
+    if (lto_gcc[i] == ' ')
+      lto_gcc_num_args++;
+
+  lto_gcc_argv = (char **) calloc (sizeof (char *), lto_gcc_num_args);
+  char **lto_arg_ptr = (char **) lto_gcc_argv;
+
+  for (i = 0; lto_gcc[i] != '\0'; i++)
+    {
+      if (lto_gcc[i] == ' ')
+	{
+	  lto_gcc[i] = '\0';
+	  i++;
+	  *lto_arg_ptr++ = &lto_gcc[i];
+	}
+    }
+}
+
 /* Called by gold after loading the plugin. TV is the transfer vector. */
 
 void
@@ -455,6 +530,9 @@ onload (struct ld_plugin_tv *tv)
 	case LDPT_ADD_INPUT_FILE:
 	  add_input_file = p->tv_u.tv_add_input_file;
 	  break;
+	case LDPT_OPTION:
+	  process_option (p->tv_u.tv_string);
+	  break;
 	default:
 	  break;
 	}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]