1;; Check that this produces the expected assembly output 2; RUN: llc -mtriple=thumbv7-windows -o - %s -verify-machineinstrs | FileCheck %s 3;; Also try to write an object file, which verifies that the SEH opcodes 4;; match the actual prologue/epilogue length. 5; RUN: llc -mtriple=thumbv7-windows -filetype=obj -o %t.obj %s -verify-machineinstrs 6 7; CHECK-LABEL: alloc_local: 8; CHECK-NEXT: .seh_proc alloc_local 9; CHECK-NEXT: @ %bb.0: @ %entry 10; CHECK-NEXT: push.w {r4, r5, r6, r7, r8, r9, r10} 11; CHECK-NEXT: .seh_save_regs_w {r4-r10} 12; CHECK-NEXT: sub sp, #4 13; CHECK-NEXT: .seh_stackalloc 4 14; CHECK-NEXT: vpush {d8, d9, d10, d11, d12, d13, d14, d15} 15; CHECK-NEXT: .seh_save_fregs {d8-d15} 16; CHECK-NEXT: push.w {r11, lr} 17; CHECK-NEXT: .seh_save_regs_w {r11, lr} 18; CHECK-NEXT: mov r11, sp 19; CHECK-NEXT: .seh_save_sp r11 20; CHECK-NEXT: .seh_endprologue 21; CHECK-NEXT: movw r4, #1256 22; CHECK-NEXT: bl __chkstk 23; CHECK-NEXT: sub.w sp, sp, r4 24; CHECK-NEXT: mov r4, sp 25; CHECK-NEXT: bfc r4, #0, #4 26; CHECK-NEXT: mov sp, r4 27 28; CHECK: ldr.w [[TMP:r[0-9]]], [r11, #104] 29; CHECK: mov r0, [[TMP]] 30 31; CHECK: .seh_startepilogue 32; CHECK-NEXT: mov sp, r11 33; CHECK-NEXT: .seh_save_sp r11 34; CHECK-NEXT: pop.w {r11, lr} 35; CHECK-NEXT: .seh_save_regs_w {r11, lr} 36; CHECK-NEXT: vpop {d8, d9, d10, d11, d12, d13, d14, d15} 37; CHECK-NEXT: .seh_save_fregs {d8-d15} 38; CHECK-NEXT: add sp, #4 39; CHECK-NEXT: .seh_stackalloc 4 40; CHECK-NEXT: pop.w {r4, r5, r6, r7, r8, r9, r10} 41; CHECK-NEXT: .seh_save_regs_w {r4-r10} 42; CHECK-NEXT: bx lr 43; CHECK-NEXT: .seh_nop 44; CHECK-NEXT: .seh_endepilogue 45; CHECK-NEXT: .seh_endproc 46 47define arm_aapcs_vfpcc void @alloc_local(i32 noundef %a, i32 noundef %b, i32 noundef %c, i32 noundef %d, i32 noundef %e) uwtable { 48entry: 49 %buf2 = alloca [5000 x i8], align 16 50 %vla = alloca i8, i32 %a, align 1 51 call void @llvm.lifetime.start.p0(i64 5000, ptr nonnull %buf2) #3 52 call arm_aapcs_vfpcc void @other(i32 noundef %e, ptr noundef nonnull %vla, ptr noundef nonnull %buf2) 53 call void asm sideeffect "", "~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12}"() 54 call void asm sideeffect "", "~{d8},~{d9},~{d10},~{d11},~{d12},~{d13},~{d14},~{d15}"() 55 call void @llvm.lifetime.end.p0(i64 5000, ptr nonnull %buf2) #3 56 ret void 57} 58 59declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) 60declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) 61 62declare arm_aapcs_vfpcc void @other(i32 noundef, ptr noundef, ptr noundef) 63 64; CHECK-LABEL: everything_varargs: 65; CHECK-NEXT: .seh_proc everything_varargs 66; CHECK-NEXT: @ %bb.0: @ %entry 67; CHECK-NEXT: sub sp, #12 68; CHECK-NEXT: .seh_stackalloc 12 69; CHECK-NEXT: push.w {r4, r5, r6, r7, r8, r9} 70; CHECK-NEXT: .seh_save_regs_w {r4-r9} 71; CHECK-NEXT: sub sp, #4 72; CHECK-NEXT: .seh_stackalloc 4 73; CHECK-NEXT: vpush {d8, d9, d10, d11, d12, d13, d14, d15} 74; CHECK-NEXT: .seh_save_fregs {d8-d15} 75; CHECK-NEXT: push.w {r11, lr} 76; CHECK-NEXT: .seh_save_regs_w {r11, lr} 77; CHECK-NEXT: mov r11, sp 78; CHECK-NEXT: .seh_save_sp r11 79; CHECK-NEXT: .seh_endprologue 80; CHECK-NEXT: movw r4, #1258 81; CHECK-NEXT: bl __chkstk 82; CHECK-NEXT: sub.w sp, sp, r4 83; CHECK-NEXT: mov r4, sp 84; CHECK-NEXT: bfc r4, #0, #4 85; CHECK-NEXT: mov sp, r4 86 87; CHECK: .seh_startepilogue 88; CHECK-NEXT: mov sp, r11 89; CHECK-NEXT: .seh_save_sp r11 90; CHECK-NEXT: pop.w {r11, lr} 91; CHECK-NEXT: .seh_save_regs_w {r11, lr} 92; CHECK-NEXT: vpop {d8, d9, d10, d11, d12, d13, d14, d15} 93; CHECK-NEXT: .seh_save_fregs {d8-d15} 94; CHECK-NEXT: add sp, #4 95; CHECK-NEXT: .seh_stackalloc 4 96; CHECK-NEXT: pop.w {r4, r5, r6, r7, r8, r9} 97; CHECK-NEXT: .seh_save_regs_w {r4-r9} 98; CHECK-NEXT: add sp, #12 99; CHECK-NEXT: .seh_stackalloc 12 100; CHECK-NEXT: bx lr 101; CHECK-NEXT: .seh_nop 102; CHECK-NEXT: .seh_endepilogue 103; CHECK-NEXT: .seh_endproc 104 105define arm_aapcs_vfpcc void @everything_varargs(i32 noundef %a, ...) { 106entry: 107 %buf2 = alloca [5000 x i8], align 16 108 %ap = alloca ptr, align 4 109 %vla = alloca i8, i32 %a, align 1 110 call void @llvm.lifetime.start.p0(i64 5000, ptr nonnull %buf2) 111 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %ap) 112 call void @llvm.va_start(ptr nonnull %ap) 113 %0 = load ptr, ptr %ap, align 4 114 call arm_aapcs_vfpcc void @other2(i32 noundef %a, ptr noundef nonnull %vla, ptr noundef nonnull %buf2, ptr noundef %0) 115 call void @llvm.va_end(ptr nonnull %ap) 116 call void asm sideeffect "", "~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r11},~{r12}"() 117 call void asm sideeffect "", "~{d8},~{d9},~{d10},~{d11},~{d12},~{d13},~{d14},~{d15}"() 118 call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %ap) 119 call void @llvm.lifetime.end.p0(i64 5000, ptr nonnull %buf2) 120 ret void 121} 122 123; CHECK-LABEL: novector_varargs: 124; CHECK-NEXT: .seh_proc novector_varargs 125; CHECK-NEXT: @ %bb.0: @ %entry 126; CHECK-NEXT: sub sp, #12 127; CHECK-NEXT: .seh_stackalloc 12 128; CHECK-NEXT: push.w {r4, r5, r6, r7, r8, r9} 129; CHECK-NEXT: .seh_save_regs_w {r4-r9} 130; CHECK-NEXT: push.w {r11, lr} 131; CHECK-NEXT: .seh_save_regs_w {r11, lr} 132; CHECK-NEXT: mov r11, sp 133; CHECK-NEXT: .seh_save_sp r11 134; CHECK-NEXT: .seh_endprologue 135; CHECK-NEXT: movw r4, #1259 136; CHECK-NEXT: bl __chkstk 137; CHECK-NEXT: sub.w sp, sp, r4 138; CHECK-NEXT: mov r4, sp 139; CHECK-NEXT: bfc r4, #0, #4 140; CHECK-NEXT: mov sp, r4 141 142; CHECK: .seh_startepilogue 143; CHECK-NEXT: mov sp, r11 144; CHECK-NEXT: .seh_save_sp r11 145; CHECK-NEXT: pop.w {r11, lr} 146; CHECK-NEXT: .seh_save_regs_w {r11, lr} 147; CHECK-NEXT: pop.w {r4, r5, r6, r7, r8, r9} 148; CHECK-NEXT: .seh_save_regs_w {r4-r9} 149; CHECK-NEXT: add sp, #12 150; CHECK-NEXT: .seh_stackalloc 12 151; CHECK-NEXT: bx lr 152; CHECK-NEXT: .seh_nop 153; CHECK-NEXT: .seh_endepilogue 154; CHECK-NEXT: .seh_endproc 155 156define arm_aapcs_vfpcc void @novector_varargs(i32 noundef %a, ...) { 157entry: 158 %buf2 = alloca [5000 x i8], align 16 159 %ap = alloca ptr, align 4 160 %vla = alloca i8, i32 %a, align 1 161 call void @llvm.lifetime.start.p0(i64 5000, ptr nonnull %buf2) 162 call void @llvm.lifetime.start.p0(i64 4, ptr nonnull %ap) 163 call void @llvm.va_start(ptr nonnull %ap) 164 %0 = load ptr, ptr %ap, align 4 165 call arm_aapcs_vfpcc void @other2(i32 noundef %a, ptr noundef nonnull %vla, ptr noundef nonnull %buf2, ptr noundef %0) 166 call void @llvm.va_end(ptr nonnull %ap) 167 call void asm sideeffect "", "~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r11},~{r12}"() 168 call void @llvm.lifetime.end.p0(i64 4, ptr nonnull %ap) 169 call void @llvm.lifetime.end.p0(i64 5000, ptr nonnull %buf2) 170 ret void 171} 172 173declare void @llvm.va_start(ptr) 174declare void @llvm.va_end(ptr) 175 176declare arm_aapcs_vfpcc void @other2(i32 noundef, ptr noundef, ptr noundef, ptr noundef) 177