diff options
author | Mark Mitchell <mark@codesourcery.com> | 2002-04-22 19:26:19 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2002-04-22 19:26:19 +0000 |
commit | 8ed8f73189d98d9960c23061be9b0cdefa7c8f0d (patch) | |
tree | 898af6988a88f160710755e9b4a121324c754dcc /gcc/function.c | |
parent | b2e4f4fda73c761ee3d7f817378241d04f11a936 (diff) | |
download | gcc-8ed8f73189d98d9960c23061be9b0cdefa7c8f0d.zip gcc-8ed8f73189d98d9960c23061be9b0cdefa7c8f0d.tar.gz gcc-8ed8f73189d98d9960c23061be9b0cdefa7c8f0d.tar.bz2 |
re PR fortran/6138 (Incorrect access of integer*1 variables on PA)
PR f/6138.
* function.c (fixup_memory_subreg): Add promoted_mode parameter.
(walk_fixup_memory_subreg): Likewise.
(fixup_var_refs_insn): Adjust accordingly.
(fixup_var_refs_1): Likewise.
From-SVN: r52631
Diffstat (limited to 'gcc/function.c')
-rw-r--r-- | gcc/function.c | 84 |
1 files changed, 54 insertions, 30 deletions
diff --git a/gcc/function.c b/gcc/function.c index e22273d..5904919 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -246,8 +246,9 @@ static void fixup_var_refs_insn PARAMS ((rtx, rtx, enum machine_mode, int, int, rtx)); static void fixup_var_refs_1 PARAMS ((rtx, enum machine_mode, rtx *, rtx, struct fixup_replacement **, rtx)); -static rtx fixup_memory_subreg PARAMS ((rtx, rtx, int)); -static rtx walk_fixup_memory_subreg PARAMS ((rtx, rtx, int)); +static rtx fixup_memory_subreg PARAMS ((rtx, rtx, enum machine_mode, int)); +static rtx walk_fixup_memory_subreg PARAMS ((rtx, rtx, enum machine_mode, + int)); static rtx fixup_stack_1 PARAMS ((rtx, rtx)); static void optimize_bit_field PARAMS ((rtx, rtx, rtx *)); static void instantiate_decls PARAMS ((tree, int)); @@ -1859,7 +1860,8 @@ fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, toplevel, no_share) /* OLD might be a (subreg (mem)). */ if (GET_CODE (replacements->old) == SUBREG) replacements->old - = fixup_memory_subreg (replacements->old, insn, 0); + = fixup_memory_subreg (replacements->old, insn, + promoted_mode, 0); else replacements->old = fixup_stack_1 (replacements->old, insn); @@ -1899,7 +1901,8 @@ fixup_var_refs_insn (insn, var, promoted_mode, unsignedp, toplevel, no_share) { if (GET_CODE (note) != INSN_LIST) XEXP (note, 0) - = walk_fixup_memory_subreg (XEXP (note, 0), insn, 1); + = walk_fixup_memory_subreg (XEXP (note, 0), insn, + promoted_mode, 1); note = XEXP (note, 1); } } @@ -2070,7 +2073,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share) return; } else - tem = fixup_memory_subreg (tem, insn, 0); + tem = fixup_memory_subreg (tem, insn, promoted_mode, 0); } else tem = fixup_stack_1 (tem, insn); @@ -2185,7 +2188,8 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share) return; } - replacement->new = *loc = fixup_memory_subreg (x, insn, 0); + replacement->new = *loc = fixup_memory_subreg (x, insn, + promoted_mode, 0); INSN_CODE (insn) = -1; if (! flag_force_mem && recog_memoized (insn) >= 0) @@ -2276,7 +2280,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share) This was legitimate when the MEM was a REG. */ if (GET_CODE (tem) == SUBREG && SUBREG_REG (tem) == var) - tem = fixup_memory_subreg (tem, insn, 0); + tem = fixup_memory_subreg (tem, insn, promoted_mode, 0); else tem = fixup_stack_1 (tem, insn); @@ -2378,7 +2382,8 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share) SET_SRC (x) = replacement->new; else if (GET_CODE (SET_SRC (x)) == SUBREG) SET_SRC (x) = replacement->new - = fixup_memory_subreg (SET_SRC (x), insn, 0); + = fixup_memory_subreg (SET_SRC (x), insn, promoted_mode, + 0); else SET_SRC (x) = replacement->new = fixup_stack_1 (SET_SRC (x), insn); @@ -2431,7 +2436,8 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share) rtx pat, last; if (GET_CODE (SET_DEST (x)) == SUBREG) - SET_DEST (x) = fixup_memory_subreg (SET_DEST (x), insn, 0); + SET_DEST (x) = fixup_memory_subreg (SET_DEST (x), insn, + promoted_mode, 0); else SET_DEST (x) = fixup_stack_1 (SET_DEST (x), insn); @@ -2476,6 +2482,7 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share) { rtx temp; rtx fixeddest = SET_DEST (x); + enum machine_mode temp_mode; /* STRICT_LOW_PART can be discarded, around a MEM. */ if (GET_CODE (fixeddest) == STRICT_LOW_PART) @@ -2483,13 +2490,17 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share) /* Convert (SUBREG (MEM)) to a MEM in a changed mode. */ if (GET_CODE (fixeddest) == SUBREG) { - fixeddest = fixup_memory_subreg (fixeddest, insn, 0); - promoted_mode = GET_MODE (fixeddest); + fixeddest = fixup_memory_subreg (fixeddest, insn, + promoted_mode, 0); + temp_mode = GET_MODE (fixeddest); } else - fixeddest = fixup_stack_1 (fixeddest, insn); + { + fixeddest = fixup_stack_1 (fixeddest, insn); + temp_mode = promoted_mode; + } - temp = gen_reg_rtx (promoted_mode); + temp = gen_reg_rtx (temp_mode); emit_insn_after (gen_move_insn (fixeddest, gen_lowpart (GET_MODE (fixeddest), @@ -2522,36 +2533,47 @@ fixup_var_refs_1 (var, promoted_mode, loc, insn, replacements, no_share) } } -/* Given X, an rtx of the form (SUBREG:m1 (MEM:m2 addr)), - return an rtx (MEM:m1 newaddr) which is equivalent. - If any insns must be emitted to compute NEWADDR, put them before INSN. +/* Previously, X had the form (SUBREG:m1 (REG:PROMOTED_MODE ...)). + The REG was placed on the stack, so X now has the form (SUBREG:m1 + (MEM:m2 ...)). + + Return an rtx (MEM:m1 newaddr) which is equivalent. If any insns + must be emitted to compute NEWADDR, put them before INSN. UNCRITICAL nonzero means accept paradoxical subregs. This is used for subregs found inside REG_NOTES. */ static rtx -fixup_memory_subreg (x, insn, uncritical) +fixup_memory_subreg (x, insn, promoted_mode, uncritical) rtx x; rtx insn; + enum machine_mode promoted_mode; int uncritical; { - int offset = SUBREG_BYTE (x); - rtx addr = XEXP (SUBREG_REG (x), 0); + int offset; + rtx mem = SUBREG_REG (x); + rtx addr = XEXP (mem, 0); enum machine_mode mode = GET_MODE (x); rtx result; /* Paradoxical SUBREGs are usually invalid during RTL generation. */ - if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) - && ! uncritical) + if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (mem)) && ! uncritical) abort (); + offset = SUBREG_BYTE (x); + if (BYTES_BIG_ENDIAN) + /* If the PROMOTED_MODE is wider than the mode of the MEM, adjust + the offset so that it points to the right location within the + MEM. */ + offset -= (GET_MODE_SIZE (promoted_mode) - GET_MODE_SIZE (GET_MODE (mem))); + if (!flag_force_addr && memory_address_p (mode, plus_constant (addr, offset))) /* Shortcut if no insns need be emitted. */ - return adjust_address (SUBREG_REG (x), mode, offset); + return adjust_address (mem, mode, offset); start_sequence (); - result = adjust_address (SUBREG_REG (x), mode, offset); + result = adjust_address (mem, mode, offset); emit_insn_before (gen_sequence (), insn); end_sequence (); return result; @@ -2562,14 +2584,14 @@ fixup_memory_subreg (x, insn, uncritical) If X itself is a (SUBREG (MEM ...) ...), return the replacement expression. Otherwise return X, with its contents possibly altered. - If any insns must be emitted to compute NEWADDR, put them before INSN. - - UNCRITICAL is as in fixup_memory_subreg. */ + INSN, PROMOTED_MODE and UNCRITICAL are as for + fixup_memory_subreg. */ static rtx -walk_fixup_memory_subreg (x, insn, uncritical) +walk_fixup_memory_subreg (x, insn, promoted_mode, uncritical) rtx x; rtx insn; + enum machine_mode promoted_mode; int uncritical; { enum rtx_code code; @@ -2582,7 +2604,7 @@ walk_fixup_memory_subreg (x, insn, uncritical) code = GET_CODE (x); if (code == SUBREG && GET_CODE (SUBREG_REG (x)) == MEM) - return fixup_memory_subreg (x, insn, uncritical); + return fixup_memory_subreg (x, insn, promoted_mode, uncritical); /* Nothing special about this RTX; fix its operands. */ @@ -2590,13 +2612,15 @@ walk_fixup_memory_subreg (x, insn, uncritical) for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) { if (fmt[i] == 'e') - XEXP (x, i) = walk_fixup_memory_subreg (XEXP (x, i), insn, uncritical); + XEXP (x, i) = walk_fixup_memory_subreg (XEXP (x, i), insn, + promoted_mode, uncritical); else if (fmt[i] == 'E') { int j; for (j = 0; j < XVECLEN (x, i); j++) XVECEXP (x, i, j) - = walk_fixup_memory_subreg (XVECEXP (x, i, j), insn, uncritical); + = walk_fixup_memory_subreg (XVECEXP (x, i, j), insn, + promoted_mode, uncritical); } } return x; |