OSDN Git Service

* config/alpha/alpha.c (alpha_emit_floatuns): Ensure we pass a REG
[pf3gnuchains/gcc-fork.git] / gcc / tlink.c
1 /* Scan linker error messages for missing template instantiations and provide
2    them.
3
4    Copyright (C) 1995, 1998, 1999 Free Software Foundation, Inc.
5    Contributed by Jason Merrill (jason@cygnus.com).
6
7 This file is part of GNU CC.
8
9 GNU CC is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
12 any later version.
13
14 GNU CC is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GNU CC; see the file COPYING.  If not, write to
21 the Free Software Foundation, 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA.  */
23
24 #include "config.h"
25 #include "system.h"
26 #include "hash.h"
27 #include "demangle.h"
28 #include "collect2.h"
29
30 #define MAX_ITERATIONS 17
31
32 /* Obstack allocation and deallocation routines.  */
33 #define obstack_chunk_alloc xmalloc
34 #define obstack_chunk_free free
35
36 /* Defined in the automatically-generated underscore.c.  */
37 extern int prepends_underscore;
38
39 static int tlink_verbose;
40 \f
41 /* Hash table boilerplate for working with hash.[ch].  We have hash tables
42    for symbol names, file names, and demangled symbols.  */
43
44 typedef struct symbol_hash_entry
45 {
46   struct hash_entry root;
47   struct file_hash_entry *file;
48   int chosen;
49   int tweaking;
50   int tweaked;
51 } symbol;
52
53 typedef struct file_hash_entry
54 {
55   struct hash_entry root;
56   const char *args;
57   const char *dir;
58   const char *main;
59   int tweaking;
60 } file;
61
62 typedef struct demangled_hash_entry
63 {
64   struct hash_entry root;
65   const char *mangled;
66 } demangled;
67
68 static struct hash_table symbol_table;
69
70 static struct hash_entry * symbol_hash_newfunc PARAMS ((struct hash_entry *,
71                                                         struct hash_table *,
72                                                         hash_table_key));
73 static struct symbol_hash_entry * symbol_hash_lookup PARAMS ((const char *,
74                                                               boolean));
75 static struct hash_entry * file_hash_newfunc PARAMS ((struct hash_entry *,
76                                                       struct hash_table *,
77                                                       hash_table_key));
78 static struct file_hash_entry * file_hash_lookup PARAMS ((const char *));
79 static struct hash_entry * demangled_hash_newfunc PARAMS ((struct hash_entry *,
80                                                            struct hash_table *,
81                                                            hash_table_key));
82 static struct demangled_hash_entry *
83   demangled_hash_lookup PARAMS ((const char *, boolean));
84 static void symbol_push PARAMS ((symbol *));
85 static symbol * symbol_pop PARAMS ((void));
86 static void file_push PARAMS ((file *));
87 static file * file_pop PARAMS ((void));
88 static void tlink_init PARAMS ((void));
89 static int tlink_execute PARAMS ((const char *, char **, const char *));
90 static char * frob_extension PARAMS ((const char *, const char *));
91 static char * obstack_fgets PARAMS ((FILE *, struct obstack *));
92 static char * tfgets PARAMS ((FILE *));
93 static char * pfgets PARAMS ((FILE *));
94 static void freadsym PARAMS ((FILE *, file *, int));
95 static void read_repo_file PARAMS ((file *));
96 static void maybe_tweak PARAMS ((char *, file *));
97 static int recompile_files PARAMS ((void));
98 static int read_repo_files PARAMS ((char **));
99 static void demangle_new_symbols PARAMS ((void));
100 static int scan_linker_output PARAMS ((const char *));
101
102 /* Create a new entry for the symbol hash table.
103    Passed to hash_table_init.  */
104
105 static struct hash_entry *
106 symbol_hash_newfunc (entry, table, string)
107      struct hash_entry *entry;
108      struct hash_table *table;
109      hash_table_key string ATTRIBUTE_UNUSED;
110 {
111   struct symbol_hash_entry *ret = (struct symbol_hash_entry *) entry;
112   if (ret == NULL)
113     {
114       ret = ((struct symbol_hash_entry *)
115              hash_allocate (table, sizeof (struct symbol_hash_entry)));
116       if (ret == NULL)
117         return NULL;
118     }
119   ret->file = NULL;
120   ret->chosen = 0;
121   ret->tweaking = 0;
122   ret->tweaked = 0;
123   return (struct hash_entry *) ret;
124 }
125
126 /* Look up an entry in the symbol hash table.  */
127
128 static struct symbol_hash_entry *
129 symbol_hash_lookup (string, create)
130      const char *string;
131      boolean create;
132 {
133   return ((struct symbol_hash_entry *)
134           hash_lookup (&symbol_table, (const hash_table_key) string, 
135                        create, string_copy));
136 }
137
138 static struct hash_table file_table;
139
140 /* Create a new entry for the file hash table.
141    Passed to hash_table_init.  */
142
143 static struct hash_entry *
144 file_hash_newfunc (entry, table, string)
145      struct hash_entry *entry;
146      struct hash_table *table;
147      hash_table_key string ATTRIBUTE_UNUSED;
148 {
149    struct file_hash_entry *ret = (struct file_hash_entry *) entry;
150   if (ret == NULL)
151     {
152       ret = ((struct file_hash_entry *)
153              hash_allocate (table, sizeof (struct file_hash_entry)));
154       if (ret == NULL)
155         return NULL;
156     }
157   ret->args = NULL;
158   ret->dir = NULL;
159   ret->main = NULL;
160   ret->tweaking = 0;
161   return (struct hash_entry *) ret;
162 }
163
164 /* Look up an entry in the file hash table.  */
165
166 static struct file_hash_entry *
167 file_hash_lookup (string)
168      const char *string;
169 {
170   return ((struct file_hash_entry *)
171           hash_lookup (&file_table, (const hash_table_key) string, true, 
172                        string_copy));
173 }
174
175 static struct hash_table demangled_table;
176
177 /* Create a new entry for the demangled name hash table.
178    Passed to hash_table_init.  */
179
180 static struct hash_entry *
181 demangled_hash_newfunc (entry, table, string)
182      struct hash_entry *entry;
183      struct hash_table *table;
184      hash_table_key string ATTRIBUTE_UNUSED;
185 {
186   struct demangled_hash_entry *ret = (struct demangled_hash_entry *) entry;
187   if (ret == NULL)
188     {
189       ret = ((struct demangled_hash_entry *)
190              hash_allocate (table, sizeof (struct demangled_hash_entry)));
191       if (ret == NULL)
192         return NULL;
193     }
194   ret->mangled = NULL;
195   return (struct hash_entry *) ret;
196 }
197
198 /* Look up an entry in the demangled name hash table.  */
199
200 static struct demangled_hash_entry *
201 demangled_hash_lookup (string, create)
202      const char *string;
203      boolean create;
204 {
205   return ((struct demangled_hash_entry *)
206           hash_lookup (&demangled_table, (const hash_table_key) string, 
207                        create, string_copy));
208 }
209 \f
210 /* Stack code.  */
211
212 struct symbol_stack_entry
213 {
214   symbol *value;
215   struct symbol_stack_entry *next;
216 };
217 struct obstack symbol_stack_obstack;
218 struct symbol_stack_entry *symbol_stack;
219
220 struct file_stack_entry
221 {
222   file *value;
223   struct file_stack_entry *next;
224 };
225 struct obstack file_stack_obstack;
226 struct file_stack_entry *file_stack;
227
228 static void
229 symbol_push (p)
230      symbol *p;
231 {
232   struct symbol_stack_entry *ep = (struct symbol_stack_entry *) obstack_alloc
233     (&symbol_stack_obstack, sizeof (struct symbol_stack_entry));
234   ep->value = p;
235   ep->next = symbol_stack;
236   symbol_stack = ep;
237 }
238
239 static symbol *
240 symbol_pop ()
241 {
242   struct symbol_stack_entry *ep = symbol_stack;
243   symbol *p;
244   if (ep == NULL)
245     return NULL;
246   p = ep->value;
247   symbol_stack = ep->next;
248   obstack_free (&symbol_stack_obstack, ep);
249   return p;
250 }
251
252 static void
253 file_push (p)
254      file *p;
255 {
256   struct file_stack_entry *ep;
257
258   if (p->tweaking)
259     return;
260
261   ep = (struct file_stack_entry *) obstack_alloc
262     (&file_stack_obstack, sizeof (struct file_stack_entry));
263   ep->value = p;
264   ep->next = file_stack;
265   file_stack = ep;
266   p->tweaking = 1;
267 }
268
269 static file *
270 file_pop ()
271 {
272   struct file_stack_entry *ep = file_stack;
273   file *p;
274   if (ep == NULL)
275     return NULL;
276   p = ep->value;
277   file_stack = ep->next;
278   obstack_free (&file_stack_obstack, ep);
279   p->tweaking = 0;
280   return p;
281 }
282 \f
283 /* Other machinery.  */
284
285 /* Initialize the tlink machinery.  Called from do_tlink.  */
286
287 static void
288 tlink_init ()
289 {
290   const char *p;
291
292   hash_table_init (&symbol_table, symbol_hash_newfunc, string_hash,
293                    string_compare);
294   hash_table_init (&file_table, file_hash_newfunc, string_hash, 
295                    string_compare);
296   hash_table_init (&demangled_table, demangled_hash_newfunc,
297                    string_hash, string_compare);
298   obstack_begin (&symbol_stack_obstack, 0);
299   obstack_begin (&file_stack_obstack, 0);
300
301   p = getenv ("TLINK_VERBOSE");
302   if (p)
303     tlink_verbose = atoi (p);
304   else
305     {
306       tlink_verbose = 1;
307       if (vflag)
308         tlink_verbose = 2;
309       if (debug)
310         tlink_verbose = 3;
311     }
312 }
313
314 static int
315 tlink_execute (prog, argv, redir)
316      const char *prog;
317      char **argv;
318      const char *redir;
319 {
320   collect_execute (prog, argv, redir);
321   return collect_wait (prog);
322
323
324 static char *
325 frob_extension (s, ext)
326      const char *s;
327      const char *ext;
328 {
329   const char *p = rindex (s, '/');
330   if (! p)
331     p = s;
332   p = rindex (p, '.');
333   if (! p)
334     p = s + strlen (s);
335
336   obstack_grow (&temporary_obstack, s, p - s);
337   return obstack_copy0 (&temporary_obstack, ext, strlen (ext));
338 }
339
340 static char *
341 obstack_fgets (stream, ob)
342      FILE *stream;
343      struct obstack *ob;
344 {
345   int c;
346   while ((c = getc (stream)) != EOF && c != '\n')
347     obstack_1grow (ob, c);
348   if (obstack_object_size (ob) == 0)
349     return NULL;
350   obstack_1grow (ob, '\0');
351   return obstack_finish (ob);
352 }
353
354 static char *
355 tfgets (stream)
356      FILE *stream;
357 {
358   return obstack_fgets (stream, &temporary_obstack);
359 }
360
361 static char *
362 pfgets (stream)
363      FILE *stream;
364 {
365   return obstack_fgets (stream, &permanent_obstack);
366 }
367 \f
368 /* Real tlink code.  */
369
370 /* Subroutine of read_repo_file.  We are reading the repo file for file F,
371    which is coming in on STREAM, and the symbol that comes next in STREAM
372    is offerred, chosen or provided if CHOSEN is 0, 1 or 2, respectively.
373
374    XXX "provided" is unimplemented, both here and in the compiler.  */
375
376 static void
377 freadsym (stream, f, chosen)
378      FILE *stream;
379      file *f;
380      int chosen;
381 {
382   symbol *sym;
383
384   {
385     const char *name = tfgets (stream);
386     sym = symbol_hash_lookup (name, true);
387   }
388
389   if (sym->file == NULL)
390     {
391       /* We didn't have this symbol already, so we choose this file.  */
392
393       symbol_push (sym);
394       sym->file = f;
395       sym->chosen = chosen;
396     }
397   else if (chosen)
398     {
399       /* We want this file; cast aside any pretender.  */
400
401       if (sym->chosen && sym->file != f)
402         {
403           if (sym->chosen == 1)
404             file_push (sym->file);
405           else
406             {
407               file_push (f);
408               f = sym->file;
409               chosen = sym->chosen;
410             }
411         }
412       sym->file = f;
413       sym->chosen = chosen;
414     }
415 }
416
417 /* Read in the repo file denoted by F, and record all its information.  */
418
419 static void
420 read_repo_file (f)
421      file *f;
422 {
423   char c;
424   FILE *stream = fopen ((char*) f->root.key, "r");
425
426   if (tlink_verbose >= 2)
427     fprintf (stderr, "collect: reading %s\n", 
428              (char*) f->root.key);
429
430   while (fscanf (stream, "%c ", &c) == 1)
431     {
432       switch (c)
433         {
434         case 'A':
435           f->args = pfgets (stream);
436           break;
437         case 'D':
438           f->dir = pfgets (stream);
439           break;
440         case 'M':
441           f->main = pfgets (stream);
442           break;
443         case 'P':
444           freadsym (stream, f, 2);
445           break;
446         case 'C':
447           freadsym (stream, f, 1);
448           break;
449         case 'O':
450           freadsym (stream, f, 0);
451           break;
452         }
453       obstack_free (&temporary_obstack, temporary_firstobj);
454     }
455   fclose (stream);
456   if (f->args == NULL)
457     f->args = getenv ("COLLECT_GCC_OPTIONS");
458   if (f->dir == NULL)
459     f->dir = ".";
460 }
461
462 /* We might want to modify LINE, which is a symbol line from file F.  We do
463    this if either we saw an error message referring to the symbol in
464    question, or we have already allocated the symbol to another file and
465    this one wants to emit it as well.  */
466
467 static void
468 maybe_tweak (line, f)
469      char *line;
470      file *f;
471 {
472   symbol *sym = symbol_hash_lookup (line + 2, false);
473
474   if ((sym->file == f && sym->tweaking)
475       || (sym->file != f && line[0] == 'C'))
476     {
477       sym->tweaking = 0;
478       sym->tweaked = 1;
479
480       if (line[0] == 'O')
481         line[0] = 'C';
482       else
483         line[0] = 'O';
484     }
485 }
486
487 /* Update the repo files for each of the object files we have adjusted and
488    recompile.
489
490    XXX Should this use collect_execute instead of system?  */
491
492 static int
493 recompile_files ()
494 {
495   file *f;
496
497   while ((f = file_pop ()) != NULL)
498     {
499       char *line, *command;
500       FILE *stream = fopen ((char*) f->root.key, "r");
501       const char *outname = frob_extension ((char*) f->root.key, ".rnw");
502       FILE *output = fopen (outname, "w");
503
504       while ((line = tfgets (stream)) != NULL)
505         {
506           switch (line[0])
507             {
508             case 'C':
509             case 'O':
510               maybe_tweak (line, f);
511             }
512           fprintf (output, "%s\n", line);
513         }
514       fclose (stream);
515       fclose (output);
516       rename (outname, (char*) f->root.key);
517
518       obstack_grow (&temporary_obstack, "cd ", 3);
519       obstack_grow (&temporary_obstack, f->dir, strlen (f->dir));
520       obstack_grow (&temporary_obstack, "; ", 2);
521       obstack_grow (&temporary_obstack, c_file_name, strlen (c_file_name));
522       obstack_1grow (&temporary_obstack, ' ');
523       obstack_grow (&temporary_obstack, f->args, strlen (f->args));
524       obstack_1grow (&temporary_obstack, ' ');
525       command = obstack_copy0 (&temporary_obstack, f->main, strlen (f->main));
526
527       if (tlink_verbose)
528         fprintf (stderr, "collect: recompiling %s\n", f->main);
529       if (tlink_verbose >= 3)
530         fprintf (stderr, "%s\n", command);
531
532       if (system (command) != 0)
533         return 0;
534
535       read_repo_file (f);
536
537       obstack_free (&temporary_obstack, temporary_firstobj);
538     }
539   return 1;
540 }
541
542 /* The first phase of processing: determine which object files have
543    .rpo files associated with them, and read in the information.  */
544
545 static int
546 read_repo_files (object_lst)
547      char **object_lst;
548 {
549   char **object = object_lst;
550
551   for (; *object; object++)
552     {
553       const char *p;
554       file *f;
555
556       /* Don't bother trying for ld flags.  */
557       if (*object[0] == '-')
558         continue;
559
560       p = frob_extension (*object, ".rpo");
561
562       if (! file_exists (p))
563         continue;
564
565       f = file_hash_lookup (p);
566
567       read_repo_file (f);
568     }
569
570   if (file_stack != NULL && ! recompile_files ())
571     return 0;
572
573   return (symbol_stack != NULL);
574 }
575
576 /* Add the demangled forms of any new symbols to the hash table.  */
577
578 static void
579 demangle_new_symbols ()
580 {
581   symbol *sym;
582
583   while ((sym = symbol_pop ()) != NULL)
584     {
585       demangled *dem;
586       const char *p = cplus_demangle ((char*) sym->root.key, 
587                                 DMGL_PARAMS | DMGL_ANSI);
588
589       if (! p)
590         continue;
591
592       dem = demangled_hash_lookup (p, true);
593       dem->mangled = (char*) sym->root.key;
594     }
595 }
596
597 /* Step through the output of the linker, in the file named FNAME, and
598    adjust the settings for each symbol encountered.  */
599
600 static int
601 scan_linker_output (fname)
602      const char *fname;
603 {
604   FILE *stream = fopen (fname, "r");
605   char *line;
606
607   while ((line = tfgets (stream)) != NULL)
608     {
609       char *p = line, *q;
610       symbol *sym;
611       int end;
612       
613       while (*p && ISSPACE ((unsigned char)*p))
614         ++p;
615
616       if (! *p)
617         continue;
618
619       for (q = p; *q && ! ISSPACE ((unsigned char)*q); ++q)
620         ;
621
622       /* Try the first word on the line.  */
623       if (*p == '.')
624         ++p;
625       if (*p == '_' && prepends_underscore)
626         ++p;
627
628       end = ! *q;
629       *q = 0;
630       sym = symbol_hash_lookup (p, false);
631
632       if (! sym && ! end)
633         /* Try a mangled name in quotes.  */
634         {
635           const char *oldq = q+1;
636           demangled *dem = 0;
637           q = 0;
638
639           /* First try `GNU style'.  */
640           p = index (oldq, '`');
641           if (p)
642             p++, q = index (p, '\'');
643           /* Then try "double quotes".  */
644           else if (p = index (oldq, '"'), p)
645             p++, q = index (p, '"');
646
647           /* Don't let the strstr's below see the demangled name; we
648              might get spurious matches.  */
649           if (p)
650             p[-1] = '\0';
651
652           /* We need to check for certain error keywords here, or we would
653              mistakenly use GNU ld's "In function `foo':" message.  */
654           if (q && (strstr (oldq, "ndefined")
655                     || strstr (oldq, "nresolved")
656                     || strstr (oldq, "ultiple")))
657             {
658               *q = 0;
659               dem = demangled_hash_lookup (p, false);
660               if (dem)
661                 sym = symbol_hash_lookup (dem->mangled, false);
662               else
663                 {
664                   if (*p == '_' && prepends_underscore)
665                     ++p;
666                   sym = symbol_hash_lookup (p, false);
667                 }
668             }
669         }
670
671       if (sym && sym->tweaked)
672         {
673           fclose (stream);
674           return 0;
675         }
676       if (sym && !sym->tweaking)
677         {
678           if (tlink_verbose >= 2)
679             fprintf (stderr, "collect: tweaking %s in %s\n",
680                      (char*) sym->root.key, (char*) sym->file->root.key);
681           sym->tweaking = 1;
682           file_push (sym->file);
683         }
684         
685       obstack_free (&temporary_obstack, temporary_firstobj);
686     }
687
688   fclose (stream);
689   return (file_stack != NULL);
690 }
691
692 /* Entry point for tlink.  Called from main in collect2.c.
693
694    Iteratively try to provide definitions for all the unresolved symbols
695    mentioned in the linker error messages.
696
697    LD_ARGV is an array of arguments for the linker.
698    OBJECT_LST is an array of object files that we may be able to recompile
699      to provide missing definitions.  Currently ignored.  */
700
701 void
702 do_tlink (ld_argv, object_lst)
703      char **ld_argv, **object_lst ATTRIBUTE_UNUSED;
704 {
705   int exit = tlink_execute ("ld", ld_argv, ldout);
706
707   tlink_init ();
708
709   if (exit)
710     {
711       int i = 0;
712
713       /* Until collect does a better job of figuring out which are object
714          files, assume that everything on the command line could be.  */
715       if (read_repo_files (ld_argv))
716         while (exit && i++ < MAX_ITERATIONS)
717           {
718             if (tlink_verbose >= 3)
719               dump_file (ldout);
720             demangle_new_symbols ();
721             if (! scan_linker_output (ldout))
722               break;
723             if (! recompile_files ())
724               break;
725             if (tlink_verbose)
726               fprintf (stderr, "collect: relinking\n");
727             exit = tlink_execute ("ld", ld_argv, ldout);
728           }
729     }
730
731   dump_file (ldout);
732   unlink (ldout);
733   if (exit)
734     {
735       error ("ld returned %d exit status", exit);
736       collect_exit (exit);
737     }
738 }