mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 12:29:58 +00:00
Swift Calling Convention: add swiftcc.
Differential Revision: http://reviews.llvm.org/D17863 llvm-svn: 265480
This commit is contained in:
parent
6e4ea9ea73
commit
d8f96bea63
@ -757,6 +757,7 @@ function. The operand fields are:
|
||||
* ``anyregcc``: code 13
|
||||
* ``preserve_mostcc``: code 14
|
||||
* ``preserve_allcc``: code 15
|
||||
* ``swiftcc`` : code 16
|
||||
* ``cxx_fast_tlscc``: code 17
|
||||
* ``x86_stdcallcc``: code 64
|
||||
* ``x86_fastcallcc``: code 65
|
||||
|
@ -427,6 +427,9 @@ added in the future:
|
||||
|
||||
- On X86-64 the callee preserves all general purpose registers, except for
|
||||
RDI and RAX.
|
||||
"``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.
|
||||
"``cc <n>``" - Numbered convention
|
||||
Any calling convention may be specified by number, allowing
|
||||
target-specific calling conventions to be used. Target specific
|
||||
|
@ -590,6 +590,7 @@ lltok::Kind LLLexer::LexIdentifier() {
|
||||
KEYWORD(x86_64_sysvcc);
|
||||
KEYWORD(x86_64_win64cc);
|
||||
KEYWORD(webkit_jscc);
|
||||
KEYWORD(swiftcc);
|
||||
KEYWORD(anyregcc);
|
||||
KEYWORD(preserve_mostcc);
|
||||
KEYWORD(preserve_allcc);
|
||||
|
@ -1610,6 +1610,7 @@ bool LLParser::ParseOptionalDLLStorageClass(unsigned &Res) {
|
||||
/// ::= 'preserve_mostcc'
|
||||
/// ::= 'preserve_allcc'
|
||||
/// ::= 'ghccc'
|
||||
/// ::= 'swiftcc'
|
||||
/// ::= 'x86_intrcc'
|
||||
/// ::= 'hhvmcc'
|
||||
/// ::= 'hhvm_ccc'
|
||||
@ -1644,6 +1645,7 @@ bool LLParser::ParseOptionalCallingConv(unsigned &CC) {
|
||||
case lltok::kw_preserve_mostcc:CC = CallingConv::PreserveMost; break;
|
||||
case lltok::kw_preserve_allcc: CC = CallingConv::PreserveAll; break;
|
||||
case lltok::kw_ghccc: CC = CallingConv::GHC; break;
|
||||
case lltok::kw_swiftcc: CC = CallingConv::Swift; break;
|
||||
case lltok::kw_x86_intrcc: CC = CallingConv::X86_INTR; break;
|
||||
case lltok::kw_hhvmcc: CC = CallingConv::HHVM; break;
|
||||
case lltok::kw_hhvm_ccc: CC = CallingConv::HHVM_C; break;
|
||||
|
@ -100,6 +100,7 @@ namespace lltok {
|
||||
kw_spir_kernel, kw_spir_func,
|
||||
kw_x86_64_sysvcc, kw_x86_64_win64cc,
|
||||
kw_webkit_jscc, kw_anyregcc,
|
||||
kw_swiftcc,
|
||||
kw_preserve_mostcc, kw_preserve_allcc,
|
||||
kw_ghccc,
|
||||
kw_x86_intrcc,
|
||||
|
@ -315,6 +315,7 @@ static void PrintCallingConv(unsigned cc, raw_ostream &Out) {
|
||||
case CallingConv::X86_64_Win64: Out << "x86_64_win64cc"; break;
|
||||
case CallingConv::SPIR_FUNC: Out << "spir_func"; break;
|
||||
case CallingConv::SPIR_KERNEL: Out << "spir_kernel"; break;
|
||||
case CallingConv::Swift: Out << "swiftcc"; break;
|
||||
case CallingConv::X86_INTR: Out << "x86_intrcc"; break;
|
||||
case CallingConv::HHVM: Out << "hhvmcc"; break;
|
||||
case CallingConv::HHVM_C: Out << "hhvm_ccc"; break;
|
||||
|
@ -192,6 +192,24 @@ def RetCC_X86_64_WebKit_JS : CallingConv<[
|
||||
CCIfType<[i64], CCAssignToReg<[RAX]>>
|
||||
]>;
|
||||
|
||||
def RetCC_X86_64_Swift : CallingConv<[
|
||||
// For integers, ECX, R8D can be used as extra return registers.
|
||||
CCIfType<[i1], CCPromoteToType<i8>>,
|
||||
CCIfType<[i8] , CCAssignToReg<[AL, DL, CL, R8B]>>,
|
||||
CCIfType<[i16], CCAssignToReg<[AX, DX, CX, R8W]>>,
|
||||
CCIfType<[i32], CCAssignToReg<[EAX, EDX, ECX, R8D]>>,
|
||||
CCIfType<[i64], CCAssignToReg<[RAX, RDX, RCX, R8]>>,
|
||||
|
||||
// XMM0, XMM1, XMM2 and XMM3 can be used to return FP values.
|
||||
CCIfType<[f32], CCAssignToReg<[XMM0, XMM1, XMM2, XMM3]>>,
|
||||
CCIfType<[f64], CCAssignToReg<[XMM0, XMM1, XMM2, XMM3]>>,
|
||||
CCIfType<[f128], CCAssignToReg<[XMM0, XMM1, XMM2, XMM3]>>,
|
||||
|
||||
// MMX vector types are returned in XMM0, XMM1, XMM2 and XMM3.
|
||||
CCIfType<[x86mmx], CCAssignToReg<[XMM0, XMM1, XMM2, XMM3]>>,
|
||||
CCDelegateTo<RetCC_X86Common>
|
||||
]>;
|
||||
|
||||
// X86-64 AnyReg return-value convention. No explicit register is specified for
|
||||
// the return-value. The register allocator is allowed and expected to choose
|
||||
// any free register.
|
||||
@ -234,6 +252,9 @@ def RetCC_X86_64 : CallingConv<[
|
||||
CCIfCC<"CallingConv::WebKit_JS", CCDelegateTo<RetCC_X86_64_WebKit_JS>>,
|
||||
CCIfCC<"CallingConv::AnyReg", CCDelegateTo<RetCC_X86_64_AnyReg>>,
|
||||
|
||||
// Handle Swift calls.
|
||||
CCIfCC<"CallingConv::Swift", CCDelegateTo<RetCC_X86_64_Swift>>,
|
||||
|
||||
// Handle explicit CC selection
|
||||
CCIfCC<"CallingConv::X86_64_Win64", CCDelegateTo<RetCC_X86_Win64_C>>,
|
||||
CCIfCC<"CallingConv::X86_64_SysV", CCDelegateTo<RetCC_X86_64_C>>,
|
||||
|
@ -2852,6 +2852,7 @@ bool X86FastISel::fastLowerCall(CallLoweringInfo &CLI) {
|
||||
case CallingConv::C:
|
||||
case CallingConv::Fast:
|
||||
case CallingConv::WebKit_JS:
|
||||
case CallingConv::Swift:
|
||||
case CallingConv::X86_FastCall:
|
||||
case CallingConv::X86_64_Win64:
|
||||
case CallingConv::X86_64_SysV:
|
||||
|
201
test/CodeGen/X86/swift-return.ll
Normal file
201
test/CodeGen/X86/swift-return.ll
Normal file
@ -0,0 +1,201 @@
|
||||
; RUN: llc -verify-machineinstrs < %s -mtriple=x86_64-unknown-unknown | FileCheck %s
|
||||
; RUN: llc -verify-machineinstrs < %s -mtriple=x86_64-unknown-unknown -O0 | FileCheck --check-prefix=CHECK-O0 %s
|
||||
|
||||
@var = global i32 0
|
||||
|
||||
; Test how llvm handles return type of {i16, i8}. The return value will be
|
||||
; passed in %eax and %dl.
|
||||
; CHECK-LABEL: test:
|
||||
; CHECK: movl %edi
|
||||
; CHECK: callq gen
|
||||
; CHECK: movsbl %dl
|
||||
; CHECK: addl %{{.*}}, %eax
|
||||
; CHECK-O0-LABEL: test
|
||||
; CHECK-O0: movl %edi
|
||||
; CHECK-O0: callq gen
|
||||
; CHECK-O0: movswl %ax
|
||||
; CHECK-O0: movsbl %dl
|
||||
; CHECK-O0: addl
|
||||
; CHECK-O0: movw %{{.*}}, %ax
|
||||
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)
|
||||
|
||||
; If we can't pass every return value in register, we will pass everything
|
||||
; in memroy. The caller provides space for the return value and passes
|
||||
; the address in %rdi. The first input argument will be in %rsi.
|
||||
; CHECK-LABEL: test2:
|
||||
; CHECK: leaq (%rsp), %rdi
|
||||
; CHECK: movl %{{.*}}, %esi
|
||||
; CHECK: callq gen2
|
||||
; CHECK: movl (%rsp)
|
||||
; CHECK-DAG: addl 4(%rsp)
|
||||
; CHECK-DAG: addl 8(%rsp)
|
||||
; CHECK-DAG: addl 12(%rsp)
|
||||
; CHECK-DAG: addl 16(%rsp)
|
||||
; CHECK-O0-LABEL: test2:
|
||||
; CHECK-O0-DAG: leaq (%rsp), %rdi
|
||||
; CHECK-O0-DAG: movl {{.*}}, %esi
|
||||
; CHECK-O0: callq gen2
|
||||
; CHECK-O0-DAG: movl (%rsp)
|
||||
; CHECK-O0-DAG: movl 4(%rsp)
|
||||
; CHECK-O0-DAG: movl 8(%rsp)
|
||||
; CHECK-O0-DAG: movl 12(%rsp)
|
||||
; CHECK-O0-DAG: movl 16(%rsp)
|
||||
; CHECK-O0: addl
|
||||
; CHECK-O0: addl
|
||||
; CHECK-O0: addl
|
||||
; CHECK-O0: addl
|
||||
; CHECK-O0: movl %{{.*}}, %eax
|
||||
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 %rdi.
|
||||
; On return, %rax will contain the adddress that has been passed in by the caller in %rdi.
|
||||
; CHECK-LABEL: gen2:
|
||||
; CHECK: movl %esi, 16(%rdi)
|
||||
; CHECK: movl %esi, 12(%rdi)
|
||||
; CHECK: movl %esi, 8(%rdi)
|
||||
; CHECK: movl %esi, 4(%rdi)
|
||||
; CHECK: movl %esi, (%rdi)
|
||||
; CHECK: movq %rdi, %rax
|
||||
; CHECK-O0-LABEL: gen2:
|
||||
; CHECK-O0-DAG: movl %esi, 16(%rdi)
|
||||
; CHECK-O0-DAG: movl %esi, 12(%rdi)
|
||||
; CHECK-O0-DAG: movl %esi, 8(%rdi)
|
||||
; CHECK-O0-DAG: movl %esi, 4(%rdi)
|
||||
; CHECK-O0-DAG: movl %esi, (%rdi)
|
||||
; CHECK-O0-DAG: movq %rdi, %rax
|
||||
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 %eax,
|
||||
; %edx, %ecx, %r8d.
|
||||
; CHECK-LABEL: test3:
|
||||
; CHECK: callq gen3
|
||||
; CHECK: addl %edx, %eax
|
||||
; CHECK: addl %ecx, %eax
|
||||
; CHECK: addl %r8d, %eax
|
||||
; CHECK-O0-LABEL: test3:
|
||||
; CHECK-O0: callq gen3
|
||||
; CHECK-O0: addl %edx, %eax
|
||||
; CHECK-O0: addl %ecx, %eax
|
||||
; CHECK-O0: addl %r8d, %eax
|
||||
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)
|
||||
|
||||
; The return value {float, float, float, float} will be returned via registers
|
||||
; %xmm0, %xmm1, %xmm2, %xmm3.
|
||||
; CHECK-LABEL: test4:
|
||||
; CHECK: callq gen4
|
||||
; CHECK: addss %xmm1, %xmm0
|
||||
; CHECK: addss %xmm2, %xmm0
|
||||
; CHECK: addss %xmm3, %xmm0
|
||||
; CHECK-O0-LABEL: test4:
|
||||
; CHECK-O0: callq gen4
|
||||
; CHECK-O0: addss %xmm1, %xmm0
|
||||
; CHECK-O0: addss %xmm2, %xmm0
|
||||
; CHECK-O0: addss %xmm3, %xmm0
|
||||
define float @test4(float %key) #0 {
|
||||
entry:
|
||||
%key.addr = alloca float, align 4
|
||||
store float %key, float* %key.addr, align 4
|
||||
%0 = load float, float* %key.addr, align 4
|
||||
%call = call swiftcc { float, float, float, float } @gen4(float %0)
|
||||
|
||||
%v3 = extractvalue { float, float, float, float } %call, 0
|
||||
%v5 = extractvalue { float, float, float, float } %call, 1
|
||||
%v6 = extractvalue { float, float, float, float } %call, 2
|
||||
%v7 = extractvalue { float, float, float, float } %call, 3
|
||||
|
||||
%add = fadd float %v3, %v5
|
||||
%add1 = fadd float %add, %v6
|
||||
%add2 = fadd float %add1, %v7
|
||||
ret float %add2
|
||||
}
|
||||
|
||||
declare swiftcc { float, float, float, float } @gen4(float %key)
|
||||
|
||||
; CHECK-LABEL: consume_i1_ret:
|
||||
; CHECK: callq produce_i1_ret
|
||||
; CHECK: andb $1, %al
|
||||
; CHECK: andb $1, %dl
|
||||
; CHECK: andb $1, %cl
|
||||
; CHECK: andb $1, %r8b
|
||||
; CHECK-O0-LABEL: consume_i1_ret:
|
||||
; CHECK-O0: callq produce_i1_ret
|
||||
; CHECK-O0: andb $1, %al
|
||||
; CHECK-O0: andb $1, %dl
|
||||
; CHECK-O0: andb $1, %cl
|
||||
; CHECK-O0: andb $1, %r8b
|
||||
define void @consume_i1_ret() {
|
||||
%call = call swiftcc { i1, i1, i1, i1 } @produce_i1_ret()
|
||||
%v3 = extractvalue { i1, i1, i1, i1 } %call, 0
|
||||
%v5 = extractvalue { i1, i1, i1, i1 } %call, 1
|
||||
%v6 = extractvalue { i1, i1, i1, i1 } %call, 2
|
||||
%v7 = extractvalue { i1, i1, i1, i1 } %call, 3
|
||||
%val = zext i1 %v3 to i32
|
||||
store i32 %val, i32* @var
|
||||
%val2 = zext i1 %v5 to i32
|
||||
store i32 %val2, i32* @var
|
||||
%val3 = zext i1 %v6 to i32
|
||||
store i32 %val3, i32* @var
|
||||
%val4 = zext i1 %v7 to i32
|
||||
store i32 %val4, i32* @var
|
||||
ret void
|
||||
}
|
||||
|
||||
declare swiftcc { i1, i1, i1, i1 } @produce_i1_ret()
|
Loading…
Reference in New Issue
Block a user