1; RUN: llc < %s -mtriple=i686-pc-linux | FileCheck %s -check-prefix=LINUX -check-prefix=CHECK 2; RUN: llc < %s -mtriple=i686-apple-darwin | FileCheck %s -check-prefix=DARWIN -check-prefix=CHECK 3; RUN: llc < %s -mtriple=i686-pc-linux -stop-after=prologepilog | FileCheck %s --check-prefix=PEI 4 5declare i32 @__gxx_personality_v0(...) 6declare void @good(i32 %a, i32 %b, i32 %c, i32 %d) 7declare void @large(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f) 8declare void @empty() 9 10; When we use an invoke, we expect a .cfi_escape GNU_ARGS_SIZE 11; with size 16 before the invocation. Without FP, we also expect 12; .cfi_adjust_cfa_offset after each push. 13; Darwin should not generate pushes in either circumstance. 14; CHECK-LABEL: test1_nofp: 15; LINUX: .cfi_escape 0x2e, 0x10 16; LINUX-NEXT: pushl $4 17; LINUX-NEXT: .cfi_adjust_cfa_offset 4 18; LINUX-NEXT: pushl $3 19; LINUX-NEXT: .cfi_adjust_cfa_offset 4 20; LINUX-NEXT: pushl $2 21; LINUX-NEXT: .cfi_adjust_cfa_offset 4 22; LINUX-NEXT: pushl $1 23; LINUX-NEXT: .cfi_adjust_cfa_offset 4 24; LINUX-NEXT: call 25; LINUX-NEXT: addl $16, %esp 26; LINUX: .cfi_adjust_cfa_offset -16 27; DARWIN-NOT: .cfi_escape 28; DARWIN-NOT: pushl 29 30; PEI-LABEL: name: test1_nofp 31; PEI: $esp = frame-setup SUB32ri $esp, 12, implicit-def dead $eflags 32; PEI-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16 33; PEI-NOT: frame-setup CFI_INSTRUCTION 34; PEI: ... 35define void @test1_nofp() #0 personality ptr @__gxx_personality_v0 { 36entry: 37 invoke void @good(i32 1, i32 2, i32 3, i32 4) 38 to label %continue unwind label %cleanup 39continue: 40 ret void 41cleanup: 42 landingpad { ptr, i32 } 43 cleanup 44 ret void 45} 46 47; CHECK-LABEL: test1_fp: 48; LINUX: .cfi_escape 0x2e, 0x10 49; LINUX-NEXT: pushl $4 50; LINUX-NEXT: pushl $3 51; LINUX-NEXT: pushl $2 52; LINUX-NEXT: pushl $1 53; LINUX-NEXT: call 54; LINUX-NEXT: addl $16, %esp 55; DARWIN: pushl %ebp 56; DARWIN-NOT: .cfi_escape 57; DARWIN-NOT: pushl 58define void @test1_fp() #1 personality ptr @__gxx_personality_v0 { 59entry: 60 invoke void @good(i32 1, i32 2, i32 3, i32 4) 61 to label %continue unwind label %cleanup 62continue: 63 ret void 64cleanup: 65 landingpad { ptr, i32 } 66 cleanup 67 ret void 68} 69 70; If the function has no handlers, we don't need to generate GNU_ARGS_SIZE, 71; even if it has an unwind table. Without FP, we still need cfi_adjust_cfa_offset, 72; so darwin should not generate pushes. 73; CHECK-LABEL: test2_nofp: 74; LINUX-NOT: .cfi_escape 75; LINUX: pushl $4 76; LINUX-NEXT: .cfi_adjust_cfa_offset 4 77; LINUX-NEXT: pushl $3 78; LINUX-NEXT: .cfi_adjust_cfa_offset 4 79; LINUX-NEXT: pushl $2 80; LINUX-NEXT: .cfi_adjust_cfa_offset 4 81; LINUX-NEXT: pushl $1 82; LINUX-NEXT: .cfi_adjust_cfa_offset 4 83; LINUX-NEXT: call 84; LINUX-NEXT: addl $28, %esp 85; LINUX: .cfi_adjust_cfa_offset -28 86; DARWIN-NOT: .cfi_escape 87; DARWIN-NOT: pushl 88define void @test2_nofp() #0 personality ptr @__gxx_personality_v0 { 89entry: 90 call void @good(i32 1, i32 2, i32 3, i32 4) 91 ret void 92} 93 94; CHECK-LABEL: test2_fp: 95; CHECK-NOT: .cfi_escape 96; CHECK-NOT: .cfi_adjust_cfa_offset 97; CHECK: pushl $4 98; CHECK-NEXT: pushl $3 99; CHECK-NEXT: pushl $2 100; CHECK-NEXT: pushl $1 101; CHECK-NEXT: call 102; CHECK-NEXT: addl $24, %esp 103define void @test2_fp() #1 personality ptr @__gxx_personality_v0 { 104entry: 105 call void @good(i32 1, i32 2, i32 3, i32 4) 106 ret void 107} 108 109; If we did not end up using any pushes, no need for GNU_ARGS_SIZE or 110; cfi_adjust_cfa_offset. 111; CHECK-LABEL: test3_nofp: 112; LINUX-NOT: .cfi_escape 113; LINUX-NOT: .cfi_adjust_cfa_offset 114; LINUX-NOT: pushl 115; LINUX: retl 116define void @test3_nofp() #0 personality ptr @__gxx_personality_v0 { 117entry: 118 invoke void @empty() 119 to label %continue unwind label %cleanup 120continue: 121 ret void 122cleanup: 123 landingpad { ptr, i32 } 124 cleanup 125 ret void 126} 127 128; If we did not end up using any pushes, no need for GNU_ARGS_SIZE or 129; cfi_adjust_cfa_offset. 130; CHECK-LABEL: test3_fp: 131; LINUX: pushl %ebp 132; LINUX-NOT: .cfi_escape 133; LINUX-NOT: .cfi_adjust_cfa_offset 134; LINUX-NOT: pushl 135; LINUX: retl 136define void @test3_fp() #1 personality ptr @__gxx_personality_v0 { 137entry: 138 invoke void @empty() 139 to label %continue unwind label %cleanup 140continue: 141 ret void 142cleanup: 143 landingpad { ptr, i32 } 144 cleanup 145 ret void 146} 147 148; Different sized stacks need different GNU_ARGS_SIZEs 149; CHECK-LABEL: test4: 150; LINUX: .cfi_escape 0x2e, 0x10 151; LINUX-NEXT: pushl $4 152; LINUX-NEXT: pushl $3 153; LINUX-NEXT: pushl $2 154; LINUX-NEXT: pushl $1 155; LINUX-NEXT: call 156; LINUX-NEXT: addl $16, %esp 157; LINUX: .cfi_escape 0x2e, 0x20 158; LINUX: subl $8, %esp 159; LINUX-NEXT: pushl $11 160; LINUX-NEXT: pushl $10 161; LINUX-NEXT: pushl $9 162; LINUX-NEXT: pushl $8 163; LINUX-NEXT: pushl $7 164; LINUX-NEXT: pushl $6 165; LINUX-NEXT: calll large 166; LINUX-NEXT: addl $32, %esp 167define void @test4() #1 personality ptr @__gxx_personality_v0 { 168entry: 169 invoke void @good(i32 1, i32 2, i32 3, i32 4) 170 to label %continue1 unwind label %cleanup 171continue1: 172 invoke void @large(i32 6, i32 7, i32 8, i32 9, i32 10, i32 11) 173 to label %continue2 unwind label %cleanup 174continue2: 175 ret void 176cleanup: 177 landingpad { ptr, i32 } 178 cleanup 179 ret void 180} 181 182; If we did use pushes, we need to reset GNU_ARGS_SIZE before a call 183; without parameters, but don't need to adjust the cfa offset 184; CHECK-LABEL: test5_nofp: 185; LINUX: .cfi_escape 0x2e, 0x10 186; LINUX-NEXT: pushl $4 187; LINUX-NEXT: .cfi_adjust_cfa_offset 4 188; LINUX-NEXT: pushl $3 189; LINUX-NEXT: .cfi_adjust_cfa_offset 4 190; LINUX-NEXT: pushl $2 191; LINUX-NEXT: .cfi_adjust_cfa_offset 4 192; LINUX-NEXT: pushl $1 193; LINUX-NEXT: .cfi_adjust_cfa_offset 4 194; LINUX-NEXT: call 195; LINUX-NEXT: addl $16, %esp 196; LINUX: .cfi_adjust_cfa_offset -16 197; LINUX-NOT: .cfi_adjust_cfa_offset 198; LINUX: .cfi_escape 0x2e, 0x00 199; LINUX-NOT: .cfi_adjust_cfa_offset 200; LINUX: call 201define void @test5_nofp() #0 personality ptr @__gxx_personality_v0 { 202entry: 203 invoke void @good(i32 1, i32 2, i32 3, i32 4) 204 to label %continue1 unwind label %cleanup 205continue1: 206 invoke void @empty() 207 to label %continue2 unwind label %cleanup 208continue2: 209 ret void 210cleanup: 211 landingpad { ptr, i32 } 212 cleanup 213 ret void 214} 215 216; CHECK-LABEL: test5_fp: 217; LINUX: .cfi_escape 0x2e, 0x10 218; LINUX-NEXT: pushl $4 219; LINUX-NEXT: pushl $3 220; LINUX-NEXT: pushl $2 221; LINUX-NEXT: pushl $1 222; LINUX-NEXT: call 223; LINUX-NEXT: addl $16, %esp 224; LINUX: .cfi_escape 0x2e, 0x00 225; LINUX-NOT: .cfi_adjust_cfa_offset 226; LINUX: call 227define void @test5_fp() #1 personality ptr @__gxx_personality_v0 { 228entry: 229 invoke void @good(i32 1, i32 2, i32 3, i32 4) 230 to label %continue1 unwind label %cleanup 231continue1: 232 invoke void @empty() 233 to label %continue2 unwind label %cleanup 234continue2: 235 ret void 236cleanup: 237 landingpad { ptr, i32 } 238 cleanup 239 ret void 240} 241 242; FIXME: This is actually inefficient - we don't need to repeat the .cfi_escape twice. 243; CHECK-LABEL: test6: 244; LINUX: .cfi_escape 0x2e, 0x10 245; LINUX: call 246; LINUX: .cfi_escape 0x2e, 0x10 247; LINUX: call 248define void @test6() #1 personality ptr @__gxx_personality_v0 { 249entry: 250 invoke void @good(i32 1, i32 2, i32 3, i32 4) 251 to label %continue1 unwind label %cleanup 252continue1: 253 invoke void @good(i32 5, i32 6, i32 7, i32 8) 254 to label %continue2 unwind label %cleanup 255continue2: 256 ret void 257cleanup: 258 landingpad { ptr, i32 } 259 cleanup 260 ret void 261} 262 263; Darwin should generate pushes in the presense of FP and an unwind table, 264; but not FP and invoke. 265; CHECK-LABEL: test7: 266; DARWIN: pushl %ebp 267; DARWIN: movl %esp, %ebp 268; DARWIN: .cfi_def_cfa_register %ebp 269; DARWIN-NOT: .cfi_adjust_cfa_offset 270; DARWIN: pushl $4 271; DARWIN-NEXT: pushl $3 272; DARWIN-NEXT: pushl $2 273; DARWIN-NEXT: pushl $1 274; DARWIN-NEXT: call 275define void @test7() #1 personality ptr @__gxx_personality_v0 { 276entry: 277 call void @good(i32 1, i32 2, i32 3, i32 4) 278 ret void 279} 280 281; CHECK-LABEL: test8: 282; DARWIN: pushl %ebp 283; DARWIN: movl %esp, %ebp 284; DARWIN-NOT: .cfi_adjust_cfa_offset 285; DARWIN-NOT: pushl 286define void @test8() #1 personality ptr @__gxx_personality_v0 { 287entry: 288 invoke void @good(i32 1, i32 2, i32 3, i32 4) 289 to label %continue unwind label %cleanup 290continue: 291 ret void 292cleanup: 293 landingpad { ptr, i32 } 294 cleanup 295 ret void 296} 297 298attributes #0 = { optsize } 299attributes #1 = { optsize "frame-pointer"="all" } 300