LLVM Bugzilla is read-only and represents the historical archive of all LLVM issues filled before November 26, 2021. Use github to submit LLVM bugs

Bug 23491 - clang doesn't follow the SysV i386 ABI for global functions returning structures.
Summary: clang doesn't follow the SysV i386 ABI for global functions returning structu...
Status: RESOLVED FIXED
Alias: None
Product: libraries
Classification: Unclassified
Component: Backend: X86 (show other bugs)
Version: trunk
Hardware: PC Linux
: P normal
Assignee: Unassigned LLVM Bugs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-05-12 05:01 PDT by abhiinnitald
Modified: 2015-05-18 18:35 PDT (History)
4 users (show)

See Also:
Fixed By Commit(s):


Attachments
main file which calls foo1(). (188 bytes, application/octet-stream)
2015-05-12 05:01 PDT, abhiinnitald
Details

Note You need to log in before you can comment on or make changes to this bug.
Description abhiinnitald 2015-05-12 05:01:25 PDT
Created attachment 14314 [details]
main file which calls foo1().

According to SysV i386 ABI document "SYSTEM V APPLICATION BINARY INTERFACE, Intel386 Architecture Processor Supplement, Fourth Edition":

A function returning structure sets %eax to the value of the original address of the structure while returning so that when the caller receives control again, the address of the returned object resides in register %eax and can be used to access the object.

Compiling sup.c (contents given below) using clang 3.7.0, the generated assembly does not update %eax with the address of the structure while returning from the function foo1() 

File sup.c contains a function foo1() that accepts a structure as an argument and returns the same structure. The contents of the file are:

struct baar{
  int a;
  int b;
};

struct baar foo1(struct baar x)
{
  return x ;
}

Compilation command used:
clang -g -O0 -m32 -c sup.c -o sup.o

Attached here is main.c file from which a call to foo1() is made. 
main.o and sup.o files were linked to generate executable.

Platform: Ubuntu 14.04, x86_64 GNU/Linux
Comment 1 Reid Kleckner 2015-05-12 10:41:02 PDT
Was this always in the ABI? I thought it was something we had to change for x86_64, but never had to bother with for 32-bit x86.
Comment 2 Reid Kleckner 2015-05-12 10:44:25 PDT
(In reply to comment #1)
> Was this always in the ABI? I thought it was something we had to change for
> x86_64, but never had to bother with for 32-bit x86.

Yep, here's the quote from the old SCO ABI doc:

%eax  Integral and pointer return values appear in %eax. A function that returns a struct or union value places the address of the result in %eax. Otherwise this is a scratch register.
Comment 3 Reid Kleckner 2015-05-12 15:58:39 PDT
Should be fixed in r237175. We don't implement the optimization side of this yet, and I don't think we will for the foreseeable future.
Comment 4 Reid Kleckner 2015-05-12 16:01:47 PDT
Also, your example is wrong. struct baar is returned in EAX:EDX. GCC does the same. Add another field and it will address the case you intended to.
Comment 5 H.J. Lu 2015-05-12 19:18:37 PDT
This is the difference between

'-fpcc-struct-return'
     Return "short" 'struct' and 'union' values in memory like longer
     ones, rather than in registers.  This convention is less efficient,
     but it has the advantage of allowing intercallability between
     GCC-compiled files and files compiled with other compilers,
     particularly the Portable C Compiler (pcc).

and

'-freg-struct-return'
     Return 'struct' and 'union' values in registers when possible.
     This is more efficient for small structures than
     '-fpcc-struct-return'.

     If you specify neither '-fpcc-struct-return' nor
     '-freg-struct-return', GCC defaults to whichever convention is
     standard for the target.  If there is no standard convention, GCC
     defaults to '-fpcc-struct-return', except on targets where GCC is
     the principal compiler.  In those cases, we can choose the
     standard, and we chose the more efficient register return
     alternative.

i386 psABI specifies -fpcc-struct-return.  But some i386 targets choose
-freg-struct-return as default.
Comment 6 abhiinnitald 2015-05-13 04:17:30 PDT
(In reply to comment #4)
> Also, your example is wrong. struct baar is returned in EAX:EDX. GCC does
> the same. Add another field and it will address the case you intended to.

At my end, if I compile sup.c with either clang or gcc, in both cases it doesn't return struct value in EAX:EDX. It updates the contents at the address (of the structure) that was passed as the first argument to the called function.

Only when I use -freg-struct-return, it returns the struct value in EAX:EDX
Comment 7 abhiinnitald 2015-05-13 05:07:51 PDT
(In reply to comment #3)
> Should be fixed in r237175. We don't implement the optimization side of this
> yet, and I don't think we will for the foreseeable future.

Just checked. This patch is reverted. Hoping to see a fix. Thanks a lot for your prompt reply and effort for a solution :)
Comment 8 Reid Kleckner 2015-05-18 18:35:44 PDT
(In reply to comment #7)
> (In reply to comment #3)
> > Should be fixed in r237175. We don't implement the optimization side of this
> > yet, and I don't think we will for the foreseeable future.
> 
> Just checked. This patch is reverted. Hoping to see a fix. Thanks a lot for
> your prompt reply and effort for a solution :)

Re-landed in r237639.