This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[lto plugin][patch] call gcc
- From: Rafael Espindola <espindola at google dot com>
- To: gcc-patches <gcc-patches at gcc dot gnu dot org>
- Cc: Diego Novillo <dnovillo at google dot com>, Ollie Wild <aaw at google dot com>
- Date: Wed, 26 Nov 2008 16:53:31 +0000
- Subject: [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++ = <o_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;
}