From 7959b94e08bcbd73e921149081e7d503525e0b77 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Thu, 25 Oct 2018 13:35:52 -0600 Subject: [PATCH] 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 --- gcc/ChangeLog | 5 ++++ gcc/config/rl78/rl78.c | 52 +++++++++++++++++++++++------------------- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 174bcbaee4d..186ffe83a8a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2018-10-25 Jeff Law + + * config/rl78/rl78.c (insn_ok_now): Always re-recognize the insn + if returning false. + 2018-10-25 Martin Sebor * doc/extend.texi (aligned): Expand attribute description. diff --git a/gcc/config/rl78/rl78.c b/gcc/config/rl78/rl78.c index 6663e355834..7986e89e3d8 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; } -- 2.30.2