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