[llvm-bugs] [Bug 38274] New: Issues with ABI and compatibility

via llvm-bugs llvm-bugs at lists.llvm.org
Mon Jul 23 06:23:15 PDT 2018


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

            Bug ID: 38274
           Summary: Issues with ABI and compatibility
           Product: libraries
           Version: 6.0
          Hardware: Other
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: Core LLVM classes
          Assignee: unassignedbugs at nondot.org
          Reporter: kenner at adacore.com
                CC: llvm-bugs at lists.llvm.org

I want to reopen the (very old) discussion that occurred in bug 1521 because I
think we have a situation where there's a high burden for front-ends.  I'm
working with x86-64.  It's not clear what the best "Component" is here.

It looks like the root cause of this issue is that GCC didn't completely follow
the 64-bit ABI for struct parameter types (it's unclear how this happened
because GCC folks were involved with AMD in the creation of that ABI, but it
did) thus causing LLVM to have to choose whether to be compatible with GCC or
the ABI.  Unfortunately, the choice seems to be "half and half".

Let's consider a function that's being passed a struct with two i32 components.
 The straightforward translation into IR is:

%r = type { i32, i32 }

define void @tworec() {
entry:
  call void @p(%r { i32 1, i32 2 })

For x86-64, this obeys the ABI and does:

        movl    $1, %edi
        movl    $2, %esi
        callq   p

This is, however, not what GCC generates, which is complex code that packs both
integers into %edi.

clang does the same, so it's compatible with GCC, but it does it with a messy
IR:

  %1 = bitcast %struct.R* %x to i64*
  %2 = load i64, i64* %1, align 4
  call void @p(i64 %2)

which is even messier for the case of the callee.

The "bug", which is really a question, is how is a front-end supposed to know
to do the above mangling rather than simply generating the straightforward IR?

Note that for large structs, what's done is neither of these, but passing by
"pointer" and using byval.  I put "pointer" in quotes because, as far as I can
tell, nothing actually passes a pointer, but just puts the value on the stack.

But this makes things worse because it means that a non-C front end that wants
to pass in a way compatible with C, when it wants to pass by value has to
choose one of *three* possibilities:

(1) Using the straightforward IR representation
(2) Packing data into integers (which means it has to know how wide an integer
to use)
(3) Using byval

How does the front-end determine this in a target-independent way?

If the idea is to use a calling sequence compatible with GCC even if it doesn't
agree with the API, why not use have such a calling sequence explicitly and use
it everywhere?  If not, what *is* a front end supposed to do?

-- 
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/20180723/0bc6211a/attachment-0001.html>


More information about the llvm-bugs mailing list