274 lines · plain
1; RUN: llc -mtriple arm64-windows -o - %s | FileCheck %s2 3; struct S { int x; };4; void foo(int n);5; void foo(struct S o);6; void simple_seh() {7; struct S o;8; 9; __try { foo(o.x); }10; __finally { foo(o.x); }11; }12; void stack_realign() {13; struct S __declspec(align(32)) o;14; 15; __try { foo(o.x); }16; __finally { foo(o.x); }17; }18; void vla_present(int n) {19; int vla[n];20; 21; __try { foo(n); }22; __finally { foo(n); }23; }24; void vla_and_realign(int n) {25; struct S __declspec(align(32)) o;26; int vla[n];27; 28; __try { foo(o.x); }29; __finally { foo(o.x); }30; }31 32%struct.S = type { i32 }33 34; Test simple SEH (__try/__finally).35define void @simple_seh() #0 personality ptr @__C_specific_handler {36entry:37; CHECK-LABEL: simple_seh38; CHECK: add x29, sp, #1639; CHECK: mov x0, #-240; CHECK: stur x0, [x29, #16]41; CHECK: .Lsimple_seh$frame_escape_0 = -842; CHECK: ldur w0, [x29, #-8]43; CHECK: bl foo44 45 %o = alloca %struct.S, align 846 call void (...) @llvm.localescape(ptr %o)47 %0 = load i32, ptr %o, align 448 invoke void @foo(i32 %0) #549 to label %invoke.cont unwind label %ehcleanup50 51invoke.cont: ; preds = %entry52 %1 = call ptr @llvm.localaddress()53 call void @fin_simple_seh(i8 0, ptr %1)54 ret void55 56ehcleanup: ; preds = %entry57 %2 = cleanuppad within none []58 %3 = call ptr @llvm.localaddress()59 call void @fin_simple_seh(i8 1, ptr %3) [ "funclet"(token %2) ]60 cleanupret from %2 unwind to caller61}62 63define void @fin_simple_seh(i8 %abnormal_termination, ptr %frame_pointer) {64entry:65; CHECK-LABEL: fin_simple_seh66; CHECK: movz x8, #:abs_g1_s:.Lsimple_seh$frame_escape_067; CHECK: movk x8, #:abs_g0_nc:.Lsimple_seh$frame_escape_068; CHECK: strb w0, [sp, #15]69; CHECK: ldr w8, [x1, x8]70; CHECK: bl foo71 72 %frame_pointer.addr = alloca ptr, align 873 %abnormal_termination.addr = alloca i8, align 174 %0 = call ptr @llvm.localrecover(ptr @simple_seh, ptr %frame_pointer, i32 0)75 store ptr %frame_pointer, ptr %frame_pointer.addr, align 876 store i8 %abnormal_termination, ptr %abnormal_termination.addr, align 177 %1 = load i32, ptr %0, align 478 call void @foo(i32 %1)79 ret void80}81 82; Test SEH when stack realignment is needed in case highly aligned stack objects are present.83define void @stack_realign() #0 personality ptr @__C_specific_handler {84entry:85; CHECK-LABEL: stack_realign86; CHECK: add x29, sp, #887; CHECK: sub x9, sp, #1688; CHECK: and sp, x9, #0xffffffffffffffe089; CHECK: mov x19, sp90; CHECK: mov x0, #-291; CHECK: stur x0, [x29, #24]92; CHECK: .Lstack_realign$frame_escape_0 = 093; CHECK: ldr w0, [x19]94; CHECK: bl foo95 96 %o = alloca %struct.S, align 3297 call void (...) @llvm.localescape(ptr %o)98 %0 = load i32, ptr %o, align 3299 invoke void @foo(i32 %0) #5100 to label %invoke.cont unwind label %ehcleanup101 102invoke.cont: ; preds = %entry103 %1 = call ptr @llvm.localaddress()104 call void @fin_stack_realign(i8 0, ptr %1)105 ret void106 107ehcleanup: ; preds = %entry108 %2 = cleanuppad within none []109 %3 = call ptr @llvm.localaddress()110 call void @fin_stack_realign(i8 1, ptr %3) [ "funclet"(token %2) ]111 cleanupret from %2 unwind to caller112}113 114define void @fin_stack_realign(i8 %abnormal_termination, ptr %frame_pointer) {115entry:116; CHECK-LABEL: fin_stack_realign117; CHECK: movz x8, #:abs_g1_s:.Lstack_realign$frame_escape_0118; CHECK: movk x8, #:abs_g0_nc:.Lstack_realign$frame_escape_0119; CHECK: strb w0, [sp, #15]120; CHECK: ldr w8, [x1, x8]121; CHECK: bl foo122 123 %frame_pointer.addr = alloca ptr, align 8124 %abnormal_termination.addr = alloca i8, align 1125 %0 = call ptr @llvm.localrecover(ptr @stack_realign, ptr %frame_pointer, i32 0)126 store ptr %frame_pointer, ptr %frame_pointer.addr, align 8127 store i8 %abnormal_termination, ptr %abnormal_termination.addr, align 1128 %1 = load i32, ptr %0, align 32129 call void @foo(i32 %1)130 ret void131}132 133; Test SEH when variable size objects are present on the stack. Note: Escaped vla's are current not supported by SEH.134define void @vla_present(i32 %n) #0 personality ptr @__C_specific_handler {135entry:136; CHECK-LABEL: vla_present137; CHECK: add x29, sp, #32138; CHECK: mov x1, #-2139; CHECK: stur x1, [x29, #16]140; CHECK: .Lvla_present$frame_escape_0 = -4141; CHECK: stur w0, [x29, #-4]142; CHECK: ldur w8, [x29, #-4]143; CHECK: mov x9, sp144; CHECK: stur x9, [x29, #-16]145; CHECK: stur x8, [x29, #-24]146; CHECK: ldur w0, [x29, #-4]147; CHECK: bl foo148 149 %n.addr = alloca i32, align 4150 %saved_stack = alloca ptr, align 8151 %__vla_expr0 = alloca i64, align 8152 call void (...) @llvm.localescape(ptr %n.addr)153 store i32 %n, ptr %n.addr, align 4154 %0 = load i32, ptr %n.addr, align 4155 %1 = zext i32 %0 to i64156 %2 = call ptr @llvm.stacksave()157 store ptr %2, ptr %saved_stack, align 8158 %vla = alloca i32, i64 %1, align 4159 store i64 %1, ptr %__vla_expr0, align 8160 %3 = load i32, ptr %n.addr, align 4161 invoke void @foo(i32 %3) #5162 to label %invoke.cont unwind label %ehcleanup163 164invoke.cont: ; preds = %entry165 %4 = call ptr @llvm.localaddress()166 call void @fin_vla_present(i8 0, ptr %4)167 %5 = load ptr, ptr %saved_stack, align 8168 call void @llvm.stackrestore(ptr %5)169 ret void170 171ehcleanup: ; preds = %entry172 %6 = cleanuppad within none []173 %7 = call ptr @llvm.localaddress()174 call void @fin_vla_present(i8 1, ptr %7) [ "funclet"(token %6) ]175 cleanupret from %6 unwind to caller176}177 178define void @fin_vla_present(i8 %abnormal_termination, ptr %frame_pointer) {179entry:180; CHECK-LABEL: fin_vla_present181; CHECK: movz x8, #:abs_g1_s:.Lvla_present$frame_escape_0182; CHECK: movk x8, #:abs_g0_nc:.Lvla_present$frame_escape_0183; CHECK: strb w0, [sp, #15]184; CHECK: ldr w8, [x1, x8]185; CHECK: bl foo186 187 %frame_pointer.addr = alloca ptr, align 8188 %abnormal_termination.addr = alloca i8, align 1189 %0 = call ptr @llvm.localrecover(ptr @vla_present, ptr %frame_pointer, i32 0)190 store ptr %frame_pointer, ptr %frame_pointer.addr, align 8191 store i8 %abnormal_termination, ptr %abnormal_termination.addr, align 1192 %1 = load i32, ptr %0, align 4193 call void @foo(i32 %1)194 ret void195}196 197; Test when both vla's and highly aligned objects are present on stack.198define void @vla_and_realign(i32 %n) #0 personality ptr @__C_specific_handler {199entry:200; CHECK-LABEL: vla_and_realign201; CHECK: add x29, sp, #8202; CHECK: sub x9, sp, #48203; CHECK: and sp, x9, #0xffffffffffffffe0204; CHECK: mov x19, sp205; CHECK: mov x1, #-2206; CHECK: stur x1, [x29, #24]207; CHECK: .Lvla_and_realign$frame_escape_0 = 32208; CHECK: str w0, [x29, #36]209; CHECK: ldr w8, [x29, #36]210; CHECK: mov x9, sp211; CHECK: str x9, [x29, #16]212; CHECK: str x8, [x19, #24]213; CHECK: ldr w0, [x19, #32]214; CHECK: bl foo215 216 %n.addr = alloca i32, align 4217 %o = alloca %struct.S, align 32218 %saved_stack = alloca ptr, align 8219 %__vla_expr0 = alloca i64, align 8220 call void (...) @llvm.localescape(ptr %o)221 store i32 %n, ptr %n.addr, align 4222 %0 = load i32, ptr %n.addr, align 4223 %1 = zext i32 %0 to i64224 %2 = call ptr @llvm.stacksave()225 store ptr %2, ptr %saved_stack, align 8226 %vla = alloca i32, i64 %1, align 4227 store i64 %1, ptr %__vla_expr0, align 8228 %3 = load i32, ptr %o, align 32229 invoke void @foo(i32 %3) #5230 to label %invoke.cont unwind label %ehcleanup231 232invoke.cont: ; preds = %entry233 %4 = call ptr @llvm.localaddress()234 call void @fin_vla_and_realign(i8 0, ptr %4)235 %5 = load ptr, ptr %saved_stack, align 8236 call void @llvm.stackrestore(ptr %5)237 ret void238 239ehcleanup: ; preds = %entry240 %6 = cleanuppad within none []241 %7 = call ptr @llvm.localaddress()242 call void @fin_vla_and_realign(i8 1, ptr %7) [ "funclet"(token %6) ]243 cleanupret from %6 unwind to caller244}245 246define void @fin_vla_and_realign(i8 %abnormal_termination, ptr %frame_pointer) {247entry:248; CHECK-LABEL: fin_vla_and_realign249; CHECK: movz x8, #:abs_g1_s:.Lvla_and_realign$frame_escape_0250; CHECK: movk x8, #:abs_g0_nc:.Lvla_and_realign$frame_escape_0251; CHECK: strb w0, [sp, #15]252; CHECK: ldr w8, [x1, x8]253; CHECK: bl foo254 255 %frame_pointer.addr = alloca ptr, align 8256 %abnormal_termination.addr = alloca i8, align 1257 %0 = call ptr @llvm.localrecover(ptr @vla_and_realign, ptr %frame_pointer, i32 0)258 store ptr %frame_pointer, ptr %frame_pointer.addr, align 8259 store i8 %abnormal_termination, ptr %abnormal_termination.addr, align 1260 %1 = load i32, ptr %0, align 32261 call void @foo(i32 %1)262 ret void263}264 265declare void @foo(i32)266declare void @llvm.stackrestore(ptr)267declare ptr @llvm.stacksave()268declare ptr @llvm.localrecover(ptr, ptr, i32)269declare ptr @llvm.localaddress()270declare void @llvm.localescape(...)271declare i32 @__C_specific_handler(...)272 273attributes #0 = { noinline optnone }274