summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormiod <miod@openbsd.org>2003-10-06 12:26:40 +0000
committermiod <miod@openbsd.org>2003-10-06 12:26:40 +0000
commit7ef7165de4b5db9f7c11b6a7cfb9b90a5cef31d3 (patch)
tree15762665d60f616e9b770fce164dc877580eed37
parentbetter output on error; ok henning@ (diff)
downloadwireguard-openbsd-7ef7165de4b5db9f7c11b6a7cfb9b90a5cef31d3.tar.xz
wireguard-openbsd-7ef7165de4b5db9f7c11b6a7cfb9b90a5cef31d3.zip
This is one of these eerie moments when you realize that a significant part
of your beliefs are wrong. In this case, trust in gcc. When computing the address of a field in a structure on stack, and: - the offset of the structure relative to the stack pointer and - the offset of the field relative to the structure have no _bits_ in common (for example, accessing field at structure(8) with the structure at sp(64)), triggers a gcc optimization in the following improvement: (plus (plus (frame_pointer offset_for_structure) offset_for_field)) changing into (plus (frame_pointer direct_offset_for_field)) In the aforementioned "no bits in common" case, gcc will use (or (plus frame_pointer offset_for_structure) offset_for_field) which is not necessarily correct, depending on the value of the frame pointer... Checking generated assembly code for a kernel compilation pointed out that ALL architectures were affected by this bug (some, such as m88k, alpha and sparc64, being much more affected than others, such as vax and m68k). Our first move was to backport a fix for this found in the gcc 3.x branch, however it relies upon several microbugfixes scattered around, and produced a misbehaving kernel on one particular machine. So what goes in with this commit is just a conservative fix which disables this particular "bitwise or is fun" optimization. Problem discovery and analysis by yours truly. Fix by etoh@ and I. Tested on all supported architectures by various people, including deraadt@, henning@, mickey@, naddy@ and I.
-rw-r--r--gnu/egcs/gcc/combine.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/gnu/egcs/gcc/combine.c b/gnu/egcs/gcc/combine.c
index 555604c3631..de6d89f448b 100644
--- a/gnu/egcs/gcc/combine.c
+++ b/gnu/egcs/gcc/combine.c
@@ -4027,6 +4027,7 @@ simplify_rtx (x, op0_mode, last, in_dest)
GET_MODE_BITSIZE (mode) - 1),
GET_MODE_BITSIZE (mode) - 1);
+#ifndef OPENBSD_NATIVE
/* If we are adding two things that have no bits in common, convert
the addition into an IOR. This will often be further simplified,
for example in cases like ((a & 1) + (a & 2)), which can
@@ -4036,6 +4037,7 @@ simplify_rtx (x, op0_mode, last, in_dest)
&& (nonzero_bits (XEXP (x, 0), mode)
& nonzero_bits (XEXP (x, 1), mode)) == 0)
return gen_binary (IOR, mode, XEXP (x, 0), XEXP (x, 1));
+#endif
break;
case MINUS: