[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