blob: e4b0ab6431a0cf6613dc88f6f855205118ace0a8 [file]
; 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