1 /* Precompiled header implementation for the C languages.
2 Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc.
4 This file is part of GCC.
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)
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.
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. */
23 #include "coretypes.h"
34 #include "langhooks.h"
35 #include "hosthooks.h"
37 /* This structure is read very early when validating the PCH, and
38 might be read for a PCH which is for a completely different compiler
39 for a different operating system. Thus, it should really only contain
40 'unsigned char' entries, at least in the initial entries.
42 If you add or change entries before version_length, you should increase
43 the version number in get_ident(). */
47 unsigned char host_machine_length;
48 unsigned char target_machine_length;
49 unsigned char version_length;
50 unsigned char debug_info_type;
55 unsigned long asm_size;
58 #define IDENT_LENGTH 8
60 /* The file we'll be writing the PCH to. */
61 static FILE *pch_outfile;
63 /* The position in the assembler output file when pch_init was called. */
64 static long asm_file_startpos;
66 /* The host and target machines. */
67 static const char host_machine[] = HOST_MACHINE;
68 static const char target_machine[] = TARGET_MACHINE;
70 static const char *get_ident (void);
72 /* Compute an appropriate 8-byte magic number for the PCH file, so that
73 utilities like file(1) can identify it, and so that GCC can quickly
74 ignore non-PCH files and PCH files that are of a completely different
80 static char result[IDENT_LENGTH];
81 static const char template[IDENT_LENGTH] = "gpch.012";
82 static const char c_language_chars[] = "Co+O";
84 memcpy (result, template, IDENT_LENGTH);
85 result[4] = c_language_chars[c_language];
90 /* Prepare to write a PCH file. This is called at the start of
97 struct c_pch_validity v;
102 f = fopen (pch_file, "w+b");
104 fatal_error ("can't open %s: %m", pch_file);
107 if (strlen (host_machine) > 255 || strlen (target_machine) > 255
108 || strlen (version_string) > 255)
111 v.host_machine_length = strlen (host_machine);
112 v.target_machine_length = strlen (target_machine);
113 v.version_length = strlen (version_string);
115 v.debug_info_type = write_symbols;
116 if (fwrite (get_ident(), IDENT_LENGTH, 1, f) != 1
117 || fwrite (&v, sizeof (v), 1, f) != 1
118 || fwrite (host_machine, v.host_machine_length, 1, f) != 1
119 || fwrite (target_machine, v.target_machine_length, 1, f) != 1
120 || fwrite (version_string, v.version_length, 1, f) != 1)
121 fatal_error ("can't write to %s: %m", pch_file);
123 /* We need to be able to re-read the output. */
124 /* The driver always provides a valid -o option. */
125 if (asm_file_name == NULL
126 || strcmp (asm_file_name, "-") == 0)
127 fatal_error ("`%s' is not a valid output file", asm_file_name);
129 asm_file_startpos = ftell (asm_out_file);
131 /* Let the debugging format deal with the PCHness. */
132 (*debug_hooks->handle_pch) (0);
134 cpp_save_state (parse_in, f);
137 /* Write the PCH file. This is called at the end of a compilation which
138 will produce a PCH file. */
141 c_common_write_pch (void)
146 struct c_pch_header h;
148 (*debug_hooks->handle_pch) (1);
150 cpp_write_pch_deps (parse_in, pch_outfile);
152 asm_file_end = ftell (asm_out_file);
153 h.asm_size = asm_file_end - asm_file_startpos;
155 if (fwrite (&h, sizeof (h), 1, pch_outfile) != 1)
156 fatal_error ("can't write %s: %m", pch_file);
158 buf = xmalloc (16384);
159 fflush (asm_out_file);
161 if (fseek (asm_out_file, asm_file_startpos, SEEK_SET) != 0)
162 fatal_error ("can't seek in %s: %m", asm_file_name);
164 for (written = asm_file_startpos; written < asm_file_end; )
166 long size = asm_file_end - written;
169 if (fread (buf, size, 1, asm_out_file) != 1)
170 fatal_error ("can't read %s: %m", asm_file_name);
171 if (fwrite (buf, size, 1, pch_outfile) != 1)
172 fatal_error ("can't write %s: %m", pch_file);
176 /* asm_out_file can be written afterwards, so must be flushed first. */
177 fflush (asm_out_file);
179 gt_pch_save (pch_outfile);
180 cpp_write_pch_state (parse_in, pch_outfile);
182 fclose (pch_outfile);
185 /* Check the PCH file called NAME, open on FD, to see if it can be used
186 in this compilation. */
189 c_common_valid_pch (cpp_reader *pfile, const char *name, int fd)
193 char ident[IDENT_LENGTH];
194 char short_strings[256 * 3];
196 const char *pch_ident;
197 struct c_pch_validity v;
199 /* Perform a quick test of whether this is a valid
200 precompiled header for the current language. */
202 sizeread = read (fd, ident, IDENT_LENGTH);
204 fatal_error ("can't read %s: %m", name);
205 else if (sizeread != IDENT_LENGTH)
208 pch_ident = get_ident();
209 if (memcmp (ident, pch_ident, IDENT_LENGTH) != 0)
211 if (cpp_get_options (pfile)->warn_invalid_pch)
213 if (memcmp (ident, pch_ident, 5) == 0)
214 /* It's a PCH, for the right language, but has the wrong version.
216 cpp_error (pfile, DL_WARNING,
217 "%s: not compatible with this GCC version", name);
218 else if (memcmp (ident, pch_ident, 4) == 0)
219 /* It's a PCH for the wrong language. */
220 cpp_error (pfile, DL_WARNING, "%s: not for %s", name,
223 /* Not any kind of PCH. */
224 cpp_error (pfile, DL_WARNING, "%s: not a PCH file", name);
229 /* At this point, we know it's a PCH file, so it ought to be long enough
230 that we can read a c_pch_validity structure. */
231 if (read (fd, &v, sizeof (v)) != sizeof (v))
232 fatal_error ("can't read %s: %m", name);
234 strings_length = (v.host_machine_length + v.target_machine_length
236 if (read (fd, short_strings, strings_length) != strings_length)
237 fatal_error ("can't read %s: %m", name);
238 if (v.host_machine_length != strlen (host_machine)
239 || memcmp (host_machine, short_strings, strlen (host_machine)) != 0)
241 if (cpp_get_options (pfile)->warn_invalid_pch)
242 cpp_error (pfile, DL_WARNING,
243 "%s: created on host `%.*s', but used on host `%s'", name,
244 v.host_machine_length, short_strings, host_machine);
247 if (v.target_machine_length != strlen (target_machine)
248 || memcmp (target_machine, short_strings + v.host_machine_length,
249 strlen (target_machine)) != 0)
251 if (cpp_get_options (pfile)->warn_invalid_pch)
252 cpp_error (pfile, DL_WARNING,
253 "%s: created for target `%.*s', but used for target `%s'",
254 name, v.target_machine_length,
255 short_strings + v.host_machine_length, target_machine);
258 if (v.version_length != strlen (version_string)
259 || memcmp (version_string,
260 (short_strings + v.host_machine_length
261 + v.target_machine_length),
262 v.version_length) != 0)
264 if (cpp_get_options (pfile)->warn_invalid_pch)
265 cpp_error (pfile, DL_WARNING,
266 "%s: created by version `%.*s', but this is version `%s'",
267 name, v.version_length,
268 (short_strings + v.host_machine_length
269 + v.target_machine_length),
274 /* The allowable debug info combinations are that either the PCH file
275 was built with the same as is being used now, or the PCH file was
276 built for some kind of debug info but now none is in use. */
277 if (v.debug_info_type != write_symbols
278 && write_symbols != NO_DEBUG)
280 if (cpp_get_options (pfile)->warn_invalid_pch)
281 cpp_error (pfile, DL_WARNING,
282 "%s: created with -g%s, but used with -g%s", name,
283 debug_type_names[v.debug_info_type],
284 debug_type_names[write_symbols]);
288 /* Check the preprocessor macros are the same as when the PCH was
291 result = cpp_valid_state (pfile, name, fd);
298 /* Load in the PCH file NAME, open on FD. It was originally searched for
302 c_common_read_pch (cpp_reader *pfile, const char *name,
303 int fd, const char *orig_name ATTRIBUTE_UNUSED)
306 struct c_pch_header h;
308 unsigned long written;
309 struct save_macro_data *smd;
311 f = fdopen (fd, "rb");
314 cpp_errno (pfile, DL_ERROR, "calling fdopen");
318 cpp_get_callbacks (parse_in)->valid_pch = NULL;
320 if (fread (&h, sizeof (h), 1, f) != 1)
322 cpp_errno (pfile, DL_ERROR, "reading");
326 buf = xmalloc (16384);
327 for (written = 0; written < h.asm_size; )
329 long size = h.asm_size - written;
332 if (fread (buf, size, 1, f) != 1
333 || fwrite (buf, size, 1, asm_out_file) != 1)
334 cpp_errno (pfile, DL_ERROR, "reading");
339 cpp_prepare_state (pfile, &smd);
343 if (cpp_read_state (pfile, name, f, smd) != 0)
349 /* Indicate that no more PCH files should be read. */
352 c_common_no_more_pch (void)
354 if (cpp_get_callbacks (parse_in)->valid_pch)
356 cpp_get_callbacks (parse_in)->valid_pch = NULL;
357 host_hooks.gt_pch_use_address (NULL, 0);