Mercury Bugs - mercury
View Issue Details
0000453mercuryBugpublic2018-03-09 15:572018-03-16 15:15
Reporterwangp 
Assigned To 
PrioritynormalSeveritycrashReproducibilityalways
StatusnewResolutionopen 
PlatformOSOS Version
Product Version 
Target VersionFixed in Version 
Summary0000453: asm_fast does not work with gcc 5.4
DescriptionOne of the test cases (of many) which crash is hard_coded/bit_buffer_test.

This configuration crashes:
Ubuntu 16.04 i386
gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.9)
Mercury rotd 2016-02-18 and rotd 2018-03-07
asm_fast.gc
(none.gc, reg.gc, hlc.gc are OK)
TagsNo tags attached.
Attached Files

Notes
(0000976)
wangp   
2018-03-13 14:23   
The previous configuration (gcc 5.4.0, asm_fast.gc, x86) passes bootcheck if the Mercury libraries are statically linked, i.e. ./configure --disable-dynamic-link
(0000988)
wangp   
2018-03-15 12:57   
I can reproduce a crash more simply with a call to string.count_codepoints/2. I've copied that predicate to a separate module for ease of debugging, and generated the assembly with mmake string2.pic_s. Then we can edit the assembly and create libmer_std.so with: as -g string2.pic_s -o string2.pic_o && mmake libmer_std.so


This is the start of string2.count_codepoints:

           .globl _entry_mercury__string2__count_codepoints_2_0
   .type _entry_mercury__string2__count_codepoints_2_0,@function
_entry_mercury__string2__count_codepoints_2_0:
   call 0f
0:
   popl %ebx
   addl $_GLOBAL_OFFSET_TABLE_+[.-0b],%ebx
      
# 0 "" 2
.LDL1:
#NO_APP
.L4:
        movl -12(%ebp), %ebx
        leal .L5@GOTOFF(%ebx), %eax
.LBB2:
        .loc 1 281 0
        movl MR_engine_base@GOT(%ebx), %eax
        movl 8(%eax), %ecx
        ...

The four lines beginning with "call 0f" are due to MR_INLINE_ASM_FIXUP_REGS, to (as I understand it) load the position of the code into ebx. Right afterwards, gcc has added an instruction to copy something off the stack into ebx (presumably it would have stashed the correct value on the stack, but we've jumped into the middle of a C function).

Inserting an instruction "movl %ebx, -12(%ebp)" to cancel out that instruction makes this particular predicate work, so I think this is on the right track.
(0000989)
wangp   
2018-03-15 14:59   
On the other hand... x86 usage is only decreasing, linking with Mercury shared libraries is not very important, and inter-function jumps were never officially supported by gcc anyway. Maybe it is time to drop support for the combination?
(0000990)
juliensf   
2018-03-15 16:14   
If you disable optimization in GCC (e.g. -O0) does the problem still occur?
(0000991)
wangp   
2018-03-15 16:26   
It works at -O0, but not -O1, and not at -O1 with -f* options I could find disabled (everything listed by "gcc -O1 -Q --help=optimizers").
(0000992)
wangp   
2018-03-15 16:40   
My guess is that it is related to this change in GCC 5.0:

https://software.intel.com/en-us/blogs/2014/12/26/new-optimizations-for-x86-in-upcoming-gcc-50-32bit-pic-mode
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54232

Previously EBX was reserved for the GOT address so GCC probably had no need to save/restore it. If EBX can be used for other purposes then GCC might try to restore a value from the stack after our inline asm. The question is how to convince GCC not to do that.
(0000993)
wangp   
2018-03-15 17:04   
(convince GCC not to restore the GOT address from the stack, not only directly after the MR_INLINE_ASM_FIXUP_REGS sequence)
(0000994)
juliensf   
2018-03-15 17:11   
You could try starting at -O0 and adding optimizations. (Past experience of this
kind of thing indicates that GCC is not entirely truthful about which optimizations it applies at which optimization level.)
(0000995)
wangp   
2018-03-16 15:15   
Ok, bootcheck still passes with these options (which are what gcc reports as being enabled by -O1):

-fbranch-count-reg
-fcombine-stack-adjustments
-fcompare-elim
-fcprop-registers
-fforward-propagate
-fguess-branch-probability
-fif-conversion
-fif-conversion2
-finline-functions-called-once
-fipa-profile
-fipa-pure-const
-fipa-reference
-freorder-blocks
-fshrink-wrap
-fsplit-wide-types
-fssa-phiopt
-ftree-bit-ccp
-ftree-builtin-call-dce
-ftree-ccp
-ftree-ch
-ftree-coalesce-vars
-ftree-copy-prop
-ftree-dce
-ftree-dse
-ftree-fre
-ftree-pta
-ftree-sink
-ftree-slsr
-ftree-sra
-ftree-ter


Regardless, gcc 5 and up do not use a fixed PIC register on x86. Jumping into the middle of a function and putting the GOT address into EBX is not going to work if the rest of the function is not expecting it there.

Issue History
2018-03-09 15:57wangpNew Issue
2018-03-13 14:23wangpNote Added: 0000976
2018-03-15 12:57wangpNote Added: 0000988
2018-03-15 14:59wangpNote Added: 0000989
2018-03-15 16:14juliensfNote Added: 0000990
2018-03-15 16:26wangpNote Added: 0000991
2018-03-15 16:40wangpNote Added: 0000992
2018-03-15 17:04wangpNote Added: 0000993
2018-03-15 17:11juliensfNote Added: 0000994
2018-03-16 15:15wangpNote Added: 0000995