[swift-dev] The swift didn't conform the calling convention for ppc64le

bluedream 48825004 at qq.com
Tue Mar 8 00:16:23 CST 2016


Hi, all,

I am trying the swift compiler these days in ppc64le, and found that, if the function return type is aggr, the code swift generated didn't conform the ppc64le ABI.

> cat test.swift 
func test() -> (Bool, Double, Int){
    return (true,3.0,3);
}

test();

> swiftc test.swift -emit-ir
; ModuleID = '-'
target datalayout = "e-m:e-i64:64-n32:64"
target triple = "powerpc64le-unknown-linux-gnu"
...
define protected signext i32 @main(i32 signext, i8**) #0 {
entry:
  %2 = bitcast i8** %1 to i8*
  store i32 %0, i32* getelementptr inbounds (%Vs5Int32, %Vs5Int32* @_TZvOs7Process5_argcVs5Int32, i32 0, i32 0), align 4
  call void @swift_once(i64* @globalinit_33_1BDF70FFC18749BAB495A73B459ED2F0_token3, i8* bitcast (void ()* @globalinit_33_1BDF70FFC18749BAB495A73B459ED2F0_func3 to i8*))
  store i8* %2, i8** getelementptr inbounds (%Sp, %Sp* @_TZvOs7Process11_unsafeArgvGSpGSpVs4Int8__, i32 0, i32 0), align 8
  %3 = call { i1, double, i64 } @_TF4test4testFT_TSbSdSi_()
  %4 = extractvalue { i1, double, i64 } %3, 0
  %5 = extractvalue { i1, double, i64 } %3, 1
  %6 = extractvalue { i1, double, i64 } %3, 2
  ret i32 0
}

We can see that, swift emit the  { i1, double, i64 } as its return type and llvm will pass the return value of _TF4test4testFT_TSbSdSi_ by register.
> objdump -dr test.o
...
            4c: R_PPC64_TOC16_HA    .toc+0x18
  50:    00 00 63 e8     ld      r3,0(r3)
            50: R_PPC64_TOC16_LO_DS    .toc+0x18
  54:    60 00 9f e8     ld      r4,96(r31)
  58:    00 00 83 f8     std     r4,0(r3)
  5c:    01 00 00 48     bl      5c <main+0x5c>
            5c: R_PPC64_REL24    _TF4test4testFT_TSbSdSi_
  60:    00 00 00 60     nop

However, for ppc64le ABI, this should be passed by address. See what clang emit the ir for return aggr of this type.

> cat test2.cpp 
struct A {
bool b;
double d;
long long m;
};

A test();

int main() {
    test();
    return 0;
}
> clang test2.cpp -S -emit-llvm 
> cat test2.ll 
; ModuleID = 'test2.cpp'
target datalayout = "e-m:e-i64:64-n32:64"
target triple = "powerpc64le-unknown-linux-gnu"

%struct.A = type { i8, double, i64 }

; Function Attrs: norecurse
define signext i32 @main() #0 {
  %1 = alloca i32, align 4
  %2 = alloca %struct.A, align 8
  store i32 0, i32* %1, align 4
  call void @_Z4testv(%struct.A* sret %2)
  ret i32 0
}

declare void @_Z4testv(%struct.A* sret) #1

Clang frontend will place it as the first parameter of the function. That would cause serious issues if we are linking with code write from other language(i.e. c/c++). Any comments?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-dev/attachments/20160308/c81db283/attachment.html>


More information about the swift-dev mailing list