1*9880d681SAndroid Build Coastguard Worker; RUN: llc < %s | FileCheck %s 2*9880d681SAndroid Build Coastguard Worker 3*9880d681SAndroid Build Coastguard Workertarget datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" 4*9880d681SAndroid Build Coastguard Workertarget triple = "x86_64-unknown-linux-gnu" 5*9880d681SAndroid Build Coastguard Worker 6*9880d681SAndroid Build Coastguard Workerdeclare hhvmcc i64 @bar(i64, i64, i64) nounwind 7*9880d681SAndroid Build Coastguard Worker 8*9880d681SAndroid Build Coastguard Worker; Simply check we can modify %rbx and %rbp before returning via call to bar. 9*9880d681SAndroid Build Coastguard Workerdefine hhvmcc i64 @foo(i64 %a, i64 %b, i64 %c) nounwind { 10*9880d681SAndroid Build Coastguard Workerentry: 11*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: foo: 12*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $1, %ebx 13*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $3, %ebp 14*9880d681SAndroid Build Coastguard Worker; CHECK: jmp bar 15*9880d681SAndroid Build Coastguard Worker %ret = musttail call hhvmcc i64 @bar(i64 1, i64 %b, i64 3) 16*9880d681SAndroid Build Coastguard Worker ret i64 %ret 17*9880d681SAndroid Build Coastguard Worker} 18*9880d681SAndroid Build Coastguard Worker 19*9880d681SAndroid Build Coastguard Worker; Check that we can read and modify %rbx returned from PHP function. 20*9880d681SAndroid Build Coastguard Workerdefine hhvmcc i64 @mod_return(i64 %a, i64 %b, i64 %c) nounwind { 21*9880d681SAndroid Build Coastguard Workerentry: 22*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: mod_return: 23*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: {{^#.*}} 24*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: callq bar 25*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: incq %rbx 26*9880d681SAndroid Build Coastguard Worker %tmp = call hhvmcc i64 @bar(i64 %a, i64 %b, i64 %c) 27*9880d681SAndroid Build Coastguard Worker %retval = add i64 %tmp, 1 28*9880d681SAndroid Build Coastguard Worker ret i64 %retval 29*9880d681SAndroid Build Coastguard Worker} 30*9880d681SAndroid Build Coastguard Worker 31*9880d681SAndroid Build Coastguard Worker%rettype = type { i64, i64, i64, i64, i64, i64, i64, 32*9880d681SAndroid Build Coastguard Worker i64, i64, i64, i64, i64, i64, i64 33*9880d681SAndroid Build Coastguard Worker} 34*9880d681SAndroid Build Coastguard Worker 35*9880d681SAndroid Build Coastguard Worker; Check that we can return up to 14 64-bit args in registers. 36*9880d681SAndroid Build Coastguard Workerdefine hhvmcc %rettype @return_all(i64 %a, i64 %b, i64 %c) nounwind { 37*9880d681SAndroid Build Coastguard Workerentry: 38*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: return_all: 39*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $1, %ebx 40*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $2, %ebp 41*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $3, %edi 42*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $4, %esi 43*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $5, %edx 44*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $6, %ecx 45*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $7, %r8 46*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $8, %r9 47*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $9, %eax 48*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $10, %r10 49*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $11, %r11 50*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $12, %r13 51*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $13, %r14 52*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $14, %r15 53*9880d681SAndroid Build Coastguard Worker; CHECK: retq 54*9880d681SAndroid Build Coastguard Worker %r1 = insertvalue %rettype zeroinitializer, i64 1, 0 55*9880d681SAndroid Build Coastguard Worker %r2 = insertvalue %rettype %r1, i64 2, 1 56*9880d681SAndroid Build Coastguard Worker %r3 = insertvalue %rettype %r2, i64 3, 2 57*9880d681SAndroid Build Coastguard Worker %r4 = insertvalue %rettype %r3, i64 4, 3 58*9880d681SAndroid Build Coastguard Worker %r5 = insertvalue %rettype %r4, i64 5, 4 59*9880d681SAndroid Build Coastguard Worker %r6 = insertvalue %rettype %r5, i64 6, 5 60*9880d681SAndroid Build Coastguard Worker %r7 = insertvalue %rettype %r6, i64 7, 6 61*9880d681SAndroid Build Coastguard Worker %r8 = insertvalue %rettype %r7, i64 8, 7 62*9880d681SAndroid Build Coastguard Worker %r9 = insertvalue %rettype %r8, i64 9, 8 63*9880d681SAndroid Build Coastguard Worker %r10 = insertvalue %rettype %r9, i64 10, 9 64*9880d681SAndroid Build Coastguard Worker %r11 = insertvalue %rettype %r10, i64 11, 10 65*9880d681SAndroid Build Coastguard Worker %r12 = insertvalue %rettype %r11, i64 12, 11 66*9880d681SAndroid Build Coastguard Worker %r13 = insertvalue %rettype %r12, i64 13, 12 67*9880d681SAndroid Build Coastguard Worker %r14 = insertvalue %rettype %r13, i64 14, 13 68*9880d681SAndroid Build Coastguard Worker ret %rettype %r14 69*9880d681SAndroid Build Coastguard Worker} 70*9880d681SAndroid Build Coastguard Worker 71*9880d681SAndroid Build Coastguard Workerdeclare hhvmcc void @return_all_tc(i64, i64, i64, i64, i64, i64, i64, i64, 72*9880d681SAndroid Build Coastguard Worker i64, i64, i64, i64, i64, i64, i64) 73*9880d681SAndroid Build Coastguard Worker 74*9880d681SAndroid Build Coastguard Worker; Check that we can return up to 14 64-bit args in registers via tail call. 75*9880d681SAndroid Build Coastguard Workerdefine hhvmcc void @test_return_all_tc(i64 %a, i64 %b, i64 %c) nounwind { 76*9880d681SAndroid Build Coastguard Workerentry: 77*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: test_return_all_tc: 78*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: {{^#.*}} 79*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $1, %ebx 80*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $3, %ebp 81*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $4, %r15 82*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $5, %edi 83*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $6, %esi 84*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $7, %edx 85*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $8, %ecx 86*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $9, %r8 87*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $10, %r9 88*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $11, %eax 89*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $12, %r10 90*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $13, %r11 91*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $14, %r13 92*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $15, %r14 93*9880d681SAndroid Build Coastguard Worker; CHECK: jmp return_all_tc 94*9880d681SAndroid Build Coastguard Worker tail call hhvmcc void @return_all_tc( 95*9880d681SAndroid Build Coastguard Worker i64 1, i64 %b, i64 3, i64 4, i64 5, i64 6, i64 7, 96*9880d681SAndroid Build Coastguard Worker i64 8, i64 9, i64 10, i64 11, i64 12, i64 13, i64 14, i64 15) 97*9880d681SAndroid Build Coastguard Worker ret void 98*9880d681SAndroid Build Coastguard Worker} 99*9880d681SAndroid Build Coastguard Worker 100*9880d681SAndroid Build Coastguard Workerdeclare hhvmcc {i64, i64} @php_short(i64, i64, i64, i64) 101*9880d681SAndroid Build Coastguard Worker 102*9880d681SAndroid Build Coastguard Workerdefine hhvmcc i64 @test_php_short(i64 %a, i64 %b, i64 %c) nounwind { 103*9880d681SAndroid Build Coastguard Workerentry: 104*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: test_php_short: 105*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: {{^#.*}} 106*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: movl $42, %r15 107*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: callq php_short 108*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: leaq (%rbp,%r12), %rbx 109*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: retq 110*9880d681SAndroid Build Coastguard Worker %pair = call hhvmcc {i64, i64} @php_short(i64 %a, i64 %b, i64 %c, i64 42) 111*9880d681SAndroid Build Coastguard Worker %fp = extractvalue {i64, i64} %pair, 1 112*9880d681SAndroid Build Coastguard Worker %rv = add i64 %fp, %b 113*9880d681SAndroid Build Coastguard Worker ret i64 %rv 114*9880d681SAndroid Build Coastguard Worker} 115*9880d681SAndroid Build Coastguard Worker 116*9880d681SAndroid Build Coastguard Workerdeclare hhvmcc %rettype @php_all(i64, i64, i64, i64, i64, i64, i64, 117*9880d681SAndroid Build Coastguard Worker i64, i64, i64, i64, i64, i64, i64, i64) 118*9880d681SAndroid Build Coastguard Worker 119*9880d681SAndroid Build Coastguard Worker; Check that we can pass 15 arguments in registers. 120*9880d681SAndroid Build Coastguard Worker; Also check that %r12 (2nd arg) is not spilled. 121*9880d681SAndroid Build Coastguard Workerdefine hhvmcc i64 @test_php_all(i64 %a, i64 %b, i64 %c) nounwind { 122*9880d681SAndroid Build Coastguard Workerentry: 123*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: test_php_all: 124*9880d681SAndroid Build Coastguard Worker; CHECK-NEXT: {{^#.*}} 125*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: sub 126*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: sub 127*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $1, %ebx 128*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $3, %ebp 129*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $4, %r15 130*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $5, %edi 131*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $6, %esi 132*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $7, %edx 133*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $8, %ecx 134*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $9, %r8 135*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $10, %r9 136*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $11, %eax 137*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $12, %r10 138*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $13, %r11 139*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $14, %r13 140*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $15, %r14 141*9880d681SAndroid Build Coastguard Worker; CHECK: callq php_all 142*9880d681SAndroid Build Coastguard Worker %pair = call hhvmcc %rettype @php_all( 143*9880d681SAndroid Build Coastguard Worker i64 1, i64 %b, i64 3, i64 4, i64 5, i64 6, i64 7, 144*9880d681SAndroid Build Coastguard Worker i64 8, i64 9, i64 10, i64 11, i64 12, i64 13, i64 14, i64 15) 145*9880d681SAndroid Build Coastguard Worker %fp = extractvalue %rettype %pair, 1 146*9880d681SAndroid Build Coastguard Worker %rv = add i64 %fp, %b 147*9880d681SAndroid Build Coastguard Worker ret i64 %rv 148*9880d681SAndroid Build Coastguard Worker} 149*9880d681SAndroid Build Coastguard Worker 150*9880d681SAndroid Build Coastguard Workerdeclare hhvmcc void @svcreq(i64, i64, i64, i64, i64, i64, i64, i64, i64, i64, 151*9880d681SAndroid Build Coastguard Worker i64, i64) 152*9880d681SAndroid Build Coastguard Worker 153*9880d681SAndroid Build Coastguard Workerdefine hhvmcc void @test_svcreq(i64 %a, i64 %b, i64 %c) nounwind { 154*9880d681SAndroid Build Coastguard Workerentry: 155*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: test_svcreq: 156*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $42, %r10 157*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $1, %edi 158*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $2, %esi 159*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $3, %edx 160*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $4, %ecx 161*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $5, %r8 162*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $6, %r9 163*9880d681SAndroid Build Coastguard Worker; CHECK: jmp svcreq 164*9880d681SAndroid Build Coastguard Worker tail call hhvmcc void @svcreq(i64 %a, i64 %b, i64 %c, i64 undef, i64 1, 165*9880d681SAndroid Build Coastguard Worker i64 2, i64 3, i64 4, i64 5, i64 6, i64 undef, 166*9880d681SAndroid Build Coastguard Worker i64 42) 167*9880d681SAndroid Build Coastguard Worker ret void 168*9880d681SAndroid Build Coastguard Worker} 169*9880d681SAndroid Build Coastguard Worker 170*9880d681SAndroid Build Coastguard Workerdeclare hhvm_ccc void @helper_short(i64, i64, i64, i64, i64, i64, i64) 171*9880d681SAndroid Build Coastguard Worker 172*9880d681SAndroid Build Coastguard Worker; Pass all arguments in registers and check that we don't adjust stack 173*9880d681SAndroid Build Coastguard Worker; for the call. 174*9880d681SAndroid Build Coastguard Workerdefine hhvmcc void @test_helper_short(i64 %a, i64 %b, i64 %c) nounwind { 175*9880d681SAndroid Build Coastguard Workerentry: 176*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: test_helper_short: 177*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: push 178*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: sub 179*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $1, %edi 180*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $2, %esi 181*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $3, %edx 182*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $4, %ecx 183*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $5, %r8 184*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $6, %r9 185*9880d681SAndroid Build Coastguard Worker; CHECK: callq helper_short 186*9880d681SAndroid Build Coastguard Worker call hhvm_ccc void @helper_short(i64 %c, i64 1, i64 2, i64 3, i64 4, 187*9880d681SAndroid Build Coastguard Worker i64 5, i64 6) 188*9880d681SAndroid Build Coastguard Worker ret void 189*9880d681SAndroid Build Coastguard Worker} 190*9880d681SAndroid Build Coastguard Worker 191*9880d681SAndroid Build Coastguard Workerdeclare hhvm_ccc void @helper(i64, i64, i64, i64, i64, i64, i64, i64, i64, i64) 192*9880d681SAndroid Build Coastguard Worker 193*9880d681SAndroid Build Coastguard Workerdefine hhvmcc void @test_helper(i64 %a, i64 %b, i64 %c) nounwind { 194*9880d681SAndroid Build Coastguard Workerentry: 195*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: test_helper: 196*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $1, %edi 197*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $2, %esi 198*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $3, %edx 199*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $4, %ecx 200*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $5, %r8 201*9880d681SAndroid Build Coastguard Worker; CHECK-DAG: movl $6, %r9 202*9880d681SAndroid Build Coastguard Worker; CHECK: callq helper 203*9880d681SAndroid Build Coastguard Worker call hhvm_ccc void @helper(i64 %c, i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, 204*9880d681SAndroid Build Coastguard Worker i64 7, i64 8, i64 9) 205*9880d681SAndroid Build Coastguard Worker ret void 206*9880d681SAndroid Build Coastguard Worker} 207*9880d681SAndroid Build Coastguard Worker 208*9880d681SAndroid Build Coastguard Worker; When we enter function with HHVM calling convention, the stack is aligned 209*9880d681SAndroid Build Coastguard Worker; at 16 bytes. This means we align objects on the stack differently and 210*9880d681SAndroid Build Coastguard Worker; adjust the stack differently for calls. 211*9880d681SAndroid Build Coastguard Workerdeclare hhvm_ccc void @stack_helper(i64, i64, i64) 212*9880d681SAndroid Build Coastguard Workerdeclare hhvm_ccc void @stack_helper2(<2 x double>, i64) 213*9880d681SAndroid Build Coastguard Worker 214*9880d681SAndroid Build Coastguard Workerdefine hhvmcc void @test_stack_helper(i64 %a, i64 %b, i64 %c) nounwind { 215*9880d681SAndroid Build Coastguard Workerentry: 216*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: test_stack_helper: 217*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: push 218*9880d681SAndroid Build Coastguard Worker; CHECK: subq $32, %rsp 219*9880d681SAndroid Build Coastguard Worker; CHECK: movaps 16(%rsp), %xmm0 220*9880d681SAndroid Build Coastguard Worker; CHECK: callq stack_helper2 221*9880d681SAndroid Build Coastguard Worker %t1 = alloca <2 x double>, align 16 222*9880d681SAndroid Build Coastguard Worker %t2 = alloca i64, align 8 223*9880d681SAndroid Build Coastguard Worker %t3 = alloca i64, align 8 224*9880d681SAndroid Build Coastguard Worker %load3 = load i64, i64 *%t3 225*9880d681SAndroid Build Coastguard Worker call hhvm_ccc void @stack_helper(i64 %c, i64 %load3, i64 42) 226*9880d681SAndroid Build Coastguard Worker %load = load <2 x double>, <2 x double> *%t1 227*9880d681SAndroid Build Coastguard Worker %load2 = load i64, i64 *%t2 228*9880d681SAndroid Build Coastguard Worker call hhvm_ccc void @stack_helper2(<2 x double> %load, i64 %load2) 229*9880d681SAndroid Build Coastguard Worker ret void 230*9880d681SAndroid Build Coastguard Worker} 231*9880d681SAndroid Build Coastguard Worker 232*9880d681SAndroid Build Coastguard Worker; Check that we are not adjusting the stack before calling the helper. 233*9880d681SAndroid Build Coastguard Workerdefine hhvmcc void @test_stack_helper2(i64 %a, i64 %b, i64 %c) nounwind { 234*9880d681SAndroid Build Coastguard Workerentry: 235*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: test_stack_helper2: 236*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: push 237*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: subq 238*9880d681SAndroid Build Coastguard Worker call hhvm_ccc void @stack_helper(i64 %c, i64 7, i64 42) 239*9880d681SAndroid Build Coastguard Worker ret void 240*9880d681SAndroid Build Coastguard Worker} 241*9880d681SAndroid Build Coastguard Worker 242