aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJeff Law <law@redhat.com>2018-10-25 13:35:52 -0600
committerJeff Law <law@gcc.gnu.org>2018-10-25 13:35:52 -0600
commit7959b94e08bcbd73e921149081e7d503525e0b77 (patch)
treebaee35d811f07a61fe73db70f348b06677f2ad46 /gcc
parentb15e280216048868aca98f2c4e3aa0b6559fd468 (diff)
downloadgcc-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')
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/config/rl78/rl78.c52
2 files changed, 34 insertions, 23 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 174bcba..186ffe8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2018-10-25 Jeff Law <law@redhat.com>
+
+ * config/rl78/rl78.c (insn_ok_now): Always re-recognize the insn
+ if returning false.
+
2018-10-25 Martin Sebor <msebor@redhat.com>
* doc/extend.texi (aligned): Expand attribute description.
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;
}