#include "config.h"
#include "system.h"
#include "toplev.h"
#include <stdio.h>
#include <assert.h>
#ifdef PFE
#include "pfe.h"
#include "pfe-header.h"
#include "tm_p.h"
#include "langhooks.h"
struct obstack;
struct _obstack_chunk;
tree pfe_predefined_global_names = NULL;
extern struct cpp_reader* parse_in;
extern int const_labelno;
extern int var_labelno;
extern int pfe_display_precomp_headers;
void (*pfe_lang_freeze_thaw_compiler_state) PARAMS ((struct pfe_lang_compiler_state **));
static void pfe_freeze_thaw_include_header PARAMS ((struct ht_identifier **));
static void pfe_check_format PARAMS ((pfe_compiler_state *));
static void pfe_check_compiler_version PARAMS ((void));
static void pfe_freeze_thaw_compiler_state PARAMS ((pfe_compiler_state *));
static void pfe_freeze_thaw_hashtable PARAMS ((struct ht **, void (*) (struct ht_identifier **)));
static void pfe_freeze_thaw_ht_identifier PARAMS ((struct ht_identifier **));
static void pfe_freeze_thaw_obstack_chunk PARAMS ((struct _obstack_chunk **));
static void pfe_freeze_thaw_obstack PARAMS ((struct obstack *));
static void pfe_check_compiler_settings PARAMS ((void));
void pfe_check_cmd_ln_macros PARAMS ((void));
static char * pfe_absolute_path_name PARAMS ((char *));
void
pfe_set_lang (lang)
enum pfe_lang lang;
{
pfe_compiler_state_ptr->lang = lang;
}
void
pfe_check_lang (lang)
enum pfe_lang lang;
{
if (pfe_compiler_state_ptr->lang != lang)
fatal_error ("Pre-compiled header for wrong language: \"%s\".", pfe_name);
}
static void
pfe_freeze_thaw_include_header (pp)
struct ht_identifier **pp;
{
struct pfe_include_header *p = (struct pfe_include_header *)PFE_FREEZE_THAW_PTR (pp);
if (!p)
return;
pfe_freeze_thaw_ptr_fp (&p->include_name.str);
}
int
pfe_check_header (fname, timestamp, inode)
const char *fname;
time_t timestamp;
ino_t inode;
{
pfe_include_header *header;
char *full_name;
if (!fname)
return 0;
full_name = pfe_absolute_path_name (fname);
header = (pfe_include_header *) ht_lookup (pfe_compiler_state_ptr->include_hash,
(const unsigned char *) full_name,
strlen (full_name), HT_NO_INSERT);
if (!header)
{
if (pfe_display_precomp_headers)
fprintf (stderr, "PFE: full_name = %s is not available in precompiled header.\n", full_name);
pfe_free (full_name);
return 0;
}
if (header->inode != inode)
{
error ("Precompiled header is invalid; header file %s is now different.", full_name);
pfe_free (full_name);
return 0;
}
if (timestamp > header->timestamp)
{
error ("Precompiled header is out of date; header file %s is newer.", full_name);
pfe_free (full_name);
return 0;
}
if (pfe_display_precomp_headers)
fprintf (stderr, "PFE: full_name = %s is loaded from precompiled header.\n", full_name);
pfe_free (full_name);
return 1;
}
void
pfe_add_header_name (fname, timestamp, inode)
const char *fname;
time_t timestamp;
ino_t inode;
{
pfe_include_header *header;
char *full_name;
if (!fname)
return;
full_name = pfe_absolute_path_name (fname);
if (pfe_operation != PFE_DUMP)
fatal_error ("pfe_add_header_name can be used only with PFE_DUMP\n");
header = (pfe_include_header *) ht_lookup (pfe_compiler_state_ptr->include_hash,
(const unsigned char *) full_name,
strlen (full_name), HT_ALLOC);
header->inode = inode;
header->timestamp = timestamp;
if (pfe_display_precomp_headers)
fprintf (stderr, "PFE: full_name = %s is added in precompiled header.\n", full_name);
pfe_free(full_name);
}
static char *
pfe_absolute_path_name (input_name)
char *input_name;
{
char *name;
if (input_name[0] != '/')
{
int alen = MAXPATHLEN + strlen (input_name) + 2;
name = (char *) pfe_malloc (sizeof (char) * alen);
name = getcwd(name, alen);
strcat (name, "/");
strcat (name, input_name);
}
else
{
name = (char *) pfe_malloc (strlen (input_name) + 1);
strcpy (name, input_name);
}
return name;
}
static void
pfe_check_format (hdr)
pfe_compiler_state *hdr;
{
if (hdr->magic_number != PFE_MAGIC_NUMBER)
fatal_error ("Unrecognizable format in pre-compiled header: \"%s\".", pfe_name);
if (hdr->format_version != PFE_FORMAT_VERSION)
fatal_error ("Incompatible format version pre-compiled header: \"%s\".", pfe_name);
}
static void
pfe_check_compiler_version ()
{
int valid_compiler;
char current_version [16];
strncpy (current_version, apple_version_str, 15);
valid_compiler = (strcmp (pfe_compiler_state_ptr->compiler_version,
current_version) == 0);
if (!valid_compiler)
{
}
if (!valid_compiler)
fatal_error ("Incompatible compiler version in pre-compiled header: \"%s\".",
pfe_name);
}
static void
pfe_check_compiler_settings ()
{
(*lang_hooks.pfe_check_settings) (pfe_compiler_state_ptr->lang_specific);
#ifdef PFE_CHECK_TARGET_SETTINGS
PFE_CHECK_TARGET_SETTINGS ();
#endif
}
void
pfe_check_cmd_ln_macros ()
{
}
void
pfe_check_compiler ()
{
pfe_check_compiler_version ();
pfe_check_compiler_settings ();
pfe_check_cmd_ln_macros ();
}
void
pfe_freeze_compiler_state (hdr)
void *hdr;
{
((pfe_compiler_state *)hdr)->magic_number = PFE_MAGIC_NUMBER;
((pfe_compiler_state *)hdr)->format_version = PFE_FORMAT_VERSION;
strncpy (((pfe_compiler_state *)hdr)->compiler_version,
apple_version_str, 15);
pfe_freeze_thaw_compiler_state ((pfe_compiler_state *)hdr);
}
void
pfe_thaw_compiler_state (hdr)
pfe_compiler_state *hdr;
{
pfe_check_format (hdr);
(*lang_hooks.pfe_lang_init) (0);
pfe_freeze_thaw_compiler_state (hdr);
}
extern tree machopic_non_lazy_pointers;
extern tree machopic_stubs;
static void
pfe_freeze_thaw_compiler_state (hdr)
pfe_compiler_state *hdr;
{
int i, n;
pfe_freeze_thaw_ptr_fp (&hdr->progname);
PFE_GLOBAL_TO_HDR_IF_FREEZING (pfe_predefined_global_names);
pfe_freeze_thaw_ptr_fp (&hdr->pfe_predefined_global_names);
PFE_HDR_TO_GLOBAL_IF_THAWING (pfe_predefined_global_names);
pfe_freeze_thaw_hashtable (&hdr->include_hash, pfe_freeze_thaw_include_header);
pfe_freeze_thaw_binding_level (NULL);
PFE_GLOBAL_TO_HDR_IF_FREEZING (ident_hash);
pfe_freeze_thaw_hashtable (&hdr->ident_hash,
(void (*) (struct ht_identifier **))
pfe_freeze_thaw_cpp_hashnode);
PFE_HDR_TO_GLOBAL_IF_THAWING (ident_hash);
PFE_FREEZE_THAW_GLOBAL_TREE_ARRAY (global_trees, TI_MAX);
PFE_FREEZE_THAW_GLOBAL_TREE_ARRAY (integer_types, itk_none);
PFE_FREEZE_THAW_GLOBAL_TREE_ARRAY (sizetype_tab, TYPE_KIND_LAST);
PFE_FREEZE_THAW_GLOBAL_TREE_ARRAY (c_global_trees, CTI_MAX);
#if 0
if (PFE_FREEZING)
memcpy (hdr->built_in_names, built_in_names,
(int)(END_BUILTINS) * sizeof (char *));
for (i = 0; i < (int)(END_BUILTINS); ++i)
PFE_FREEZE_THAW_PTR (&hdr->built_in_names[i]);
if (PFE_THAWING)
memcpy (built_in_names, hdr->built_in_names,
(int)(END_BUILTINS) * sizeof (char *));
#endif
PFE_FREEZE_THAW_GLOBAL_TREE_ARRAY (built_in_decls, END_BUILTINS);
PFE_FREEZE_THAW_GLOBAL_RTX_ARRAY (global_rtl, GR_MAX);
n = MAX_SAVED_CONST_INT * 2 + 1;
PFE_FREEZE_THAW_GLOBAL_RTX_ARRAY (const_int_rtx, n);
for (n = 0; n <= 2; ++n)
PFE_FREEZE_THAW_GLOBAL_RTX_ARRAY (const_tiny_rtx[n], MAX_MACHINE_MODE);
PFE_GLOBAL_TO_HDR_IF_FREEZING (const_labelno);
PFE_HDR_TO_GLOBAL_IF_THAWING (const_labelno);
PFE_GLOBAL_TO_HDR_IF_FREEZING (var_labelno);
PFE_HDR_TO_GLOBAL_IF_THAWING (var_labelno);
PFE_FREEZE_THAW_GLOBAL_RTX (const_true_rtx);
PFE_FREEZE_THAW_GLOBAL_RTX (return_address_pointer_rtx);
PFE_FREEZE_THAW_GLOBAL_RTX (struct_value_rtx);
PFE_FREEZE_THAW_GLOBAL_RTX (struct_value_incoming_rtx);
PFE_FREEZE_THAW_GLOBAL_RTX (static_chain_rtx);
PFE_FREEZE_THAW_GLOBAL_RTX (static_chain_incoming_rtx);
PFE_FREEZE_THAW_GLOBAL_RTX (pic_offset_table_rtx);
pfe_freeze_thaw_emitrtl (hdr);
pfe_freeze_thaw_ggc (&hdr->ggc_globals);
pfe_freeze_thaw_dbxout (hdr);
#ifdef PFE_TARGET_ADDITIONS
if (hdr->pfe_target_additions)
PFE_TARGET_ADDITIONS (&hdr->pfe_target_additions);
#endif
if (hdr->lang_specific)
(*lang_hooks.pfe_freeze_thaw_compiler_state) (&hdr->lang_specific);
#if PFE_NEW_TREE_WALK
pfe_freeze_thaw_tree_walk ();
#endif
}
void
pfe_freeze_thaw_cpp_hashnode (hnp)
struct cpp_hashnode **hnp;
{
struct cpp_hashnode *hn_orig = *hnp;
struct cpp_hashnode *hn = PFE_FREEZE_THAW_PTR (hnp);
struct ht_identifier *temp_ident;
tree temp_tree;
if (!hn)
return;
#if 0
if (pfe_operation == PFE_DUMP)
{
printf ("pfe_freeze_thaw_cpp_hashnode: 0x%x\n", (unsigned int)hn);
if (hn->ident.str != NULL)
printf (" hn->ident.str: 0x%x '%s'\n",
(unsigned int)hn->ident.str,
pfe_real_ptr(hn->ident.str));
if (hn->type == NT_MACRO)
printf (" hn->type: NT_MACRO\n");
else if (hn->type == NT_VOID)
printf (" hn->type: NT_VOID\n");
else
printf (" hn->type: ???\n");
if (hn->value.macro != NULL)
printf (" hn->value.macro: 0x%x\n", (unsigned int)hn->value.macro);
}
#endif
#if 0
if (PFE_IS_FROZEN (hn->ident.str))
return;
#endif
if (pfe_operation == PFE_DUMP && hn->type == NT_MACRO)
{
if (! ustrncmp (pfe_real_ptr (hn->ident.str), DSC ("__STDC_")))
{
if (hn->flags & NODE_WARN)
hn->flags ^= NODE_WARN;
else
hn->flags &= NODE_WARN;
}
}
pfe_using_temp_ptr ((void **)&temp_ident);
temp_ident = (struct ht_identifier *) hn_orig;
pfe_freeze_thaw_ht_identifier (&temp_ident);
switch (hn->type) {
case NT_VOID:
break;
case NT_MACRO:
if (! (hn->flags & NODE_BUILTIN))
pfe_freeze_thaw_cpp_macro (&hn->value.macro);
break;
case NT_ASSERTION:
pfe_freeze_thaw_answer (&hn->value.answers);
break;
}
pfe_using_temp_ptr ((void **)&temp_tree);
temp_tree = HT_IDENT_TO_GCC_IDENT (hn);
PFE_FREEZE_THAW_WALK (temp_tree);
#if 0
if (pfe_operation == PFE_LOAD)
{
printf ("pfe_freeze_thaw_cpp_hashnode: 0x%x\n", (unsigned)hn);
if (hn->ident.str != NULL)
printf (" hn->ident.str: 0x%x '%s'\n",
(unsigned int)hn->ident.str,
pfe_real_ptr(hn->ident.str));
if (hn->type == NT_MACRO)
printf (" hn->type: NT_MACRO\n");
else if (hn->type == NT_VOID)
printf (" hn->type: NT_VOID\n");
else
printf (" hn->type: ???\n");
if (hn->value.macro != NULL)
printf (" hn->value.macro: 0x%x\n", (unsigned)hn->value.macro);
}
#endif
}
static void
pfe_freeze_thaw_obstack_chunk (pp)
struct _obstack_chunk **pp;
{
struct _obstack_chunk *p = (struct _obstack_chunk *)PFE_FREEZE_THAW_PTR (pp);
while (p)
{
PFE_FREEZE_THAW_PTR_WITH_VARIANCE (&p->limit, 1);
p = PFE_FREEZE_THAW_PTR (&p->prev);
}
}
static void
pfe_freeze_thaw_obstack (p)
struct obstack *p;
{
pfe_freeze_thaw_obstack_chunk (&p->chunk);
pfe_freeze_thaw_ptr_fp (&p->object_base);
pfe_freeze_thaw_ptr_fp (&p->next_free);
PFE_FREEZE_THAW_PTR_WITH_VARIANCE (&p->chunk_limit, 1);
if (PFE_THAWING)
{
p->chunkfun = (struct _obstack_chunk *(*)(void *, long)) pfe_malloc;
p->freefun = (void (*) (void *, struct _obstack_chunk *))pfe_free;
}
}
static void
pfe_freeze_thaw_ht_identifier (pp)
struct ht_identifier **pp;
{
struct ht_identifier *p = (struct ht_identifier *)PFE_FREEZE_THAW_PTR (pp);
if (!p)
return;
#if 0
if (pfe_operation == PFE_DUMP && !PFE_IS_FROZEN(p->str))
printf ("pfe_freeze_thaw_ht_identifier: 0x%x '%s'\n",
(unsigned)p, pfe_real_ptr(p->str));
#endif
pfe_freeze_thaw_ptr_fp (&p->str);
#if 0
if (pfe_operation == PFE_LOAD)
printf ("pfe_freeze_thaw_ht_identifier: 0x%x '%s'\n",
(unsigned)p, pfe_real_ptr(p->str));
#endif
}
static void
pfe_freeze_thaw_hashtable (pp, ff)
struct ht **pp;
void (*ff) (struct ht_identifier **);
{
hashnode *q;
unsigned int i;
struct ht *p;
typedef hashnode (*alloc_node_fp)(hash_table *);
extern alloc_node_fp pfe_get_cpphash_alloc_node PARAMS ((void));
p = (struct ht *)pfe_freeze_thaw_ptr_fp (pp);
assert (p);
if (PFE_THAWING)
p->alloc_node = pfe_get_cpphash_alloc_node ();
pfe_freeze_thaw_obstack (&p->stack);
q = PFE_FREEZE_THAW_PTR (&p->entries);
if (q)
for (i = 0; i < p->nslots; ++i, ++q)
if (*q)
(*ff) ((struct ht_identifier **)q);
}
void
pfe_freeze_thaw_cpp_token (tp)
struct cpp_token **tp;
{
struct cpp_token *t = PFE_FREEZE_THAW_PTR (tp);
if (!t)
return;
#if 0
printf ("pfe_freeze_thaw_cpp_token: 0x%x\n", (unsigned) t);
#endif
switch (t->type) {
case CPP_NAME:
pfe_freeze_thaw_cpp_hashnode (&t->val.node);
break;
case CPP_NUMBER:
case CPP_STRING:
case CPP_CHAR:
case CPP_WCHAR:
case CPP_WSTRING:
case CPP_HEADER_NAME:
case CPP_COMMENT:
#if 0
if (pfe_operation == PFE_DUMP && !pfe_is_pfe_mem(t->val.str.text))
{
printf ("pfe_freeze_thaw_cpp_token: token->val.str.text not in PFE memory: 0x%x\n",
(unsigned) t->val.str.text);
switch (t->type) {
case CPP_NUMBER:
printf(" t->type = %s '%s'\n", "CPP_NUMBER", t->val.str.text); break;
case CPP_STRING:
printf(" t->type = %s\n", "CPP_STRING"); break;
case CPP_CHAR:
printf(" t->type = %s\n", "CPP_CHAR"); break;
case CPP_WCHAR:
printf(" t->type = %s\n", "CPP_WCHAR"); break;
case CPP_WSTRING:
printf(" t->type = %s\n", "CPP_WSTRING"); break;
case CPP_HEADER_NAME:
printf(" t->type = %s\n", "CPP_HEADER_NAME"); break;
case CPP_COMMENT:
printf(" t->type = %s\n", "CPP_COMMENT"); break;
}
}
#endif
pfe_freeze_thaw_ptr_fp (&t->val.str.text);
#if 0
if (pfe_operation == PFE_LOAD && !pfe_is_pfe_mem(t->val.str.text))
{
printf ("pfe_freeze_thaw_cpp_token: token->val.str.text not in PFE memory: 0x%x\n",
(unsigned) t->val.str.text);
switch (t->type) {
case CPP_NUMBER:
printf(" t->type = %s\n", "CPP_NUMBER"); break;
case CPP_STRING:
printf(" t->type = %s\n", "CPP_STRING"); break;
case CPP_CHAR:
printf(" t->type = %s\n", "CPP_CHAR"); break;
case CPP_WCHAR:
printf(" t->type = %s\n", "CPP_WCHAR"); break;
case CPP_WSTRING:
printf(" t->type = %s\n", "CPP_WSTRING"); break;
case CPP_HEADER_NAME:
printf(" t->type = %s\n", "CPP_HEADER_NAME"); break;
case CPP_COMMENT:
printf(" t->type = %s\n", "CPP_COMMENT"); break;
}
}
#endif
break;
default:
break;
}
}
#include "tree.h"
#include "rtl.h"
#include "varray.h"
#include "cpplib.h"
#define GCC_STRUCTS
#define DEFCHECKSTRUCT(name, assumed_size) \
extern void CONCAT2(check_struct_, name) PARAMS ((int));
#include "structs-to-check.def"
#undef DEFCHECKSTRUCT
#define DEFCHECKSTRUCT(name, n) CONCAT2(check_struct_, name),
static pfe_check_struct_t struct_check_functions[] =
{
#include "structs-to-check.def"
NULL
};
#undef DEFCHECKSTRUCT
#define DEFCHECKSTRUCT(name, assumed_size) assumed_size,
static int assumed_struct_size[] =
{
#include "structs-to-check.def"
0
};
#undef DEFCHECKSTRUCT
#undef GCC_STRUCTS
void
pfe_check_all_struct_sizes ()
{
int i;
for (i = 0; i < (int)ARRAY_SIZE (struct_check_functions) - 1; ++i)
(*struct_check_functions[i]) (assumed_struct_size[i]);
(*lang_hooks.pfe_check_all_struct_sizes) ();
}
void
pfe_check_struct_size (actual_size, assumed_size, name)
int actual_size;
int assumed_size;
const char *name;
{
if (actual_size != assumed_size)
fprintf (stderr, "### struct %s: was %d, now %d\n",
name, assumed_size, actual_size);
}
struct rtunion_def_union {
union rtunion_def u;
};
struct tree_node_union {
union tree_node u;
};
struct varray_data_union {
union varray_data_tag u;
};
DEFINE_CHECK_STRUCT_FUNCTION (rtunion_def_union)
DEFINE_CHECK_STRUCT_FUNCTION (rtx_def)
DEFINE_CHECK_STRUCT_FUNCTION (rtvec_def)
DEFINE_CHECK_STRUCT_FUNCTION (tree_node_union)
DEFINE_CHECK_STRUCT_FUNCTION (tree_common)
DEFINE_CHECK_STRUCT_FUNCTION (tree_int_cst)
DEFINE_CHECK_STRUCT_FUNCTION (tree_real_cst)
DEFINE_CHECK_STRUCT_FUNCTION (tree_string)
DEFINE_CHECK_STRUCT_FUNCTION (tree_complex)
DEFINE_CHECK_STRUCT_FUNCTION (tree_vector)
DEFINE_CHECK_STRUCT_FUNCTION (tree_identifier)
DEFINE_CHECK_STRUCT_FUNCTION (tree_decl)
DEFINE_CHECK_STRUCT_FUNCTION (tree_type)
DEFINE_CHECK_STRUCT_FUNCTION (tree_list)
DEFINE_CHECK_STRUCT_FUNCTION (tree_vec)
DEFINE_CHECK_STRUCT_FUNCTION (tree_exp)
DEFINE_CHECK_STRUCT_FUNCTION (tree_block)
DEFINE_CHECK_STRUCT_FUNCTION (varray_data_union)
DEFINE_CHECK_STRUCT_FUNCTION (varray_head_tag)
DEFINE_CHECK_STRUCT_FUNCTION(cpp_token)
DEFINE_CHECK_STRUCT_FUNCTION(cpp_hashnode)
DEFINE_CHECK_STRUCT_FUNCTION (language_function)
DEFINE_CHECK_STRUCT_FUNCTION (stmt_tree_s)
#endif