diff options
author | obrien <obrien@FreeBSD.org> | 1999-10-16 06:09:09 +0000 |
---|---|---|
committer | obrien <obrien@FreeBSD.org> | 1999-10-16 06:09:09 +0000 |
commit | cae8fa8120c70195f34a2456f18c4c848a2d3e0c (patch) | |
tree | f7d3a3ab9c32694206552e767626366f016f2062 /contrib/gcc/emit-rtl.c | |
parent | 84656b55b6e25e30322dc903a05de53706361d3d (diff) | |
download | FreeBSD-src-cae8fa8120c70195f34a2456f18c4c848a2d3e0c.zip FreeBSD-src-cae8fa8120c70195f34a2456f18c4c848a2d3e0c.tar.gz |
Virgin import of the GCC 2.95.1 compilers
Diffstat (limited to 'contrib/gcc/emit-rtl.c')
-rw-r--r-- | contrib/gcc/emit-rtl.c | 408 |
1 files changed, 331 insertions, 77 deletions
diff --git a/contrib/gcc/emit-rtl.c b/contrib/gcc/emit-rtl.c index 2ca007a..36b030a 100644 --- a/contrib/gcc/emit-rtl.c +++ b/contrib/gcc/emit-rtl.c @@ -1,5 +1,5 @@ /* Emit RTL for the GNU C-Compiler expander. - Copyright (C) 1987, 88, 92-97, 1998 Free Software Foundation, Inc. + Copyright (C) 1987, 88, 92-97, 1998, 1999 Free Software Foundation, Inc. This file is part of GNU CC. @@ -35,12 +35,8 @@ Boston, MA 02111-1307, USA. */ is the kind of rtx's they make and what arguments they use. */ #include "config.h" -#ifdef __STDC__ -#include <stdarg.h> -#else -#include <varargs.h> -#endif #include "system.h" +#include "toplev.h" #include "rtl.h" #include "tree.h" #include "flags.h" @@ -96,18 +92,27 @@ static int no_line_numbers; All of these except perhaps the floating-point CONST_DOUBLEs are unique; no other rtx-object will be equal to any of these. */ +/* Avoid warnings by initializing the `fld' field. Since its a union, + bypass problems with KNR compilers by only doing so when __GNUC__. */ +#ifdef __GNUC__ +#define FLDI , {{0}} +#else +#define FLDI +#endif + struct _global_rtl global_rtl = { - {PC, VOIDmode}, /* pc_rtx */ - {CC0, VOIDmode}, /* cc0_rtx */ - {REG}, /* stack_pointer_rtx */ - {REG}, /* frame_pointer_rtx */ - {REG}, /* hard_frame_pointer_rtx */ - {REG}, /* arg_pointer_rtx */ - {REG}, /* virtual_incoming_args_rtx */ - {REG}, /* virtual_stack_vars_rtx */ - {REG}, /* virtual_stack_dynamic_rtx */ - {REG}, /* virtual_outgoing_args_rtx */ + {PC, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* pc_rtx */ + {CC0, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* cc0_rtx */ + {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* stack_pointer_rtx */ + {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* frame_pointer_rtx */ + {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* hard_frame_pointer_rtx */ + {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* arg_pointer_rtx */ + {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* virtual_incoming_args_rtx */ + {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* virtual_stack_vars_rtx */ + {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* virtual_stack_dynamic_rtx */ + {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* virtual_outgoing_args_rtx */ + {REG, VOIDmode, 0, 0, 0, 0, 0, 0, 0, 0 FLDI }, /* virtual_cfa_rtx */ }; /* We record floating-point CONST_DOUBLEs in each floating-point mode for @@ -260,6 +265,29 @@ gen_rtx_CONST_INT (mode, arg) return gen_rtx_raw_CONST_INT (mode, arg); } +/* CONST_DOUBLEs needs special handling because its length is known + only at run-time. */ +rtx +gen_rtx_CONST_DOUBLE (mode, arg0, arg1, arg2) + enum machine_mode mode; + rtx arg0; + HOST_WIDE_INT arg1, arg2; +{ + rtx r = rtx_alloc (CONST_DOUBLE); + int i; + + PUT_MODE (r, mode); + XEXP (r, 0) = arg0; + XEXP (r, 1) = NULL_RTX; + XWINT (r, 2) = arg1; + XWINT (r, 3) = arg2; + + for (i = GET_RTX_LENGTH (CONST_DOUBLE) - 1; i > 3; --i) + XWINT (r, i) = 0; + + return r; +} + rtx gen_rtx_REG (mode, regno) enum machine_mode mode; @@ -346,7 +374,7 @@ gen_rtx_MEM (mode, addr) rtx gen_rtx VPROTO((enum rtx_code code, enum machine_mode mode, ...)) { -#ifndef __STDC__ +#ifndef ANSI_PROTOTYPES enum rtx_code code; enum machine_mode mode; #endif @@ -357,19 +385,35 @@ gen_rtx VPROTO((enum rtx_code code, enum machine_mode mode, ...)) VA_START (p, mode); -#ifndef __STDC__ +#ifndef ANSI_PROTOTYPES code = va_arg (p, enum rtx_code); mode = va_arg (p, enum machine_mode); #endif - if (code == CONST_INT) - rt_val = gen_rtx_CONST_INT (mode, va_arg (p, HOST_WIDE_INT)); - else if (code == REG) - rt_val = gen_rtx_REG (mode, va_arg (p, int)); - else if (code == MEM) - rt_val = gen_rtx_MEM (mode, va_arg (p, rtx)); - else + switch (code) { + case CONST_INT: + rt_val = gen_rtx_CONST_INT (mode, va_arg (p, HOST_WIDE_INT)); + break; + + case CONST_DOUBLE: + { + rtx arg0 = va_arg (p, rtx); + HOST_WIDE_INT arg1 = va_arg (p, HOST_WIDE_INT); + HOST_WIDE_INT arg2 = va_arg (p, HOST_WIDE_INT); + rt_val = gen_rtx_CONST_DOUBLE (mode, arg0, arg1, arg2); + } + break; + + case REG: + rt_val = gen_rtx_REG (mode, va_arg (p, int)); + break; + + case MEM: + rt_val = gen_rtx_MEM (mode, va_arg (p, rtx)); + break; + + default: rt_val = rtx_alloc (code); /* Allocate the storage space. */ rt_val->mode = mode; /* Store the machine mode... */ @@ -414,9 +458,11 @@ gen_rtx VPROTO((enum rtx_code code, enum machine_mode mode, ...)) abort (); } } + break; } + va_end (p); - return rt_val; /* Return the new RTX... */ + return rt_val; } /* gen_rtvec (n, [rt1, ..., rtn]) @@ -429,7 +475,7 @@ gen_rtx VPROTO((enum rtx_code code, enum machine_mode mode, ...)) rtvec gen_rtvec VPROTO((int n, ...)) { -#ifndef __STDC__ +#ifndef ANSI_PROTOTYPES int n; #endif int i; @@ -438,7 +484,7 @@ gen_rtvec VPROTO((int n, ...)) VA_START (p, n); -#ifndef __STDC__ +#ifndef ANSI_PROTOTYPES n = va_arg (p, int); #endif @@ -501,11 +547,9 @@ gen_reg_rtx (mode) { register rtx val; - /* Don't let anything called by or after reload create new registers - (actually, registers can't be created after flow, but this is a good - approximation). */ - - if (reload_in_progress || reload_completed) + /* Don't let anything called after initial flow analysis create new + registers. */ + if (no_new_pseudos) abort (); if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT @@ -586,9 +630,15 @@ mark_reg_pointer (reg, align) rtx reg; int align; { - REGNO_POINTER_FLAG (REGNO (reg)) = 1; + if (! REGNO_POINTER_FLAG (REGNO (reg))) + { + REGNO_POINTER_FLAG (REGNO (reg)) = 1; - if (align) + if (align) + REGNO_POINTER_ALIGN (REGNO (reg)) = align; + } + else if (align && align < REGNO_POINTER_ALIGN (REGNO (reg))) + /* We can no-longer be sure just how aligned this pointer is */ REGNO_POINTER_ALIGN (REGNO (reg)) = align; } @@ -852,6 +902,22 @@ gen_lowpart_common (mode, x) r = REAL_VALUE_FROM_TARGET_SINGLE (i); return CONST_DOUBLE_FROM_REAL_VALUE (r, mode); } + else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT + && HOST_BITS_PER_WIDE_INT == BITS_PER_WORD) + || flag_pretend_float) + && GET_MODE_CLASS (mode) == MODE_FLOAT + && GET_MODE_SIZE (mode) == UNITS_PER_WORD + && GET_CODE (x) == CONST_INT + && (sizeof (double) * HOST_BITS_PER_CHAR + == HOST_BITS_PER_WIDE_INT)) + { + REAL_VALUE_TYPE r; + HOST_WIDE_INT i; + + i = INTVAL (x); + r = REAL_VALUE_FROM_TARGET_DOUBLE (&i); + return CONST_DOUBLE_FROM_REAL_VALUE (r, mode); + } #endif /* Similarly, if this is converting a floating-point value into a @@ -906,6 +972,11 @@ gen_realpart (mode, x) { if (GET_CODE (x) == CONCAT && GET_MODE (XEXP (x, 0)) == mode) return XEXP (x, 0); + else if (WORDS_BIG_ENDIAN + && GET_MODE_BITSIZE (mode) < BITS_PER_WORD + && REG_P (x) + && REGNO (x) < FIRST_PSEUDO_REGISTER) + fatal ("Unable to access real part of complex value in a hard register on this target"); else if (WORDS_BIG_ENDIAN) return gen_highpart (mode, x); else @@ -924,6 +995,11 @@ gen_imagpart (mode, x) return XEXP (x, 1); else if (WORDS_BIG_ENDIAN) return gen_lowpart (mode, x); + else if (!WORDS_BIG_ENDIAN + && GET_MODE_BITSIZE (mode) < BITS_PER_WORD + && REG_P (x) + && REGNO (x) < FIRST_PSEUDO_REGISTER) + fatal ("Unable to access imaginary part of complex value in a hard register on this target"); else return gen_highpart (mode, x); } @@ -940,7 +1016,7 @@ subreg_realpart_p (x) if (GET_CODE (x) != SUBREG) abort (); - return SUBREG_WORD (x) == 0; + return SUBREG_WORD (x) * UNITS_PER_WORD < GET_MODE_UNIT_SIZE (GET_MODE (SUBREG_REG (x))); } /* Assuming that X is an rtx (e.g., MEM, REG or SUBREG) for a value, @@ -1134,12 +1210,16 @@ operand_subword (op, i, validate_address, mode) if (mode == VOIDmode) abort (); - /* If OP is narrower than a word or if we want a word outside OP, fail. */ + /* If OP is narrower than a word, fail. */ if (mode != BLKmode - && (GET_MODE_SIZE (mode) < UNITS_PER_WORD - || (i + 1) * UNITS_PER_WORD > GET_MODE_SIZE (mode))) + && (GET_MODE_SIZE (mode) < UNITS_PER_WORD)) return 0; + /* If we want a word outside OP, return zero. */ + if (mode != BLKmode + && (i + 1) * UNITS_PER_WORD > GET_MODE_SIZE (mode)) + return const0_rtx; + /* If OP is already an integer word, return it. */ if (GET_MODE_CLASS (mode) == MODE_INT && GET_MODE_SIZE (mode) == UNITS_PER_WORD) @@ -1148,10 +1228,33 @@ operand_subword (op, i, validate_address, mode) /* If OP is a REG or SUBREG, we can handle it very simply. */ if (GET_CODE (op) == REG) { - /* If the register is not valid for MODE, return 0. If we don't - do this, there is no way to fix up the resulting REG later. */ + /* ??? There is a potential problem with this code. It does not + properly handle extractions of a subword from a hard register + that is larger than word_mode. Presumably the check for + HARD_REGNO_MODE_OK catches these most of these cases. */ + + /* If OP is a hard register, but OP + I is not a hard register, + then extracting a subword is impossible. + + For example, consider if OP is the last hard register and it is + larger than word_mode. If we wanted word N (for N > 0) because a + part of that hard register was known to contain a useful value, + then OP + I would refer to a pseudo, not the hard register we + actually wanted. */ if (REGNO (op) < FIRST_PSEUDO_REGISTER - && ! HARD_REGNO_MODE_OK (REGNO (op) + i, word_mode)) + && REGNO (op) + i >= FIRST_PSEUDO_REGISTER) + return 0; + + /* If the register is not valid for MODE, return 0. Note we + have to check both OP and OP + I since they may refer to + different parts of the register file. + + Consider if OP refers to the last 96bit FP register and we want + subword 3 because that subword is known to contain a value we + needed. */ + if (REGNO (op) < FIRST_PSEUDO_REGISTER + && (! HARD_REGNO_MODE_OK (REGNO (op), word_mode) + || ! HARD_REGNO_MODE_OK (REGNO (op) + i, word_mode))) return 0; else if (REGNO (op) >= FIRST_PSEUDO_REGISTER || (REG_FUNCTION_VALUE_P (op) @@ -1197,8 +1300,7 @@ operand_subword (op, i, validate_address, mode) new = gen_rtx_MEM (word_mode, addr); - MEM_VOLATILE_P (new) = MEM_VOLATILE_P (op); - MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (op); + MEM_COPY_ATTRIBUTES (new, op); RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (op); return new; @@ -1226,24 +1328,35 @@ operand_subword (op, i, validate_address, mode) /* We handle 32-bit and >= 64-bit words here. Note that the order in which the words are written depends on the word endianness. - ??? This is a potential portability problem and should - be fixed at some point. */ + be fixed at some point. + + We must excercise caution with the sign bit. By definition there + are 32 significant bits in K; there may be more in a HOST_WIDE_INT. + Consider a host with a 32-bit long and a 64-bit HOST_WIDE_INT. + So we explicitly mask and sign-extend as necessary. */ if (BITS_PER_WORD == 32) - return GEN_INT ((HOST_WIDE_INT) k[i]); -#if HOST_BITS_PER_WIDE_INT > 32 + { + val = k[i]; + val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000; + return GEN_INT (val); + } +#if HOST_BITS_PER_WIDE_INT >= 64 else if (BITS_PER_WORD >= 64 && i == 0) - return GEN_INT ((((HOST_WIDE_INT) k[! WORDS_BIG_ENDIAN]) << 32) - | (HOST_WIDE_INT) k[WORDS_BIG_ENDIAN]); + { + val = k[! WORDS_BIG_ENDIAN]; + val = (((val & 0xffffffff) ^ 0x80000000) - 0x80000000) << 32; + val |= (HOST_WIDE_INT) k[WORDS_BIG_ENDIAN] & 0xffffffff; + return GEN_INT (val); + } #endif else if (BITS_PER_WORD == 16) { - long value; - value = k[i >> 1]; - if ((i & 0x1) == !WORDS_BIG_ENDIAN) - value >>= 16; - value &= 0xffff; - return GEN_INT ((HOST_WIDE_INT) value); + val = k[i >> 1]; + if ((i & 1) == !WORDS_BIG_ENDIAN) + val >>= 16; + val &= 0xffff; + return GEN_INT (val); } else abort (); @@ -1260,7 +1373,13 @@ operand_subword (op, i, validate_address, mode) REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, k); if (BITS_PER_WORD == 32) - return GEN_INT ((HOST_WIDE_INT) k[i]); + { + val = k[i]; + val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000; + return GEN_INT (val); + } + else + abort (); } #else /* no REAL_ARITHMETIC */ if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT @@ -1298,13 +1417,18 @@ operand_subword (op, i, validate_address, mode) REAL_VALUE_FROM_CONST_DOUBLE (rv, op); REAL_VALUE_TO_TARGET_SINGLE (rv, l); + /* Sign extend from known 32-bit value to HOST_WIDE_INT. */ + val = l; + val = ((val & 0xffffffff) ^ 0x80000000) - 0x80000000; + if (BITS_PER_WORD == 16) { - if ((i & 0x1) == !WORDS_BIG_ENDIAN) - l >>= 16; - l &= 0xffff; + if ((i & 1) == !WORDS_BIG_ENDIAN) + val >>= 16; + val &= 0xffff; } - return GEN_INT ((HOST_WIDE_INT) l); + + return GEN_INT (val); } #else if (((HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT @@ -1497,9 +1621,8 @@ change_address (memref, mode, addr) return memref; new = gen_rtx_MEM (mode, addr); - MEM_VOLATILE_P (new) = MEM_VOLATILE_P (memref); RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (memref); - MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (memref); + MEM_COPY_ATTRIBUTES (new, memref); return new; } @@ -2264,7 +2387,8 @@ try_split (pat, trial, last) Ignore deleted insns, which can be occur if not optimizing. */ for (tem = NEXT_INSN (before); tem != after; tem = NEXT_INSN (tem)) - if (! INSN_DELETED_P (tem)) + if (! INSN_DELETED_P (tem) + && GET_RTX_CLASS (GET_CODE (tem)) == 'i') tem = try_split (PATTERN (tem), tem, 1); } /* Avoid infinite loop if the result matches the original pattern. */ @@ -2468,6 +2592,64 @@ add_insn_before (insn, before) PREV_INSN (XVECEXP (PATTERN (before), 0, 0)) = insn; } +/* Remove an insn from its doubly-linked list. This function knows how + to handle sequences. */ +void +remove_insn (insn) + rtx insn; +{ + rtx next = NEXT_INSN (insn); + rtx prev = PREV_INSN (insn); + if (prev) + { + NEXT_INSN (prev) = next; + if (GET_CODE (prev) == INSN && GET_CODE (PATTERN (prev)) == SEQUENCE) + { + rtx sequence = PATTERN (prev); + NEXT_INSN (XVECEXP (sequence, 0, XVECLEN (sequence, 0) - 1)) = next; + } + } + else if (first_insn == insn) + first_insn = next; + else + { + struct sequence_stack *stack = sequence_stack; + /* Scan all pending sequences too. */ + for (; stack; stack = stack->next) + if (insn == stack->first) + { + stack->first = next; + break; + } + + if (stack == 0) + abort (); + } + + if (next) + { + PREV_INSN (next) = prev; + if (GET_CODE (next) == INSN && GET_CODE (PATTERN (next)) == SEQUENCE) + PREV_INSN (XVECEXP (PATTERN (next), 0, 0)) = prev; + } + else if (last_insn == insn) + last_insn = prev; + else + { + struct sequence_stack *stack = sequence_stack; + /* Scan all pending sequences too. */ + for (; stack; stack = stack->next) + if (insn == stack->last) + { + stack->last = prev; + break; + } + + if (stack == 0) + abort (); + } +} + /* Delete all insns made since FROM. FROM becomes the new last instruction. */ @@ -2635,7 +2817,7 @@ emit_call_insn_before (pattern, before) } /* Make an insn of code BARRIER - and output it before the insn AFTER. */ + and output it before the insn BEFORE. */ rtx emit_barrier_before (before) @@ -2649,6 +2831,23 @@ emit_barrier_before (before) return insn; } +/* Emit the label LABEL before the insn BEFORE. */ + +rtx +emit_label_before (label, before) + rtx label, before; +{ + /* This can be called twice for the same label as a result of the + confusion that follows a syntax error! So make it harmless. */ + if (INSN_UID (label) == 0) + { + INSN_UID (label) = cur_insn_uid++; + add_insn_before (label, before); + } + + return label; +} + /* Emit a note of subtype SUBTYPE before the insn BEFORE. */ rtx @@ -3038,7 +3237,7 @@ emit_note (file, line) return note; } -/* Emit a NOTE, and don't omit it even if LINE it the previous note. */ +/* Emit a NOTE, and don't omit it even if LINE is the previous note. */ rtx emit_line_note_force (file, line) @@ -3057,6 +3256,24 @@ force_next_line_note () { last_linenum = -1; } + +/* Place a note of KIND on insn INSN with DATUM as the datum. If a + note of this type already exists, remove it first. */ + +void +set_unique_reg_note (insn, kind, datum) + rtx insn; + enum reg_note kind; + rtx datum; +{ + rtx note = find_reg_note (insn, kind, NULL_RTX); + + /* First remove the note if there already is one. */ + if (note) + remove_note (insn, note); + + REG_NOTES (insn) = gen_rtx_EXPR_LIST (kind, datum, REG_NOTES (insn)); +} /* Return an indication of which type of insn should have X as a body. The value is CODE_LABEL, INSN, CALL_INSN or JUMP_INSN. */ @@ -3122,7 +3339,13 @@ emit (x) abort (); } -/* Begin emitting insns to a sequence which can be packaged in an RTL_EXPR. */ +/* Begin emitting insns to a sequence which can be packaged in an + RTL_EXPR. If this sequence will contain something that might cause + the compiler to pop arguments to function calls (because those + pops have previously been deferred; see INHIBIT_DEFER_POP for more + details), use do_pending_stack_adjust before calling this function. + That will ensure that the deferred pops are not accidentally + emitted in the middel of this sequence. */ void start_sequence () @@ -3149,8 +3372,9 @@ start_sequence () last_insn = 0; } -/* Similarly, but indicate that this sequence will be placed in - T, an RTL_EXPR. */ +/* Similarly, but indicate that this sequence will be placed in T, an + RTL_EXPR. See the documentation for start_sequence for more + information about how to use this function. */ void start_sequence_for_rtl_expr (t) @@ -3161,8 +3385,9 @@ start_sequence_for_rtl_expr (t) sequence_rtl_expr = t; } -/* Set up the insn chain starting with FIRST - as the current sequence, saving the previously current one. */ +/* Set up the insn chain starting with FIRST as the current sequence, + saving the previously current one. See the documentation for + start_sequence for more information about how to use this function. */ void push_to_sequence (first) @@ -3216,8 +3441,16 @@ pop_topmost_sequence () /* After emitting to a sequence, restore previous saved state. - To get the contents of the sequence just made, - you must call `gen_sequence' *before* calling here. */ + To get the contents of the sequence just made, you must call + `gen_sequence' *before* calling here. + + If the compiler might have deferred popping arguments while + generating this sequence, and this sequence will not be immediately + inserted into the instruction stream, use do_pending_stack_adjust + before calling gen_sequence. That will ensure that the deferred + pops are inserted into this sequence, and not into some random + location in the instruction stream. See INHIBIT_DEFER_POP for more + information about deferred popping of arguments. */ void end_sequence () @@ -3296,6 +3529,18 @@ gen_sequence () return result; } +/* Put the various virtual registers into REGNO_REG_RTX. */ + +void +init_virtual_regs () +{ + regno_reg_rtx[VIRTUAL_INCOMING_ARGS_REGNUM] = virtual_incoming_args_rtx; + regno_reg_rtx[VIRTUAL_STACK_VARS_REGNUM] = virtual_stack_vars_rtx; + regno_reg_rtx[VIRTUAL_STACK_DYNAMIC_REGNUM] = virtual_stack_dynamic_rtx; + regno_reg_rtx[VIRTUAL_OUTGOING_ARGS_REGNUM] = virtual_outgoing_args_rtx; + regno_reg_rtx[VIRTUAL_CFA_REGNUM] = virtual_cfa_rtx; +} + /* Initialize data structures and variables in this file before generating rtl for each function. */ @@ -3338,10 +3583,7 @@ init_emit () bzero ((char *) regno_reg_rtx, regno_pointer_flag_length * sizeof (rtx)); /* Put copies of all the virtual register rtx into regno_reg_rtx. */ - regno_reg_rtx[VIRTUAL_INCOMING_ARGS_REGNUM] = virtual_incoming_args_rtx; - regno_reg_rtx[VIRTUAL_STACK_VARS_REGNUM] = virtual_stack_vars_rtx; - regno_reg_rtx[VIRTUAL_STACK_DYNAMIC_REGNUM] = virtual_stack_dynamic_rtx; - regno_reg_rtx[VIRTUAL_OUTGOING_ARGS_REGNUM] = virtual_outgoing_args_rtx; + init_virtual_regs (); /* Indicate that the virtual registers and stack locations are all pointers. */ @@ -3354,6 +3596,7 @@ init_emit () REGNO_POINTER_FLAG (VIRTUAL_STACK_VARS_REGNUM) = 1; REGNO_POINTER_FLAG (VIRTUAL_STACK_DYNAMIC_REGNUM) = 1; REGNO_POINTER_FLAG (VIRTUAL_OUTGOING_ARGS_REGNUM) = 1; + REGNO_POINTER_FLAG (VIRTUAL_CFA_REGNUM) = 1; #ifdef STACK_BOUNDARY REGNO_POINTER_ALIGN (STACK_POINTER_REGNUM) = STACK_BOUNDARY / BITS_PER_UNIT; @@ -3370,6 +3613,7 @@ init_emit () = STACK_BOUNDARY / BITS_PER_UNIT; REGNO_POINTER_ALIGN (VIRTUAL_OUTGOING_ARGS_REGNUM) = STACK_BOUNDARY / BITS_PER_UNIT; + REGNO_POINTER_ALIGN (VIRTUAL_CFA_REGNUM) = UNITS_PER_WORD; #endif #ifdef INIT_EXPANDERS @@ -3504,6 +3748,8 @@ init_emit_once (line_numbers) PUT_MODE (virtual_stack_dynamic_rtx, Pmode); REGNO (virtual_outgoing_args_rtx) = VIRTUAL_OUTGOING_ARGS_REGNUM; PUT_MODE (virtual_outgoing_args_rtx, Pmode); + REGNO (virtual_cfa_rtx) = VIRTUAL_CFA_REGNUM; + PUT_MODE (virtual_cfa_rtx, Pmode); #ifdef RETURN_ADDRESS_POINTER_REGNUM return_address_pointer_rtx @@ -3551,6 +3797,14 @@ init_emit_once (line_numbers) #ifdef PIC_OFFSET_TABLE_REGNUM pic_offset_table_rtx = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM); #endif + +#ifdef INIT_EXPANDERS + /* This is to initialize save_machine_status and restore_machine_status before + the first call to push_function_context_to. This is needed by the Chill + front end which calls push_function_context_to before the first cal to + init_function_start. */ + INIT_EXPANDERS; +#endif } /* Query and clear/ restore no_line_numbers. This is used by the |