/* Definitions of target machine for GNU compiler,
for some generic XCOFF file format
- Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002, 2003, 2004, 2007, 2008
+ Free Software Foundation, Inc.
-This file is part of GNU CC.
+ This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
#define TARGET_OBJECT_FORMAT OBJECT_XCOFF
/* The RS/6000 uses the XCOFF format. */
-#define XCOFF_DEBUGGING_INFO
+#define XCOFF_DEBUGGING_INFO 1
/* Define if the object format being used is COFF or a superset. */
#define OBJECT_FORMAT_COFF
#define DOLLARS_IN_IDENTIFIERS 0
-/* Define the extra sections we need. We define three: one is the read-only
- data section which is used for constants. This is a csect whose name is
- derived from the name of the input file. The second is for initialized
- global variables. This is a csect whose name is that of the variable.
- The third is the TOC. */
-
-#define EXTRA_SECTIONS \
- read_only_data, private_data, read_only_private_data, toc, bss
-
-/* Define the routines to implement these extra sections.
- BIGGEST_ALIGNMENT is 64, so align the sections that much. */
-
-#define EXTRA_SECTION_FUNCTIONS \
- \
-void \
-read_only_data_section () \
-{ \
- if (in_section != read_only_data) \
- { \
- fprintf (asm_out_file, "\t.csect %s[RO],3\n", \
- xcoff_read_only_section_name); \
- in_section = read_only_data; \
- } \
-} \
- \
-void \
-private_data_section () \
-{ \
- if (in_section != private_data) \
- { \
- fprintf (asm_out_file, "\t.csect %s[RW],3\n", \
- xcoff_private_data_section_name); \
- in_section = private_data; \
- } \
-} \
- \
-void \
-read_only_private_data_section () \
-{ \
- if (in_section != read_only_private_data) \
- { \
- fprintf (asm_out_file, "\t.csect %s[RO],3\n", \
- xcoff_private_data_section_name); \
- in_section = read_only_private_data; \
- } \
-} \
- \
-void \
-toc_section () \
-{ \
- if (TARGET_MINIMAL_TOC) \
- { \
- /* toc_section is always called at least once from ASM_FILE_START, \
- so this is guaranteed to always be defined once and only once \
- in each file. */ \
- if (! toc_initialized) \
- { \
- fputs ("\t.toc\nLCTOC..1:\n", asm_out_file); \
- fputs ("\t.tc toc_table[TC],toc_table[RW]\n", asm_out_file); \
- toc_initialized = 1; \
- } \
- \
- if (in_section != toc) \
- fprintf (asm_out_file, "\t.csect toc_table[RW]%s\n", \
- (TARGET_32BIT ? "" : ",3")); \
- } \
- else \
- { \
- if (in_section != toc) \
- fputs ("\t.toc\n", asm_out_file); \
- } \
- in_section = toc; \
-}
+/* AIX .align pseudo-op accept value from 0 to 12, corresponding to
+ log base 2 of the alignment in bytes; 12 = 4096 bytes = 32768 bits. */
-/* Define the name of our readonly data section. */
-
-#define READONLY_DATA_SECTION read_only_data_section
-
-/* Select the section for an initialized data object.
-
- On the RS/6000, we have a special section for all variables except those
- that are static. */
-
-#define SELECT_SECTION(EXP,RELOC,ALIGN) \
-{ \
- if ((TREE_CODE (EXP) == STRING_CST \
- && ! flag_writable_strings) \
- || (TREE_CODE_CLASS (TREE_CODE (EXP)) == 'd' \
- && TREE_READONLY (EXP) && ! TREE_THIS_VOLATILE (EXP) \
- && DECL_INITIAL (EXP) \
- && (DECL_INITIAL (EXP) == error_mark_node \
- || TREE_CONSTANT (DECL_INITIAL (EXP))) \
- && ! (RELOC))) \
- { \
- if (TREE_PUBLIC (EXP)) \
- read_only_data_section (); \
- else \
- read_only_private_data_section (); \
- } \
- else \
- { \
- if (TREE_PUBLIC (EXP)) \
- data_section (); \
- else \
- private_data_section (); \
- } \
-}
+#define MAX_OFILE_ALIGNMENT 32768
-/* Return non-zero if this entry is to be written into the constant
+/* Default alignment factor for csect directives, chosen to honor
+ BIGGEST_ALIGNMENT. */
+#define XCOFF_CSECT_DEFAULT_ALIGNMENT_STR "4"
+
+/* Return nonzero if this entry is to be written into the constant
pool in a special way. We do so if this is a SYMBOL_REF, LABEL_REF
or a CONST containing one of them. If -mfp-in-toc (the default),
we also do this for floating-point constants. We actually can only
|| (GET_CODE (X) == CONST_INT \
&& GET_MODE_BITSIZE (MODE) <= GET_MODE_BITSIZE (Pmode)) \
|| (GET_CODE (X) == CONST_DOUBLE \
- && (TARGET_POWERPC64 \
- || TARGET_MINIMAL_TOC \
- || (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \
+ && (TARGET_MINIMAL_TOC \
+ || (SCALAR_FLOAT_MODE_P (GET_MODE (X)) \
&& ! TARGET_NO_FP_IN_TOC)))))
-/* Select section for constant in constant pool.
-
- On RS/6000, all constants are in the private read-only data area.
- However, if this is being placed in the TOC it must be output as a
- toc entry. */
-
-#define SELECT_RTX_SECTION(MODE, X, ALIGN) \
-{ if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (X, MODE)) \
- toc_section (); \
- else \
- read_only_private_data_section (); \
-}
-
-/* If we are referencing a function that is static or is known to be
- in this file, make the SYMBOL_REF special. We can use this to indicate
- that we can branch to this function without emitting a no-op after the
- call. Do not set this flag if the function is weakly defined. */
-
-#define ENCODE_SECTION_INFO(DECL) \
- if (TREE_CODE (DECL) == FUNCTION_DECL \
- && !TREE_PUBLIC (DECL) \
- && !DECL_WEAK (DECL)) \
- SYMBOL_REF_FLAG (XEXP (DECL_RTL (DECL), 0)) = 1;
+#define TARGET_ASM_OUTPUT_ANCHOR rs6000_xcoff_asm_output_anchor
+#define TARGET_ASM_GLOBALIZE_LABEL rs6000_xcoff_asm_globalize_label
+#define TARGET_ASM_INIT_SECTIONS rs6000_xcoff_asm_init_sections
+#define TARGET_ASM_RELOC_RW_MASK rs6000_xcoff_reloc_rw_mask
+#define TARGET_ASM_NAMED_SECTION rs6000_xcoff_asm_named_section
+#define TARGET_ASM_SELECT_SECTION rs6000_xcoff_select_section
+#define TARGET_ASM_SELECT_RTX_SECTION rs6000_xcoff_select_rtx_section
+#define TARGET_ASM_UNIQUE_SECTION rs6000_xcoff_unique_section
+#define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
+#define TARGET_STRIP_NAME_ENCODING rs6000_xcoff_strip_name_encoding
+#define TARGET_SECTION_TYPE_FLAGS rs6000_xcoff_section_type_flags
/* FP save and restore routines. */
#define SAVE_FP_PREFIX "._savef"
#define RESTORE_FP_SUFFIX ""
/* Function name to call to do profiling. */
-#undef RS6000_MCOUNT
+#undef RS6000_MCOUNT
#define RS6000_MCOUNT ".__mcount"
-/* Function names to call to do floating point truncation. */
-
-#undef RS6000_ITRUNC
-#define RS6000_ITRUNC "__itrunc"
-#undef RS6000_UITRUNC
-#define RS6000_UITRUNC "__uitrunc"
-
/* This outputs NAME to FILE up to the first null or '['. */
-#define RS6000_OUTPUT_BASENAME(FILE, NAME) \
- { \
- const char *_p; \
- \
- STRIP_NAME_ENCODING (_p, (NAME)); \
- assemble_name ((FILE), _p); \
- }
+#define RS6000_OUTPUT_BASENAME(FILE, NAME) \
+ assemble_name ((FILE), (*targetm.strip_name_encoding) (NAME))
/* This is how to output the definition of a user-level label named NAME,
such as the label on a static function or variable NAME. */
/* This is how to output a command to make the user-level label named NAME
defined for reference from other files. */
-#define ASM_GLOBALIZE_LABEL(FILE,NAME) \
- do { fputs ("\t.globl ", FILE); \
- RS6000_OUTPUT_BASENAME (FILE, NAME); putc ('\n', FILE);} while (0)
-
-/* Remove any trailing [DS] or the like from the symbol name. */
-
-#define STRIP_NAME_ENCODING(VAR,NAME) \
- do \
- { \
- const char *_name = (NAME); \
- size_t _len; \
- if (*_name == '*') \
- _name++; \
- _len = strlen (_name); \
- if (_name[_len - 1] != ']') \
- (VAR) = _name; \
- else \
- { \
- char *_new_name = (char *) alloca (_len + 1); \
- strcpy (_new_name, _name); \
- _new_name[_len - 4] = '\0'; \
- (VAR) = _new_name; \
- } \
- } \
- while (0)
-
-/* Output at beginning of assembler file.
-
- Initialize the section names for the RS/6000 at this point.
-
- Specify filename, including full path, to assembler.
-
- We want to go into the TOC section so at least one .toc will be emitted.
- Also, in order to output proper .bs/.es pairs, we need at least one static
- [RW] section emitted.
-
- Finally, declare mcount when profiling to make the assembler happy. */
-
-#define ASM_FILE_START(FILE) \
-{ \
- rs6000_gen_section_name (&xcoff_bss_section_name, \
- main_input_filename, ".bss_"); \
- rs6000_gen_section_name (&xcoff_private_data_section_name, \
- main_input_filename, ".rw_"); \
- rs6000_gen_section_name (&xcoff_read_only_section_name, \
- main_input_filename, ".ro_"); \
- \
- fprintf (FILE, "\t.file\t\"%s\"\n", main_input_filename); \
- if (TARGET_64BIT) \
- fputs ("\t.machine\t\"ppc64\"\n", FILE); \
- toc_section (); \
- if (write_symbols != NO_DEBUG) \
- private_data_section (); \
- text_section (); \
- if (profile_flag) \
- fprintf (FILE, "\t.extern %s\n", RS6000_MCOUNT); \
- rs6000_file_start (FILE, TARGET_CPU_DEFAULT); \
-}
-
-/* Output at end of assembler file.
-
- On the RS/6000, referencing data should automatically pull in text. */
+/* Globalizing directive for a label. */
+#define GLOBAL_ASM_OP "\t.globl "
-#define ASM_FILE_END(FILE) \
-{ \
- text_section (); \
- fputs ("_section_.text:\n", FILE); \
- data_section (); \
- fputs (TARGET_32BIT \
- ? "\t.long _section_.text\n" : "\t.llong _section_.text\n", FILE); \
-}
+#undef TARGET_ASM_FILE_START
+#define TARGET_ASM_FILE_START rs6000_xcoff_file_start
+#define TARGET_ASM_FILE_END rs6000_xcoff_file_end
+#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
+#define TARGET_ASM_FILE_START_FILE_DIRECTIVE false
/* This macro produces the initial definition of a function name.
On the RS/6000, we need to place an extra '.' in the function name and
output the function descriptor.
+ Dollar signs are converted to underscores.
- The csect for the function will have already been created by the
- `text_section' call previously done. We do have to go back to that
- csect, however.
-
- We also record that the function exists in the current compilation
- unit, reachable by short branch, by setting SYMBOL_REF_FLAG.
+ The csect for the function will have already been created when
+ text_section was selected. We do have to go back to that csect, however.
The third and fourth parameters to the .function pseudo-op (16 and 044)
are placeholders which no longer have any use. */
#define ASM_DECLARE_FUNCTION_NAME(FILE,NAME,DECL) \
-{ rtx sym_ref = XEXP (DECL_RTL (DECL), 0); \
- if (!DECL_WEAK (DECL)) \
- SYMBOL_REF_FLAG (sym_ref) = 1; \
+{ char *buffer = (char *) alloca (strlen (NAME) + 1); \
+ char *p; \
+ int dollar_inside = 0; \
+ strcpy (buffer, NAME); \
+ p = strchr (buffer, '$'); \
+ while (p) { \
+ *p = '_'; \
+ dollar_inside++; \
+ p = strchr (p + 1, '$'); \
+ } \
if (TREE_PUBLIC (DECL)) \
{ \
if (!RS6000_WEAK || !DECL_WEAK (decl)) \
{ \
+ if (dollar_inside) { \
+ fprintf(FILE, "\t.rename .%s,\".%s\"\n", buffer, NAME); \
+ fprintf(FILE, "\t.rename %s,\"%s\"\n", buffer, NAME); \
+ } \
fputs ("\t.globl .", FILE); \
- RS6000_OUTPUT_BASENAME (FILE, NAME); \
+ RS6000_OUTPUT_BASENAME (FILE, buffer); \
putc ('\n', FILE); \
} \
} \
else \
{ \
+ if (dollar_inside) { \
+ fprintf(FILE, "\t.rename .%s,\".%s\"\n", buffer, NAME); \
+ fprintf(FILE, "\t.rename %s,\"%s\"\n", buffer, NAME); \
+ } \
fputs ("\t.lglobl .", FILE); \
- RS6000_OUTPUT_BASENAME (FILE, NAME); \
+ RS6000_OUTPUT_BASENAME (FILE, buffer); \
putc ('\n', FILE); \
} \
fputs ("\t.csect ", FILE); \
- RS6000_OUTPUT_BASENAME (FILE, NAME); \
+ RS6000_OUTPUT_BASENAME (FILE, buffer); \
fputs (TARGET_32BIT ? "[DS]\n" : "[DS],3\n", FILE); \
- RS6000_OUTPUT_BASENAME (FILE, NAME); \
+ RS6000_OUTPUT_BASENAME (FILE, buffer); \
fputs (":\n", FILE); \
fputs (TARGET_32BIT ? "\t.long ." : "\t.llong .", FILE); \
- RS6000_OUTPUT_BASENAME (FILE, NAME); \
+ RS6000_OUTPUT_BASENAME (FILE, buffer); \
fputs (", TOC[tc0], 0\n", FILE); \
- in_section = no_section; \
- function_section(DECL); \
+ in_section = NULL; \
+ switch_to_section (function_section (DECL)); \
putc ('.', FILE); \
- RS6000_OUTPUT_BASENAME (FILE, NAME); \
+ RS6000_OUTPUT_BASENAME (FILE, buffer); \
fputs (":\n", FILE); \
- if (write_symbols == XCOFF_DEBUG) \
- xcoffout_declare_function (FILE, DECL, NAME); \
+ if (write_symbols != NO_DEBUG) \
+ xcoffout_declare_function (FILE, DECL, buffer); \
}
/* Output a reference to SYM on FILE. */
#define ASM_OUTPUT_SYMBOL_REF(FILE, SYM) \
rs6000_output_symbol_ref (FILE, SYM)
-/* This says how to output an external. */
-
-#undef ASM_OUTPUT_EXTERNAL
-#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \
-{ rtx _symref = XEXP (DECL_RTL (DECL), 0); \
- if ((TREE_CODE (DECL) == VAR_DECL \
- || TREE_CODE (DECL) == FUNCTION_DECL) \
- && (NAME)[strlen (NAME) - 1] != ']') \
- { \
- char *_name = (char *) permalloc (strlen (XSTR (_symref, 0)) + 5); \
- strcpy (_name, XSTR (_symref, 0)); \
- strcat (_name, TREE_CODE (DECL) == FUNCTION_DECL ? "[DS]" : "[RW]"); \
- XSTR (_symref, 0) = _name; \
- } \
+/* This says how to output an external.
+ Dollar signs are converted to underscores. */
+
+#undef ASM_OUTPUT_EXTERNAL
+#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \
+{ char *buffer = (char *) alloca (strlen (NAME) + 1); \
+ char *p; \
+ rtx _symref = XEXP (DECL_RTL (DECL), 0); \
+ int dollar_inside = 0; \
+ strcpy (buffer, NAME); \
+ p = strchr (buffer, '$'); \
+ while (p) { \
+ *p = '_'; \
+ dollar_inside++; \
+ p = strchr (p + 1, '$'); \
+ } \
+ if (dollar_inside) { \
+ fputs ("\t.extern .", FILE); \
+ RS6000_OUTPUT_BASENAME (FILE, buffer); \
+ putc ('\n', FILE); \
+ fprintf(FILE, "\t.rename .%s,\".%s\"\n", buffer, NAME); \
+ } \
+ if ((TREE_CODE (DECL) == VAR_DECL \
+ || TREE_CODE (DECL) == FUNCTION_DECL) \
+ && (NAME)[strlen (NAME) - 1] != ']') \
+ { \
+ XSTR (_symref, 0) = concat (XSTR (_symref, 0), \
+ (TREE_CODE (DECL) == FUNCTION_DECL \
+ ? "[DS]" : "[RW]"), \
+ NULL); \
+ } \
}
-/* This is how to output an internal numbered label where
- PREFIX is the class of label and NUM is the number within the class. */
+/* This is how to output a reference to a user-level label named NAME.
+ `assemble_name' uses this. */
-#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
- fprintf (FILE, "%s..%u:\n", (PREFIX), (unsigned) (NUM))
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+ asm_fprintf ((FILE), "%U%s", rs6000_xcoff_strip_dollar (NAME));
/* This is how to output an internal label prefix. rs6000.c uses this
when generating traceback tables. */
fprintf (FILE, "%s..", PREFIX)
/* This is how to output a label for a jump table. Arguments are the same as
- for ASM_OUTPUT_INTERNAL_LABEL, except the insn for the jump table is
+ for (*targetm.asm_out.internal_label), except the insn for the jump table is
passed. */
#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLEINSN) \
-{ ASM_OUTPUT_ALIGN (FILE, 2); ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM); }
+{ ASM_OUTPUT_ALIGN (FILE, 2); (*targetm.asm_out.internal_label) (FILE, PREFIX, NUM); }
/* This is how to store into the string LABEL
the symbol_ref name of an internal numbered label where
This is suitable for output with `assemble_name'. */
#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
- sprintf (LABEL, "*%s..%u", (PREFIX), (unsigned) (NUM))
+ sprintf (LABEL, "*%s..%u", rs6000_xcoff_strip_dollar (PREFIX), (unsigned) (NUM))
/* This is how to output an assembler line to define N characters starting
at P to FILE. */
/* This is how to advance the location counter by SIZE bytes. */
+#define SKIP_ASM_OP "\t.space "
+
#define ASM_OUTPUT_SKIP(FILE,SIZE) \
- fprintf (FILE, "\t.space %d\n", (SIZE))
+ fprintf (FILE, "%s"HOST_WIDE_INT_PRINT_UNSIGNED"\n", SKIP_ASM_OP, (SIZE))
/* This says how to output an assembler line
to define a global common symbol. */
-#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGNMENT) \
- do { fputs ("\t.comm ", (FILE)); \
+#define COMMON_ASM_OP "\t.comm "
+
+#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \
+ do { fputs (COMMON_ASM_OP, (FILE)); \
RS6000_OUTPUT_BASENAME ((FILE), (NAME)); \
- if ( (SIZE) > 4) \
- fprintf ((FILE), ",%d,3\n", (SIZE)); \
+ if ((ALIGN) > 32) \
+ fprintf ((FILE), ","HOST_WIDE_INT_PRINT_UNSIGNED",%u\n", (SIZE), \
+ exact_log2 ((ALIGN) / BITS_PER_UNIT)); \
+ else if ((SIZE) > 4) \
+ fprintf ((FILE), ","HOST_WIDE_INT_PRINT_UNSIGNED",3\n", (SIZE)); \
else \
- fprintf ((FILE), ",%d\n", (SIZE)); \
+ fprintf ((FILE), ","HOST_WIDE_INT_PRINT_UNSIGNED"\n", (SIZE)); \
} while (0)
/* This says how to output an assembler line
alignment after preceding TOC section if it was aligned
for 64-bit mode. */
+#define LOCAL_COMMON_ASM_OP "\t.lcomm "
+
#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
- do { fputs ("\t.lcomm ", (FILE)); \
+ do { fputs (LOCAL_COMMON_ASM_OP, (FILE)); \
RS6000_OUTPUT_BASENAME ((FILE), (NAME)); \
- fprintf ((FILE), ",%d,%s\n", (TARGET_32BIT ? (SIZE) : (ROUNDED)), \
+ fprintf ((FILE), ","HOST_WIDE_INT_PRINT_UNSIGNED",%s\n", \
+ (TARGET_32BIT ? (SIZE) : (ROUNDED)), \
xcoff_bss_section_name); \
} while (0)
/* Output before instructions. */
#define TEXT_SECTION_ASM_OP "\t.csect .text[PR]"
-/* Output before writable data.
- Align entire section to BIGGEST_ALIGNMENT. */
-#define DATA_SECTION_ASM_OP "\t.csect .data[RW],3"
-
-/* Define unique section name -- functions only. */
-#define UNIQUE_SECTION(DECL,RELOC) \
- do { \
- int len; \
- const char *name; \
- char *string; \
- \
- if (TREE_CODE (DECL) == FUNCTION_DECL) { \
- name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (DECL)); \
- len = strlen (name) + 5; \
- string = alloca (len + 1); \
- sprintf (string, ".%s[PR]", name); \
- DECL_SECTION_NAME (DECL) = build_string (len, string); \
- } \
- } while (0)
-
-/* Switch into a generic section. */
-#define TARGET_ASM_NAMED_SECTION xcoff_asm_named_section
+/* Output before writable data. */
+#define DATA_SECTION_ASM_OP \
+ "\t.csect .data[RW]," XCOFF_CSECT_DEFAULT_ALIGNMENT_STR
-/* Define the name of the section to use for the EH language specific
- data areas (.gcc_except_table on most other systems). */
-#define TARGET_ASM_EXCEPTION_SECTION data_section
/* Define to prevent DWARF2 unwind info in the data section rather
than in the .eh_frame section. We do this because the AIX linker