aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
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;
}