1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 18:42:46 +02:00

Swift Calling Convention: swiftcc for ARM.

Differential Revision: http://reviews.llvm.org/D18769

llvm-svn: 265482
This commit is contained in:
Manman Ren 2016-04-05 22:44:44 +00:00
parent c80f414fe8
commit 6e8ec540e6
5 changed files with 205 additions and 0 deletions

View File

@ -430,6 +430,7 @@ added in the future:
"``swiftcc``" - This calling convention is used for Swift language.
- On X86-64 RCX and R8 are available for additional integer returns, and
XMM2 and XMM3 are available for additional FP/vector returns.
- On iOS platforms, we use AAPCS-VFP calling convention.
"``cc <n>``" - Numbered convention
Any calling convention may be specified by number, allowing
target-specific calling conventions to be used. Target specific

View File

@ -1859,6 +1859,7 @@ CCAssignFn *ARMFastISel::CCAssignFnForCall(CallingConv::ID CC,
return (Return ? RetCC_ARM_APCS: CC_ARM_APCS);
}
case CallingConv::ARM_AAPCS_VFP:
case CallingConv::Swift:
if (!isVarArg)
return (Return ? RetCC_ARM_AAPCS_VFP: CC_ARM_AAPCS_VFP);
// Fall through to soft float variant, variadic functions don't
@ -3007,6 +3008,7 @@ bool ARMFastISel::fastLowerArguments() {
case CallingConv::ARM_AAPCS_VFP:
case CallingConv::ARM_AAPCS:
case CallingConv::ARM_APCS:
case CallingConv::Swift:
break;
}

View File

