OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [lto-wrapper.c] - Blame information for rev 328

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 280 jeremybenn
/* Wrapper to call lto.  Used by collect2 and the linker plugin.
2
   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
3
 
4
   Factored out of collect2 by Rafael Espindola <espindola@google.com>
5
 
6
This file is part of GCC.
7
 
8
GCC is free software; you can redistribute it and/or modify it under
9
the terms of the GNU General Public License as published by the Free
10
Software Foundation; either version 3, or (at your option) any later
11
version.
12
 
13
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14
WARRANTY; without even the implied warranty of MERCHANTABILITY or
15
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16
for more details.
17
 
18
You should have received a copy of the GNU General Public License
19
along with GCC; see the file COPYING3.  If not see
20
<http://www.gnu.org/licenses/>.  */
21
 
22
 
23
/* This program is passed a gcc, a list of gcc arguments and a list of
24
   object files containing IL. It scans the argument list to check if
25
   we are in whopr mode or not modifies the arguments and needed and
26
   prints a list of output files on stdout.
27
 
28
   Example:
29
 
30
   $ lto-wrapper gcc/xgcc -B gcc a.o b.o -o test -flto
31
 
32
   The above will print something like
33
   /tmp/ccwbQ8B2.lto.o
34
 
35
   If -fwhopr is used instead, more than one file might be produced
36
   ./ccXj2DTk.lto.ltrans.o
37
   ./ccCJuXGv.lto.ltrans.o
38
*/
39
 
40
#include "config.h"
41
#include "system.h"
42
#include "coretypes.h"
43
#include "tm.h"
44
#include "intl.h"
45
#include "libiberty.h"
46
 
47
int debug;                              /* true if -debug */
48
 
49
enum lto_mode_d {
50
  LTO_MODE_NONE,                        /* Not doing LTO. */
51
  LTO_MODE_LTO,                         /* Normal LTO. */
52
  LTO_MODE_WHOPR                        /* WHOPR. */
53
};
54
 
55
/* Current LTO mode.  */
56
static enum lto_mode_d lto_mode = LTO_MODE_NONE;
57
 
58
static char *ltrans_output_file;
59
static char *flto_out;
60
static char *args_name;
61
 
62
static void maybe_unlink_file (const char *);
63
 
64
/* Delete tempfiles and exit function.  */
65
 
66
static void
67
lto_wrapper_exit (int status)
68
{
69
  static bool cleanup_done = false;
70
  if (!cleanup_done)
71
    {
72
      /* Setting cleanup_done prevents an infinite loop if one of the
73
         calls to maybe_unlink_file fails. */
74
      cleanup_done = true;
75
 
76
      if (ltrans_output_file)
77
        maybe_unlink_file (ltrans_output_file);
78
      if (flto_out)
79
        maybe_unlink_file (flto_out);
80
      if (args_name)
81
        maybe_unlink_file (args_name);
82
    }
83
  exit (status);
84
}
85
 
86
/* Just die. CMSGID is the error message. */
87
 
88
static void __attribute__ ((format (printf, 1, 2)))
89
fatal (const char * cmsgid, ...)
90
{
91
  va_list ap;
92
 
93
  va_start (ap, cmsgid);
94
  fprintf (stderr, "lto-wrapper: ");
95
  vfprintf (stderr, _(cmsgid), ap);
96
  fprintf (stderr, "\n");
97
  va_end (ap);
98
 
99
  lto_wrapper_exit (FATAL_EXIT_CODE);
100
}
101
 
102
 
103
/* Die when sys call fails. CMSGID is the error message.  */
104
 
105
static void __attribute__ ((format (printf, 1, 2)))
106
fatal_perror (const char *cmsgid, ...)
107
{
108
  int e = errno;
109
  va_list ap;
110
 
111
  va_start (ap, cmsgid);
112
  fprintf (stderr, "lto-wrapper: ");
113
  vfprintf (stderr, _(cmsgid), ap);
114
  fprintf (stderr, ": %s\n", xstrerror (e));
115
  va_end (ap);
116
 
117
  lto_wrapper_exit (FATAL_EXIT_CODE);
118
}
119
 
120
 
121
/* Execute a program, and wait for the reply. ARGV are the arguments. The
122
   last one must be NULL. */
123
 
