]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/tlink.c
system.h: Include libiberty.h.
[thirdparty/gcc.git] / gcc / tlink.c
1 /* Scan linker error messages for missing template instantiations and provide
2 them.
3
4 Copyright (C) 1995, 1998 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
22
23 #include "config.h"
24 #include "system.h"
25 #include "hash.h"
26 #include "demangle.h"
27 #include "toplev.h"
28
29 #define MAX_ITERATIONS 17
30
31 /* Obstack allocation and deallocation routines. */
32 #define obstack_chunk_alloc xmalloc
33 #define obstack_chunk_free free
34
35 /* Defined in collect2.c. */
36 extern int vflag, debug;
37 extern char *ldout;
38 extern char *c_file_name;
39 extern struct obstack temporary_obstack;
40 extern struct obstack permanent_obstack;
41 extern char * temporary_firstobj;
42
43 /* Defined in the automatically-generated underscore.c. */
44 extern int prepends_underscore;
45
46 static int tlink_verbose;
47 \f
48 /* Hash table code. */
49
50 typedef struct symbol_hash_entry
51 {
52 struct hash_entry root;
53 struct file_hash_entry *file;
54 int chosen;
55 int tweaking;
56 int tweaked;
57 } symbol;
58
59 typedef struct file_hash_entry
60 {
61 struct hash_entry root;
62 const char *args;
63 const char *dir;
64 const char *main;
65 int tweaking;
66 } file;
67
68 typedef struct demangled_hash_entry
69 {
70 struct hash_entry root;
71 const char *mangled;
72 } demangled;
73
74 static struct hash_table symbol_table;
75
76 static struct hash_entry *
77 symbol_hash_newfunc (entry, table, string)
78 struct hash_entry *entry;
79 struct hash_table *table;
80 const char *string;
81 {
82 struct symbol_hash_entry *ret = (struct symbol_hash_entry *) entry;
83 if (ret == NULL)
84 {
85 ret = ((struct symbol_hash_entry *)
86 hash_allocate (table, sizeof (struct symbol_hash_entry)));
87 if (ret == NULL)
88 return NULL;
89 }
90 ret = ((struct symbol_hash_entry *)
91 hash_newfunc ((struct hash_entry *) ret, table,
92 (hash_table_key) string));
93 ret->file = NULL;
94 ret->chosen = 0;
95 ret->tweaking = 0;
96 ret->tweaked = 0;
97 return (struct hash_entry *) ret;
98 }
99
100 static struct symbol_hash_entry *
101 symbol_hash_lookup (string, create)
102 const char *string;
103 boolean create;
104 {
105 return ((struct symbol_hash_entry *)
106 hash_lookup (&symbol_table, (hash_table_key) string,
107 create, &string_copy));
108 }
109
110 static struct hash_table file_table;
111
112 static struct hash_entry *
113 file_hash_newfunc (entry, table, string)
114 struct hash_entry *entry;
115 struct hash_table *table;
116 const char *string;
117 {
118 struct file_hash_entry *ret = (struct file_hash_entry *) entry;
119 if (ret == NULL)
120 {
121 ret = ((struct file_hash_entry *)
122 hash_allocate (table, sizeof (struct file_hash_entry)));
123 if (ret == NULL)
124 return NULL;
125 }
126 ret = ((struct file_hash_entry *)
127 hash_newfunc ((struct hash_entry *) ret, table,
128 (hash_table_key) string));
129 ret->args = NULL;
130 ret->dir = NULL;
131 ret->main = NULL;
132 ret->tweaking = 0;
133 return (struct hash_entry *) ret;
134 }
135
136 static struct file_hash_entry *
137 file_hash_lookup (string)
138 const char *string;
139 {
140 return ((struct file_hash_entry *)
141 hash_lookup (&file_table, (hash_table_key) string, true,
142 &string_copy));
143 }
144
145 static struct hash_table demangled_table;
146
147 static struct hash_entry *
148 demangled_hash_newfunc (entry, table, string)
149 struct hash_entry *entry;
150 struct hash_table *table;
151 const char *string;
152 {
153 struct demangled_hash_entry *ret = (struct demangled_hash_entry *) entry;
154 if (ret == NULL)
155 {
156 ret = ((struct demangled_hash_entry *)
157 hash_allocate (table, sizeof (struct demangled_hash_entry)));
158 if (ret == NULL)
159 return NULL;
160 }
161 ret = ((struct demangled_hash_entry *)
162 hash_newfunc ((struct hash_entry *) ret, table,
163 (hash_table_key) string));
164 ret->mangled = NULL;
165 return (struct hash_entry *) ret;
166 }
167
168 static struct demangled_hash_entry *
169 demangled_hash_lookup (string, create)
170 const char *string;
171 boolean create;
172 {
173 return ((struct demangled_hash_entry *)
174 hash_lookup (&demangled_table, (hash_table_key) string,
175 create, &string_copy));
176 }
177 \f
178 /* Stack code. */
179
180 struct symbol_stack_entry
181 {
182 symbol *value;
183 struct symbol_stack_entry *next;
184 };
185 struct obstack symbol_stack_obstack;
186 struct symbol_stack_entry *symbol_stack;
187
188 struct file_stack_entry
189 {
190 file *value;
191 struct file_stack_entry *next;
192 };
193 struct obstack file_stack_obstack;
194 struct file_stack_entry *file_stack;
195
196 static void
197 symbol_push (p)
198 symbol *p;
199 {
200 struct symbol_stack_entry *ep = (struct symbol_stack_entry *) obstack_alloc
201 (&symbol_stack_obstack, sizeof (struct symbol_stack_entry));
202 ep->value = p;
203 ep->next = symbol_stack;
204 symbol_stack = ep;
205 }
206
207 static symbol *
208 symbol_pop ()
209 {
210 struct symbol_stack_entry *ep = symbol_stack;
211 symbol *p;
212 if (ep == NULL)
213 return NULL;
214 p = ep->value;
215 symbol_stack = ep->next;
216 obstack_free (&symbol_stack_obstack, ep);
217 return p;
218 }
219
220 static void
221 file_push (p)
222 file *p;
223 {
224 struct file_stack_entry *ep;
225
226 if (p->tweaking)
227 return;
228
229 ep = (struct file_stack_entry *) obstack_alloc
230 (&file_stack_obstack, sizeof (struct file_stack_entry));
231 ep->value = p;
232 ep->next = file_stack;
233 file_stack = ep;
234 p->tweaking = 1;
235 }
236
237 static file *
238 file_pop ()
239 {
240 struct file_stack_entry *ep = file_stack;
241 file *p;
242 if (ep == NULL)
243 return NULL;
244 p = ep->value;
245 file_stack = ep->next;
246 obstack_free (&file_stack_obstack, ep);
247 p->tweaking = 0;
248 return p;
249 }
250 \f
251 /* Other machinery. */
252
253 static void
254 tlink_init ()
255 {
256 char *p;
257
258 hash_table_init (&symbol_table, symbol_hash_newfunc, &string_hash,
259 &string_compare);
260 hash_table_init (&file_table, file_hash_newfunc, &string_hash,
261 &string_compare);
262 hash_table_init (&demangled_table, demangled_hash_newfunc,
263 &string_hash, &string_compare);
264 obstack_begin (&symbol_stack_obstack, 0);
265 obstack_begin (&file_stack_obstack, 0);
266
267 p = getenv ("TLINK_VERBOSE");
268 if (p)
269 tlink_verbose = atoi (p);
270 else
271 {
272 tlink_verbose = 1;
273 if (vflag)
274 tlink_verbose = 2;
275 if (debug)
276 tlink_verbose = 3;
277 }
278 }
279
280 static int
281 tlink_execute (prog, argv, redir)
282 char *prog;
283 char **argv;
284 char *redir;
285 {
286 collect_execute (prog, argv, redir);
287 return collect_wait (prog);
288 }
289
290 static char *
291 frob_extension (s, ext)
292 char *s, *ext;
293 {
294 char *p = rindex (s, '/');
295 if (! p)
296 p = s;
297 p = rindex (p, '.');
298 if (! p)
299 p = s + strlen (s);
300
301 obstack_grow (&temporary_obstack, s, p - s);
302 return obstack_copy0 (&temporary_obstack, ext, strlen (ext));
303 }
304
305 static char *
306 obstack_fgets (stream, ob)
307 FILE *stream;
308 struct obstack *ob;
309 {
310 int c;
311 while ((c = getc (stream)) != EOF && c != '\n')
312 obstack_1grow (ob, c);
313 if (obstack_object_size (ob) == 0)
314 return NULL;
315 obstack_1grow (ob, '\0');
316 return obstack_finish (ob);
317 }
318
319 static char *
320 tfgets (stream)
321 FILE *stream;
322 {
323 return obstack_fgets (stream, &temporary_obstack);
324 }
325
326 static char *
327 pfgets (stream)
328 FILE *stream;
329 {
330 return obstack_fgets (stream, &permanent_obstack);
331 }
332 \f
333 /* Real tlink code. */
334
335 static void
336 freadsym (stream, f, chosen)
337 FILE *stream;
338 file *f;
339 int chosen;
340 {
341 symbol *sym;
342
343 {
344 char *name = tfgets (stream);
345 sym = symbol_hash_lookup (name, true);
346 }
347
348 if (sym->file == NULL)
349 {
350 symbol_push (sym);
351 sym->file = f;
352 sym->chosen = chosen;
353 }
354 else if (chosen)
355 {
356 if (sym->chosen && sym->file != f)
357 {
358 if (sym->chosen == 1)
359 file_push (sym->file);
360 else
361 {
362 file_push (f);
363 f = sym->file;
364 chosen = sym->chosen;
365 }
366 }
367 sym->file = f;
368 sym->chosen = chosen;
369 }
370 }
371
372 static void
373 read_repo_file (f)
374 file *f;
375 {
376 char c;
377 FILE *stream = fopen ((char*) f->root.key, "r");
378
379 if (tlink_verbose >= 2)
380 fprintf (stderr, "collect: reading %s\n",
381 (char*) f->root.key);
382
383 while (fscanf (stream, "%c ", &c) == 1)
384 {
385 switch (c)
386 {
387 case 'A':
388 f->args = pfgets (stream);
389 break;
390 case 'D':
391 f->dir = pfgets (stream);
392 break;
393 case 'M':
394 f->main = pfgets (stream);
395 break;
396 case 'P':
397 freadsym (stream, f, 2);
398 break;
399 case 'C':
400 freadsym (stream, f, 1);
401 break;
402 case 'O':
403 freadsym (stream, f, 0);
404 break;
405 }
406 obstack_free (&temporary_obstack, temporary_firstobj);
407 }
408 fclose (stream);
409 if (f->args == NULL)
410 f->args = getenv ("COLLECT_GCC_OPTIONS");
411 if (f->dir == NULL)
412 f->dir = ".";
413 }
414
415 static void
416 maybe_tweak (line, f)
417 char *line;
418 file *f;
419 {
420 symbol *sym = symbol_hash_lookup (line + 2, false);
421
422 if ((sym->file == f && sym->tweaking)
423 || (sym->file != f && line[0] == 'C'))
424 {
425 sym->tweaking = 0;
426 sym->tweaked = 1;
427
428 if (line[0] == 'O')
429 line[0] = 'C';
430 else
431 line[0] = 'O';
432 }
433 }
434
435 static int
436 recompile_files ()
437 {
438 file *f;
439
440 while ((f = file_pop ()) != NULL)
441 {
442 char *line, *command;
443 FILE *stream = fopen ((char*) f->root.key, "r");
444 char *outname = frob_extension ((char*) f->root.key, ".rnw");
445 FILE *output = fopen (outname, "w");
446
447 while ((line = tfgets (stream)) != NULL)
448 {
449 switch (line[0])
450 {
451 case 'C':
452 case 'O':
453 maybe_tweak (line, f);
454 }
455 fprintf (output, "%s\n", line);
456 }
457 fclose (stream);
458 fclose (output);
459 rename (outname, (char*) f->root.key);
460
461 obstack_grow (&temporary_obstack, "cd ", 3);
462 obstack_grow (&temporary_obstack, f->dir, strlen (f->dir));
463 obstack_grow (&temporary_obstack, "; ", 2);
464 obstack_grow (&temporary_obstack, c_file_name, strlen (c_file_name));
465 obstack_1grow (&temporary_obstack, ' ');
466 obstack_grow (&temporary_obstack, f->args, strlen (f->args));
467 obstack_1grow (&temporary_obstack, ' ');
468 command = obstack_copy0 (&temporary_obstack, f->main, strlen (f->main));
469
470 if (tlink_verbose)
471 fprintf (stderr, "collect: recompiling %s\n", f->main);
472 if (tlink_verbose >= 3)
473 fprintf (stderr, "%s\n", command);
474
475 if (system (command) != 0)
476 return 0;
477
478 read_repo_file (f);
479
480 obstack_free (&temporary_obstack, temporary_firstobj);
481 }
482 return 1;
483 }
484
485 static int
486 read_repo_files (object_lst)
487 char **object_lst;
488 {
489 char **object = object_lst;
490
491 for (; *object; object++)
492 {
493 char *p = frob_extension (*object, ".rpo");
494 file *f;
495
496 if (! file_exists (p))
497 continue;
498
499 f = file_hash_lookup (p);
500
501 read_repo_file (f);
502 }
503
504 if (file_stack != NULL && ! recompile_files ())
505 return 0;
506
507 return (symbol_stack != NULL);
508 }
509
510 static void
511 demangle_new_symbols ()
512 {
513 symbol *sym;
514
515 while ((sym = symbol_pop ()) != NULL)
516 {
517 demangled *dem;
518 char *p = cplus_demangle ((char*) sym->root.key,
519 DMGL_PARAMS | DMGL_ANSI);
520
521 if (! p)
522 continue;
523
524 dem = demangled_hash_lookup (p, true);
525 dem->mangled = (char*) sym->root.key;
526 }
527 }
528
529 static int
530 scan_linker_output (fname)
531 char *fname;
532 {
533 FILE *stream = fopen (fname, "r");
534 char *line;
535
536 while ((line = tfgets (stream)) != NULL)
537 {
538 char *p = line, *q;
539 symbol *sym;
540 int end;
541
542 while (*p && ISSPACE ((unsigned char)*p))
543 ++p;
544
545 if (! *p)
546 continue;
547
548 for (q = p; *q && ! ISSPACE ((unsigned char)*q); ++q)
549 ;
550
551 /* Try the first word on the line. */
552 if (*p == '.')
553 ++p;
554 if (*p == '_' && prepends_underscore)
555 ++p;
556
557 end = ! *q;
558 *q = 0;
559 sym = symbol_hash_lookup (p, false);
560
561 if (! sym && ! end)
562 /* Try a mangled name in quotes. */
563 {
564 char *oldq = q+1;
565 demangled *dem = 0;
566 q = 0;
567
568 /* First try `GNU style'. */
569 p = index (oldq, '`');
570 if (p)
571 p++, q = index (p, '\'');
572 /* Then try "double quotes". */
573 else if (p = index (oldq, '"'), p)
574 p++, q = index (p, '"');
575
576 if (q)
577 {
578 *q = 0;
579 dem = demangled_hash_lookup (p, false);
580 if (dem)
581 sym = symbol_hash_lookup (dem->mangled, false);
582 else
583 sym = symbol_hash_lookup (p, false);
584 }
585 }
586
587 if (sym && sym->tweaked)
588 {
589 fclose (stream);
590 return 0;
591 }
592 if (sym && !sym->tweaking)
593 {
594 if (tlink_verbose >= 2)
595 fprintf (stderr, "collect: tweaking %s in %s\n",
596 (char*) sym->root.key, (char*) sym->file->root.key);
597 sym->tweaking = 1;
598 file_push (sym->file);
599 }
600
601 obstack_free (&temporary_obstack, temporary_firstobj);
602 }
603
604 fclose (stream);
605 return (file_stack != NULL);
606 }
607
608 void
609 do_tlink (ld_argv, object_lst)
610 char **ld_argv, **object_lst;
611 {
612 int exit = tlink_execute ("ld", ld_argv, ldout);
613
614 tlink_init ();
615
616 if (exit)
617 {
618 int i = 0;
619
620 /* Until collect does a better job of figuring out which are object
621 files, assume that everything on the command line could be. */
622 if (read_repo_files (ld_argv))
623 while (exit && i++ < MAX_ITERATIONS)
624 {
625 if (tlink_verbose >= 3)
626 dump_file (ldout);
627 demangle_new_symbols ();
628 if (! scan_linker_output (ldout))
629 break;
630 if (! recompile_files ())
631 break;
632 if (tlink_verbose)
633 fprintf (stderr, "collect: relinking\n");
634 exit = tlink_execute ("ld", ld_argv, ldout);
635 }
636 }
637
638 dump_file (ldout);
639 unlink (ldout);
640 if (exit)
641 {
642 error ("ld returned %d exit status", exit);
643 collect_exit (exit);
644 }
645 }