Merge from vendor branch NTPD:
[dragonfly.git] / contrib / gcc-3.4 / gcc / c-pch.c
1 /* Precompiled header implementation for the C languages.
2    Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GCC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING.  If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.  */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "version.h"
25 #include "cpplib.h"
26 #include "tree.h"
27 #include "flags.h"
28 #include "c-common.h"
29 #include "output.h"
30 #include "toplev.h"
31 #include "debug.h"
32 #include "c-pragma.h"
33 #include "ggc.h"
34 #include "langhooks.h"
35 #include "hosthooks.h"
36 #include "target.h"
37
38 /* This structure is read very early when validating the PCH, and
39    might be read for a PCH which is for a completely different compiler
40    for a different operating system.  Thus, it should really only contain
41    'unsigned char' entries, at least in the initial entries.  
42
43    If you add or change entries before version_length, you should increase
44    the version number in get_ident().  
45
46    There are a bunch of fields named *_length; those are lengths of data that
47    follows this structure in the same order as the fields in the structure.
48
49    The flags_info field is used to verify that certain flags settings that
50    have to be the same during the compilation of the PCH and a compilation
51    using the PCH are indeed the same.  */
52
53 struct c_pch_validity
54 {
55   unsigned char host_machine_length;
56   unsigned char target_machine_length;
57   unsigned char version_length;
58   unsigned char debug_info_type;
59   unsigned int flags_info;
60   void (*pch_init) (void);
61   size_t target_data_length;
62 };
63
64 /* If -funit-at-a-time is set, we require that it was also set during the
65    compilation of the PCH we may be using.  */
66 #define FLAG_UNIT_AT_A_TIME_SET 1 << 0
67
68 struct c_pch_header 
69 {
70   unsigned long asm_size;
71 };
72
73 #define IDENT_LENGTH 8
74
75 /* The file we'll be writing the PCH to.  */
76 static FILE *pch_outfile;
77
78 /* The position in the assembler output file when pch_init was called.  */
79 static long asm_file_startpos;
80
81 /* The host and target machines.  */
82 static const char host_machine[] = HOST_MACHINE;
83 static const char target_machine[] = TARGET_MACHINE;
84
85 static const char *get_ident (void);
86
87 /* Compute an appropriate 8-byte magic number for the PCH file, so that
88    utilities like file(1) can identify it, and so that GCC can quickly
89    ignore non-PCH files and PCH files that are of a completely different
90    format.  */
91
92 static const char *
93 get_ident(void)
94 {
95   static char result[IDENT_LENGTH];
96   static const char template[IDENT_LENGTH] = "gpch.012";
97   static const char c_language_chars[] = "Co+O";
98   
99   memcpy (result, template, IDENT_LENGTH);
100   result[4] = c_language_chars[c_language];
101
102   return result;
103 }
104
105 /* Prepare to write a PCH file.  This is called at the start of 
106    compilation.  */
107
108 void
109 pch_init (void)
110 {
111   FILE *f;
112   struct c_pch_validity v;
113   void *target_validity;
114   static const char partial_pch[IDENT_LENGTH] = "gpcWrite";
115   unsigned int current_flags_info = 0;
116   
117   if (! pch_file)
118     return;
119
120   if (flag_unit_at_a_time)
121     current_flags_info |= FLAG_UNIT_AT_A_TIME_SET;
122
123   f = fopen (pch_file, "w+b");
124   if (f == NULL)
125     fatal_error ("can't create precompiled header %s: %m", pch_file);
126   pch_outfile = f;
127   
128   if (strlen (host_machine) > 255 || strlen (target_machine) > 255
129       || strlen (version_string) > 255)
130     abort ();
131   
132   v.host_machine_length = strlen (host_machine);
133   v.target_machine_length = strlen (target_machine);
134   v.version_length = strlen (version_string);
135   v.debug_info_type = write_symbols;
136   v.flags_info = current_flags_info;
137   v.pch_init = &pch_init;
138   target_validity = targetm.get_pch_validity (&v.target_data_length);
139   
140   if (fwrite (partial_pch, IDENT_LENGTH, 1, f) != 1
141       || fwrite (&v, sizeof (v), 1, f) != 1
142       || fwrite (host_machine, v.host_machine_length, 1, f) != 1
143       || fwrite (target_machine, v.target_machine_length, 1, f) != 1
144       || fwrite (version_string, v.version_length, 1, f) != 1
145       || fwrite (target_validity, v.target_data_length, 1, f) != 1)
146     fatal_error ("can't write to %s: %m", pch_file);
147
148   /* We need to be able to re-read the output.  */
149   /* The driver always provides a valid -o option.  */
150   if (asm_file_name == NULL
151       || strcmp (asm_file_name, "-") == 0)
152     fatal_error ("`%s' is not a valid output file", asm_file_name);
153   
154   asm_file_startpos = ftell (asm_out_file);
155   
156   /* Let the debugging format deal with the PCHness.  */
157   (*debug_hooks->handle_pch) (0);
158   
159   cpp_save_state (parse_in, f);
160 }
161
162 /* Write the PCH file.  This is called at the end of a compilation which
163    will produce a PCH file.  */
164
165 void
166 c_common_write_pch (void)
167 {
168   char *buf;
169   long asm_file_end;
170   long written;
171   struct c_pch_header h;
172
173   (*debug_hooks->handle_pch) (1);
174
175   cpp_write_pch_deps (parse_in, pch_outfile);
176
177   asm_file_end = ftell (asm_out_file);
178   h.asm_size = asm_file_end - asm_file_startpos;
179   
180   if (fwrite (&h, sizeof (h), 1, pch_outfile) != 1)
181     fatal_error ("can't write %s: %m", pch_file);
182   
183   buf = xmalloc (16384);
184   fflush (asm_out_file);
185
186   if (fseek (asm_out_file, asm_file_startpos, SEEK_SET) != 0)
187     fatal_error ("can't seek in %s: %m", asm_file_name);
188
189   for (written = asm_file_startpos; written < asm_file_end; )
190     {
191       long size = asm_file_end - written;
192       if (size > 16384)
193         size = 16384;
194       if (fread (buf, size, 1, asm_out_file) != 1)
195         fatal_error ("can't read %s: %m", asm_file_name);
196       if (fwrite (buf, size, 1, pch_outfile) != 1)
197         fatal_error ("can't write %s: %m", pch_file);
198       written += size;
199     }
200   free (buf);
201   /* asm_out_file can be written afterwards, so must be flushed first.  */
202   fflush (asm_out_file);
203
204   gt_pch_save (pch_outfile);
205   cpp_write_pch_state (parse_in, pch_outfile);
206
207   if (fseek (pch_outfile, 0, SEEK_SET) != 0
208       || fwrite (get_ident (), IDENT_LENGTH, 1, pch_outfile) != 1)
209     fatal_error ("can't write %s: %m", pch_file);
210
211   fclose (pch_outfile);
212 }
213
214 /* Check the PCH file called NAME, open on FD, to see if it can be
215    used in this compilation.  Return 1 if valid, 0 if the file can't
216    be used now but might be if it's seen later in the compilation, and
217    2 if this file could never be used in the compilation.  */
218
219 int
220 c_common_valid_pch (cpp_reader *pfile, const char *name, int fd)
221 {
222   int sizeread;
223   int result;
224   char ident[IDENT_LENGTH];
225   char short_strings[256 * 3];
226   int strings_length;
227   const char *pch_ident;
228   struct c_pch_validity v;
229   unsigned int current_flags_info = 0;
230
231   if (flag_unit_at_a_time)
232     current_flags_info |= FLAG_UNIT_AT_A_TIME_SET;
233
234   /* Perform a quick test of whether this is a valid
235      precompiled header for the current language
236      and with the current flag settings.  */
237
238   sizeread = read (fd, ident, IDENT_LENGTH);
239   if (sizeread == -1)
240     fatal_error ("can't read %s: %m", name);
241   else if (sizeread != IDENT_LENGTH)
242     return 2;
243   
244   pch_ident = get_ident();
245   if (memcmp (ident, pch_ident, IDENT_LENGTH) != 0)
246     {
247       if (cpp_get_options (pfile)->warn_invalid_pch)
248         {
249           if (memcmp (ident, pch_ident, 5) == 0)
250             /* It's a PCH, for the right language, but has the wrong version.
251              */
252             cpp_error (pfile, CPP_DL_WARNING, 
253                        "%s: not compatible with this GCC version", name);
254           else if (memcmp (ident, pch_ident, 4) == 0)
255             /* It's a PCH for the wrong language.  */
256             cpp_error (pfile, CPP_DL_WARNING, "%s: not for %s", name,
257                        lang_hooks.name);
258           else 
259             /* Not any kind of PCH.  */
260             cpp_error (pfile, CPP_DL_WARNING, "%s: not a PCH file", name);
261         }
262       return 2;
263     }
264
265   /* At this point, we know it's a PCH file, so it ought to be long enough
266      that we can read a c_pch_validity structure.  */
267   if (read (fd, &v, sizeof (v)) != sizeof (v))
268     fatal_error ("can't read %s: %m", name);
269
270   strings_length = (v.host_machine_length + v.target_machine_length 
271                     + v.version_length);
272   if (read (fd, short_strings, strings_length) != strings_length)
273     fatal_error ("can't read %s: %m", name);
274   if (v.host_machine_length != strlen (host_machine)
275       || memcmp (host_machine, short_strings, strlen (host_machine)) != 0)
276     {
277       if (cpp_get_options (pfile)->warn_invalid_pch)
278         cpp_error (pfile, CPP_DL_WARNING, 
279                    "%s: created on host `%.*s', but used on host `%s'", name,
280                    v.host_machine_length, short_strings, host_machine);
281       return 2;
282     }
283   if (v.target_machine_length != strlen (target_machine)
284       || memcmp (target_machine, short_strings + v.host_machine_length,
285                  strlen (target_machine)) != 0)
286     {
287       if (cpp_get_options (pfile)->warn_invalid_pch)
288         cpp_error (pfile, CPP_DL_WARNING, 
289                    "%s: created for target `%.*s', but used for target `%s'", 
290                    name, v.target_machine_length, 
291                    short_strings + v.host_machine_length, target_machine);
292       return 2;
293     }
294   if (v.version_length != strlen (version_string)
295       || memcmp (version_string, 
296                  (short_strings + v.host_machine_length 
297                   + v.target_machine_length),
298                  v.version_length) != 0)
299     {
300       if (cpp_get_options (pfile)->warn_invalid_pch)
301         cpp_error (pfile, CPP_DL_WARNING,
302                    "%s: created by version `%.*s', but this is version `%s'", 
303                    name, v.version_length, 
304                    (short_strings + v.host_machine_length 
305                     + v.target_machine_length), 
306                    version_string);
307       return 2;
308     }
309   if (v.flags_info != current_flags_info)
310     {
311       if (cpp_get_options (pfile)->warn_invalid_pch)
312         cpp_error (pfile, CPP_DL_WARNING,
313                    "%s: created using different flags",
314                    name);
315       return 2;
316     }
317
318   /* The allowable debug info combinations are that either the PCH file
319      was built with the same as is being used now, or the PCH file was
320      built for some kind of debug info but now none is in use.  */
321   if (v.debug_info_type != write_symbols
322       && write_symbols != NO_DEBUG)
323     {
324       if (cpp_get_options (pfile)->warn_invalid_pch)
325         cpp_error (pfile, CPP_DL_WARNING, 
326                    "%s: created with -g%s, but used with -g%s", name,
327                    debug_type_names[v.debug_info_type],
328                    debug_type_names[write_symbols]);
329       return 2;
330     }
331
332   /* If the text segment was not loaded at the same address as it was
333      when the PCH file was created, function pointers loaded from the
334      PCH will not be valid.  We could in theory remap all the function
335      pointers, but no support for that exists at present.  */
336   if (v.pch_init != &pch_init)
337     {
338       if (cpp_get_options (pfile)->warn_invalid_pch)
339         cpp_error (pfile, CPP_DL_WARNING, 
340                    "%s: had text segment at different address", name);
341       return 2;
342     }
343
344   /* Check the target-specific validity data.  */
345   {
346     void *this_file_data = xmalloc (v.target_data_length);
347     const char *msg;
348     
349     if ((size_t) read (fd, this_file_data, v.target_data_length)
350         != v.target_data_length)
351       fatal_error ("can't read %s: %m", name);
352     msg = targetm.pch_valid_p (this_file_data, v.target_data_length);
353     free (this_file_data);
354     if (msg != NULL)
355       {
356         if (cpp_get_options (pfile)->warn_invalid_pch)
357           cpp_error (pfile, CPP_DL_WARNING, "%s: %s", name, msg);
358         return 2;
359       }
360   }
361
362   /* Check the preprocessor macros are the same as when the PCH was
363      generated.  */
364   
365   result = cpp_valid_state (pfile, name, fd);
366   if (result == -1)
367     return 2;
368   else
369     return result == 0;
370 }
371
372 /* Load in the PCH file NAME, open on FD.  It was originally searched for
373    by ORIG_NAME.  */
374
375 void
376 c_common_read_pch (cpp_reader *pfile, const char *name,
377                    int fd, const char *orig_name ATTRIBUTE_UNUSED)
378 {
379   FILE *f;
380   struct c_pch_header h;
381   char *buf;
382   unsigned long written;
383   struct save_macro_data *smd;
384   
385   f = fdopen (fd, "rb");
386   if (f == NULL)
387     {
388       cpp_errno (pfile, CPP_DL_ERROR, "calling fdopen");
389       return;
390     }
391
392   cpp_get_callbacks (parse_in)->valid_pch = NULL;
393
394   if (fread (&h, sizeof (h), 1, f) != 1)
395     {
396       cpp_errno (pfile, CPP_DL_ERROR, "reading");
397       return;
398     }
399
400   buf = xmalloc (16384);
401   for (written = 0; written < h.asm_size; )
402     {
403       long size = h.asm_size - written;
404       if (size > 16384)
405         size = 16384;
406       if (fread (buf, size, 1, f) != 1
407           || fwrite (buf, size, 1, asm_out_file) != 1)
408         cpp_errno (pfile, CPP_DL_ERROR, "reading");
409       written += size;
410     }
411   free (buf);
412
413   cpp_prepare_state (pfile, &smd);
414
415   gt_pch_restore (f);
416
417   if (cpp_read_state (pfile, name, f, smd) != 0)
418     return;
419
420   fclose (f);
421 }
422
423 /* Indicate that no more PCH files should be read.  */
424
425 void
426 c_common_no_more_pch (void)
427 {
428   if (cpp_get_callbacks (parse_in)->valid_pch)
429     {
430       cpp_get_callbacks (parse_in)->valid_pch = NULL;
431       host_hooks.gt_pch_use_address (NULL, 0);
432     }
433 }