124
static struct pex_obj *
125
collect_execute (char **argv)
126
{
127
  struct pex_obj *pex;
128
  const char *errmsg;
129
  int err;
130
 
131
  if (debug)
132
    {
133
      char **p_argv;
134
      const char *str;
135
 
136
      for (p_argv = argv; (str = *p_argv) != (char *) 0; p_argv++)
137
        fprintf (stderr, " %s", str);
138
 
139
      fprintf (stderr, "\n");
140
    }
141
 
142
  fflush (stdout);
143
  fflush (stderr);
144
 
145
  pex = pex_init (0, "lto-wrapper", NULL);
146
  if (pex == NULL)
147
    fatal_perror ("pex_init failed");
148
 
149
  errmsg = pex_run (pex, PEX_LAST | PEX_SEARCH, argv[0], argv, NULL,
150
                    NULL, &err);
151
  if (errmsg != NULL)
152
    {
153
      if (err != 0)
154
        {
155
          errno = err;
156
          fatal_perror (errmsg);
157
        }
158
      else
159
        fatal (errmsg);
160
    }
161
 
162
  return pex;
163
}
164
 
165
 
166
/* Wait for a process to finish, and exit if a nonzero status is found.
167
   PROG is the program name. PEX is the process we should wait for. */
168
 
169
static int
170
collect_wait (const char *prog, struct pex_obj *pex)
171
{
172
  int status;
173
 
174
  if (!pex_get_status (pex, 1, &status))
175
    fatal_perror ("can't get program status");
176
  pex_free (pex);
177
 
178
  if (status)
179
    {
180
      if (WIFSIGNALED (status))
181
        {
182
          int sig = WTERMSIG (status);
183
          if (WCOREDUMP (status))
184
            fatal ("%s terminated with signal %d [%s], core dumped",
185
                   prog, sig, strsignal (sig));
186
          else
187
            fatal ("%s terminated with signal %d [%s]",
188
                   prog, sig, strsignal (sig));
189
        }
190
 
191
      if (WIFEXITED (status))
192
        fatal ("%s returned %d exit status", prog, WEXITSTATUS (status));
193
    }
194
 
195
  return 0;
196
}
197
 
198
 
199
/* Unlink a temporary LTRANS file unless requested otherwise.  */
200
 
201
static void
202
maybe_unlink_file (const char *file)
203
{
204
  if (! debug)
205
    {
206
      if (unlink_if_ordinary (file))
207
        fatal_perror ("deleting LTRANS file %s", file);
208
    }
209
  else
210
    fprintf (stderr, "[Leaving LTRANS %s]\n", file);
211
}
212
 
213
 
214
/* Execute program ARGV[0] with arguments ARGV. Wait for it to finish.  */
215
 
216
static void
217
fork_execute (char **argv)
218
{
219
  struct pex_obj *pex;
220
  char *new_argv[3];
221
  char *at_args;
222
  FILE *args;
223
  int status;
224
 
225
  args_name = make_temp_file (".args");
226
  at_args = concat ("@", args_name, NULL);
227
  args = fopen (args_name, "w");
228
  if (args == NULL)
229
    fatal ("failed to open %s", args_name);
230
 
231
  status = writeargv (&argv[1], args);
232
 
233
  if (status)
234
    fatal ("could not write to temporary file %s",  args_name);
235
 
236
  fclose (args);
237
 
238
  new_argv[0] = argv[0];
239
  new_argv[1] = at_args;
240
  new_argv[2] = NULL;
241
 
242
  pex = collect_execute (new_argv);
243
  collect_wait (new_argv[0], pex);
244
 
245
  maybe_unlink_file (args_name);
246
  free (at_args);
247
}
248
 
249
 
250
/* Execute gcc. ARGC is the number of arguments. ARGV contains the arguments. */
251
 
