diff options
author | Jeff Law <law@redhat.com> | 2018-10-25 13:35:52 -0600 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 2018-10-25 13:35:52 -0600 |
commit | 7959b94e08bcbd73e921149081e7d503525e0b77 (patch) | |
tree | baee35d811f07a61fe73db70f348b06677f2ad46 /gcc/config | |
parent | b15e280216048868aca98f2c4e3aa0b6559fd468 (diff) | |
download | gcc-7959b94e08bcbd73e921149081e7d503525e0b77.zip gcc-7959b94e08bcbd73e921149081e7d503525e0b77.tar.gz gcc-7959b94e08bcbd73e921149081e7d503525e0b77.tar.bz2 |
rl78.c (insn_ok_now): Always re-recognize the insn if returning false.
* config/rl78/rl78.c (insn_ok_now): Always re-recognize the insn
if returning false.
From-SVN: r265505
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/rl78/rl78.c | 52 |
1 files changed, 29 insertions, 23 deletions
diff --git a/gcc/config/rl78/rl78.c b/gcc/config/rl78/rl78.c index 6663e35..7986e89 100644 --- a/gcc/config/rl78/rl78.c +++ b/gcc/config/rl78/rl78.c @@ -2736,38 +2736,44 @@ insn_ok_now (rtx_insn * insn) if (GET_CODE (OP (i)) == MEM && GET_MODE (XEXP (OP (i), 0)) == SImode && GET_CODE (XEXP (OP (i), 0)) != UNSPEC) - return false; + goto not_ok; return true; } } - else - { - /* We need to re-recog the insn with virtual registers to get - the operands. */ - cfun->machine->virt_insns_ok = 1; - if (recog (pattern, insn, 0) > -1) - { - extract_insn (insn); - if (constrain_operands (0, get_preferred_alternatives (insn))) - { - cfun->machine->virt_insns_ok = 0; - return false; - } - } -#if DEBUG_ALLOC - fprintf (stderr, "\033[41;30m Unrecognized *virtual* insn \033[0m\n"); - debug_rtx (insn); -#endif - gcc_unreachable (); - } + /* INSN is not OK as-is. It may not be recognized in real mode or + it might not have satisfied its constraints in real mode. Either + way it will require fixups. + + It is vital we always re-recognize at this point as some insns + have fewer operands in real mode than virtual mode. If we do + not re-recognize, then the recog_data will refer to real mode + operands and we may read invalid data. Usually this isn't a + problem, but once in a while the data we read is bogus enough + to cause a segfault or other undesirable behavior. */ + not_ok: + + /* We need to re-recog the insn with virtual registers to get + the operands. */ + INSN_CODE (insn) = -1; + cfun->machine->virt_insns_ok = 1; + if (recog (pattern, insn, 0) > -1) + { + extract_insn (insn); + /* In theory this should always be true. */ + if (constrain_operands (0, get_preferred_alternatives (insn))) + { + cfun->machine->virt_insns_ok = 0; + return false; + } + } #if DEBUG_ALLOC - fprintf (stderr, "\033[31m"); + fprintf (stderr, "\033[41;30m Unrecognized *virtual* insn \033[0m\n"); debug_rtx (insn); - fprintf (stderr, "\033[0m"); #endif + gcc_unreachable (); return false; } |