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