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