[llvm] r265480 - Swift Calling Convention: add swiftcc.
Manman Ren via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 5 15:41:48 PDT 2016
Author: mren
Date: Tue Apr 5 17:41:47 2016
New Revision: 265480
URL: http://llvm.org/viewvc/llvm-project?rev=265480&view=rev
Log:
Swift Calling Convention: add swiftcc.
Differential Revision: http://reviews.llvm.org/D17863
Added:
llvm/trunk/test/CodeGen/X86/swift-return.ll
Modified:
llvm/trunk/docs/BitCodeFormat.rst
llvm/trunk/docs/LangRef.rst
llvm/trunk/lib/AsmParser/LLLexer.cpp
llvm/trunk/lib/AsmParser/LLParser.cpp
llvm/trunk/lib/AsmParser/LLToken.h
llvm/trunk/lib/IR/AsmWriter.cpp
llvm/trunk/lib/Target/X86/X86CallingConv.td
llvm/trunk/lib/Target/X86/X86FastISel.cpp
Modified: llvm/trunk/docs/BitCodeFormat.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/BitCodeFormat.rst?rev=265480&r1=265479&r2=265480&view=diff
==============================================================================
--- llvm/trunk/docs/BitCodeFormat.rst (original)
+++ llvm/trunk/docs/BitCodeFormat.rst Tue Apr 5 17:41:47 2016
@@ -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
Modified: llvm/trunk/docs/LangRef.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=265480&r1=265479&r2=265480&view=diff
==============================================================================
--- llvm/trunk/docs/LangRef.rst (original)
+++ llvm/trunk/docs/LangRef.rst Tue Apr 5 17:41:47 2016
@@ -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
Modified: llvm/trunk/lib/AsmParser/LLLexer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLLexer.cpp?rev=265480&r1=265479&r2=265480&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLLexer.cpp (original)
+++ llvm/trunk/lib/AsmParser/LLLexer.cpp Tue Apr 5 17:41:47 2016
@@ -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);
Modified: llvm/trunk/lib/AsmParser/LLParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=265480&r1=265479&r2=265480&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLParser.cpp (original)
+++ llvm/trunk/lib/AsmParser/LLParser.cpp Tue Apr 5 17:41:47 2016
@@ -1610,6 +1610,7 @@ bool LLParser::ParseOptionalDLLStorageCl
/// ::= 'preserve_mostcc'
/// ::= 'preserve_allcc'
/// ::= 'ghccc'
+/// ::= 'swiftcc'
/// ::= 'x86_intrcc'
/// ::= 'hhvmcc'
/// ::= 'hhvm_ccc'
@@ -1644,6 +1645,7 @@ bool LLParser::ParseOptionalCallingConv(
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;
Modified: llvm/trunk/lib/AsmParser/LLToken.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLToken.h?rev=265480&r1=265479&r2=265480&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLToken.h (original)
+++ llvm/trunk/lib/AsmParser/LLToken.h Tue Apr 5 17:41:47 2016
@@ -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,
Modified: llvm/trunk/lib/IR/AsmWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/AsmWriter.cpp?rev=265480&r1=265479&r2=265480&view=diff
==============================================================================
--- llvm/trunk/lib/IR/AsmWriter.cpp (original)
+++ llvm/trunk/lib/IR/AsmWriter.cpp Tue Apr 5 17:41:47 2016
@@ -315,6 +315,7 @@ static void PrintCallingConv(unsigned cc
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;
Modified: llvm/trunk/lib/Target/X86/X86CallingConv.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86CallingConv.td?rev=265480&r1=265479&r2=265480&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86CallingConv.td (original)
+++ llvm/trunk/lib/Target/X86/X86CallingConv.td Tue Apr 5 17:41:47 2016
@@ -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>>,
Modified: llvm/trunk/lib/Target/X86/X86FastISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86FastISel.cpp?rev=265480&r1=265479&r2=265480&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86FastISel.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86FastISel.cpp Tue Apr 5 17:41:47 2016
@@ -2852,6 +2852,7 @@ bool X86FastISel::fastLowerCall(CallLowe
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:
Added: llvm/trunk/test/CodeGen/X86/swift-return.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/swift-return.ll?rev=265480&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/swift-return.ll (added)
+++ llvm/trunk/test/CodeGen/X86/swift-return.ll Tue Apr 5 17:41:47 2016
@@ -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
+
+ at 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()
More information about the llvm-commits
mailing list