[LLVMbugs] [Bug 16565] New: "add (i32 X, i32 -1)" in global initializer fails on x86-32 but not elsewhere

bugzilla-daemon at llvm.org bugzilla-daemon at llvm.org
Mon Jul 8 14:26:58 PDT 2013


            Bug ID: 16565
           Summary: "add (i32 X, i32 -1)" in global initializer fails on
                    x86-32 but not elsewhere
           Product: tools
           Version: trunk
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: llc
          Assignee: unassignedbugs at nondot.org
          Reporter: mseaborn at chromium.org
                CC: llvmbugs at cs.uiuc.edu
    Classification: Unclassified

The following LLVM IR fails on x86-32:

$ cat negative_reloc.ll
@var = internal global i32 123, align 1
@negative_offset = internal global i32 add (i32 ptrtoint (i32* @negative_offset
to i32), i32 -1), align 4

$ build-64/Release+Asserts/bin/llc negative_reloc.ll -o tmp.o -filetype=obj
llc: /home/mseaborn/sw/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp:106:
virtual void {anonymous}::X86AsmBackend::applyFixup(const llvm::MCFixup&,
char*, unsigned int, uint64_t) const: Assertion `isIntN(Size * 8 + 1, Value) &&
"Value does not fit in the Fixup field"' failed.

It fails because it produces the following assembly:

$ build-64/Release+Asserts/bin/llc negative_reloc.ll -o -
    .long    negative_offset+4294967295
[where 4294967295 = 0xffffffff]

The GNU assembler also complains about this assembly:
$ build-64/Release+Asserts/bin/llc negative_reloc.ll -o tmp.s
$ gcc -m32 -c tmp.s
tmp.s: Assembler messages:
tmp.s:12: Error: value of 4294967299 too large for field of 4 bytes at 4
[where 4294967299 = 0x100000003]

This happens because the assembler adds 0xffffffff to the offset of
"negative_offset" within the data section and gets an overflow.

However, the same code works fine on ARM:

$ build-64/Release+Asserts/bin/llc negative_reloc.ll -o tmp.o -filetype=obj

When the pointer is changed to be i64, the same code also works fine on x86-64:

$ cat negative_reloc_64.ll
@var = internal global i32 123, align 1
@negative_offset = internal global i64 add (i64 ptrtoint (i64* @negative_offset
to i64), i64 -1), align 4

$ build-64/Release+Asserts/bin/llc negative_reloc_64.ll -o tmp.o -filetype=obj
$ build-64/Release+Asserts/bin/llc negative_reloc_64.ll -o -
    .quad    negative_offset-1

At the assembler level, the following minimal example reproduces the assertion
failure in LLVM's assembler and gives a clean error in GNU 'as':

        .byte 1
        .long negative_offset + 0xffffffff

However, there's no equivalent check for 64-bit overflow.  The following is
accepted by both LLVM and GNU 'as':

        .byte 1
        .quad negative_offset + 0xffffffffffffffff

This overflow check is problematic because it breaks the equivalence between
"add (i32 X, i32 -1)" and "sub (i32 X, i32 1)".  Whether this fails depends on
the offset of the variable within the data section.

Should we remove this overflow check?  If not, the LLVM assembler should
presumably be consistent and apply the same check on ARM and for 64-bit values.
 It shouldn't just be an assertion because these checks will be omitted in
release builds.

(See also: https://code.google.com/p/nativeclient/issues/detail?id=3548)

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/20130708/443a531b/attachment.html>

More information about the llvm-bugs mailing list