the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
+/* Let mips.c know we need the Irix6 functions. */
+#define TARGET_IRIX6 1
+
/* Default to -mabi=n32 and -mips3. */
#define MIPS_ISA_DEFAULT 3
#define MIPS_ABI_DEFAULT ABI_N32
#include "mips/abi64.h"
/* Irix6 assembler does handle DWARF2 directives. Override setting in
- irix5.h file. */
+ irix5.h file. */
#undef DWARF2_UNWIND_INFO
/* The Irix6 assembler will sometimes assign labels to the wrong
/* Force the generation of dwarf .debug_frame sections even if not
compiling -g. This guarantees that we can unwind the stack. */
#define DWARF2_FRAME_INFO 1
+
/* The size in bytes of a DWARF field indicating an offset or length
relative to a debug info section, specified to be 4 bytes in the DWARF-2
specification. The SGI/MIPS ABI defines it to be the same as PTR_SIZE. */
fprintf (asm_out_file, "%s\n", CONST_SECTION_ASM_OP_32); \
in_section = in_rdata; \
} \
+} \
+ \
+const char * \
+current_section_name () \
+{ \
+ switch (in_section) \
+ { \
+ case no_section: return NULL; \
+ case in_text: return ".text"; \
+ case in_data: return ".data"; \
+ case in_sdata: return ".sdata"; \
+ case in_bss: return ".bss"; \
+ case in_rdata: \
+ case in_const: \
+ if (mips_abi != ABI_32 && mips_abi != ABI_O64) \
+ return ".rodata"; \
+ else \
+ return ".rdata"; \
+ case in_named: \
+ return in_named_name; \
+ } \
+ abort (); \
+} \
+ \
+unsigned int \
+current_section_flags () \
+{ \
+ switch (in_section) \
+ { \
+ case no_section: return 0; \
+ case in_text: return SECTION_CODE; \
+ case in_data: return SECTION_WRITE; \
+ case in_sdata: return SECTION_WRITE | SECTION_SMALL; \
+ case in_bss: return SECTION_WRITE | SECTION_BSS; \
+ case in_rdata: \
+ case in_const: return 0; \
+ case in_named: return get_named_section_flags (in_named_name); \
+ } \
+ abort (); \
}
/* Switch into a generic section. */
#undef TARGET_ASM_NAMED_SECTION
#define TARGET_ASM_NAMED_SECTION iris6_asm_named_section
-/* ??? Perhaps just include svr4.h in this file? */
+/* SGI assembler needs all sorts of extra help to do alignment properly. */
+#undef ASM_OUTPUT_ALIGN
+#define ASM_OUTPUT_ALIGN iris6_asm_output_align
+#undef ASM_FILE_START
+#define ASM_FILE_START iris6_asm_file_start
+#undef ASM_FILE_END
+#define ASM_FILE_END iris6_asm_file_end
+
+#undef MAX_OFILE_ALIGNMENT
+#define MAX_OFILE_ALIGNMENT (32768*8)
/* ??? SGI assembler may core dump when compiling with -g.
Sometimes as succeeds, but then we get a linker error. (cmds.c in 072.sc)
{ \
if (mips_abi != ABI_32 && mips_abi != ABI_O64) \
{ \
- fprintf (STREAM, "%s\n", BSS_SECTION_ASM_OP); \
+ bss_section (); \
mips_declare_object (STREAM, NAME, "", ":\n", 0); \
ASM_OUTPUT_ALIGN (STREAM, floor_log2 (ALIGN / BITS_PER_UNIT)); \
ASM_OUTPUT_SKIP (STREAM, SIZE); \
- fprintf (STREAM, "%s\n", POPSECTION_ASM_OP); \
} \
else \
mips_declare_object (STREAM, NAME, "\n\t.lcomm\t", ",%u\n", (SIZE)); \
#include "recog.h"
#include "toplev.h"
#include "output.h"
-
#include "tree.h"
#include "function.h"
#include "expr.h"
#include "tm_p.h"
#include "ggc.h"
#include "gstab.h"
+#include "hashtab.h"
+#include "debug.h"
#include "target.h"
#include "target-def.h"
int,
rtx, rtx));
static void block_move_call PARAMS ((rtx, rtx, rtx));
-static FILE *mips_make_temp_file PARAMS ((void));
static rtx mips_add_large_offset_to_sp PARAMS ((HOST_WIDE_INT,
FILE *));
static void mips_annotate_frame_insn PARAMS ((rtx, rtx));
static void mips_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
static void mips_output_function_prologue PARAMS ((FILE *, HOST_WIDE_INT));
static enum processor_type mips_parse_cpu PARAMS ((const char *));
+static void copy_file_data PARAMS ((FILE *, FILE *));
+#ifdef TARGET_IRIX6
+static void iris6_asm_named_section_1 PARAMS ((const char *,
+ unsigned int,
+ unsigned int));
static void iris6_asm_named_section PARAMS ((const char *,
unsigned int));
+static int iris_section_align_entry_eq PARAMS ((const PTR, const PTR));
+static hashval_t iris_section_align_entry_hash PARAMS ((const PTR));
+static int iris6_section_align_1 PARAMS ((void **, void *));
+#endif
+
/* Global variables for machine-dependent things. */
/* Threshold for data being put into the small data/bss area, instead
/* Zero structure to initialize current_frame_info. */
struct mips_frame_info zero_frame_info;
-/* Temporary filename used to buffer .text until end of program
- for -mgpopt. */
-static char *temp_filename;
-
/* Pseudo-reg holding the address of the current function when
generating embedded PIC code. Created by LEGITIMIZE_ADDRESS, used
by mips_finalize_pic if it was created. */
}
#endif
\f
-/* Compute a string to use as a temporary file name. */
-
-static FILE *
-mips_make_temp_file ()
-{
- FILE *stream;
-
- temp_filename = make_temp_file (0);
- stream = fopen (temp_filename, "w+");
- if (!stream)
- fatal_io_error ("can't open %s", temp_filename);
- return stream;
-}
-\f
/* Emit a new filename to a stream. If this is MIPS ECOFF, watch out
for .file's that start within a function. If we are smuggling stabs, try to
put out a MIPS ECOFF file and a stab. */
if (TARGET_MIPS16)
fprintf (stream, "\t.set\tmips16\n");
- /* Start a section, so that the first .popsection directive is guaranteed
- to have a previously defined section to pop back to. */
- if (mips_abi != ABI_32 && mips_abi != ABI_O64 && mips_abi != ABI_EABI)
- fprintf (stream, "\t.section\t.text\n");
-
/* This code exists so that we can put all externs before all symbol
references. This is necessary for the MIPS assembler's global pointer
optimizations to work. */
if (TARGET_FILE_SWITCHING)
{
asm_out_data_file = stream;
- asm_out_text_file = mips_make_temp_file ();
+ asm_out_text_file = tmpfile ();
}
-
else
asm_out_data_file = asm_out_text_file = stream;
mips_asm_file_end (file)
FILE *file;
{
- char buffer[8192];
tree name_tree;
struct extern_list *p;
- int len;
if (HALF_PIC_P ())
{
if (TARGET_FILE_SWITCHING)
{
fprintf (file, "\n\t.text\n");
- rewind (asm_out_text_file);
- if (ferror (asm_out_text_file))
- fatal_io_error ("can't rewind %s", temp_filename);
+ copy_file_data (file, asm_out_text_file);
+ }
+}
- while ((len = fread (buffer, 1, sizeof (buffer), asm_out_text_file)) > 0)
- if ((int) fwrite (buffer, 1, len, file) != len)
- fatal_io_error ("can't write to %s", asm_file_name);
+static void
+copy_file_data (to, from)
+ FILE *to, *from;
+{
+ char buffer[8192];
+ size_t len;
- if (len < 0)
- fatal_io_error ("can't read from %s", temp_filename);
+ rewind (from);
+ if (ferror (from))
+ fatal_io_error ("can't rewind temp file");
- if (fclose (asm_out_text_file) != 0)
- fatal_io_error ("can't close %s", temp_filename);
+ while ((len = fread (buffer, 1, sizeof (buffer), from)) > 0)
+ if (fwrite (buffer, 1, len, to) != len)
+ fatal_io_error ("can't write to output file");
- unlink (temp_filename);
- free (temp_filename);
- }
+ if (ferror (from))
+ fatal_io_error ("can't read from temp file");
+
+ if (fclose (from))
+ fatal_io_error ("can't close temp file");
}
/* Emit either a label, .comm, or .lcomm directive, and mark that the symbol
return cpu;
}
-/* Output assembly to switch to section NAME with attribute FLAGS. */
-
-static void
-iris6_asm_named_section (name, flags)
- const char *name;
- unsigned int flags;
-{
- unsigned int sh_type, sh_flags, sh_entsize;
-
- sh_flags = 0;
- if (!(flags & SECTION_DEBUG))
- sh_flags |= 2; /* SHF_ALLOC */
- if (flags & SECTION_WRITE)
- sh_flags |= 1; /* SHF_WRITE */
- if (flags & SECTION_CODE)
- sh_flags |= 4; /* SHF_EXECINSTR */
- if (flags & SECTION_SMALL)
- sh_flags |= 0x10000000; /* SHF_MIPS_GPREL */
- if (strcmp (name, ".debug_frame") == 0)
- sh_flags |= 0x08000000; /* SHF_MIPS_NOSTRIP */
-
- if (flags & SECTION_DEBUG)
- sh_type = 0x7000001e; /* SHT_MIPS_DWARF */
- else if (flags & SECTION_BSS)
- sh_type = 8; /* SHT_NOBITS */
- else
- sh_type = 1; /* SHT_PROGBITS */
-
- if (flags & SECTION_CODE)
- sh_entsize = 4;
- else
- sh_entsize = 0;
-
- fprintf (asm_out_file, "\t.section %s,%u,%u,%u,%u\n",
- name, sh_type, sh_flags, sh_entsize, 0);
-}
-
/* Cover function for UNIQUE_SECTION. */
void
int reloc;
{
int len, size, sec;
- char *name, *string, *prefix;
- static char *prefixes[4][2] = {
+ const char *name, *prefix;
+ char *string;
+ static const char *prefixes[4][2] = {
{ ".text.", ".gnu.linkonce.t." },
{ ".rodata.", ".gnu.linkonce.r." },
{ ".data.", ".gnu.linkonce.d." },
DECL_SECTION_NAME (decl) = build_string (len, string);
}
+\f
+#ifdef TARGET_IRIX6
+/* Output assembly to switch to section NAME with attribute FLAGS. */
+
+static void
+iris6_asm_named_section_1 (name, flags, align)
+ const char *name;
+ unsigned int flags;
+ unsigned int align;
+{
+ unsigned int sh_type, sh_flags, sh_entsize;
+
+ sh_flags = 0;
+ if (!(flags & SECTION_DEBUG))
+ sh_flags |= 2; /* SHF_ALLOC */
+ if (flags & SECTION_WRITE)
+ sh_flags |= 1; /* SHF_WRITE */
+ if (flags & SECTION_CODE)
+ sh_flags |= 4; /* SHF_EXECINSTR */
+ if (flags & SECTION_SMALL)
+ sh_flags |= 0x10000000; /* SHF_MIPS_GPREL */
+ if (strcmp (name, ".debug_frame") == 0)
+ sh_flags |= 0x08000000; /* SHF_MIPS_NOSTRIP */
+
+ if (flags & SECTION_DEBUG)
+ sh_type = 0x7000001e; /* SHT_MIPS_DWARF */
+ else if (flags & SECTION_BSS)
+ sh_type = 8; /* SHT_NOBITS */
+ else
+ sh_type = 1; /* SHT_PROGBITS */
+
+ if (flags & SECTION_CODE)
+ sh_entsize = 4;
+ else
+ sh_entsize = 0;
+
+ fprintf (asm_out_file, "\t.section %s,%#x,%#x,%u,%u\n",
+ name, sh_type, sh_flags, sh_entsize, align);
+}
+
+static void
+iris6_asm_named_section (name, flags)
+ const char *name;
+ unsigned int flags;
+{
+ if (TARGET_FILE_SWITCHING && (flags & SECTION_CODE))
+ asm_out_file = asm_out_text_file;
+ iris6_asm_named_section_1 (name, flags, 0);
+}
+
+/* In addition to emitting a .align directive, record the maximum
+ alignment requested for the current section. */
+
+struct iris_section_align_entry
+{
+ const char *name;
+ unsigned int log;
+ unsigned int flags;
+};
+
+static htab_t iris_section_align_htab;
+static FILE *iris_orig_asm_out_file;
+
+static int
+iris_section_align_entry_eq (p1, p2)
+ const PTR p1;
+ const PTR p2;
+{
+ const struct iris_section_align_entry *old = p1;
+ const char *new = p2;
+
+ return strcmp (old->name, new) == 0;
+}
+
+static hashval_t
+iris_section_align_entry_hash (p)
+ const PTR p;
+{
+ const struct iris_section_align_entry *old = p;
+ return htab_hash_string (old->name);
+}
+
+void
+iris6_asm_output_align (file, log)
+ FILE *file;
+ unsigned int log;
+{
+ const char *section = current_section_name ();
+ struct iris_section_align_entry **slot, *entry;
+
+ if (! section)
+ abort ();
+
+ slot = (struct iris_section_align_entry **)
+ htab_find_slot_with_hash (iris_section_align_htab, section,
+ htab_hash_string (section), INSERT);
+ entry = *slot;
+ if (! entry)
+ {
+ entry = (struct iris_section_align_entry *)
+ xmalloc (sizeof (struct iris_section_align_entry));
+ *slot = entry;
+ entry->name = section;
+ entry->log = log;
+ entry->flags = current_section_flags ();
+ }
+ else if (entry->log < log)
+ entry->log = log;
+
+ fprintf (file, "\t.align\t%u\n", log);
+}
+
+/* The Iris assembler does not record alignment from .align directives,
+ but takes it from the first .section directive seen. Play yet more
+ file switching games so that we can emit a .section directive at the
+ beginning of the file with the proper alignment attached. */
+
+void
+iris6_asm_file_start (stream)
+ FILE *stream;
+{
+ mips_asm_file_start (stream);
+
+ iris_orig_asm_out_file = asm_out_file;
+ stream = tmpfile ();
+ asm_out_file = stream;
+ asm_out_data_file = stream;
+ if (! TARGET_FILE_SWITCHING)
+ asm_out_text_file = stream;
+
+ iris_section_align_htab = htab_create (31, iris_section_align_entry_hash,
+ iris_section_align_entry_eq, NULL);
+}
+
+static int
+iris6_section_align_1 (slot, data)
+ void **slot;
+ void *data ATTRIBUTE_UNUSED;
+{
+ const struct iris_section_align_entry *entry
+ = *(const struct iris_section_align_entry **) slot;
+
+ iris6_asm_named_section_1 (entry->name, entry->flags, 1 << entry->log);
+ return 1;
+}
+
+void
+iris6_asm_file_end (stream)
+ FILE *stream;
+{
+ /* Emit section directives with the proper alignment at the top of the
+ real output file. */
+ asm_out_file = iris_orig_asm_out_file;
+ htab_traverse (iris_section_align_htab, iris6_section_align_1, NULL);
+
+ /* Copy the data emitted to the temp file to the real output file. */
+ copy_file_data (asm_out_file, stream);
+
+ mips_asm_file_end (stream);
+}
+#endif /* TARGET_IRIX6 */