https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80759
--- Comment #50 from Daniel Santos <daniel.santos at pobox dot com> --- Created attachment 41605 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=41605&action=edit darwin fixup (on top of v6) (In reply to r...@cebitec.uni-bielefeld.de from comment #49) > > No worries at all: don't even think about this stuff before you're well > again! Thank you, but this is chronic and comes and goes. The trend line seems to be heading upward for the moment, however. >[...] > > In hopes of making your review easier, below is a delta between this new > > (v6) > > patch set and your last posted patches. > > The new patch works fine for me on both x86_64-pc-linux-gnu (as > expected) and i386-pc-solaris2.12. > > On x86_64-apple-darwin11.4.2, there are a couple of isues, some of which > I'd already resolved before you posted the revised patch. > > * Initially all tests SEGVed like this (e.g. with -p0 and compiled with -O2): > > Program received signal SIGSEGV, Segmentation fault. > 0x000000010004664d in regs_to_mem () > 1: x/i $pc > => 0x10004664d <regs_to_mem>: movaps %xmm6,(%rax) > (gdb) where > #0 0x000000010004664d in regs_to_mem () > #1 0x00000001000465df in do_test_body () > #2 0x000000010002f227 in do_tests_0000 () > #3 0x00000001000468e3 in main () > > Here, %rax is 0x0. > > This happens because some setup happens between do_test_body0 and > do_test_body, and do_test_aligned jumps directly to do_test_body: > > .globl _do_test_body0 > .no_dead_strip _do_test_body0 > _do_test_body0: > movq _test_data@GOTPCREL(%rip), %rax > > .globl _do_test_body > _do_test_body: > > # Save registers. > lea (%rax), %rax > call _regs_to_mem > > By that jump, you bypass the setup of %rax and make the test FAIL. I > managed to avoid this by changing the jmp to do_test_body0 instead. > This gets me past this failure, and works on Linux/x86_64, too. > However, this makes the tests FAIL on Solaris/x86, supposedly due to > the -fomit-frame-pointer/-fno-omit-frame-pointer difference (though I > haven't looked more closely). Thanks again for your help on this. All of this asm is a big ABI hack and presumes I'm working with 64-bit SystemV ABI, but apple's ABI appears to differ somewhat (I've may have found a good description of that here: https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/MachOTopics/1-Articles/x86_64_code.html). My hope in declaring my own global symbol in the assembly and then explicitly RET-ing was to bypass any ABI-specific setup and tear-down, most notably the hard frame pointer. In the case of Darwin, this doesn't appear to work since the asm template instantiation of my "global + offset" seems to work quite differently and wants to store the base address in a register that is already being used for something else (actually, every register except XMM0-5 and XMM16+ are volatile at this point). I had expected it to generate something akin to: lea test_data + 224(%rip), %rax It would be nice if the "naked" function attribute were available for the i386 back-end, then I wouldn't have to screw around with trying to hack-away the ABI. (maybe a worthwhile future venture) The attached patch (on top of v6) *might* solve the problem on Darwin, but I don't understand exactly how GOTPCREL works, other than it's using a global offset table for linking. Hopefully, the linker can translate this directly into a constant rip-rel offset. What I'm doing here is that instead of feeding addresses to the asm template, I'm giving in the offsets and schlepping together an address operand from that, e.g.: lea %p0 + test_data@GOTPCREL(%%rip), %%rax Now if this fix *does* work, then I might need to investigate if this is a performance problem for Darwin -- why use an extra instruction to copy the address to a register before modifying it? If it doesn't work then it's probably because it really *needs* two instructions. I'm curious what the disassembly of the linked program looks like. > > * With the do_test_body0 jump, I hit the next issue on Darwin with -O0: > the test SEGVs here: > > Program received signal SIGSEGV, Segmentation fault. > 0x0000000100031c4e in do_test_body0 () > at > /vol/gcc/src/hg/trunk/solaris/gcc/testsuite/gcc.target/x86_64/abi/ms-sysv/ms- > sysv.c:163 > 163 __asm__ ("\n" > 1: x/i $pc > => 0x100031c4e <do_test_body0+21>: mov %rax,0x2a8(%rdi) > (gdb) where > (gdb) p/x $rdi > $1 = 0x5dc3340b214ef45c Yeah, this won't work because the reality is that all GP registers are volatile at this point, but gcc will generate code that clobbers them based upon the alleged ABI of the function -- which is a lie. :) If the attached patch doesn't work, then I think it's best to just move the assembly back into do-test.S and hard-code the offsets in a shared header file, so we can use them as a macro from do-test.S and also check them with asserts in ms-sysv.c. I suppose another option would be to just declare everything as clobbered in the asm clobber list, but that somehow just makes me feel dirty. :) Thanks, Daniel