Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
1998, 1999, 2000, 2001 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 2, 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.
+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 GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
/* This is the final pass of the compiler.
It looks at the rtl code for a function and outputs assembler code.
(the one that tests the condition codes) to be modified.
The code for the function prologue and epilogue are generated
- directly as assembler code by the macros FUNCTION_PROLOGUE and
- FUNCTION_EPILOGUE. Those instructions never exist as rtl. */
+ directly in assembler by the target functions function_prologue and
+ function_epilogue. Those instructions never exist as rtl. */
#include "config.h"
#include "system.h"
#include "reload.h"
#include "intl.h"
#include "basic-block.h"
-
-#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
-#include "dbxout.h"
-#endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */
+#include "target.h"
+#include "debug.h"
#ifdef XCOFF_DEBUGGING_INFO
-#include "xcoffout.h"
-#endif
-
-#ifdef DWARF_DEBUGGING_INFO
-#include "dwarfout.h"
+#include "xcoffout.h" /* Needed for external data
+ declarations for e.g. AIX 4.x. */
#endif
#if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
#include "dwarf2out.h"
#endif
-#ifdef SDB_DEBUGGING_INFO
-#include "sdbout.h"
-#endif
-
/* If we aren't using cc0, CC_STATUS_INIT shouldn't exist. So define a
null default for it to save conditionalization later. */
#ifndef CC_STATUS_INIT
static void profile_after_prologue PARAMS ((FILE *));
static void add_bb PARAMS ((FILE *));
static int add_bb_string PARAMS ((const char *, int));
-static void output_source_line PARAMS ((FILE *, rtx));
+static void notice_source_line PARAMS ((rtx));
static rtx walk_alter_subreg PARAMS ((rtx));
static void output_asm_name PARAMS ((void));
static void output_operand PARAMS ((rtx, int));
int long_bytes = LONG_TYPE_SIZE / BITS_PER_UNIT;
int gcov_type_bytes = GCOV_TYPE_SIZE / BITS_PER_UNIT;
int pointer_bytes = POINTER_SIZE / BITS_PER_UNIT;
+ unsigned int align2 = LONG_TYPE_SIZE;
if (profile_block_flag)
size = long_bytes * count_basic_blocks;
rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
* (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
+ /* ??? This _really_ ought to be done with a structure layout
+ and with assemble_constructor. If long_bytes != pointer_bytes
+ we'll be emitting unaligned data at some point. */
+ if (long_bytes != pointer_bytes)
+ abort ();
+
data_section ();
/* Output the main header, of 11 words:
ASM_OUTPUT_ALIGN (asm_out_file, align);
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 0);
- /* zero word */
- assemble_integer (const0_rtx, long_bytes, 1);
- /* address of filename */
+ /* Zero word. */
+ assemble_integer (const0_rtx, long_bytes, align2, 1);
+
+ /* Address of filename. */
ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 1);
- assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name), pointer_bytes, 1);
+ assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name), pointer_bytes,
+ align2, 1);
- /* address of count table */
+ /* Address of count table. */
ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2);
- assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name), pointer_bytes, 1);
+ assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name), pointer_bytes,
+ align2, 1);
- /* count of the # of basic blocks or # of instrumented arcs */
- if (profile_block_flag)
- assemble_integer (GEN_INT (count_basic_blocks), long_bytes, 1);
- else
- assemble_integer (GEN_INT (count_instrumented_edges), long_bytes, 1);
+ /* Count of the # of basic blocks or # of instrumented arcs. */
+ assemble_integer (GEN_INT (profile_block_flag
+ ? count_basic_blocks
+ : count_instrumented_edges),
+ long_bytes, align2, 1);
- /* zero word (link field) */
- assemble_integer (const0_rtx, pointer_bytes, 1);
+ /* Zero word (link field). */
+ assemble_integer (const0_rtx, pointer_bytes, align2, 1);
/* address of basic block start address table */
if (profile_block_flag)
{
ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 3);
- assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name), pointer_bytes,
- 1);
+ assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name),
+ pointer_bytes, align2, 1);
}
else
- assemble_integer (const0_rtx, pointer_bytes, 1);
+ assemble_integer (const0_rtx, pointer_bytes, align2, 1);
- /* byte count for extended structure. */
- assemble_integer (GEN_INT (11 * UNITS_PER_WORD), long_bytes, 1);
+ /* Byte count for extended structure. */
+ assemble_integer (GEN_INT (11 * UNITS_PER_WORD), long_bytes, align2, 1);
- /* address of function name table */
+ /* Address of function name table. */
if (profile_block_flag)
{
ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 4);
- assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name), pointer_bytes,
- 1);
+ assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name),
+ pointer_bytes, align2, 1);
}
else
- assemble_integer (const0_rtx, pointer_bytes, 1);
+ assemble_integer (const0_rtx, pointer_bytes, align2, 1);
- /* address of line number and filename tables if debugging. */
+ /* Address of line number and filename tables if debugging. */
if (write_symbols != NO_DEBUG && profile_block_flag)
{
ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 5);
assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name),
- pointer_bytes, 1);
+ pointer_bytes, align2, 1);
ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 6);
assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name),
- pointer_bytes, 1);
+ pointer_bytes, align2, 1);
}
else
{
- assemble_integer (const0_rtx, pointer_bytes, 1);
- assemble_integer (const0_rtx, pointer_bytes, 1);
+ assemble_integer (const0_rtx, pointer_bytes, align2, 1);
+ assemble_integer (const0_rtx, pointer_bytes, align2, 1);
}
- /* space for extension ptr (link field) */
- assemble_integer (const0_rtx, UNITS_PER_WORD, 1);
+ /* Space for extension ptr (link field). */
+ assemble_integer (const0_rtx, UNITS_PER_WORD, align2, 1);
- /* Output the file name changing the suffix to .d for Sun tcov
- compatibility. */
+ /* Output the file name changing the suffix to .d for
+ Sun tcov compatibility. */
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 1);
{
char *cwd = getpwd ();
{
ASM_GENERATE_INTERNAL_LABEL (name, "LPB", i);
assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name),
- pointer_bytes, 1);
+ pointer_bytes, align2, 1);
}
}
ASM_GENERATE_INTERNAL_LABEL (name, "LPBC",
ptr->func_label_num);
assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name),
- pointer_bytes, 1);
+ pointer_bytes, align2, 1);
}
else
- assemble_integer (const0_rtx, pointer_bytes, 1);
+ assemble_integer (const0_rtx, pointer_bytes, align2, 1);
}
for (; i < count_basic_blocks; i++)
- assemble_integer (const0_rtx, pointer_bytes, 1);
+ assemble_integer (const0_rtx, pointer_bytes, align2, 1);
}
if (write_symbols != NO_DEBUG && profile_block_flag)
/* Output the table of line numbers. */
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 5);
for ((ptr = bb_head), (i = 0); ptr != 0; (ptr = ptr->next), i++)
- assemble_integer (GEN_INT (ptr->line_num), long_bytes, 1);
+ assemble_integer (GEN_INT (ptr->line_num), long_bytes, align2, 1);
for (; i < count_basic_blocks; i++)
- assemble_integer (const0_rtx, long_bytes, 1);
+ assemble_integer (const0_rtx, long_bytes, align2, 1);
/* Output the table of file names. */
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 6);
ASM_GENERATE_INTERNAL_LABEL (name, "LPBC",
ptr->file_label_num);
assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name),
- pointer_bytes, 1);
+ pointer_bytes, align2, 1);
}
else
- assemble_integer (const0_rtx, pointer_bytes, 1);
+ assemble_integer (const0_rtx, pointer_bytes, align2, 1);
}
for (; i < count_basic_blocks; i++)
- assemble_integer (const0_rtx, pointer_bytes, 1);
+ assemble_integer (const0_rtx, pointer_bytes, align2, 1);
}
/* End with the address of the table of addresses,
if (profile_block_flag)
{
ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 3);
- assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name), pointer_bytes,
- 1);
+ assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name),
+ pointer_bytes, align2, 1);
}
}
}
+/* Default target function prologue and epilogue assembler output.
+
+ If not overridden for epilogue code, then the function body itself
+ contains return instructions wherever needed. */
+void
+default_function_pro_epilogue (file, size)
+ FILE *file ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED;
+{
+}
+
+/* Default target hook that outputs nothing to a stream. */
+void
+no_asm_to_stream (file)
+ FILE *file ATTRIBUTE_UNUSED;
+{
+}
+
/* Enable APP processing of subsequent output.
Used before the output from an `asm' statement. */
void
init_insn_lengths ()
{
- if (label_align)
- {
- free (label_align);
- label_align = 0;
- }
if (uid_shuid)
{
free (uid_shuid);
#endif
#ifndef LABEL_ALIGN_AFTER_BARRIER
-#define LABEL_ALIGN_AFTER_BARRIER(LABEL) align_jumps_log
+#define LABEL_ALIGN_AFTER_BARRIER(LABEL) 0
#endif
#ifndef LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP
-#define LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP (align_jumps-1)
+#define LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP 0
+#endif
+
+#ifndef JUMP_ALIGN
+#define JUMP_ALIGN(LABEL) align_jumps_log
+#endif
+
+#ifndef JUMP_ALIGN_MAX_SKIP
+#define JUMP_ALIGN_MAX_SKIP (align_jumps-1)
#endif
#ifndef ADDR_VEC_ALIGN
return insn_current_address;
dest = JUMP_LABEL (branch);
- /* BRANCH has no proper alignment chain set, so use SEQ.
+ /* BRANCH has no proper alignment chain set, so use SEQ.
BRANCH also has no INSN_SHUID. */
if (INSN_SHUID (seq) < INSN_SHUID (dest))
{
}
#endif /* HAVE_ATTR_length */
\f
+void
+compute_alignments ()
+{
+ int i;
+ int log, max_skip, max_log;
+
+ if (label_align)
+ {
+ free (label_align);
+ label_align = 0;
+ }
+
+ max_labelno = max_label_num ();
+ min_labelno = get_first_label_num ();
+ label_align = (struct label_alignment *)
+ xcalloc (max_labelno - min_labelno + 1, sizeof (struct label_alignment));
+
+ /* If not optimizing or optimizing for size, don't assign any alignments. */
+ if (! optimize || optimize_size)
+ return;
+
+ for (i = 0; i < n_basic_blocks; i++)
+ {
+ basic_block bb = BASIC_BLOCK (i);
+ rtx label = bb->head;
+ int fallthru_frequency = 0, branch_frequency = 0, has_fallthru = 0;
+ edge e;
+
+ if (GET_CODE (label) != CODE_LABEL)
+ continue;
+ max_log = LABEL_ALIGN (label);
+ max_skip = LABEL_ALIGN_MAX_SKIP;
+
+ for (e = bb->pred; e; e = e->pred_next)
+ {
+ if (e->flags & EDGE_FALLTHRU)
+ has_fallthru = 1, fallthru_frequency += EDGE_FREQUENCY (e);
+ else
+ branch_frequency += EDGE_FREQUENCY (e);
+ }
+
+ /* There are two purposes to align block with no fallthru incomming edge:
+ 1) to avoid fetch stalls when branch destination is near cache boundary
+ 2) to improve cache effciency in case the previous block is not executed
+ (so it does not need to be in the cache).
+
+ We to catch first case, we align frequently executed blocks.
+ To catch the second, we align blocks that are executed more frequently
+ than the predecesor and the predecesor is likely to not be executed
+ when function is called. */
+
+ if (!has_fallthru
+ && (branch_frequency > BB_FREQ_MAX / 10
+ || (bb->frequency > BASIC_BLOCK (i - 1)->frequency * 10
+ && (BASIC_BLOCK (i - 1)->frequency
+ <= ENTRY_BLOCK_PTR->frequency / 2))))
+ {
+ log = JUMP_ALIGN (label);
+ if (max_log < log)
+ {
+ max_log = log;
+ max_skip = JUMP_ALIGN_MAX_SKIP;
+ }
+ }
+ /* In case block is frequent and reached mostly by non-fallthru edge,
+ align it. It is most likely an first block of loop. */
+ if (has_fallthru
+ && branch_frequency + fallthru_frequency > BB_FREQ_MAX / 10
+ && branch_frequency > fallthru_frequency * 5)
+ {
+ log = LOOP_ALIGN (label);
+ if (max_log < log)
+ {
+ max_log = log;
+ max_skip = LOOP_ALIGN_MAX_SKIP;
+ }
+ }
+ LABEL_TO_ALIGNMENT (label) = max_log;
+ LABEL_TO_MAX_SKIP (label) = max_skip;
+ }
+}
+\f
/* Make a pass over all insns and compute their actual lengths by shortening
any branches of variable length if possible. */
#endif
- /* We must do some computations even when not actually shortening, in
- order to get the alignment information for the labels. */
-
- init_insn_lengths ();
-
/* Compute maximum UID and allocate label_align / uid_shuid. */
max_uid = get_max_uid ();
- max_labelno = max_label_num ();
- min_labelno = get_first_label_num ();
- label_align = (struct label_alignment *)
- xcalloc ((max_labelno - min_labelno + 1), sizeof (struct label_alignment));
-
uid_shuid = (int *) xmalloc (max_uid * sizeof *uid_shuid);
+ if (max_labelno != max_label_num ())
+ {
+ int old = max_labelno;
+ int n_labels;
+ int n_old_labels;
+
+ max_labelno = max_label_num ();
+
+ n_labels = max_labelno - min_labelno + 1;
+ n_old_labels = old - min_labelno + 1;
+
+ label_align = (struct label_alignment *) xrealloc
+ (label_align, n_labels * sizeof (struct label_alignment));
+
+ /* Range of labels grows monotonically in the function. Abort here
+ means that the initialization of array got lost. */
+ if (n_old_labels > n_labels)
+ abort ();
+
+ memset (label_align + n_old_labels, 0,
+ (n_labels - n_old_labels) * sizeof (struct label_alignment));
+ }
+
/* Initialize label_align and set up uid_shuid to be strictly
monotonically rising with insn order. */
/* We use max_log here to keep track of the maximum alignment we want to
else if (GET_CODE (insn) == CODE_LABEL)
{
rtx next;
+
+ /* Merge in alignments computed by compute_alignments. */
+ log = LABEL_TO_ALIGNMENT (insn);
+ if (max_log < log)
+ {
+ max_log = log;
+ max_skip = LABEL_TO_MAX_SKIP (insn);
+ }
log = LABEL_ALIGN (insn);
if (max_log < log)
break;
}
}
- /* Again, we allow NOTE_INSN_LOOP_BEG - INSN - CODE_LABEL
- sequences in order to handle reorg output efficiently. */
- else if (GET_CODE (insn) == NOTE
- && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
- {
- rtx label;
- int nest = 0;
-
- /* Search for the label that starts the loop.
- Don't skip past the end of the loop, since that could
- lead to putting an alignment where it does not belong.
- However, a label after a nested (non-)loop would be OK. */
- for (label = insn; label; label = NEXT_INSN (label))
- {
- if (GET_CODE (label) == NOTE
- && NOTE_LINE_NUMBER (label) == NOTE_INSN_LOOP_BEG)
- nest++;
- else if (GET_CODE (label) == NOTE
- && NOTE_LINE_NUMBER (label) == NOTE_INSN_LOOP_END
- && --nest == 0)
- break;
- else if (GET_CODE (label) == CODE_LABEL)
- {
- log = LOOP_ALIGN (label);
- if (max_log < log)
- {
- max_log = log;
- max_skip = LOOP_ALIGN_MAX_SKIP;
- }
- break;
- }
- }
- }
- else
- continue;
}
#ifdef HAVE_ATTR_length
if (! (varying_length[uid]))
{
- insn_current_address += insn_lengths[uid];
+ if (GET_CODE (insn) == INSN
+ && GET_CODE (PATTERN (insn)) == SEQUENCE)
+ {
+ int i;
+
+ body = PATTERN (insn);
+ for (i = 0; i < XVECLEN (body, 0); i++)
+ {
+ rtx inner_insn = XVECEXP (body, 0, i);
+ int inner_uid = INSN_UID (inner_insn);
+
+ INSN_ADDRESSES (inner_uid) = insn_current_address;
+
+ insn_current_address += insn_lengths[inner_uid];
+ }
+ }
+ else
+ insn_current_address += insn_lengths[uid];
+
continue;
}
+
if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
{
int i;
}
#endif
- /* Initial line number is supposed to be output
- before the function's prologue and label
- so that the function's address will not appear to be
- in the last statement of the preceding function. */
if (NOTE_LINE_NUMBER (first) != NOTE_INSN_DELETED)
- last_linenum = high_block_linenum = high_function_linenum
- = NOTE_LINE_NUMBER (first);
+ notice_source_line (first);
+ high_block_linenum = high_function_linenum = last_linenum;
-#if defined (DWARF2_UNWIND_INFO) || defined (IA64_UNWIND_INFO) \
- || defined (DWARF2_DEBUGGING_INFO)
- dwarf2out_begin_prologue ();
-#endif
+ (*debug_hooks->begin_prologue) (last_linenum, last_filename);
- /* For SDB and XCOFF, the function beginning must be marked between
- the function label and the prologue. We always need this, even when
- -g1 was used. Defer on MIPS systems so that parameter descriptions
- follow function entry. */
-#if defined(SDB_DEBUGGING_INFO) && !defined(MIPS_DEBUGGING_INFO)
- if (write_symbols == SDB_DEBUG)
- sdbout_begin_function (last_linenum);
- else
+#if defined (DWARF2_UNWIND_INFO) || defined (IA64_UNWIND_INFO)
+ if (write_symbols != DWARF2_DEBUG)
+ dwarf2out_begin_prologue (0, NULL);
#endif
-#ifdef XCOFF_DEBUGGING_INFO
- if (write_symbols == XCOFF_DEBUG)
- xcoffout_begin_function (file, last_linenum);
- else
-#endif
- /* But only output line number for other debug info types if -g2
- or better. */
- if (NOTE_LINE_NUMBER (first) != NOTE_INSN_DELETED)
- output_source_line (file, first);
#ifdef LEAF_REG_REMAP
if (current_function_uses_only_leaf_regs)
function. */
if (write_symbols)
{
- number_blocks (current_function_decl);
remove_unnecessary_notes ();
+ reorder_blocks ();
+ number_blocks (current_function_decl);
/* We never actually put out begin/end notes for the top-level
block in the function. But, conceptually, that block is
always needed. */
TREE_ASM_WRITTEN (DECL_INITIAL (current_function_decl)) = 1;
}
-#ifdef FUNCTION_PROLOGUE
/* First output the function prologue: code to set up the stack frame. */
- FUNCTION_PROLOGUE (file, get_frame_size ());
-#endif
+ (*targetm.asm_out.function_prologue) (file, get_frame_size ());
/* If the machine represents the prologue as RTL, the profiling code must
be emitted when NOTE_INSN_PROLOGUE_END is scanned. */
data_section ();
ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));
ASM_OUTPUT_INTERNAL_LABEL (file, "LP", profile_label_no);
- assemble_integer (const0_rtx, LONG_TYPE_SIZE / BITS_PER_UNIT, 1);
+ assemble_integer (const0_rtx, LONG_TYPE_SIZE / BITS_PER_UNIT, align, 1);
#endif
function_section (current_function_decl);
even though not all of them are needed. */
void
-final_end_function (first, file, optimize)
- rtx first ATTRIBUTE_UNUSED;
- FILE *file ATTRIBUTE_UNUSED;
- int optimize ATTRIBUTE_UNUSED;
+final_end_function ()
{
app_disable ();
-#ifdef SDB_DEBUGGING_INFO
- if (write_symbols == SDB_DEBUG)
- sdbout_end_function (high_function_linenum);
-#endif
+ (*debug_hooks->end_function) (high_function_linenum);
-#ifdef DWARF_DEBUGGING_INFO
- if (write_symbols == DWARF_DEBUG)
- dwarfout_end_function ();
-#endif
-
-#ifdef XCOFF_DEBUGGING_INFO
- if (write_symbols == XCOFF_DEBUG)
- xcoffout_end_function (file, high_function_linenum);
-#endif
-
-#ifdef FUNCTION_EPILOGUE
/* Finally, output the function epilogue:
code to restore the stack frame and return to the caller. */
- FUNCTION_EPILOGUE (file, get_frame_size ());
-#endif
+ (*targetm.asm_out.function_epilogue) (asm_out_file, get_frame_size ());
-#ifdef SDB_DEBUGGING_INFO
- if (write_symbols == SDB_DEBUG)
- sdbout_end_epilogue ();
-#endif
+ /* And debug output. */
+ (*debug_hooks->end_epilogue) ();
-#ifdef DWARF_DEBUGGING_INFO
- if (write_symbols == DWARF_DEBUG)
- dwarfout_end_epilogue ();
-#endif
-
-#if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO)
- if (dwarf2out_do_frame ())
+#if defined (DWARF2_UNWIND_INFO)
+ if (write_symbols != DWARF2_DEBUG && dwarf2out_do_frame ())
dwarf2out_end_epilogue ();
#endif
-#ifdef XCOFF_DEBUGGING_INFO
- if (write_symbols == XCOFF_DEBUG)
- xcoffout_end_epilogue (file);
-#endif
-
bb_func_label_num = -1; /* not in function, nuke label # */
-
- /* If FUNCTION_EPILOGUE is not defined, then the function body
- itself contains return instructions wherever needed. */
}
\f
/* Add a block to the linked list that remembers the current line/file/function
for (insn = NEXT_INSN (first); insn;)
{
#ifdef HAVE_ATTR_length
- if (INSN_UID (insn) >= INSN_ADDRESSES_SIZE ())
+ if ((unsigned) INSN_UID (insn) >= INSN_ADDRESSES_SIZE ())
{
#ifdef STACK_REGS
/* Irritatingly, the reg-stack pass is creating new instructions
case NOTE_INSN_LOOP_CONT:
case NOTE_INSN_LOOP_VTOP:
case NOTE_INSN_FUNCTION_END:
- case NOTE_INSN_SETJMP:
case NOTE_INSN_REPEATED_LINE_NUMBER:
case NOTE_INSN_RANGE_BEG:
case NOTE_INSN_RANGE_END:
break;
case NOTE_INSN_PROLOGUE_END:
-#ifdef FUNCTION_END_PROLOGUE
- FUNCTION_END_PROLOGUE (file);
-#endif
+ (*targetm.asm_out.function_end_prologue) (file);
profile_after_prologue (file);
break;
case NOTE_INSN_EPILOGUE_BEG:
-#ifdef FUNCTION_BEGIN_EPILOGUE
- FUNCTION_BEGIN_EPILOGUE (file);
-#endif
+ (*targetm.asm_out.function_begin_epilogue) (file);
break;
case NOTE_INSN_FUNCTION_BEG:
-#if defined(SDB_DEBUGGING_INFO) && defined(MIPS_DEBUGGING_INFO)
- /* MIPS stabs require the parameter descriptions to be after the
- function entry point rather than before. */
- if (write_symbols == SDB_DEBUG)
- {
- app_disable ();
- sdbout_begin_function (last_linenum);
- }
-#endif
-#ifdef DWARF_DEBUGGING_INFO
- /* This outputs a marker where the function body starts, so it
- must be after the prologue. */
- if (write_symbols == DWARF_DEBUG)
- {
- app_disable ();
- dwarfout_begin_function ();
- }
-#endif
+ app_disable ();
+ (*debug_hooks->end_prologue) (last_linenum);
break;
case NOTE_INSN_BLOCK_BEG:
++block_depth;
high_block_linenum = last_linenum;
- /* Output debugging info about the symbol-block beginning. */
-#ifdef SDB_DEBUGGING_INFO
- if (write_symbols == SDB_DEBUG)
- sdbout_begin_block (file, last_linenum, n);
-#endif
-#ifdef XCOFF_DEBUGGING_INFO
- if (write_symbols == XCOFF_DEBUG)
- xcoffout_begin_block (file, last_linenum, n);
-#endif
-#ifdef DBX_DEBUGGING_INFO
- if (write_symbols == DBX_DEBUG)
- ASM_OUTPUT_INTERNAL_LABEL (file, "LBB", n);
-#endif
-#ifdef DWARF_DEBUGGING_INFO
- if (write_symbols == DWARF_DEBUG)
- dwarfout_begin_block (n);
-#endif
-#ifdef DWARF2_DEBUGGING_INFO
- if (write_symbols == DWARF2_DEBUG)
- dwarf2out_begin_block (n);
-#endif
+ /* Output debugging info about the symbol-block beginning. */
+ (*debug_hooks->begin_block) (last_linenum, n);
/* Mark this block as output. */
TREE_ASM_WRITTEN (NOTE_BLOCK (insn)) = 1;
if (block_depth < 0)
abort ();
-#ifdef XCOFF_DEBUGGING_INFO
- if (write_symbols == XCOFF_DEBUG)
- xcoffout_end_block (file, high_block_linenum, n);
-#endif
-#ifdef DBX_DEBUGGING_INFO
- if (write_symbols == DBX_DEBUG)
- ASM_OUTPUT_INTERNAL_LABEL (file, "LBE", n);
-#endif
-#ifdef SDB_DEBUGGING_INFO
- if (write_symbols == SDB_DEBUG)
- sdbout_end_block (file, high_block_linenum, n);
-#endif
-#ifdef DWARF_DEBUGGING_INFO
- if (write_symbols == DWARF_DEBUG)
- dwarfout_end_block (n);
-#endif
-#ifdef DWARF2_DEBUGGING_INFO
- if (write_symbols == DWARF2_DEBUG)
- dwarf2out_end_block (n);
-#endif
+ (*debug_hooks->end_block) (high_block_linenum, n);
}
break;
/* Output this line note if it is the first or the last line
note in a row. */
if (!note_after)
- output_source_line (file, insn);
+ {
+ notice_source_line (insn);
+ (*debug_hooks->source_line) (last_linenum, last_filename);
+ }
}
break;
}
FINAL_PRESCAN_INSN (insn, NULL, 0);
#endif
-#ifdef SDB_DEBUGGING_INFO
- if (write_symbols == SDB_DEBUG && LABEL_NAME (insn))
- sdbout_label (insn);
-#endif
+ if (LABEL_NAME (insn))
+ (*debug_hooks->label) (insn);
+
if (app_on)
{
fputs (ASM_APP_OFF, file);
#else
if (! JUMP_TABLES_IN_TEXT_SECTION)
{
+ int log_align;
+
readonly_data_section ();
-#ifdef READONLY_DATA_SECTION
- ASM_OUTPUT_ALIGN (file,
- exact_log2 (BIGGEST_ALIGNMENT
- / BITS_PER_UNIT));
-#endif /* READONLY_DATA_SECTION */
+
+#ifdef ADDR_VEC_ALIGN
+ log_align = ADDR_VEC_ALIGN (NEXT_INSN (insn));
+#else
+ log_align = exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT);
+#endif
+ ASM_OUTPUT_ALIGN (file, log_align);
}
else
function_section (current_function_decl);
if (GET_CODE (body) == ASM_INPUT)
{
+ const char *string = XSTR (body, 0);
+
/* There's no telling what that did to the condition codes. */
CC_STATUS_INIT;
if (prescan > 0)
break;
- if (! app_on)
+
+ if (string[0])
{
- fputs (ASM_APP_ON, file);
- app_on = 1;
+ if (! app_on)
+ {
+ fputs (ASM_APP_ON, file);
+ app_on = 1;
+ }
+ fprintf (asm_out_file, "\t%s\n", string);
}
- fprintf (asm_out_file, "\t%s\n", XSTR (body, 0));
break;
}
if (prescan > 0)
break;
- if (! app_on)
- {
- fputs (ASM_APP_ON, file);
- app_on = 1;
- }
-
/* Get out the operand values. */
string = decode_asm_operands (body, ops, NULL, NULL, NULL);
/* Inhibit aborts on what would otherwise be compiler bugs. */
this_is_asm_operands = insn;
/* Output the insn using them. */
- output_asm_insn (string, ops);
+ if (string[0])
+ {
+ if (! app_on)
+ {
+ fputs (ASM_APP_ON, file);
+ app_on = 1;
+ }
+ output_asm_insn (string, ops);
+ }
+
this_is_asm_operands = 0;
break;
}
print_rtl_single (asm_out_file, insn);
print_rtx_head = "";
}
-
+
if (! constrain_operands_cached (1))
fatal_insn_not_found (insn);
based on the NOTE-insn INSN, assumed to be a line number. */
static void
-output_source_line (file, insn)
- FILE *file ATTRIBUTE_UNUSED;
+notice_source_line (insn)
rtx insn;
{
register const char *filename = NOTE_SOURCE_FILE (insn);
last_linenum = NOTE_LINE_NUMBER (insn);
high_block_linenum = MAX (last_linenum, high_block_linenum);
high_function_linenum = MAX (last_linenum, high_function_linenum);
-
- if (write_symbols != NO_DEBUG)
- {
-#ifdef SDB_DEBUGGING_INFO
- if (write_symbols == SDB_DEBUG
-#if 0 /* People like having line numbers even in wrong file! */
- /* COFF can't handle multiple source files--lose, lose. */
- && !strcmp (filename, main_input_filename)
-#endif
- /* COFF relative line numbers must be positive. */
- && last_linenum > sdb_begin_function_line)
- {
-#ifdef ASM_OUTPUT_SOURCE_LINE
- ASM_OUTPUT_SOURCE_LINE (file, last_linenum);
-#else
- fprintf (file, "\t.ln\t%d\n",
- ((sdb_begin_function_line > -1)
- ? last_linenum - sdb_begin_function_line : 1));
-#endif
- }
-#endif
-
-#if defined (DBX_DEBUGGING_INFO)
- if (write_symbols == DBX_DEBUG)
- dbxout_source_line (file, filename, NOTE_LINE_NUMBER (insn));
-#endif
-
-#if defined (XCOFF_DEBUGGING_INFO)
- if (write_symbols == XCOFF_DEBUG)
- xcoffout_source_line (file, filename, insn);
-#endif
-
-#ifdef DWARF_DEBUGGING_INFO
- if (write_symbols == DWARF_DEBUG)
- dwarfout_line (filename, NOTE_LINE_NUMBER (insn));
-#endif
-
-#ifdef DWARF2_DEBUGGING_INFO
- if (write_symbols == DWARF2_DEBUG)
- dwarf2out_line (filename, NOTE_LINE_NUMBER (insn));
-#endif
- }
}
\f
/* For each operand in INSN, simplify (subreg (reg)) so that it refers
}
else if (GET_CODE (y) == MEM)
{
- register int offset = SUBREG_BYTE (x);
+ HOST_WIDE_INT offset = SUBREG_BYTE (x);
/* Catch these instead of generating incorrect code. */
if ((offset % GET_MODE_SIZE (GET_MODE (x))) != 0)
&& INTVAL (XEXP (x, 1)) < 0)
|| GET_CODE (XEXP (x, 1)) != CONST_INT)
{
- fprintf (file, "%s", ASM_OPEN_PAREN);
+ fputs (targetm.asm_out.open_paren, file);
output_addr_const (file, XEXP (x, 1));
- fprintf (file, "%s", ASM_CLOSE_PAREN);
+ fputs (targetm.asm_out.close_paren, file);
}
else
output_addr_const (file, XEXP (x, 1));
void
asm_fprintf VPARAMS ((FILE *file, const char *p, ...))
{
-#ifndef ANSI_PROTOTYPES
- FILE *file;
- const char *p;
-#endif
- va_list argptr;
char buf[10];
char *q, c;
- VA_START (argptr, p);
-
-#ifndef ANSI_PROTOTYPES
- file = va_arg (argptr, FILE *);
- p = va_arg (argptr, const char *);
-#endif
+ VA_OPEN (argptr, p);
+ VA_FIXEDARG (argptr, FILE *, file);
+ VA_FIXEDARG (argptr, const char *, p);
buf[0] = '%';
default:
fputc (c, file);
}
- va_end (argptr);
+ VA_CLOSE (argptr);
}
\f
/* Split up a CONST_DOUBLE or integer constant rtx