Is there an ABI conflict between Swift and C++ regarding multiple return values?


(Bryan Chan) #1

I have observed that swiftc on Linux assumes it can return tuples of at
most three integer-type elements in registers (rax, rdx and rcx, in that
order), while clang++ supports returning at most two integer-type values in
registers (rax and rdx), in accordance to the System V ABI. Doesn't this
cause a problem when a Swift function calls a C++ function that returns a
three-word struct indirectly while expecting the return values in
registers?

I ran into this issue when porting Swift to Linux s390x, in the
ManagedBufferPointer constructor which calls a runtime function written in
C++, and they follow conflicting ABIs. I worked around it by setting
target.MaxScalarsForDirectResult to 1 in SwiftTargetInfo, but I wonder if
this affects other architectures as well. Can any one shed some light on
this?

Thanks,
Bryan


(Dmitri Gribenko) #2

The Swift ABI is not guaranteed to match the C or C++ ABI for an
"equivalent" function. We do take advantage in the runtime of some
cases that happen to match on platforms that we currently support, but
it is clear that there exist platforms where this assumption is
broken.

John McCall is currently implementing support for the Swift calling
convention in LLVM and Clang. Once that lands, we would be able to
mark C functions in the runtime with an attribute to use the Swift
calling convention.

Dmitri

ยทยทยท

On Tue, Mar 8, 2016 at 2:17 AM, Bryan Chan via swift-dev <swift-dev@swift.org> wrote:

I have observed that swiftc on Linux assumes it can return tuples of at most
three integer-type elements in registers (rax, rdx and rcx, in that order),
while clang++ supports returning at most two integer-type values in
registers (rax and rdx), in accordance to the System V ABI. Doesn't this
cause a problem when a Swift function calls a C++ function that returns a
three-word struct indirectly while expecting the return values in registers?

I ran into this issue when porting Swift to Linux s390x, in the
ManagedBufferPointer constructor which calls a runtime function written in
C++, and they follow conflicting ABIs. I worked around it by setting
target.MaxScalarsForDirectResult to 1 in SwiftTargetInfo, but I wonder if
this affects other architectures as well. Can any one shed some light on
this?

--
main(i,j){for(i=2;;i++){for(j=2;j<i;j++){if(!(i%j)){j=0;break;}}if
(j){printf("%d\n",i);}}} /*Dmitri Gribenko <gribozavr@gmail.com>*/