@ -1388,6 +1388,7 @@ ARMTargetLowering::getEffectiveCallingConv(CallingConv::ID CC,
case CallingConv::PreserveMost:
return CallingConv::PreserveMost;
case CallingConv::ARM_AAPCS_VFP:
case CallingConv::Swift:
return isVarArg ? CallingConv::ARM_AAPCS : CallingConv::ARM_AAPCS_VFP;
case CallingConv::C:
if (!Subtarget->isAAPCS_ABI())

View File

@ -0,0 +1,68 @@
; RUN: llc -mtriple=armv7-apple-ios < %s | FileCheck %s
define swiftcc float @t1(float %a, float %b) {
entry:
; CHECK: t1
; CHECK-NOT: vmov
; CHECK: vadd.f32
%add = fadd float %a, %b
ret float %add
}
define swiftcc double @t2(double %a, double %b) {
entry:
; CHECK: t2
; CHECK-NOT: vmov
; CHECK: vadd.f64
%add = fadd double %a, %b
ret double %add
}
define swiftcc double @t9(double %d0, double %d1, double %d2, double %d3,
double %d4, double %d5, double %d6, double %d7, float %a, float %b) {
entry:
; CHECK-LABEL: t9:
; CHECK-NOT: vmov
; CHECK: vldr
%add = fadd float %a, %b
%conv = fpext float %add to double
ret double %conv
}
define swiftcc double @t10(double %d0, double %d1, double %d2, double %d3,
double %d4, double %d5, double %a, float %b, double %c) {
entry:
; CHECK-LABEL: t10:
; CHECK-NOT: vmov
; CHECK: vldr
%add = fadd double %a, %c
ret double %add
}
define swiftcc float @t11(double %d0, double %d1, double %d2, double %d3,
double %d4, double %d5, double %d6, float %a, double %b, float %c) {
entry:
; CHECK-LABEL: t11:
; CHECK: vldr
%add = fadd float %a, %c
ret float %add
}
define swiftcc double @t12(double %a, double %b) {
entry:
; CHECK-LABEL: t12:
; CHECK: vstr
%add = fadd double %a, %b
%sub = fsub double %a, %b
%call = tail call swiftcc double @x(double 0.000000e+00, double 0.000000e+00,
double 0.000000e+00, double 0.000000e+00, double 0.000000e+00,
double 0.000000e+00, double %add, float 0.000000e+00,
double %sub)
ret double %call
}
declare swiftcc double @x(double, double, double, double, double, double,
double, float, double)
attributes #0 = { readnone }
attributes #1 = { readonly }

View File

@ -0,0 +1,133 @@
; RUN: llc -mtriple=armv7k-apple-ios8.0 -mcpu=cortex-a7 -verify-machineinstrs < %s | FileCheck %s
; RUN: llc -mtriple=armv7k-apple-ios8.0 -mcpu=cortex-a7 -verify-machineinstrs < %s -O0 | FileCheck --check-prefix=CHECK-O0 %s
; RUN: llc -mtriple=armv7-apple-ios -verify-machineinstrs < %s | FileCheck %s
; RUN: llc -mtriple=armv7-apple-ios -verify-machineinstrs < %s -O0 | FileCheck --check-prefix=CHECK-O0 %s
; Test how llvm handles return type of {i16, i8}. The return value will be
; passed in %r0 and %r1.
; CHECK-LABEL: test:
; CHECK: bl {{.*}}gen
; CHECK: sxth {{.*}}, r0
; CHECK: sxtab r0, {{.*}}, r1
; CHECK-O0-LABEL: test:
; CHECK-O0: bl {{.*}}gen
; CHECK-O0: sxth r0, r0
; CHECK-O0: sxtb r1, r1
; CHECK-O0: add r0, r0, r1
define i16 @test(i32 %key) {
entry:
%key.addr = alloca i32, align 4
store i32 %key, i32* %key.addr, align 4
%0 = load i32, i32* %key.addr, align 4
%call = call swiftcc { i16, i8 } @gen(i32 %0)
%v3 = extractvalue { i16, i8 } %call, 0
%v1 = sext i16 %v3 to i32
%v5 = extractvalue { i16, i8 } %call, 1
%v2 = sext i8 %v5 to i32
%add = add nsw i32 %v1, %v2
%conv = trunc i32 %add to i16
ret i16 %conv
}
declare swiftcc { i16, i8 } @gen(i32)
; We can't pass every return value in register, instead, pass everything in
; memroy.
; The caller provides space for the return value and passes the address in %r0.
; The first input argument will be in %r1.
; CHECK-LABEL: test2:
; CHECK: mov r1, r0
; CHECK: mov r0, sp
; CHECK: bl {{.*}}gen2
; CHECK-DAG: add
; CHECK-DAG: ldr {{.*}}, [sp, #16]
; CHECK-DAG: add
; CHECK-DAG: add
; CHECK-DAG: add
; CHECK-O0-LABEL: test2:
; CHECK-O0: str r0
; CHECK-O0: mov r0, sp
; CHECK-O0: bl {{.*}}gen2
; CHECK-O0-DAG: ldr {{.*}}, [sp]
; CHECK-O0-DAG: ldr {{.*}}, [sp, #4]
; CHECK-O0-DAG: ldr {{.*}}, [sp, #8]
; CHECK-O0-DAG: ldr {{.*}}, [sp, #12]
; CHECK-O0-DAG: ldr {{.*}}, [sp, #16]
; CHECK-O0-DAG: add
; CHECK-O0-DAG: add
; CHECK-O0-DAG: add
; CHECK-O0-DAG: add
define i32 @test2(i32 %key) #0 {
entry:
%key.addr = alloca i32, align 4
store i32 %key, i32* %key.addr, align 4
%0 = load i32, i32* %key.addr, align 4
%call = call swiftcc { i32, i32, i32, i32, i32 } @gen2(i32 %0)
%v3 = extractvalue { i32, i32, i32, i32, i32 } %call, 0
%v5 = extractvalue { i32, i32, i32, i32, i32 } %call, 1
%v6 = extractvalue { i32, i32, i32, i32, i32 } %call, 2
%v7 = extractvalue { i32, i32, i32, i32, i32 } %call, 3
%v8 = extractvalue { i32, i32, i32, i32, i32 } %call, 4
%add = add nsw i32 %v3, %v5
%add1 = add nsw i32 %add, %v6
%add2 = add nsw i32 %add1, %v7
%add3 = add nsw i32 %add2, %v8
ret i32 %add3
}
; The address of the return value is passed in %r0.
; CHECK-LABEL: gen2:
; CHECK-DAG: str r1, [r0]
; CHECK-DAG: str r1, [r0, #4]
; CHECK-DAG: str r1, [r0, #8]
; CHECK-DAG: str r1, [r0, #12]
; CHECK-DAG: str r1, [r0, #16]
; CHECK-O0-LABEL: gen2:
; CHECK-O0-DAG: str r1, [r0]
; CHECK-O0-DAG: str r1, [r0, #4]
; CHECK-O0-DAG: str r1, [r0, #8]
; CHECK-O0-DAG: str r1, [r0, #12]
; CHECK-O0-DAG: str r1, [r0, #16]
define swiftcc { i32, i32, i32, i32, i32 } @gen2(i32 %key) {
%Y = insertvalue { i32, i32, i32, i32, i32 } undef, i32 %key, 0
%Z = insertvalue { i32, i32, i32, i32, i32 } %Y, i32 %key, 1
%Z2 = insertvalue { i32, i32, i32, i32, i32 } %Z, i32 %key, 2
%Z3 = insertvalue { i32, i32, i32, i32, i32 } %Z2, i32 %key, 3
%Z4 = insertvalue { i32, i32, i32, i32, i32 } %Z3, i32 %key, 4
ret { i32, i32, i32, i32, i32 } %Z4
}
; The return value {i32, i32, i32, i32} will be returned via registers %r0, %r1,
; %r2, %r3.
; CHECK-LABEL: test3:
; CHECK: bl {{.*}}gen3
; CHECK: add r0, r0, r1
; CHECK: add r0, r0, r2
; CHECK: add r0, r0, r3
; CHECK-O0-LABEL: test3:
; CHECK-O0: bl {{.*}}gen3
; CHECK-O0: add r0, r0, r1
; CHECK-O0: add r0, r0, r2
; CHECK-O0: add r0, r0, r3
define i32 @test3(i32 %key) #0 {
entry:
%key.addr = alloca i32, align 4
store i32 %key, i32* %key.addr, align 4
%0 = load i32, i32* %key.addr, align 4
%call = call swiftcc { i32, i32, i32, i32 } @gen3(i32 %0)
%v3 = extractvalue { i32, i32, i32, i32 } %call, 0
%v5 = extractvalue { i32, i32, i32, i32 } %call, 1
%v6 = extractvalue { i32, i32, i32, i32 } %call, 2
%v7 = extractvalue { i32, i32, i32, i32 } %call, 3
%add = add nsw i32 %v3, %v5
%add1 = add nsw i32 %add, %v6
%add2 = add nsw i32 %add1, %v7
ret i32 %add2
}
declare swiftcc { i32, i32, i32, i32 } @gen3(i32 %key)