aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/darwin.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/darwin.c')
-rw-r--r--gcc/config/darwin.c706
1 files changed, 681 insertions, 25 deletions
diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c
index 858d150d45e..67a03505415 100644
--- a/gcc/config/darwin.c
+++ b/gcc/config/darwin.c
@@ -42,11 +42,76 @@ Boston, MA 02111-1307, USA. */
#include "langhooks.h"
#include "tm_p.h"
#include "errors.h"
+/* APPLE LOCAL begin constant cfstrings */
+#include "hashtab.h"
+#include "toplev.h"
+
+static tree darwin_build_constant_cfstring (tree);
+/* APPLE LOCAL end constant cfstrings */
static int machopic_data_defined_p (const char *);
static void update_non_lazy_ptrs (const char *);
static void update_stubs (const char *);
-static const char *machopic_non_lazy_ptr_name (const char*);
+const char *machopic_non_lazy_ptr_name (const char*);
+
+/* APPLE LOCAL begin constant cfstrings */
+enum darwin_builtins
+{
+ DARWIN_BUILTIN_MIN = (int)TARGET_BUILTIN_MAX,
+
+ DARWIN_BUILTIN_CFSTRINGMAKECONSTANTSTRING,
+ DARWIN_BUILTIN_MAX
+};
+/* APPLE LOCAL end constant cfstrings */
+
+/* APPLE LOCAL prototypes */
+static tree machopic_non_lazy_ptr_list_entry PARAMS ((const char*, int));
+static tree machopic_stub_list_entry PARAMS ((const char *));
+
+/* APPLE LOCAL begin coalescing */
+void
+make_decl_coalesced (tree decl, int private_extern_p)
+ /* 0 for global, 1 for private extern */
+{
+ int no_toc_p = 1; /* Don't add to table of contents */
+#if 0
+ const char *decl_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+#endif
+ static const char *const names[4] = {
+ "__TEXT,__textcoal,coalesced",
+ "__TEXT,__textcoal_nt,coalesced,no_toc",
+ "__DATA,__datacoal,coalesced",
+ "__DATA,__datacoal_nt,coalesced,no_toc",
+ };
+ const char *sec;
+ int idx;
+
+ /* Do nothing if coalescing is disabled. */
+ if (!COALESCING_ENABLED_P())
+ return;
+
+ /* We *do* need to mark these *INTERNAL* functions coalesced: though
+ these pseudo-functions themselves will never appear, their cloned
+ descendants need to be marked coalesced too. */
+#if 0
+ /* Don't touch anything with " *INTERNAL" in its name. */
+ if (strstr (decl_name, " *INTERNAL") != NULL)
+ return;
+#endif
+
+ DECL_COALESCED (decl) = 1;
+ if (private_extern_p)
+ DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+ TREE_PUBLIC (decl) = 1;
+
+ idx = 0;
+ if (TREE_CODE (decl) != FUNCTION_DECL)
+ idx = 2;
+ sec = names[idx + (no_toc_p ? 1 : 0)];
+
+ DECL_SECTION_NAME (decl) = build_string (strlen (sec), sec);
+}
+/* APPLE LOCAL end coalescing */
int
name_needs_quotes (const char *name)
@@ -187,6 +252,14 @@ machopic_ident_defined_p (tree ident)
static int
machopic_data_defined_p (const char *name)
{
+ /* APPLE LOCAL BEGIN fix-and-continue mrs */
+#ifndef TARGET_INDIRECT_ALL_DATA
+#define TARGET_INDIRECT_ALL_DATA 0
+#endif
+ if (TARGET_INDIRECT_ALL_DATA)
+ return 0;
+ /* APPLE LOCAL END fix-and-continue mrs */
+
switch (machopic_classify_ident (get_identifier (name)))
{
case MACHOPIC_DEFINED_DATA:
@@ -264,18 +337,19 @@ static GTY(()) tree machopic_non_lazy_pointers;
either by finding it in our list of pointer names, or by generating
a new one. */
-static const char *
-machopic_non_lazy_ptr_name (const char *name)
+/* APPLE LOCAL weak import */
+/* machopic_non_lazy_ptr_list_entry separated from machopic_non_lazy_ptr_name */
+static tree
+machopic_non_lazy_ptr_list_entry (const char *name, int create_p)
{
- const char *temp_name;
- tree temp, ident = get_identifier (name);
-
+ tree temp, ident = (create_p) ? get_identifier (name) : NULL;
+
for (temp = machopic_non_lazy_pointers;
temp != NULL_TREE;
temp = TREE_CHAIN (temp))
{
if (ident == TREE_VALUE (temp))
- return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
+ return temp;
}
name = darwin_strip_name_encoding (name);
@@ -287,14 +361,14 @@ machopic_non_lazy_ptr_name (const char *name)
{
if (TREE_VALUE (temp))
{
- temp_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
+ const char *temp_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
temp_name = darwin_strip_name_encoding (temp_name);
if (strcmp (name, temp_name) == 0)
- return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
+ return temp;
}
}
- {
+ if (create_p) {
char *buffer;
int namelen = strlen (name);
int bufferlen = 0;
@@ -325,17 +399,39 @@ machopic_non_lazy_ptr_name (const char *name)
TREE_USED (machopic_non_lazy_pointers) = 0;
- return IDENTIFIER_POINTER (ptr_name);
+ return machopic_non_lazy_pointers;
}
+
+ return NULL;
+}
+
+/* APPLE LOCAL begin coalescing */
+/* Was the variable NAME ever referenced? */
+int
+machopic_var_referred_to_p (const char *name)
+{
+ return (machopic_non_lazy_ptr_list_entry (name, /*create:*/ 0) != NULL);
+}
+/* APPLE LOCAL end coalescing */
+
+/* APPLE LOCAL begin weak import */
+const char *
+machopic_non_lazy_ptr_name (const char *name)
+{
+ return IDENTIFIER_POINTER (TREE_PURPOSE
+ (machopic_non_lazy_ptr_list_entry (name, /*create:*/ 1)));
}
+/* APPLE LOCAL end weak import */
static GTY(()) tree machopic_stubs;
/* Return the name of the stub corresponding to the given name,
generating a new stub name if necessary. */
-const char *
-machopic_stub_name (const char *name)
+/* APPLE LOCAL begin weak import */
+/* machopic_stub_list_entry separated from machopic_stub_name */
+static tree
+machopic_stub_list_entry (const char *name)
{
tree temp, ident = get_identifier (name);
const char *tname;
@@ -345,16 +441,22 @@ machopic_stub_name (const char *name)
temp = TREE_CHAIN (temp))
{
if (ident == TREE_VALUE (temp))
- return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
+ return temp;
tname = IDENTIFIER_POINTER (TREE_VALUE (temp));
if (strcmp (name, tname) == 0)
- return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
+ return temp;
+
+ /* APPLE LOCAL Stripped encodings ('!T_' and '!t_') should match. */
+ if (name [0] == '!' && tname[0] == '!'
+ && strcmp (name + 4, tname + 4) == 0)
+ return temp;
+
/* A library call name might not be section-encoded yet, so try
it against a stripped name. */
if (name[0] != '!'
&& tname[0] == '!'
&& strcmp (name, tname + 4) == 0)
- return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
+ return temp;
}
name = darwin_strip_name_encoding (name);
@@ -406,10 +508,17 @@ machopic_stub_name (const char *name)
machopic_stubs = tree_cons (ptr_name, ident, machopic_stubs);
TREE_USED (machopic_stubs) = 0;
- return IDENTIFIER_POINTER (ptr_name);
+ return machopic_stubs;
}
}
+const char *
+machopic_stub_name (const char *name)
+{
+ return IDENTIFIER_POINTER (TREE_PURPOSE (machopic_stub_list_entry (name)));
+}
+/* APPLE LOCAL end weak import */
+
void
machopic_validate_stub_or_non_lazy_ptr (const char *name, int validate_stub)
{
@@ -448,6 +557,8 @@ machopic_indirect_data_reference (rtx orig, rtx reg)
if (GET_CODE (orig) == SYMBOL_REF)
{
const char *name = XSTR (orig, 0);
+ /* APPLE LOCAL weak import */
+ tree sym;
int defined = machopic_data_defined_p (name);
if (defined && MACHO_DYNAMIC_NO_PIC_P)
@@ -499,8 +610,14 @@ machopic_indirect_data_reference (rtx orig, rtx reg)
return orig;
}
+ /* APPLE LOCAL weak import */
+ sym = machopic_non_lazy_ptr_list_entry (name, /*create:*/ 1);
+ IDENTIFIER_WEAK_IMPORT (TREE_PURPOSE (sym)) =
+ IDENTIFIER_WEAK_IMPORT (TREE_VALUE (sym)) =
+ SYMBOL_REF_WEAK_IMPORT (orig);
+
ptr_ref = gen_rtx_SYMBOL_REF (Pmode,
- machopic_non_lazy_ptr_name (name));
+ IDENTIFIER_POINTER (TREE_PURPOSE (sym)));
ptr_ref = gen_rtx_MEM (Pmode, ptr_ref);
RTX_UNCHANGING_P (ptr_ref) = 1;
@@ -585,9 +702,14 @@ machopic_indirect_call_target (rtx target)
if (!machopic_name_defined_p (name))
{
- const char *stub_name = machopic_stub_name (name);
-
- XEXP (target, 0) = gen_rtx_SYMBOL_REF (mode, stub_name);
+ /* APPLE LOCAL weak import */
+ tree stub = machopic_stub_list_entry (name);
+ IDENTIFIER_WEAK_IMPORT (TREE_PURPOSE (stub)) =
+ IDENTIFIER_WEAK_IMPORT (TREE_VALUE (stub)) =
+ SYMBOL_REF_WEAK_IMPORT (XEXP (target, 0));
+
+ XEXP (target, 0) = gen_rtx_SYMBOL_REF (mode,
+ IDENTIFIER_POINTER (TREE_PURPOSE (stub)));
RTX_UNCHANGING_P (target) = 1;
}
}
@@ -855,6 +977,43 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
RTX_UNCHANGING_P (pic_ref) = 1;
+ /* APPLE LOCAL begin gen ADD */
+#ifdef MASK_80387
+ {
+ rtx mem, other;
+
+ if (GET_CODE (orig) == MEM) {
+ mem = orig; other = base;
+ /* Swap the kids only if there is only one MEM, and it's on the right. */
+ if (GET_CODE (base) != MEM) {
+ XEXP (pic_ref, 0) = orig;
+ XEXP (pic_ref, 1) = base;
+ }
+ }
+ else if (GET_CODE (base) == MEM) {
+ mem = base; other = orig;
+ } else
+ mem = other = NULL_RTX;
+
+ /* Both kids are MEMs. */
+ if (other && GET_CODE (other) == MEM)
+ other = force_reg (GET_MODE (other), other);
+
+ /* The x86 can't post-index a MEM; emit an ADD instruction to handle this. */
+ if (mem && GET_CODE (mem) == MEM) {
+ if ( ! reload_in_progress) {
+ rtx set = gen_rtx_SET (VOIDmode, reg, pic_ref);
+ rtx clobber_cc = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG));
+ pic_ref = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set, clobber_cc));
+ emit_insn (pic_ref);
+ pic_ref = reg;
+ is_complex = 0;
+ }
+ }
+ }
+#endif
+ /* APPLE LOCAL end gen ADD */
+
if (reg && is_complex)
{
emit_move_insn (reg, pic_ref);
@@ -871,7 +1030,12 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
else if (GET_CODE (orig) == MEM
&& GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
{
- rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
+ /* APPLE LOCAL use new pseudo for temp; reusing reg confuses PRE */
+ rtx tempreg = reg;
+ rtx addr;
+ if ( !no_new_pseudos )
+ tempreg = gen_reg_rtx (Pmode);
+ addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, tempreg);
addr = gen_rtx_MEM (GET_MODE (orig), addr);
RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
@@ -916,6 +1080,14 @@ machopic_finish (FILE *asm_out_file)
else
stub[0] = '_', strcpy (stub + 1, stub_name);
+ /* APPLE LOCAL weak import */
+ if ( IDENTIFIER_WEAK_IMPORT (TREE_VALUE (temp)))
+ {
+ fprintf (asm_out_file, "\t.weak_reference ");
+ assemble_name (asm_out_file, sym_name);
+ fprintf (asm_out_file, "\n");
+ }
+
machopic_output_stub (asm_out_file, sym, stub);
}
@@ -929,7 +1101,11 @@ machopic_finish (FILE *asm_out_file)
if (! TREE_USED (temp))
continue;
- if (machopic_ident_defined_p (TREE_VALUE (temp)))
+ /* APPLE LOCAL fix-and-continue mrs */
+ if (! TARGET_INDIRECT_ALL_DATA
+ && (machopic_ident_defined_p (TREE_VALUE (temp))
+ /* APPLE LOCAL private extern */
+ || (sym_name[0] == '!' && sym_name[2] == 'p')))
{
data_section ();
assemble_align (GET_MODE_ALIGNMENT (Pmode));
@@ -940,6 +1116,17 @@ machopic_finish (FILE *asm_out_file)
}
else
{
+ /* APPLE LOCAL fix-and-continue mrs */
+ rtx init = const0_rtx;
+
+ /* APPLE LOCAL weak import */
+ if ( IDENTIFIER_WEAK_IMPORT (TREE_VALUE (temp)))
+ {
+ fprintf (asm_out_file, "\t.weak_reference ");
+ assemble_name (asm_out_file, sym_name);
+ fprintf (asm_out_file, "\n");
+ }
+
machopic_nl_symbol_ptr_section ();
assemble_name (asm_out_file, lazy_name);
fprintf (asm_out_file, ":\n");
@@ -948,8 +1135,14 @@ machopic_finish (FILE *asm_out_file)
assemble_name (asm_out_file, sym_name);
fprintf (asm_out_file, "\n");
- assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
+ /* APPLE LOCAL BEGIN fix-and-continue mrs */
+ if (sym_name[3] == 's'
+ && machopic_ident_defined_p (TREE_VALUE (temp)))
+ init = gen_rtx_SYMBOL_REF (Pmode, sym_name);
+
+ assemble_integer (init, GET_MODE_SIZE (Pmode),
GET_MODE_ALIGNMENT (Pmode), 1);
+ /* APPLE LOCAL END fix-and-continue mrs */
}
}
}
@@ -1004,11 +1197,28 @@ darwin_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
if ((TREE_CODE (decl) == FUNCTION_DECL
|| TREE_CODE (decl) == VAR_DECL)
&& !DECL_EXTERNAL (decl)
+ /* APPLE LOCAL coalescing */
+#ifdef DECL_IS_COALESCED_OR_WEAK
+ && ! DECL_IS_COALESCED_OR_WEAK (decl)
+#endif
&& ((TREE_STATIC (decl)
&& (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
|| (DECL_INITIAL (decl)
&& DECL_INITIAL (decl) != error_mark_node)))
defined = 1;
+ /* APPLE LOCAL fix OBJC codegen */
+ if (TREE_CODE (decl) == VAR_DECL)
+ {
+ sym_ref = XEXP (DECL_RTL (decl), 0);
+ orig_str = XSTR (sym_ref, 0);
+ if ( orig_str[0] == '_'
+ && orig_str[1] == 'O'
+ && orig_str[2] == 'B'
+ && orig_str[3] == 'J'
+ && orig_str[4] == 'C'
+ && orig_str[5] == '_')
+ defined = 1;
+ }
if (TREE_CODE (decl) == FUNCTION_DECL)
code = (defined ? 'T' : 't');
@@ -1041,7 +1251,15 @@ darwin_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
new_str[0] = '!';
new_str[1] = code;
new_str[2] = '_';
+ /* APPLE LOCAL private extern */
+ if (DECL_VISIBILITY (decl) == VISIBILITY_HIDDEN)
+ new_str[2] = 'p';
new_str[3] = '_';
+ /* APPLE LOCAL BEGIN fix-and-continue mrs */
+ if (TARGET_INDIRECT_ALL_DATA
+ && TREE_CODE (decl) == VAR_DECL && ! TREE_PUBLIC (decl))
+ new_str[3] = 's';
+ /* APPLE LOCAL END fix-and-continue mrs */
memcpy (new_str + 4, orig_str, len);
XSTR (sym_ref, 0) = ggc_alloc_string (new_str, new_len);
}
@@ -1161,9 +1379,24 @@ machopic_select_section (tree exp, int reloc,
&& TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
&& TYPE_NAME (TREE_TYPE (exp)))
{
+ /* APPLE LOCAL begin constant strings */
+ extern int flag_next_runtime;
+ extern const char *constant_string_class_name;
+ /* APPLE LOCAL end constant strings */
tree name = TYPE_NAME (TREE_TYPE (exp));
if (TREE_CODE (name) == TYPE_DECL)
name = DECL_NAME (name);
+ /* APPLE LOCAL begin constant strings */
+ if (constant_string_class_name
+ && !strcmp (IDENTIFIER_POINTER (name),
+ constant_string_class_name))
+ {
+ if (flag_next_runtime)
+ objc_constant_string_object_section ();
+ else
+ objc_string_object_section ();
+ }
+ /* APPLE LOCAL end constant strings */
if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
objc_constant_string_object_section ();
else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
@@ -1171,6 +1404,26 @@ machopic_select_section (tree exp, int reloc,
else
base_function ();
}
+ /* APPLE LOCAL begin constant cfstrings */
+ else if (TREE_CODE (exp) == CONSTRUCTOR
+ && TREE_TYPE (exp)
+ && TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE
+ && TREE_OPERAND (exp, 0))
+ {
+ tree name = TREE_OPERAND (exp, 0);
+ if (TREE_CODE (name) == TREE_LIST && TREE_VALUE (name)
+ && TREE_CODE (TREE_VALUE (name)) == NOP_EXPR
+ && TREE_OPERAND (TREE_VALUE (name), 0)
+ && TREE_OPERAND (TREE_OPERAND (TREE_VALUE (name), 0), 0))
+ name = TREE_OPERAND (TREE_OPERAND (TREE_VALUE (name), 0), 0);
+ if (TREE_CODE (name) == VAR_DECL
+ && !strcmp (IDENTIFIER_POINTER (DECL_NAME (name)),
+ "__CFConstantStringClassReference"))
+ cfstring_constant_object_section ();
+ else
+ base_function ();
+ }
+ /* APPLE LOCAL end constant cfstrings */
else if (TREE_CODE (exp) == VAR_DECL &&
DECL_NAME (exp) &&
TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
@@ -1228,6 +1481,10 @@ machopic_select_section (tree exp, int reloc,
else
base_function ();
}
+ /* APPLE LOCAL begin darwin_set_section_for_var_p */
+ else if (darwin_set_section_for_var_p (exp, reloc, align))
+ ;
+ /* APPLE LOCAL end darwin_set_section_for_var_p */
else
base_function ();
}
@@ -1289,6 +1546,175 @@ darwin_globalize_label (FILE *stream, const char *name)
default_globalize_label (stream, name);
}
+/* APPLE LOCAL begin assembly "abort" directive */
+/* This can be called instead of EXIT. It will emit a '.abort' directive
+ into any existing assembly file, causing assembly to immediately abort,
+ thus preventing the assembler from spewing out numerous, irrelevant
+ error messages. */
+
+void
+abort_assembly_and_exit (int status)
+{
+ /* If we're aborting, get the assembler to abort, too. */
+ if (status == FATAL_EXIT_CODE && asm_out_file != 0)
+ fprintf (asm_out_file, "\n.abort\n");
+
+ exit (status);
+}
+/* APPLE LOCAL end assembly "abort" directive */
+
+/* APPLE LOCAL coalescing */
+void
+darwin_asm_named_section (const char *name, unsigned int flags ATTRIBUTE_UNUSED)
+{
+ fprintf (asm_out_file, ".section %s\n", name);
+}
+
+unsigned int
+darwin_section_type_flags (tree decl, const char *name, int reloc)
+{
+ unsigned int flags = default_section_type_flags (decl, name, reloc);
+
+ /* Weak or coalesced variables live in a writable section. */
+ if (decl != 0 && TREE_CODE (decl) != FUNCTION_DECL
+ && DECL_IS_COALESCED_OR_WEAK (decl))
+ flags |= SECTION_WRITE;
+
+ return flags;
+}
+/* APPLE LOCAL end coalescing */
+
+/* APPLE LOCAL begin double destructor turly 20020214 */
+#include "c-common.h"
+
+/* Handle __attribute__ ((apple_kext_compatibility)).
+ This only applies to darwin kexts for 295 compatibility -- it shrinks the
+ vtable for classes with this attribute (and their descendants) by not
+ outputting the new 3.0 nondeleting destructor. This means that such
+ objects CANNOT be allocated on the stack or as globals UNLESS they have
+ a completely empty `operator delete'.
+ Luckily, this fits in with the Darwin kext model.
+
+ This attribute also disables gcc3's potential overlaying of derived
+ class data members on the padding at the end of the base class. */
+
+tree
+darwin_handle_odd_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
+ int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+{
+ if (! POSSIBLY_COMPILING_APPLE_KEXT_P ())
+ {
+ warning ("`%s' 2.95 vtable-compatability attribute applies "
+ "only when compiling a kext", IDENTIFIER_POINTER (name));
+
+ *no_add_attrs = true;
+ }
+ else if (TREE_CODE (*node) != RECORD_TYPE)
+ {
+ warning ("`%s' 2.95 vtable-compatability attribute applies "
+ "only to C++ classes", IDENTIFIER_POINTER (name));
+
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+/* APPLE LOCAL end double destructor turly 20020214 */
+
+/* APPLE LOCAL begin darwin_set_section_for_var_p turly 20020226 */
+
+/* This is specifically for any initialised static class constants
+ which may be output by the C++ front end at the end of compilation.
+ SELECT_SECTION () macro won't do because these are VAR_DECLs, not
+ STRING_CSTs or INTEGER_CSTs. And by putting 'em in appropriate
+ sections, we save space. */
+
+extern void cstring_section (void),
+ literal4_section (void), literal8_section (void);
+int
+darwin_set_section_for_var_p (tree exp, int reloc, int align)
+{
+ if (!reloc && TREE_CODE (exp) == VAR_DECL
+ && DECL_ALIGN (exp) == align
+ && TREE_READONLY (exp) && DECL_INITIAL (exp))
+ {
+ /* Put constant string vars in ".cstring" section. */
+
+ if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (exp))) == INTEGER_TYPE
+ && integer_onep (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (exp))))
+ && TREE_CODE (DECL_INITIAL (exp)) == STRING_CST)
+ {
+
+ /* Compare string length with actual number of characters
+ the compiler will write out (which is not necessarily
+ TREE_STRING_LENGTH, in the case of a constant array of
+ characters that is not null-terminated). Select appropriate
+ section accordingly. */
+
+ if (MIN ( TREE_STRING_LENGTH (DECL_INITIAL(exp)),
+ int_size_in_bytes (TREE_TYPE (exp)))
+ == (long) strlen (TREE_STRING_POINTER (DECL_INITIAL (exp))) + 1)
+ {
+ cstring_section ();
+ return 1;
+ }
+ else
+ {
+ const_section ();
+ return 1;
+ }
+ }
+ else
+ if (TREE_READONLY (TREE_TYPE (exp))
+ && ((TREE_CODE (TREE_TYPE (exp)) == INTEGER_TYPE
+ && TREE_CODE (DECL_INITIAL (exp)) == INTEGER_CST)
+ || (TREE_CODE (TREE_TYPE (exp)) == REAL_TYPE
+ && TREE_CODE (DECL_INITIAL (exp)) == REAL_CST))
+ && TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (DECL_INITIAL (exp))))
+ == INTEGER_CST)
+ {
+ tree size = TYPE_SIZE_UNIT (TREE_TYPE (DECL_INITIAL (exp)));
+ if (TREE_INT_CST_HIGH (size) != 0)
+ return 0;
+
+ /* Put integer and float consts in the literal4|8 sections. */
+
+ if (TREE_INT_CST_LOW (size) == 4)
+ {
+ literal4_section ();
+ return 1;
+ }
+ else if (TREE_INT_CST_LOW (size) == 8)
+ {
+ literal8_section ();
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+/* APPLE LOCAL end darwin_set_section_for_var_p turly 20020226 */
+
+/* APPLE LOCAL begin C++ EH */
+/* Generate a PC-relative reference to a Mach-O non-lazy-symbol. */
+void
+darwin_non_lazy_pcrel (FILE *file, rtx addr)
+{
+ const char *str;
+ const char *nlp_name;
+
+ if (GET_CODE (addr) != SYMBOL_REF)
+ abort ();
+
+ str = darwin_strip_name_encoding (XSTR (addr, 0));
+ nlp_name = machopic_non_lazy_ptr_name (str);
+ fputs ("\t.long\t", file);
+ ASM_OUTPUT_LABELREF (file, nlp_name);
+ fputs ("-.", file);
+}
+/* APPLE LOCAL end C++ EH */
+
/* Emit an assembler directive to set visibility for a symbol. The
only supported visibilities are VISIBILITY_DEFAULT and
VISIBILITY_HIDDEN; the latter corresponds to Darwin's "private
@@ -1343,7 +1769,8 @@ void
darwin_file_end (void)
{
machopic_finish (asm_out_file);
- if (strcmp (lang_hooks.name, "GNU C++") == 0)
+ /* APPLE LOCAL constant cfstrings */
+ if (darwin_running_cxx)
{
constructor_section ();
destructor_section ();
@@ -1351,4 +1778,233 @@ darwin_file_end (void)
}
}
+/* APPLE LOCAL begin constant cfstrings */
+int darwin_constant_cfstrings = 0;
+const char *darwin_constant_cfstrings_switch;
+int darwin_warn_nonportable_cfstrings = 1; /* on by default. */
+const char *darwin_warn_nonportable_cfstrings_switch;
+int darwin_pascal_strings = 0;
+const char *darwin_pascal_strings_switch;
+int darwin_running_cxx;
+
+static GTY(()) tree cfstring_class_reference = NULL_TREE;
+static GTY(()) tree cfstring_type_node = NULL_TREE;
+static GTY(()) tree ccfstring_type_node = NULL_TREE;
+static GTY(()) tree pccfstring_type_node = NULL_TREE;
+static GTY(()) tree pcint_type_node = NULL_TREE;
+static GTY(()) tree pcchar_type_node = NULL_TREE;
+
+/* Store all constructed constant CFStrings in a hash table so that
+ they get uniqued properly. */
+
+struct cfstring_descriptor GTY(())
+{
+ /* The literal argument . */
+ tree literal;
+
+ /* The resulting constant CFString. */
+ tree constructor;
+};
+
+static GTY((param_is (struct cfstring_descriptor))) htab_t cfstring_htab;
+
+static hashval_t cfstring_hash (const void *);
+static int cfstring_eq (const void *, const void *);
+
+void
+darwin_init_cfstring_builtins (void)
+{
+ tree field, fields, pccfstring_ftype_pcchar;
+
+ /* struct __builtin_CFString {
+ const int *isa; (will point at
+ int flags; __CFConstantStringClassReference)
+ const char *str;
+ int length;
+ }; */
+
+ pcint_type_node
+ = build_pointer_type (build_qualified_type (integer_type_node,
+ TYPE_QUAL_CONST));
+ pcchar_type_node
+ = build_pointer_type (build_qualified_type (char_type_node,
+ TYPE_QUAL_CONST));
+ cfstring_type_node = (*lang_hooks.types.make_type) (RECORD_TYPE);
+ fields = build_decl (FIELD_DECL, NULL_TREE, pcint_type_node);
+ field = build_decl (FIELD_DECL, NULL_TREE, integer_type_node);
+ TREE_CHAIN (field) = fields; fields = field;
+ field = build_decl (FIELD_DECL, NULL_TREE, pcchar_type_node);
+ TREE_CHAIN (field) = fields; fields = field;
+ field = build_decl (FIELD_DECL, NULL_TREE, integer_type_node);
+ TREE_CHAIN (field) = fields; fields = field;
+ /* NB: The finish_builtin_struct() routine expects FIELD_DECLs in
+ reverse order! */
+ finish_builtin_struct (cfstring_type_node, "__builtin_CFString",
+ fields, NULL_TREE);
+
+ /* const struct __builtin_CFstring *
+ __builtin___CFStringMakeConstantString (const char *); */
+
+ ccfstring_type_node
+ = build_qualified_type (cfstring_type_node, TYPE_QUAL_CONST);
+ pccfstring_type_node
+ = build_pointer_type (ccfstring_type_node);
+ pccfstring_ftype_pcchar
+ = build_function_type_list (pccfstring_type_node,
+ pcchar_type_node, NULL_TREE);
+ builtin_function ("__builtin___CFStringMakeConstantString",
+ pccfstring_ftype_pcchar,
+ DARWIN_BUILTIN_CFSTRINGMAKECONSTANTSTRING,
+ BUILT_IN_NORMAL, NULL, NULL_TREE);
+
+ /* extern int __CFConstantStringClassReference[]; */
+ cfstring_class_reference
+ = build_decl (VAR_DECL,
+ get_identifier ("__CFConstantStringClassReference"),
+ build_array_type (integer_type_node, NULL_TREE));
+ DECL_EXTERNAL (cfstring_class_reference) = 1;
+ TREE_PUBLIC (cfstring_class_reference) = 1;
+ TREE_USED (cfstring_class_reference) = 1;
+ DECL_ARTIFICIAL (cfstring_class_reference) = 1;
+ (*lang_hooks.decls.pushdecl) (cfstring_class_reference);
+ rest_of_decl_compilation (cfstring_class_reference, 0, 0, 0);
+
+ /* Initialize the hash table used to hold the constant CFString objects. */
+ cfstring_htab = htab_create_ggc (31, cfstring_hash,
+ cfstring_eq, NULL);
+}
+
+tree
+darwin_expand_tree_builtin (tree function, tree params,
+ tree coerced_params ATTRIBUTE_UNUSED)
+{
+ unsigned int fcode = DECL_FUNCTION_CODE (function);
+
+ switch (fcode)
+ {
+ case DARWIN_BUILTIN_CFSTRINGMAKECONSTANTSTRING:
+ if (!darwin_constant_cfstrings)
+ {
+ error ("built-in function `%s' requires `-fconstant-cfstrings' flag",
+ IDENTIFIER_POINTER (DECL_NAME (function)));
+ return error_mark_node;
+ }
+
+ return darwin_build_constant_cfstring (TREE_VALUE (params));
+ default:
+ break;
+ }
+
+ return NULL_TREE;
+}
+
+static hashval_t
+cfstring_hash (const void *ptr)
+{
+ tree str = ((struct cfstring_descriptor *)ptr)->literal;
+ const unsigned char *p = (const unsigned char *) TREE_STRING_POINTER (str);
+ int i, len = TREE_STRING_LENGTH (str);
+ hashval_t h = len;
+
+ for (i = 0; i < len; i++)
+ h = ((h * 613) + p[i]);
+
+ return h;
+}
+
+static int
+cfstring_eq (const void *ptr1, const void *ptr2)
+{
+ tree str1 = ((struct cfstring_descriptor *)ptr1)->literal;
+ tree str2 = ((struct cfstring_descriptor *)ptr2)->literal;
+ int len1 = TREE_STRING_LENGTH (str1);
+
+ return (len1 == TREE_STRING_LENGTH (str2)
+ && !memcmp (TREE_STRING_POINTER (str1), TREE_STRING_POINTER (str2),
+ len1));
+}
+
+tree
+darwin_construct_objc_string (tree str)
+{
+ if (!darwin_constant_cfstrings)
+ return NULL_TREE; /* Fall back to NSConstantString. */
+
+ return darwin_build_constant_cfstring (str);
+}
+
+static tree
+darwin_build_constant_cfstring (tree str)
+{
+ struct cfstring_descriptor *desc, key;
+ void **loc;
+
+ if (!str || TREE_CODE (str) != STRING_CST)
+ {
+ error ("CFString literal expression is not constant");
+ return error_mark_node;
+ }
+
+ /* Perhaps we already constructed a constant CFString just like this one? */
+ key.literal = str;
+ loc = htab_find_slot (cfstring_htab, &key, INSERT);
+ desc = *loc;
+
+ if (!desc)
+ {
+ tree initlist, constructor, field = TYPE_FIELDS (ccfstring_type_node);
+ int length = TREE_STRING_LENGTH (str) - 1;
+
+ if (darwin_warn_nonportable_cfstrings)
+ {
+ extern int isascii (int);
+ const char *s = TREE_STRING_POINTER (str);
+ int l = 0;
+
+ for (l = 0; l < length; l++)
+ if (!s[l] || !isascii (s[l]))
+ {
+ warning ("%s in CFString literal",
+ s[l] ? "non-ASCII character" : "embedded NUL");
+ break;
+ }
+ }
+
+ *loc = desc = ggc_alloc (sizeof (*desc));
+ desc->literal = str;
+
+ initlist = build_tree_list
+ (field, build1 (ADDR_EXPR, pcint_type_node,
+ cfstring_class_reference));
+ field = TREE_CHAIN (field);
+ initlist = tree_cons (field, build_int_2 (0x000007c8, 0),
+ initlist);
+ field = TREE_CHAIN (field);
+ initlist = tree_cons (field,
+ build1 (ADDR_EXPR, pcchar_type_node,
+ str), initlist);
+ field = TREE_CHAIN (field);
+ initlist = tree_cons (field, build_int_2 (length, 0),
+ initlist);
+
+ constructor = build_constructor (ccfstring_type_node,
+ nreverse (initlist));
+ TREE_READONLY (constructor) = 1;
+ TREE_CONSTANT (constructor) = 1;
+ TREE_STATIC (constructor) = 1;
+
+ /* Fromage: The C++ flavor of 'build_unary_op' expects constructor nodes
+ to have the TREE_HAS_CONSTRUCTOR (...) bit set. However, this file is
+ being built without any knowledge of C++ tree accessors; hence, we shall
+ use the generic accessor that TREE_HAS_CONSTRUCTOR actually maps to! */
+ if (darwin_running_cxx)
+ TREE_LANG_FLAG_4 (constructor) = 1; /* TREE_HAS_CONSTRUCTOR */
+
+ desc->constructor = constructor;
+ }
+
+ return build1 (ADDR_EXPR, pccfstring_type_node, desc->constructor);
+}
+/* APPLE LOCAL end constant cfstrings */
+
#include "gt-darwin.h"