aboutsummaryrefslogtreecommitdiff
path: root/gcc/final.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/final.c')
-rw-r--r--gcc/final.c142
1 files changed, 89 insertions, 53 deletions
diff --git a/gcc/final.c b/gcc/final.c
index 29c0db5b9db..350a24e0f32 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -1,5 +1,5 @@
/* Convert RTL to assembler code and output it, for GNU compiler.
- Copyright (C) 1987, 88, 89, 92-97, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 89, 92-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
@@ -65,6 +65,7 @@ Boston, MA 02111-1307, USA. */
#include "except.h"
#include "toplev.h"
#include "reload.h"
+#include "intl.h"
/* Get N_SLINE and N_SOL from stab.h if we can expect the file to exist. */
#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
@@ -283,7 +284,7 @@ static int bb_func_label_num = -1; /* Current label # for func */
struct bb_str {
struct bb_str *next; /* pointer to next string */
- char *string; /* string */
+ const char *string; /* string */
int label_num; /* label number */
int length; /* string length */
};
@@ -300,7 +301,7 @@ static int asm_insn_count PROTO((rtx));
static void profile_function PROTO((FILE *));
static void profile_after_prologue PROTO((FILE *));
static void add_bb PROTO((FILE *));
-static int add_bb_string PROTO((char *, int));
+static int add_bb_string PROTO((const char *, int));
static void output_source_line PROTO((FILE *, rtx));
static rtx walk_alter_subreg PROTO((rtx));
static void output_asm_name PROTO((void));
@@ -336,7 +337,7 @@ init_final (filename)
void
end_final (filename)
- char *filename;
+ const char *filename;
{
int i;
@@ -413,7 +414,7 @@ end_final (filename)
assemble_integer (const0_rtx, pointer_bytes, 1);
/* byte count for extended structure. */
- assemble_integer (GEN_INT (10 * UNITS_PER_WORD), long_bytes, 1);
+ assemble_integer (GEN_INT (11 * UNITS_PER_WORD), long_bytes, 1);
/* address of function name table */
if (profile_block_flag)
@@ -1312,6 +1313,8 @@ shorten_branches (first)
/* If needed, do any adjustment. */
#ifdef ADJUST_INSN_LENGTH
ADJUST_INSN_LENGTH (insn, insn_lengths[uid]);
+ if (insn_lengths[uid] < 0)
+ fatal_insn ("Negative insn length", insn);
#endif
}
@@ -1861,7 +1864,7 @@ add_bb (file)
static int
add_bb_string (string, perm_p)
- char *string;
+ const char *string;
int perm_p;
{
int len;
@@ -2030,7 +2033,6 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
int prescan;
int nopeepholes;
{
- register int i;
#ifdef HAVE_cc0
rtx set;
#endif
@@ -2179,28 +2181,30 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
PENDING_BLOCKS and output debugging info based on that. */
--block_depth;
+ if (block_depth < 0)
+ abort ();
#ifdef XCOFF_DEBUGGING_INFO
- if (write_symbols == XCOFF_DEBUG && block_depth >= 0)
+ if (write_symbols == XCOFF_DEBUG)
xcoffout_end_block (file, high_block_linenum,
pending_blocks[block_depth]);
#endif
#ifdef DBX_DEBUGGING_INFO
- if (write_symbols == DBX_DEBUG && block_depth >= 0)
+ if (write_symbols == DBX_DEBUG)
ASM_OUTPUT_INTERNAL_LABEL (file, "LBE",
pending_blocks[block_depth]);
#endif
#ifdef SDB_DEBUGGING_INFO
- if (write_symbols == SDB_DEBUG && block_depth >= 0)
+ if (write_symbols == SDB_DEBUG)
sdbout_end_block (file, high_block_linenum,
pending_blocks[block_depth]);
#endif
#ifdef DWARF_DEBUGGING_INFO
- if (write_symbols == DWARF_DEBUG && block_depth >= 0)
+ if (write_symbols == DWARF_DEBUG)
dwarfout_end_block (pending_blocks[block_depth]);
#endif
#ifdef DWARF2_DEBUGGING_INFO
- if (write_symbols == DWARF2_DEBUG && block_depth >= 0)
+ if (write_symbols == DWARF2_DEBUG)
dwarf2out_end_block (pending_blocks[block_depth]);
#endif
}
@@ -2389,7 +2393,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
{
register rtx body = PATTERN (insn);
int insn_code_number;
- char *template;
+ const char *template;
#ifdef HAVE_cc0
rtx note;
#endif
@@ -2420,7 +2424,9 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC)
{
+#if !(defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC))
register int vlen, idx;
+#endif
if (prescan > 0)
break;
@@ -2836,27 +2842,11 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
since `reload' should have changed them so that they do. */
insn_code_number = recog_memoized (insn);
- insn_extract (insn);
- for (i = 0; i < insn_n_operands[insn_code_number]; 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]);
- }
-
- for (i = 0; i < insn_n_dups[insn_code_number]; 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]);
- }
+ extract_insn (insn);
+ cleanup_subreg_operands (insn);
#ifdef REGISTER_CONSTRAINTS
- if (! constrain_operands (insn_code_number, 1))
+ if (! constrain_operands (1))
fatal_insn_not_found (insn);
#endif
@@ -2864,8 +2854,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
it is output. */
#ifdef FINAL_PRESCAN_INSN
- FINAL_PRESCAN_INSN (insn, recog_operand,
- insn_n_operands[insn_code_number]);
+ FINAL_PRESCAN_INSN (insn, recog_operand, recog_n_operands);
#endif
#ifdef HAVE_cc0
@@ -3032,6 +3021,35 @@ output_source_line (file, insn)
}
}
+
+/* For each operand in INSN, simplify (subreg (reg)) so that it refers
+ directly to the desired hard register. */
+void
+cleanup_subreg_operands (insn)
+ rtx insn;
+{
+ int i;
+
+ extract_insn (insn);
+ for (i = 0; i < recog_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]);
+ }
+
+ for (i = 0; i < recog_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 X is a SUBREG, replace it with a REG or a MEM,
based on the thing it is a subreg of. */
@@ -3065,6 +3083,9 @@ alter_subreg (x)
#else
REGNO (x) = REGNO (y) + SUBREG_WORD (x);
#endif
+ /* This field has a different meaning for REGs and SUBREGs. Make sure
+ to clear it! */
+ x->used = 0;
}
else if (GET_CODE (y) == MEM)
{
@@ -3073,8 +3094,7 @@ alter_subreg (x)
offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x)))
- MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (y))));
PUT_CODE (x, MEM);
- MEM_VOLATILE_P (x) = MEM_VOLATILE_P (y);
- MEM_IN_STRUCT_P (x) = MEM_IN_STRUCT_P (y);
+ MEM_COPY_ATTRIBUTES (x, y);
MEM_ALIAS_SET (x) = MEM_ALIAS_SET (y);
XEXP (x, 0) = plus_constant (XEXP (y, 0), offset);
}
@@ -3276,13 +3296,13 @@ alter_cond (cond)
In an `asm', it's the user's fault; otherwise, the compiler's fault. */
void
-output_operand_lossage (str)
- char *str;
+output_operand_lossage (msgid)
+ const char *msgid;
{
if (this_is_asm_operands)
- error_for_asm (this_is_asm_operands, "invalid `asm': %s", str);
+ error_for_asm (this_is_asm_operands, "invalid `asm': %s", _(msgid));
else
- fatal ("Internal compiler error, output_operand_lossage `%s'", str);
+ fatal ("Internal compiler error, output_operand_lossage `%s'", _(msgid));
}
/* Output of assembler code from a template, and its subroutines. */
@@ -3313,11 +3333,13 @@ output_asm_name ()
if (debug_insn)
{
register int num = INSN_CODE (debug_insn);
- fprintf (asm_out_file, " %s %d %s",
+ 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)
fprintf (asm_out_file, "/%d", which_alternative + 1);
-
+#ifdef HAVE_ATTR_length
+ 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. */
debug_insn = 0;
@@ -3327,10 +3349,10 @@ output_asm_name ()
void
output_asm_insn (template, operands)
- char *template;
+ const char *template;
rtx *operands;
{
- register char *p;
+ register const char *p;
register int c;
/* An insn may return a null string template
@@ -3460,7 +3482,7 @@ output_asm_insn (template, operands)
punctuation character alone, with no operand.
The PRINT_OPERAND macro decides what is actually done. */
#ifdef PRINT_OPERAND_PUNCT_VALID_P
- else if (PRINT_OPERAND_PUNCT_VALID_P (*p))
+ else if (PRINT_OPERAND_PUNCT_VALID_P ((unsigned char)*p))
output_operand (NULL_RTX, *p++);
#endif
else
@@ -3655,11 +3677,11 @@ output_addr_const (file, x)
We handle alternate assembler dialects here, just like output_asm_insn. */
void
-asm_fprintf VPROTO((FILE *file, char *p, ...))
+asm_fprintf VPROTO((FILE *file, const char *p, ...))
{
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
FILE *file;
- char *p;
+ const char *p;
#endif
va_list argptr;
char buf[10];
@@ -3667,9 +3689,9 @@ asm_fprintf VPROTO((FILE *file, char *p, ...))
VA_START (argptr, p);
-#ifndef __STDC__
+#ifndef ANSI_PROTOTYPES
file = va_arg (argptr, FILE *);
- p = va_arg (argptr, char *);
+ p = va_arg (argptr, const char *);
#endif
buf[0] = '%';
@@ -3793,9 +3815,7 @@ asm_fprintf VPROTO((FILE *file, char *p, ...))
break;
case 'U':
-#ifdef USER_LABEL_PREFIX
- fprintf (file, "%s", USER_LABEL_PREFIX);
-#endif
+ fputs (user_label_prefix, file);
break;
default:
@@ -3906,6 +3926,22 @@ split_double (value, first, second)
not necessarily BITS_PER_WORD bits. */
REAL_VALUE_TO_TARGET_DOUBLE (r, l);
+ /* If 32 bits is an entire word for the target, but not for the host,
+ then sign-extend on the host so that the number will look the same
+ way on the host that it would on the target. See for instance
+ simplify_unary_operation. The #if is needed to avoid compiler
+ warnings. */
+
+#if HOST_BITS_PER_LONG > 32
+ if (BITS_PER_WORD < HOST_BITS_PER_LONG && BITS_PER_WORD == 32)
+ {
+ if (l[0] & ((long) 1 << 31))
+ l[0] |= ((long) (-1) << 32);
+ if (l[1] & ((long) 1 << 31))
+ l[1] |= ((long) (-1) << 32);
+ }
+#endif
+
*first = GEN_INT ((HOST_WIDE_INT) l[0]);
*second = GEN_INT ((HOST_WIDE_INT) l[1]);
#else