| ; Test the stack protector under XPLINK on z/OS |
| ; |
| ; RUN: llc < %s -mtriple=s390x-ibm-zos -mcpu=z13 --verify-machineinstrs | FileCheck --check-prefixes=CHECK %s |
| |
| ; Test stack protector for non-XPLEAF. |
| |
| ; Small stack frame. |
| ; CHECK-LABEL: func0 |
| ; CHECK: * DSA Size [[#%#x,DSA_SIZE:]] |
| ; CHECK: aghi 4,-[[#%u,mul(div(DSA_SIZE,32),32)]] |
| ; CHECK: llgt [[REG1:[0-9]+]],1208 |
| ; CHECK: mvc [[#%u,2040+mul(div(DSA_SIZE,32),32)]](8,4),152([[REG1]]) |
| ; ... |
| ; CHECK: llgt [[REG3:[0-9]+]],1208 |
| ; CHECK: clc [[#%u,2040+mul(div(DSA_SIZE,32),32)]](8,4),152([[REG3]]) |
| ; CHECK: jlh [[FAIL_LABEL:L#BB[0-9_]+]] |
| ; success block |
| ; CHECK: aghi 4,[[#%u,mul(div(DSA_SIZE,32),32)]] |
| ; CHECK: b 2(7) |
| ; failure block |
| ; CHECK: [[FAIL_LABEL]] DS 0H |
| ; invoke __stack_chk_fail |
| ; CHECK: lg 6,[[#CHK_FAIL_OFF:]]({{[0-9]+}}) |
| ; CHECK: lg 5,[[#CHK_FAIL_OFF-8]]({{[0-9]+}}) |
| ; CHECK: basr 7,6 |
| ; CHECK-NEXT: bcr 0,0 |
| |
| define void @func0() sspreq { |
| call i64 (i64) @fun(i64 10) |
| ret void |
| } |
| |
| ; Large stack frame. |
| ; Larger than 1M in XPLINK64. |
| ; CHECK-LABEL: func1 |
| ; CHECK: * DSA Size [[#%#x,DSA_SIZE:]] |
| ; CHECK: stmg 6,{{[0-9]+}},2064(4) |
| ; CHECK: llgt [[REG1:[0-9]+]],1208 |
| ; CHECK: llilh [[REG_CANARY_OFF_HIGH:[0-9]+]],[[#%u,CANARY_OFF_HIGH:div(DSA_SIZE,65536)]] |
| ; CHECK: la [[REG_CANARY_OFF_HIGH]],0([[REG_CANARY_OFF_HIGH]],4) |
| ; CHECK: mvc [[#%u,2040+mul(div(DSA_SIZE,32),32)-mul(CANARY_OFF_HIGH,65536)]](8,[[REG_CANARY_OFF_HIGH]]),152([[REG1]]) |
| ; ... |
| ; CHECK: llgt [[REG3:[0-9]+]],1208 |
| ; CHECK: llilh [[REG_CANARY_OFF_HIGH_2:[0-9]+]],[[#%u,CANARY_OFF_HIGH_2:div(DSA_SIZE,65536)]] |
| ; CHECK: la [[REG_CANARY_OFF_HIGH_2]],0([[REG_CANARY_OFF_HIGH_2]],4) |
| ; CHECK: clc [[#%u,2040+mul(div(DSA_SIZE,32),32)-mul(CANARY_OFF_HIGH_2,65536)]](8,[[REG_CANARY_OFF_HIGH_2]]),152([[REG3]]) |
| ; CHECK: jlh [[FAIL_LABEL:L#BB[0-9_]+]] |
| ; success block |
| ; CHECK: agfi 4,[[#%u,mul(div(DSA_SIZE,32),32)]] |
| ; CHECK: b 2(7) |
| ; failure block |
| ; CHECK: [[FAIL_LABEL]] DS 0H |
| ; invoke __stack_chk_fail |
| ; CHECK: lg 6,[[#CHK_FAIL_OFF:]]({{[0-9]+}}) |
| ; CHECK: lg 5,[[#CHK_FAIL_OFF-8]]({{[0-9]+}}) |
| ; CHECK: basr 7,6 |
| ; CHECK-NEXT: bcr 0,0 |
| |
| define void @func1() sspreq { |
| %arr = alloca [131072 x i64], align 8 |
| call i64 (ptr) @fun1(ptr %arr) |
| ret void |
| } |
| |
| ; Test converting XPLeaf functions to non-leaf functions if they need stack protection |
| |
| ; Based on func3_64 in call-zos-03.ll |
| ; CHECK-LABEL: func2_64 |
| ; CHECK: * Entry Flags |
| ; CHECK-NEXT: * Bit 1: 0 = Non-leaf function |
| define i64 @func2_64(i64 %arg0) sspreq { |
| %out = add i64 %arg0, 55 |
| ret i64 %out |
| } |
| |
| ; Based on func6 in zos-prologue-epilog.ll. R15 is callee-saved, so needs to be |
| ; spilled to the stack before we use it. As a result this currently gets |
| ; converted to a non-leaf function (even without sspreq). |
| ; CHECK-LABEL: func3 |
| ; CHECK: * Entry Flags |
| ; CHECK-NEXT: * Bit 1: 0 = Non-leaf function |
| define void @func3() local_unnamed_addr sspreq #0 { |
| entry: |
| tail call void asm sideeffect " lhi 15,1\0A", "~{r15}"() |
| ret void |
| } |
| |
| ; Test stack protector for function that uses alloca() |
| |
| ; CHECK-LABEL: func4 |
| ; CHECK: * DSA Size [[#%#x,DSA_SIZE:]] |
| ; CHECK: * Entry Flags |
| ; CHECK-NEXT: * Bit 1: 0 = Non-leaf function |
| ; CHECK-NEXT: * Bit 2: 1 = Uses alloca |
| ; CHECK: stmg 4,[[SPILLHI:[0-9]+]],[[#%u,2048-mul(div(DSA_SIZE,32),32)]](4) |
| ; CHECK: aghi 4,-[[#%u,mul(div(DSA_SIZE,32),32)]] |
| ; CHECK: lgr [[ALLOCAREG:[0-9]+]],4 |
| ; CHECK: llgt [[REG1:[0-9]+]],1208 |
| ; CHECK: mvc [[#%u,2040+mul(div(DSA_SIZE,32),32)]](8,[[ALLOCAREG]]),152([[REG1]]) |
| ; ... |
| ; CHECK: llgt [[REG3:[0-9]+]],1208 |
| ; CHECK: clc [[#%u,2040+mul(div(DSA_SIZE,32),32)]](8,[[ALLOCAREG]]),152([[REG3]]) |
| ; CHECK: jlh [[FAIL_LABEL:L#BB[0-9_]+]] |
| ; success block |
| ; CHECK: lmg 4,[[SPILLHI]],2048(4) |
| ; CHECK: b 2(7) |
| ; failure block |
| ; CHECK: [[FAIL_LABEL]] DS 0H |
| ; invoke __stack_chk_fail |
| ; CHECK: lg 6,[[#CHK_FAIL_OFF:]]({{[0-9]+}}) |
| ; CHECK: lg 5,[[#CHK_FAIL_OFF-8]]({{[0-9]+}}) |
| ; CHECK: basr 7,6 |
| ; CHECK-NEXT: bcr 0,0 |
| |
| define i64 @func4(i64 %n) sspreq { |
| %vla = alloca i64, i64 %n, align 8 |
| %call = call i64 @fun2(i64 %n, ptr nonnull %vla, ptr nonnull %vla) |
| ret i64 %call |
| } |
| |
| ; Test stack protector off. |
| |
| ; CHECK-LABEL: func5 |
| define void @func5() { |
| call i64 (i64) @fun(i64 10) |
| ret void |
| } |
| |
| declare i64 @fun(i64 %arg0) |
| declare i64 @fun1(ptr %ptr) |
| declare i64 @fun2(i64 %n, ptr %arr0, ptr %arr1) |
| |
| ; CHECK-LABEL: L#PPA1_func0_0 DS 0H |
| ; CHECK: * PPA1 Flags 2 |
| ; CHECK-NOT: * PPA1 Flags 3 |
| ; CHECK: * Bit 3: 1 = STACKPROTECT is enabled |
| |
| ; CHECK-LABEL: L#PPA1_func1_0 DS 0H |
| ; CHECK: * PPA1 Flags 2 |
| ; CHECK-NOT: * PPA1 Flags 3 |
| ; CHECK: * Bit 3: 1 = STACKPROTECT is enabled |
| |
| ; CHECK-LABEL: L#PPA1_func2_64_0 DS 0H |
| ; CHECK: * PPA1 Flags 2 |
| ; CHECK-NOT: * PPA1 Flags 3 |
| ; CHECK: * Bit 3: 1 = STACKPROTECT is enabled |
| |
| ; CHECK-LABEL: L#PPA1_func3_0 DS 0H |
| ; CHECK: * PPA1 Flags 2 |
| ; CHECK-NOT: * PPA1 Flags 3 |
| ; CHECK: * Bit 3: 1 = STACKPROTECT is enabled |
| |
| ; CHECK-LABEL: L#PPA1_func4_0 DS 0H |
| ; CHECK: * PPA1 Flags 2 |
| ; CHECK-NOT: * PPA1 Flags 3 |
| ; CHECK: * Bit 3: 1 = STACKPROTECT is enabled |
| |
| ; CHECK-LABEL: L#PPA1_func5_0 DS 0H |
| ; CHECK: * PPA1 Flags 2 |
| ; CHECK-NOT: * PPA1 Flags 3 |
| ; CHECK: * Bit 3: 0 = STACKPROTECT is not enabled |