252
static void
253
run_gcc (unsigned argc, char *argv[])
254
{
255
  unsigned i;
256
  unsigned new_argc = argc;
257
  const char **new_argv;
258
  const char **argv_ptr;
259
  char *list_option_full = NULL;
260
 
261
  new_argc += 12;
262
  new_argv = (const char **) xcalloc (sizeof (char *), new_argc);
263
 
264
  argv_ptr = new_argv;
265
 
266
  *argv_ptr++ = argv[0];
267
  *argv_ptr++ = "-combine";
268
  *argv_ptr++ = "-x";
269
  *argv_ptr++ = "lto";
270
  *argv_ptr++ = "-c";
271
  if (lto_mode == LTO_MODE_LTO)
272
    {
273
      flto_out = make_temp_file (".lto.o");
274
      *argv_ptr++ = "-o";
275
      *argv_ptr++ = flto_out;
276
    }
277
  else if (lto_mode == LTO_MODE_WHOPR)
278
    {
279
      const char *list_option = "-fltrans-output-list=";
280
      size_t list_option_len = strlen (list_option);
281
      char *tmp;
282
 
283
      ltrans_output_file = make_temp_file (".ltrans.out");
284
      list_option_full = (char *) xmalloc (sizeof (char) *
285
                         (strlen (ltrans_output_file) + list_option_len + 1));
286
      tmp = list_option_full;
287
 
288
      *argv_ptr++ = tmp;
289
      strcpy (tmp, list_option);
290
      tmp += list_option_len;
291
      strcpy (tmp, ltrans_output_file);
292
 
293
      *argv_ptr++ = "-fwpa";
294
    }
295
  else
296
    fatal ("invalid LTO mode");
297
 
298
  /* Add inherited GCC options to the LTO back end command line.
299
     Filter out some obviously inappropriate options that will
300
     conflict with  the options that we force above.  We pass
301
     all of the remaining options on to LTO, and let it complain
302
     about any it doesn't like. Note that we invoke LTO via the
303
     `gcc' driver, so the usual option processing takes place.
304
     Except for `-flto' and `-fwhopr', we should only filter options that
305
     are meaningful to `ld', lest an option go silently unclaimed.  */
306
  for (i = 1; i < argc; i++)
307
    {
308
      const char *s = argv[i];
309
 
310
      if (strcmp (s, "-flto") == 0 || strcmp (s, "-fwhopr") == 0)
311
        /* We've handled this LTO option, don't pass it on.  */
312
        ;
313
      else if (*s == '-' && s[1] == 'o')
314
        {
315
          /* Drop `-o' and its filename argument.  We will use a
316
             temporary file for the LTO output.  The `-o' option
317
             will be interpreted by the linker.  */
318
          if (s[2] == '\0')
319
            {
320
              char *output_dir, *base, *name;
321
 
322
              i++;
323
              output_dir = xstrdup (argv[i]);
324
              base = output_dir;
325
              for (name = base; *name; name++)
326
                if (IS_DIR_SEPARATOR (*name))
327
                  base = name + 1;
328
              *base = '\0';
329
 
330
              *argv_ptr++ = "-dumpbase";
331
              if (*output_dir == '\0')
332
                {
333
                  static char current_dir[] =
334
                    { '.', DIR_SEPARATOR, '\0' };
335
                  output_dir = current_dir;
336
                  *argv_ptr++ = argv[i];
337
                }
338
              else
339
                *argv_ptr++ = &argv[i][base - output_dir];
340
 
341
              *argv_ptr++ = "-dumpdir";
342
              *argv_ptr++ = output_dir;
343
            }
344
        }
345
      else
346
        /* Pass the option or argument to LTO.  */
347
        *argv_ptr++ = s;
348
    }
349
 
350
  *argv_ptr = NULL;
351
 
352
  fork_execute (CONST_CAST (char **, new_argv));
353
  free (new_argv);
354
  new_argv = NULL;
355
 
356
  if (lto_mode == LTO_MODE_LTO)
357
    {
358
      printf("%s\n", flto_out);
359
      free (flto_out);
360
      flto_out = NULL;
361
    }
362
  else if (lto_mode == LTO_MODE_WHOPR)
363
    {
364
      FILE *stream = fopen (ltrans_output_file, "r");
365
      int c;
366
 
367
      if (!stream)
368
        fatal_perror ("fopen: %s", ltrans_output_file);
369
 
370
      while ((c = getc (stream)) != EOF)
371
        putc (c, stdout);
372
      fclose (stream);
373
      maybe_unlink_file (ltrans_output_file);
374
      free (list_option_full);
375
    }
376
  else
377
    fatal ("invalid LTO mode");
378
}
379
 
380
 
381
/* Parse the command line. Copy any unused argument to GCC_ARGV. ARGC is the
382
   number of arguments. ARGV contains the arguments. */
383
 
384
static int
385
process_args (int argc, char *argv[], char *gcc_argv[])
386
{
387
  int i;
388
  int j = 0;
389
 
390
  for (i = 1; i < argc; i ++)
391
    {
392
      if (! strcmp (argv[i], "-debug"))
393
        debug = 1;
394
      else if (! strcmp (argv[i], "-flto"))
395
        lto_mode = LTO_MODE_LTO;
396
      else if (! strcmp (argv[i], "-fwhopr"))
397
        lto_mode = LTO_MODE_WHOPR;
398
      else
399
        {
400
          gcc_argv[j] = argv[i];
401
          j++;
402
        }
403
    }
404
 
405
  return j;
406
}
407
 
408
 
409
/* Entry point.  */
410
 
411
int
412
main (int argc, char *argv[])
413
{
414
  char **gcc_argv;
415
  int gcc_argc;
416
 
417
  gcc_init_libintl ();
418
 
419
  /* We may be called with all the arguments stored in some file and
420
     passed with @file.  Expand them into argv before processing.  */
421
  expandargv (&argc, &argv);
422
  gcc_argv = (char **) xcalloc (sizeof (char *), argc);
423
  gcc_argc = process_args (argc, argv, gcc_argv);
424
  run_gcc (gcc_argc, gcc_argv);
425
  free (gcc_argv);
426
 
427
  return 0;
428
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.