diff options
Diffstat (limited to 'gcc/config/darwin-c.c')
-rw-r--r-- | gcc/config/darwin-c.c | 349 |
1 files changed, 339 insertions, 10 deletions
diff --git a/gcc/config/darwin-c.c b/gcc/config/darwin-c.c index feb26f185d2..c25a15ace7b 100644 --- a/gcc/config/darwin-c.c +++ b/gcc/config/darwin-c.c @@ -32,42 +32,88 @@ Boston, MA 02111-1307, USA. */ #include "tm_p.h" #include "cppdefault.h" #include "prefix.h" +/* APPLE LOCAL include options.h */ +#include "options.h" +/* APPLE LOCAL begin optimization pragmas 3124235/3420242 */ +#include "flags.h" +#include "opts.h" +#include "varray.h" +/* APPLE LOCAL end optimization pragmas 3124235/3420242 */ /* Pragmas. */ #define BAD(msgid) do { warning (msgid); return; } while (0) +/* APPLE LOCAL Macintosh alignment 2002-1-22 --ff */ +#define BAD2(msgid, arg) do { warning (msgid, arg); return; } while (0) static bool using_frameworks = false; +/* APPLE LOCAL begin CALL_ON_LOAD/CALL_ON_UNLOAD pragmas 20020202 --turly */ +static void directive_with_named_function (const char *, void (*sec_f)(void)); +/* APPLE LOCAL end CALL_ON_LOAD/CALL_ON_UNLOAD pragmas 20020202 --turly */ + /* Maintain a small stack of alignments. This is similar to pragma pack's stack, but simpler. */ -static void push_field_alignment (int); +/* APPLE LOCAL begin Macintosh alignment 2001-12-17 --ff */ +static void push_field_alignment (int, int, int); +/* APPLE LOCAL end Macintosh alignment 2001-12-17 --ff */ static void pop_field_alignment (void); static const char *find_subframework_file (const char *, const char *); static void add_system_framework_path (char *); static const char *find_subframework_header (cpp_reader *pfile, const char *header, cpp_dir **dirp); +/* APPLE LOCAL begin Macintosh alignment 2002-1-22 --ff */ +/* There are four alignment modes supported on the Apple Macintosh + platform: power, mac68k, natural, and packed. These modes are + identified as follows: + if maximum_field_alignment != 0 + mode = packed + else if TARGET_ALIGN_NATURAL + mode = natural + else if TARGET_ALIGN_MAC68K + mode + else + mode = power + These modes are saved on the alignment stack by saving the values + of maximum_field_alignment, TARGET_ALIGN_MAC68K, and + TARGET_ALIGN_NATURAL. */ typedef struct align_stack { int alignment; + unsigned long mac68k; + unsigned long natural; struct align_stack * prev; } align_stack; +/* APPLE LOCAL end Macintosh alignment 2002-1-22 --ff */ static struct align_stack * field_align_stack = NULL; +/* APPLE LOCAL begin Macintosh alignment 2001-12-17 --ff */ static void -push_field_alignment (int bit_alignment) +push_field_alignment (int bit_alignment, + int mac68k_alignment, int natural_alignment) { align_stack *entry = (align_stack *) xmalloc (sizeof (align_stack)); entry->alignment = maximum_field_alignment; + entry->mac68k = TARGET_ALIGN_MAC68K; + entry->natural = TARGET_ALIGN_NATURAL; entry->prev = field_align_stack; field_align_stack = entry; maximum_field_alignment = bit_alignment; + if (mac68k_alignment) + rs6000_alignment_flags |= MASK_ALIGN_MAC68K; + else + rs6000_alignment_flags &= ~MASK_ALIGN_MAC68K; + if (natural_alignment) + rs6000_alignment_flags |= MASK_ALIGN_NATURAL; + else + rs6000_alignment_flags &= ~MASK_ALIGN_NATURAL; } +/* APPLE LOCAL end Macintosh alignment 2001-12-17 --ff */ static void pop_field_alignment (void) @@ -77,6 +123,16 @@ pop_field_alignment (void) align_stack *entry = field_align_stack; maximum_field_alignment = entry->alignment; +/* APPLE LOCAL begin Macintosh alignment 2001-12-17 --ff */ + if (entry->mac68k) + rs6000_alignment_flags |= MASK_ALIGN_MAC68K; + else + rs6000_alignment_flags &= ~MASK_ALIGN_MAC68K; + if (entry->natural) + rs6000_alignment_flags |= MASK_ALIGN_NATURAL; + else + rs6000_alignment_flags &= ~MASK_ALIGN_NATURAL; +/* APPLE LOCAL end Macintosh alignment 2001-12-17 --ff */ field_align_stack = entry->prev; free (entry); } @@ -92,6 +148,20 @@ darwin_pragma_ignore (cpp_reader *pfile ATTRIBUTE_UNUSED) /* Do nothing. */ } +/* APPLE LOCAL begin pragma fenv */ +/* #pragma GCC fenv + This is kept in <fenv.h>. The point is to allow trapping + math to default to off. According to C99, any program + that requires trapping math must include <fenv.h>, so + we enable trapping math when that gets included. */ + +void +darwin_pragma_fenv (cpp_reader *pfile ATTRIBUTE_UNUSED) +{ + flag_trapping_math = 1; +} +/* APPLE LOCAL end pragma fenv */ + /* #pragma options align={mac68k|power|reset} */ void @@ -114,16 +184,89 @@ darwin_pragma_options (cpp_reader *pfile ATTRIBUTE_UNUSED) warning ("junk at end of '#pragma options'"); arg = IDENTIFIER_POINTER (t); +/* APPLE LOCAL begin Macintosh alignment 2002-1-22 --ff */ if (!strcmp (arg, "mac68k")) - push_field_alignment (16); + { + if (POINTER_SIZE == 64) + warning ("mac68k alignment pragma is deprecated for 64-bit Darwin"); + push_field_alignment (0, 1, 0); + } + else if (!strcmp (arg, "native")) /* equivalent to power on PowerPC */ + push_field_alignment (0, 0, 0); + else if (!strcmp (arg, "natural")) + push_field_alignment (0, 0, 1); + else if (!strcmp (arg, "packed")) + push_field_alignment (8, 0, 0); else if (!strcmp (arg, "power")) - push_field_alignment (0); + push_field_alignment (0, 0, 0); else if (!strcmp (arg, "reset")) pop_field_alignment (); else - warning ("malformed '#pragma options align={mac68k|power|reset}', ignoring"); + warning ("malformed '#pragma options align={mac68k|power|natural|reset}', ignoring"); +/* APPLE LOCAL end Macintosh alignment 2002-1-22 --ff */ } +/* APPLE LOCAL begin Macintosh alignment 2002-1-22 --ff */ +/* #pragma pack () + #pragma pack (N) + + We have a problem handling the semantics of these directives since, + to play well with the Macintosh alignment directives, we want the + usual pack(N) form to do a push of the previous alignment state. + Do we want pack() to do another push or a pop? */ + +void +darwin_pragma_pack (cpp_reader *pfile ATTRIBUTE_UNUSED) +{ + tree x; + int align = -1; + enum cpp_ttype token; + enum { set, push, pop } action; + + if (c_lex (&x) != CPP_OPEN_PAREN) + BAD ("missing '(' after '#pragma pack' - ignored"); + token = c_lex (&x); + if (token == CPP_CLOSE_PAREN) + { + action = pop; /* or "set" ??? */ + align = 0; + } + else if (token == CPP_NUMBER) + { + align = TREE_INT_CST_LOW (x); + action = push; + if (c_lex (&x) != CPP_CLOSE_PAREN) + BAD ("malformed '#pragma pack' - ignored"); + } + else + BAD ("malformed '#pragma pack' - ignored"); + + if (c_lex (&x) != CPP_EOF) + warning ("junk at end of '#pragma pack'"); + + switch (align) + { + case 0: + case 1: + case 2: + case 4: + case 8: + case 16: + align *= BITS_PER_UNIT; + break; + default: + BAD2 ("alignment must be a small power of two, not %d", align); + } + + switch (action) + { + case pop: pop_field_alignment (); break; + case push: push_field_alignment (align, 0, 0); break; + case set: break; + } +} +/* APPLE LOCAL end Macintosh alignment 2002-1-22 --ff */ + /* #pragma unused ([var {, var}*]) */ void @@ -157,6 +300,132 @@ darwin_pragma_unused (cpp_reader *pfile ATTRIBUTE_UNUSED) warning ("junk at end of '#pragma unused'"); } +/* APPLE LOCAL begin pragma reverse_bitfields */ +/* Handle the reverse_bitfields pragma. */ + +void +darwin_pragma_reverse_bitfields (cpp_reader *pfile ATTRIBUTE_UNUSED) +{ + const char* arg; + tree t; + + if (c_lex (&t) != CPP_NAME) + BAD ("malformed '#pragma reverse_bitfields', ignoring"); + arg = IDENTIFIER_POINTER (t); + + if (!strcmp (arg, "on")) + darwin_reverse_bitfields = true; + else if (!strcmp (arg, "off") || !strcmp (arg, "reset")) + darwin_reverse_bitfields = false; + else + warning ("malformed '#pragma reverse_bitfields {on|off|reset}', ignoring"); + if (c_lex (&t) != CPP_EOF) + warning ("junk at end of '#pragma reverse_bitfields'"); +} +/* APPLE LOCAL end pragma reverse_bitfields */ + +/* APPLE LOCAL begin optimization pragmas 3124235/3420242 */ +varray_type va_opt; + +static void +push_opt_level (int level, int size) +{ + if (!va_opt) + VARRAY_INT_INIT (va_opt, 5, "va_opt"); + VARRAY_PUSH_INT (va_opt, size << 16 | level); +} + +static void +pop_opt_level (void) +{ + int level; + if (!va_opt) + VARRAY_INT_INIT (va_opt, 5, "va_opt"); + if (!VARRAY_ACTIVE_SIZE (va_opt)) + { + warning ("optimization pragma stack underflow"); + return; + } + level = VARRAY_TOP_INT (va_opt); + VARRAY_POP (va_opt); + + optimize_size = level >> 16; + optimize = level & 0xffff; +} + +void +darwin_pragma_opt_level (cpp_reader *pfile ATTRIBUTE_UNUSED) +{ + tree t; + enum cpp_ttype argtype = c_lex (&t); + + if (argtype == CPP_NAME) + { + const char* arg = IDENTIFIER_POINTER (t); + if (strcmp (arg, "reset") != 0) + BAD ("malformed '#pragma optimization_level [GCC] {0|1|2|3|reset}', ignoring"); + pop_opt_level (); + } + else if (argtype == CPP_NUMBER) + { + if (TREE_CODE (t) != INTEGER_CST + || INT_CST_LT (t, integer_zero_node) + || TREE_INT_CST_HIGH (t) != 0) + BAD ("malformed '#pragma optimization_level [GCC] {0|1|2|3|reset}', ignoring"); + + push_opt_level (optimize, optimize_size); + optimize = TREE_INT_CST_LOW (t); + if (optimize > 3) + optimize = 3; + optimize_size = 0; + } + else + BAD ("malformed '#pragma optimization_level [GCC] {0|1|2|3|reset}', ignoring"); + + set_flags_from_O (false); + + /* This is expected to be defined in each target. */ + reset_optimization_options (optimize, optimize_size); + + if (c_lex (&t) != CPP_EOF) + warning ("junk at end of '#pragma optimization_level'"); +} + +void +darwin_pragma_opt_size (cpp_reader *pfile ATTRIBUTE_UNUSED) +{ + const char* arg; + tree t; + + if (c_lex (&t) != CPP_NAME) + BAD ("malformed '#pragma optimize_for_size { on | off | reset}', ignoring"); + arg = IDENTIFIER_POINTER (t); + + if (!strcmp (arg, "on")) + { + push_opt_level (optimize, optimize_size); + optimize_size = 1; + optimize = 2; + } + else if (!strcmp (arg, "off")) + /* Not clear what this should do exactly. CW does not do a pop so + we don't either. */ + optimize_size = 0; + else if (!strcmp (arg, "reset")) + pop_opt_level (); + else + BAD ("malformed '#pragma optimize_for_size { on | off | reset }', ignoring"); + + set_flags_from_O (false); + + /* This is expected to be defined in each target. */ + reset_optimization_options (optimize, optimize_size); + + if (c_lex (&t) != CPP_EOF) + warning ("junk at end of '#pragma optimize_for_size'"); +} +/* APPLE LOCAL end optimization pragmas 3124235/3420242 */ + static struct { size_t len; const char *name; @@ -270,6 +539,28 @@ framework_construct_pathname (const char *fname, cpp_dir *dir) strncpy (&frname[frname_len], ".framework/", strlen (".framework/")); frname_len += strlen (".framework/"); + /* APPLE LOCAL begin mainline */ + if (fast_dir == 0) + { + frname[frname_len-1] = 0; + if (stat (frname, &st) == 0) + { + /* As soon as we find the first instance of the framework, + we stop and never use any later instance of that + framework. */ + add_framework (fname, fname_len, dir); + } + else + { + /* If we can't find the parent directory, no point looking + further. */ + free (frname); + return 0; + } + frname[frname_len-1] = '/'; + } + /* APPLE LOCAL end mainline */ + /* Append framework_header_dirs and header file name */ for (i = 0; framework_header_dirs[i].dirName; i++) { @@ -280,11 +571,8 @@ framework_construct_pathname (const char *fname, cpp_dir *dir) &fname[fname_len]); if (stat (frname, &st) == 0) - { - if (fast_dir == 0) - add_framework (fname, fname_len, dir); - return frname; - } + /* APPLE LOCAL mainline */ + return frname; } free (frname); @@ -525,3 +813,44 @@ find_subframework_header (cpp_reader *pfile, const char *header, cpp_dir **dirp) return 0; } + +/* APPLE LOCAL begin CALL_ON_LOAD/CALL_ON_UNLOAD pragmas 20020202 --turly */ +extern void mod_init_section (void), mod_term_section (void); +/* Grab the function name from the pragma line and output it to the + assembly output file with the parameter DIRECTIVE. Called by the + pragma CALL_ON_LOAD and CALL_ON_UNLOAD handlers below. + So: "#pragma CALL_ON_LOAD foo" will output ".mod_init_func _foo". */ + +static void directive_with_named_function (const char *pragma_name, + void (*section_function) (void)) +{ + tree decl; + int tok; + + tok = c_lex (&decl); + if (tok == CPP_NAME && decl) + { + extern FILE *asm_out_file; + + section_function (); + fprintf (asm_out_file, "\t.long _%s\n", IDENTIFIER_POINTER (decl)); + + if (c_lex (&decl) != CPP_EOF) + warning ("junk at end of #pragma %s <function_name>\n", pragma_name); + } + else + warning ("function name expected after #pragma %s\n", pragma_name); +} +void +darwin_pragma_call_on_load (cpp_reader *pfile ATTRIBUTE_UNUSED) +{ + warning("Pragma CALL_ON_LOAD is deprecated; use constructor attribute instead"); + directive_with_named_function ("CALL_ON_LOAD", mod_init_section); +} +void +darwin_pragma_call_on_unload (cpp_reader *pfile ATTRIBUTE_UNUSED) +{ + warning("Pragma CALL_ON_UNLOAD is deprecated; use destructor attribute instead"); + directive_with_named_function ("CALL_ON_UNLOAD", mod_term_section); +} +/* APPLE LOCAL end CALL_ON_LOAD/CALL_ON_UNLOAD pragmas 20020202 --turly */ |