1 ; RUN: llc < %s -tailcallopt -mtriple=x86_64-linux-gnu | FileCheck %s 2 3 ; Check the GHC call convention works (x86-64) 4 5 @base = external global i64 ; assigned to register: R13 6 @sp = external global i64 ; assigned to register: RBP 7 @hp = external global i64 ; assigned to register: R12 8 @r1 = external global i64 ; assigned to register: RBX 9 @r2 = external global i64 ; assigned to register: R14 10 @r3 = external global i64 ; assigned to register: RSI 11 @r4 = external global i64 ; assigned to register: RDI 12 @r5 = external global i64 ; assigned to register: R8 13 @r6 = external global i64 ; assigned to register: R9 14 @splim = external global i64 ; assigned to register: R15 15 16 @f1 = external global float ; assigned to register: XMM1 17 @f2 = external global float ; assigned to register: XMM2 18 @f3 = external global float ; assigned to register: XMM3 19 @f4 = external global float ; assigned to register: XMM4 20 @d1 = external global double ; assigned to register: XMM5 21 @d2 = external global double ; assigned to register: XMM6 22 23 define void @zap(i64 %a, i64 %b) nounwind { 24 entry: 25 ; CHECK: movq %rdi, %r13 26 ; CHECK-NEXT: movq %rsi, %rbp 27 ; CHECK-NEXT: callq addtwo 28 %0 = call ghccc i64 @addtwo(i64 %a, i64 %b) 29 ; CHECK: callq foo 30 call void @foo() nounwind 31 ret void 32 } 33 34 define ghccc i64 @addtwo(i64 %x, i64 %y) nounwind { 35 entry: 36 ; CHECK: leaq (%r13,%rbp), %rax 37 %0 = add i64 %x, %y 38 ; CHECK-NEXT: ret 39 ret i64 %0 40 } 41 42 define ghccc void @foo() nounwind { 43 entry: 44 ; CHECK: movsd d2(%rip), %xmm6 45 ; CHECK-NEXT: movsd d1(%rip), %xmm5 46 ; CHECK-NEXT: movss f4(%rip), %xmm4 47 ; CHECK-NEXT: movss f3(%rip), %xmm3 48 ; CHECK-NEXT: movss f2(%rip), %xmm2 49 ; CHECK-NEXT: movss f1(%rip), %xmm1 50 ; CHECK-NEXT: movq splim(%rip), %r15 51 ; CHECK-NEXT: movq r6(%rip), %r9 52 ; CHECK-NEXT: movq r5(%rip), %r8 53 ; CHECK-NEXT: movq r4(%rip), %rdi 54 ; CHECK-NEXT: movq r3(%rip), %rsi 55 ; CHECK-NEXT: movq r2(%rip), %r14 56 ; CHECK-NEXT: movq r1(%rip), %rbx 57 ; CHECK-NEXT: movq hp(%rip), %r12 58 ; CHECK-NEXT: movq sp(%rip), %rbp 59 ; CHECK-NEXT: movq base(%rip), %r13 60 %0 = load double, double* @d2 61 %1 = load double, double* @d1 62 %2 = load float, float* @f4 63 %3 = load float, float* @f3 64 %4 = load float, float* @f2 65 %5 = load float, float* @f1 66 %6 = load i64, i64* @splim 67 %7 = load i64, i64* @r6 68 %8 = load i64, i64* @r5 69 %9 = load i64, i64* @r4 70 %10 = load i64, i64* @r3 71 %11 = load i64, i64* @r2 72 %12 = load i64, i64* @r1 73 %13 = load i64, i64* @hp 74 %14 = load i64, i64* @sp 75 %15 = load i64, i64* @base 76 ; CHECK: jmp bar 77 tail call ghccc void @bar( i64 %15, i64 %14, i64 %13, i64 %12, i64 %11, 78 i64 %10, i64 %9, i64 %8, i64 %7, i64 %6, 79 float %5, float %4, float %3, float %2, double %1, 80 double %0 ) nounwind 81 ret void 82 } 83 84 declare ghccc void @bar(i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, 85 float, float, float, float, double, double) 86