#include "tree.h"
#include "rtl.h"
+#include "tm_p.h"
#include "regs.h"
#include "insn-config.h"
#include "insn-flags.h"
#include "defaults.h"
#include "output.h"
#include "except.h"
+#include "function.h"
#include "toplev.h"
#include "reload.h"
#include "intl.h"
int length; /* string length */
};
+#ifdef HAVE_peephole
extern rtx peephole PROTO((rtx));
+#endif
static struct bb_str *sbb_head = 0; /* Head of string list. */
static struct bb_str **sbb_tail = &sbb_head; /* Ptr to store next bb str */
#ifdef HAVE_cc0
static int alter_cond PROTO((rtx));
#endif
-
-extern char *getpwd ();
\f
/* Initialize data in final at the beginning of a compilation. */
void
init_final (filename)
- char *filename;
+ const char *filename ATTRIBUTE_UNUSED;
{
next_block_index = 2;
app_on = 0;
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);
+ assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name),
+ pointer_bytes, 1);
ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 6);
- assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name), pointer_bytes, 1);
+ assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name),
+ pointer_bytes, 1);
}
else
{
address mod X to one mod Y, which is Y - X. */
#ifndef LABEL_ALIGN
-#define LABEL_ALIGN(LABEL) 0
+#define LABEL_ALIGN(LABEL) align_labels_log
#endif
#ifndef LABEL_ALIGN_MAX_SKIP
-#define LABEL_ALIGN_MAX_SKIP 0
+#define LABEL_ALIGN_MAX_SKIP (align_labels-1)
#endif
#ifndef LOOP_ALIGN
-#define LOOP_ALIGN(LABEL) 0
+#define LOOP_ALIGN(LABEL) align_loops_log
#endif
#ifndef LOOP_ALIGN_MAX_SKIP
-#define LOOP_ALIGN_MAX_SKIP 0
+#define LOOP_ALIGN_MAX_SKIP (align_loops-1)
#endif
#ifndef LABEL_ALIGN_AFTER_BARRIER
-#define LABEL_ALIGN_AFTER_BARRIER(LABEL) 0
+#define LABEL_ALIGN_AFTER_BARRIER(LABEL) align_jumps_log
#endif
#ifndef LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP
-#define LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP 0
+#define LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP (align_jumps-1)
#endif
#ifndef ADDR_VEC_ALIGN
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
{
rtx old = insn;
- insn = try_split (PATTERN (old), old, 1);
+ /* Don't split the insn if it has been deleted. */
+ if (! INSN_DELETED_P (old))
+ insn = try_split (PATTERN (old), old, 1);
/* When not optimizing, the old insn will be still left around
with only the 'deleted' bit set. Transform it into a note
to avoid confusion of subsequent processing. */
max_labelno = max_label_num ();
min_labelno = get_first_label_num ();
- label_align = (struct label_alignment *) xmalloc (
- (max_labelno - min_labelno + 1) * sizeof (struct label_alignment));
- bzero ((char *) label_align,
- (max_labelno - min_labelno + 1) * sizeof (struct label_alignment));
+ label_align = (struct label_alignment *)
+ xcalloc ((max_labelno - min_labelno + 1), sizeof (struct label_alignment));
uid_shuid = (int *) xmalloc (max_uid * sizeof *uid_shuid);
&& 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) == CODE_LABEL)
- {
- log = LOOP_ALIGN (insn);
- if (max_log < log)
- {
- max_log = log;
- max_skip = LOOP_ALIGN_MAX_SKIP;
- }
+ {
+ 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 (insn);
+ if (max_log < log)
+ {
+ max_log = log;
+ max_skip = LOOP_ALIGN_MAX_SKIP;
+ }
+ break;
+ }
+ }
}
else
continue;
/* Allocate the rest of the arrays. */
insn_lengths = (short *) xmalloc (max_uid * sizeof (short));
- insn_addresses = (int *) xmalloc (max_uid * sizeof (int));
insn_lengths_max_uid = max_uid;
/* Syntax errors can lead to labels being outside of the main insn stream.
Initialize insn_addresses, so that we get reproducible results. */
- bzero ((char *)insn_addresses, max_uid * sizeof *insn_addresses);
- uid_align = (rtx *) xmalloc (max_uid * sizeof *uid_align);
+ insn_addresses = (int *) xcalloc (max_uid, sizeof (int));
- varying_length = (char *) xmalloc (max_uid * sizeof (char));
-
- bzero (varying_length, max_uid);
+ varying_length = (char *) xcalloc (max_uid, sizeof (char));
/* Initialize uid_align. We scan instructions
from end to start, and keep in align_tab[n] the last seen insn
that does an alignment of at least n+1, i.e. the successor
in the alignment chain for an insn that does / has a known
alignment of n. */
-
- bzero ((char *) uid_align, max_uid * sizeof *uid_align);
+ uid_align = (rtx *) xcalloc (max_uid, sizeof *uid_align);
for (i = MAX_CODE_ALIGN; --i >= 0; )
align_tab[i] = NULL_RTX;
final_start_function (first, file, optimize)
rtx first;
FILE *file;
- int optimize;
+ int optimize ATTRIBUTE_UNUSED;
{
block_depth = 0;
void
final_end_function (first, file, optimize)
- rtx first;
+ rtx first ATTRIBUTE_UNUSED;
FILE *file;
- int optimize;
+ int optimize ATTRIBUTE_UNUSED;
{
if (app_on)
{
free_insn_eh_region ();
}
\f
+const char *
+get_insn_template (code, insn)
+ int code;
+ rtx insn;
+{
+ const void *output = insn_data[code].output;
+ switch (insn_data[code].output_format)
+ {
+ case INSN_OUTPUT_FORMAT_SINGLE:
+ return (const char *) output;
+ case INSN_OUTPUT_FORMAT_MULTI:
+ return ((const char * const *) output)[which_alternative];
+ case INSN_OUTPUT_FORMAT_FUNCTION:
+ if (insn == NULL)
+ abort ();
+ return (* (insn_output_fn) output) (recog_data.operand, insn);
+
+ default:
+ abort ();
+ }
+}
/* The final scan for one insn, INSN.
Args are same as in `final', except that INSN
is the insn being scanned.
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG
&& ! exceptions_via_longjmp)
{
- ASM_OUTPUT_INTERNAL_LABEL (file, "LEHB", NOTE_BLOCK_NUMBER (insn));
+ ASM_OUTPUT_INTERNAL_LABEL (file, "LEHB", NOTE_EH_HANDLER (insn));
if (! flag_new_exceptions)
- add_eh_table_entry (NOTE_BLOCK_NUMBER (insn));
+ add_eh_table_entry (NOTE_EH_HANDLER (insn));
#ifdef ASM_OUTPUT_EH_REGION_BEG
- ASM_OUTPUT_EH_REGION_BEG (file, NOTE_BLOCK_NUMBER (insn));
+ ASM_OUTPUT_EH_REGION_BEG (file, NOTE_EH_HANDLER (insn));
#endif
break;
}
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END
&& ! exceptions_via_longjmp)
{
- ASM_OUTPUT_INTERNAL_LABEL (file, "LEHE", NOTE_BLOCK_NUMBER (insn));
+ ASM_OUTPUT_INTERNAL_LABEL (file, "LEHE", NOTE_EH_HANDLER (insn));
if (flag_new_exceptions)
- add_eh_table_entry (NOTE_BLOCK_NUMBER (insn));
+ add_eh_table_entry (NOTE_EH_HANDLER (insn));
#ifdef ASM_OUTPUT_EH_REGION_END
- ASM_OUTPUT_EH_REGION_END (file, NOTE_BLOCK_NUMBER (insn));
+ ASM_OUTPUT_EH_REGION_END (file, NOTE_EH_HANDLER (insn));
#endif
break;
}
#endif
+#ifdef HAVE_peephole
/* Do machine-specific peephole optimizations if desired. */
if (optimize && !flag_no_peephole && !nopeepholes)
/* PEEPHOLE might have changed this. */
body = PATTERN (insn);
}
+#endif
/* Try to recognize the instruction.
If successful, verify that the operands satisfy the
extract_insn (insn);
cleanup_subreg_operands (insn);
-#ifdef REGISTER_CONSTRAINTS
if (! constrain_operands (1))
fatal_insn_not_found (insn);
-#endif
/* Some target machines need to prescan each insn before
it is output. */
#ifdef FINAL_PRESCAN_INSN
- FINAL_PRESCAN_INSN (insn, recog_operand, recog_n_operands);
+ FINAL_PRESCAN_INSN (insn, recog_data.operand, recog_data.n_operands);
#endif
#ifdef HAVE_cc0
dwarf2out_frame_debug (insn);
#endif
- /* If the proper template needs to be chosen by some C code,
- run that code and get the real template. */
+ /* Find the proper template for this insn. */
+ template = get_insn_template (insn_code_number, insn);
- template = insn_template[insn_code_number];
+ /* If the C code returns 0, it means that it is a jump insn
+ which follows a deleted test insn, and that test insn
+ needs to be reinserted. */
if (template == 0)
{
- template = (*insn_outfun[insn_code_number]) (recog_operand, insn);
-
- /* If the C code returns 0, it means that it is a jump insn
- which follows a deleted test insn, and that test insn
- needs to be reinserted. */
- if (template == 0)
- {
- if (prev_nonnote_insn (insn) != last_ignored_compare)
- abort ();
- new_block = 0;
- return prev_nonnote_insn (insn);
- }
+ if (prev_nonnote_insn (insn) != last_ignored_compare)
+ abort ();
+ new_block = 0;
+ return prev_nonnote_insn (insn);
}
/* If the template is the string "#", it means that this insn must
/* Output assembler code from the template. */
- output_asm_insn (template, recog_operand);
+ output_asm_insn (template, recog_data.operand);
#if defined (DWARF2_UNWIND_INFO)
#if !defined (ACCUMULATE_OUTGOING_ARGS)
static void
output_source_line (file, insn)
- FILE *file;
+ FILE *file ATTRIBUTE_UNUSED;
rtx insn;
{
register char *filename = NOTE_SOURCE_FILE (insn);
int i;
extract_insn (insn);
- for (i = 0; i < recog_n_operands; i++)
+ for (i = 0; i < recog_data.n_operands; i++)
{
- if (GET_CODE (recog_operand[i]) == SUBREG)
- recog_operand[i] = alter_subreg (recog_operand[i]);
- else if (GET_CODE (recog_operand[i]) == PLUS
- || GET_CODE (recog_operand[i]) == MULT)
- recog_operand[i] = walk_alter_subreg (recog_operand[i]);
+ if (GET_CODE (recog_data.operand[i]) == SUBREG)
+ recog_data.operand[i] = alter_subreg (recog_data.operand[i]);
+ else if (GET_CODE (recog_data.operand[i]) == PLUS
+ || GET_CODE (recog_data.operand[i]) == MULT)
+ recog_data.operand[i] = walk_alter_subreg (recog_data.operand[i]);
}
- for (i = 0; i < recog_n_dups; i++)
+ for (i = 0; i < recog_data.n_dups; i++)
{
- if (GET_CODE (*recog_dup_loc[i]) == SUBREG)
- *recog_dup_loc[i] = alter_subreg (*recog_dup_loc[i]);
- else if (GET_CODE (*recog_dup_loc[i]) == PLUS
- || GET_CODE (*recog_dup_loc[i]) == MULT)
- *recog_dup_loc[i] = walk_alter_subreg (*recog_dup_loc[i]);
+ if (GET_CODE (*recog_data.dup_loc[i]) == SUBREG)
+ *recog_data.dup_loc[i] = alter_subreg (*recog_data.dup_loc[i]);
+ else if (GET_CODE (*recog_data.dup_loc[i]) == PLUS
+ || GET_CODE (*recog_data.dup_loc[i]) == MULT)
+ *recog_data.dup_loc[i] = walk_alter_subreg (*recog_data.dup_loc[i]);
}
}
if (GET_CODE (y) == REG)
{
+ int regno;
/* If the word size is larger than the size of this register,
adjust the register number to compensate. */
/* ??? Note that this just catches stragglers created by/for
earlier, or kept _all_ subregs until now and eliminate
gen_lowpart and friends. */
- PUT_CODE (x, REG);
#ifdef ALTER_HARD_SUBREG
- REGNO (x) = ALTER_HARD_SUBREG(GET_MODE (x), SUBREG_WORD (x),
- GET_MODE (y), REGNO (y));
+ regno = ALTER_HARD_SUBREG(GET_MODE (x), SUBREG_WORD (x),
+ GET_MODE (y), REGNO (y));
#else
- REGNO (x) = REGNO (y) + SUBREG_WORD (x);
+ regno = REGNO (y) + SUBREG_WORD (x);
#endif
+ PUT_CODE (x, REG);
+ REGNO (x) = regno;
/* This field has a different meaning for REGs and SUBREGs. Make sure
to clear it! */
x->used = 0;
if (this_is_asm_operands)
error_for_asm (this_is_asm_operands, "invalid `asm': %s", _(msgid));
else
- fatal ("Internal compiler error, output_operand_lossage `%s'", _(msgid));
+ {
+ error ("output_operand: %s", _(msgid));
+ abort ();
+ }
}
\f
/* Output of assembler code from a template, and its subroutines. */
{
register int num = INSN_CODE (debug_insn);
fprintf (asm_out_file, "\t%s %d\t%s",
- ASM_COMMENT_START, INSN_UID (debug_insn), insn_name[num]);
- if (insn_n_alternatives[num] > 1)
+ ASM_COMMENT_START, INSN_UID (debug_insn),
+ insn_data[num].name);
+ if (insn_data[num].n_alternatives > 1)
fprintf (asm_out_file, "/%d", which_alternative + 1);
#ifdef HAVE_ATTR_length
- fprintf (asm_out_file, "\t[length = %d]", get_attr_length (debug_insn));
+ fprintf (asm_out_file, "\t[length = %d]",
+ get_attr_length (debug_insn));
#endif
/* Clear this so only the first assembler insn
of any rtl insn will get the special comment for -dp. */
DIALECT_NUMBER of strings ending with '|'. */
for (i = 0; i < dialect_number; i++)
{
- while (*p && *p++ != '|')
+ while (*p && *p != '}' && *p++ != '|')
;
-
+ if (*p == '}')
+ break;
if (*p == '|')
p++;
}
if (GET_CODE (XEXP (x, 1)) == CONST_INT
&& INTVAL (XEXP (x, 1)) < 0)
{
- fprintf (file, ASM_OPEN_PAREN);
+ fprintf (file, "%s", ASM_OPEN_PAREN);
output_addr_const (file, XEXP (x, 1));
- fprintf (file, ASM_CLOSE_PAREN);
+ fprintf (file, "%s", ASM_CLOSE_PAREN);
}
else
output_addr_const (file, XEXP (x, 1));
fputs (user_label_prefix, file);
break;
+#ifdef ASM_FPRINTF_EXTENSIONS
+ /* Upper case letters are reserved for general use by asm_fprintf
+ and so are not available to target specific code. In order to
+ prevent the ASM_FPRINTF_EXTENSIONS macro from using them then,
+ they are defined here. As they get turned into real extensions
+ to asm_fprintf they should be removed from this list. */
+ case 'A': case 'B': case 'C': case 'D': case 'E':
+ case 'F': case 'G': case 'H': case 'J': case 'K':
+ case 'M': case 'N': case 'P': case 'Q': case 'S':
+ case 'T': case 'V': case 'W': case 'Y': case 'Z':
+ break;
+
+ ASM_FPRINTF_EXTENSIONS (file, argptr, p)
+#endif
default:
abort ();
}
default:
fputc (c, file);
}
+ va_end (argptr);
}
\f
/* Split up a CONST_DOUBLE or integer constant rtx
register rtx in_rtx;
{
register int i, j;
- register char *format_ptr;
+ register const char *format_ptr;
if (in_rtx == 0)
return;