[llvm-bugs] [Bug 40554] New: misaligned float in PowerPC code causes SIGBUS in OpenBSD/macppc

via llvm-bugs llvm-bugs at lists.llvm.org
Thu Jan 31 13:58:33 PST 2019


https://bugs.llvm.org/show_bug.cgi?id=40554

            Bug ID: 40554
           Summary: misaligned float in PowerPC code causes SIGBUS in
                    OpenBSD/macppc
           Product: new-bugs
           Version: 7.0
          Hardware: Macintosh
                OS: OpenBSD
            Status: NEW
          Severity: normal
          Priority: P
         Component: new bugs
          Assignee: unassignedbugs at nondot.org
          Reporter: kernigh at gmail.com
                CC: htmldeveloper at gmail.com, llvm-bugs at lists.llvm.org

Created attachment 21415
  --> https://bugs.llvm.org/attachment.cgi?id=21415&action=edit
try to avoid misaligned floats

clang -O2 can emit PowerPC instructions like lfs or lfsx that load or store a
misaligned float.  Such instruction crashes with SIGBUS in OpenBSD/macppc. 
This crash happened with clang 6 and clang 7, not with gcc.  This crash only
happened if I told clang to optimize.  This seems to be a bad optimization in
LLVM's PowerPC target.

This is a simple example of the problem:

$ cat bustest.c                                                    
#include <stdio.h>
struct {int i; char c[5];} s = {0, {0, 0x42, 0xf6, 0xe9, 0x79}};
int main() {
        union {float f; int i;} u;
        u.i = (s.c[1]<<24) + (s.c[2]<<16) + (s.c[3]<<8) + s.c[4];
        printf("%g\n", u.f);
}
$ clang -O2 -o bustest bustest.c
$ ./bustest
Bus error (core dumped)
$ egdb bustest bustest.core
...
#0  0x0610055c in main ()
(gdb) disas $pc, $pc +4
Dump of assembler code from 0x610055c to 0x6100560:
=> 0x0610055c <main+48>:        lfs     f1,5(r3)
End of assembler dump.
(gdb) print 5 + $r3
$1 = 101847053

The example assumes that int has 4-bytes and float is a 4-byte IEEE float.  The
correct output is 123.456.  The idea is to read 4 bytes from a file (but this
example hardcodes the bytes), convert them from big to native endian, and
interpret them as a float.  The target is big-endian PowerPC, so one may
optimize away the endian conversion, but LLVM has optimized too far by using
`lfs f1,5(r3)` to load float register f1 directly from the array.  This is
misalignment because 5(r3) is not a multiple of 4.

I believe that lfs/stfs, lfd/stfd, lfsx, and other instructions for loading or
storing a float register need the address to be a multiple of 4.  This minimum
4-byte alignment is for both 4-byte floats and 8-byte doubles (but 8-byte
doubles prefer 8-byte alignment).  Freescale Semiconductor, *Programming
Environments Manual for 32-Bit Implementations of the PowerPC Architecture*
(MPCFPE32B.pdf), section 6.5.6 "Alignment Interrupt", says that a memory access
may fail because, "An operand of a floating-point load or store instruction is
not word-aligned."  A word has 4 bytes.  The processor in my PowerBook G4
(running OpenBSD/macppc) is an MPC7447A.

The attached patch tries to fix the problem.  The patch is for llvm-project.git
master.  I can't run master (I say why in #40553), but I am using the same
patch in clang 7.0.1, where it seems to fix my example.  I don't know if my
patch is correct, because I don't understand LLVM's code.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20190131/e8808ffd/attachment.html>


More information about the llvm-bugs mailing list