1; RUN: llc < %s -frame-pointer=all -mcpu=cortex-a8 -mtriple arm-linux-gnu -target-abi=apcs -o - | FileCheck %s 2; This test is fairly fragile. The goal is to ensure that "large" stack 3; objects are allocated closest to the stack protector (i.e., farthest away 4; from the Stack Pointer.) In standard SSP mode this means that large (>= 5; ssp-buffer-size) arrays and structures containing such arrays are 6; closet to the protector. With sspstrong and sspreq this means large 7; arrays/structures-with-arrays are closest, followed by small (< ssp-buffer-size) 8; arrays/structures-with-arrays, and then addr-taken variables. 9; 10; Ideally, we only want verify that the objects appear in the correct groups 11; and that the groups have the correct relative stack offset. The ordering 12; within a group is not relevant to this test. Unfortunately, there is not 13; an elegant way to do this, so just match the offset for each object. 14 15%struct.struct_large_char = type { [8 x i8] } 16%struct.struct_large_char2 = type { [2 x i8], [8 x i8] } 17%struct.struct_small_char = type { [2 x i8] } 18%struct.struct_large_nonchar = type { [8 x i32] } 19%struct.struct_small_nonchar = type { [2 x i16] } 20 21define void @layout_ssp() ssp { 22entry: 23; Expected stack layout for ssp is 24; 180 large_char . Group 1, nested arrays, arrays >= ssp-buffer-size 25; 172 struct_large_char . 26; 168 scalar1 | Everything else 27; 164 scalar2 28; 160 scalar3 29; 156 addr-of 30; 152 small_nonchar 31; 112 large_nonchar 32; 110 small_char 33; 108 struct_small_char 34; 72 struct_large_nonchar 35; 68 struct_small_nonchar 36 37; CHECK: layout_ssp: 38 39; CHECK: bl get_scalar1 40; CHECK: str r0, [sp, #168] 41; CHECK: bl end_scalar1 42 43; CHECK: bl get_scalar2 44; CHECK: str r0, [sp, #164] 45; CHECK: bl end_scalar 46 47; CHECK: bl get_scalar3 48; CHECK: str r0, [sp, #160] 49; CHECK: bl end_scalar3 50 51; CHECK: bl get_addrof 52; CHECK: str r0, [sp, #156] 53; CHECK: bl end_addrof 54 55; CHECK: get_small_nonchar 56; CHECK: strh r0, [sp, #152] 57; CHECK: bl end_small_nonchar 58 59; CHECK: bl get_large_nonchar 60; CHECK: str r0, [sp, #112] 61; CHECK: bl end_large_nonchar 62 63; CHECK: bl get_small_char 64; CHECK: strb r0, [sp, #110] 65; CHECK: bl end_small_char 66 67; CHECK: bl get_large_char 68; CHECK: strb r0, [sp, #180] 69; CHECK: bl end_large_char 70 71; CHECK: bl get_struct_large_char 72; CHECK: strb r0, [sp, #172] 73; CHECK: bl end_struct_large_char 74 75; CHECK: bl get_struct_small_char 76; CHECK: strb r0, [sp, #108] 77; CHECK: bl end_struct_small_char 78 79; CHECK: bl get_struct_large_nonchar 80; CHECK:str r0, [sp, #72] 81; CHECK: bl end_struct_large_nonchar 82 83; CHECK: bl get_struct_small_nonchar 84; CHECK: strh r0, [sp, #68] 85; CHECK: bl end_struct_small_nonchar 86 %x = alloca i32, align 4 87 %y = alloca i32, align 4 88 %z = alloca i32, align 4 89 %ptr = alloca i32, align 4 90 %small2 = alloca [2 x i16], align 2 91 %large2 = alloca [8 x i32], align 16 92 %small = alloca [2 x i8], align 1 93 %large = alloca [8 x i8], align 1 94 %a = alloca %struct.struct_large_char, align 1 95 %b = alloca %struct.struct_small_char, align 1 96 %c = alloca %struct.struct_large_nonchar, align 8 97 %d = alloca %struct.struct_small_nonchar, align 2 98 %call = call i32 @get_scalar1() 99 store i32 %call, ptr %x, align 4 100 call void @end_scalar1() 101 %call1 = call i32 @get_scalar2() 102 store i32 %call1, ptr %y, align 4 103 call void @end_scalar2() 104 %call2 = call i32 @get_scalar3() 105 store i32 %call2, ptr %z, align 4 106 call void @end_scalar3() 107 %call3 = call i32 @get_addrof() 108 store i32 %call3, ptr %ptr, align 4 109 call void @end_addrof() 110 %call4 = call signext i16 @get_small_nonchar() 111 store i16 %call4, ptr %small2, align 2 112 call void @end_small_nonchar() 113 %call5 = call i32 @get_large_nonchar() 114 store i32 %call5, ptr %large2, align 4 115 call void @end_large_nonchar() 116 %call7 = call signext i8 @get_small_char() 117 store i8 %call7, ptr %small, align 1 118 call void @end_small_char() 119 %call9 = call signext i8 @get_large_char() 120 store i8 %call9, ptr %large, align 1 121 call void @end_large_char() 122 %call11 = call signext i8 @get_struct_large_char() 123 store i8 %call11, ptr %a, align 1 124 call void @end_struct_large_char() 125 %call13 = call signext i8 @get_struct_small_char() 126 store i8 %call13, ptr %b, align 1 127 call void @end_struct_small_char() 128 %call16 = call i32 @get_struct_large_nonchar() 129 store i32 %call16, ptr %c, align 4 130 call void @end_struct_large_nonchar() 131 %call19 = call signext i16 @get_struct_small_nonchar() 132 store i16 %call19, ptr %d, align 2 133 call void @end_struct_small_nonchar() 134 %0 = load i32, ptr %x, align 4 135 %1 = load i32, ptr %y, align 4 136 %2 = load i32, ptr %z, align 4 137 %3 = load i64, ptr %a, align 1 138 %4 = load i16, ptr %b, align 1 139 %5 = load i32, ptr %d, align 1 140 call void @takes_all(i64 %3, i16 %4, ptr byval(%struct.struct_large_nonchar) align 4 %c, i32 %5, ptr %large, ptr %small, ptr %large2, ptr %small2, ptr %ptr, i32 %0, i32 %1, i32 %2) 141 ret void 142} 143 144define void @layout_sspstrong() sspstrong { 145entry: 146; Expected stack layout for sspstrong is 147; 144 large_nonchar . Group 1, nested arrays, 148; 136 large_char . arrays >= ssp-buffer-size 149; 128 struct_large_char . 150; 96 struct_large_nonchar . 151; 84+8 small_non_char | Group 2, nested arrays, 152; 90 small_char | arrays < ssp-buffer-size 153; 88 struct_small_char | 154; 84 struct_small_nonchar | 155; 80 addrof * Group 3, addr-of local 156; 76 scalar1 + Group 4, everything else 157; 72 scalar2 + 158; 68 scalar3 + 159; 160; CHECK: layout_sspstrong: 161 162; CHECK: bl get_scalar1 163; CHECK: str r0, [sp, #76] 164; CHECK: bl end_scalar1 165 166; CHECK: bl get_scalar2 167; CHECK: str r0, [sp, #72] 168; CHECK: bl end_scalar2 169 170; CHECK: bl get_scalar3 171; CHECK: str r0, [sp, #68] 172; CHECK: bl end_scalar3 173 174; CHECK: bl get_addrof 175; CHECK: str r0, [sp, #80] 176; CHECK: bl end_addrof 177 178; CHECK: get_small_nonchar 179; CHECK: strh r0, [sp, #92] 180; CHECK: bl end_small_nonchar 181 182; CHECK: bl get_large_nonchar 183; CHECK: str r0, [sp, #144] 184; CHECK: bl end_large_nonchar 185 186; CHECK: bl get_small_char 187; CHECK: strb r0, [sp, #90] 188; CHECK: bl end_small_char 189 190; CHECK: bl get_large_char 191; CHECK: strb r0, [sp, #136] 192; CHECK: bl end_large_char 193 194; CHECK: bl get_struct_large_char 195; CHECK: strb r0, [sp, #128] 196; CHECK: bl end_struct_large_char 197 198; CHECK: bl get_struct_small_char 199; CHECK: strb r0, [sp, #88] 200; CHECK: bl end_struct_small_char 201 202; CHECK: bl get_struct_large_nonchar 203; CHECK: str r0, [sp, #96] 204; CHECK: bl end_struct_large_nonchar 205 206; CHECK: bl get_struct_small_nonchar 207; CHECK: strh r0, [sp, #84] 208; CHECK: bl end_struct_small_nonchar 209 %x = alloca i32, align 4 210 %y = alloca i32, align 4 211 %z = alloca i32, align 4 212 %ptr = alloca i32, align 4 213 %small2 = alloca [2 x i16], align 2 214 %large2 = alloca [8 x i32], align 16 215 %small = alloca [2 x i8], align 1 216 %large = alloca [8 x i8], align 1 217 %a = alloca %struct.struct_large_char, align 1 218 %b = alloca %struct.struct_small_char, align 1 219 %c = alloca %struct.struct_large_nonchar, align 8 220 %d = alloca %struct.struct_small_nonchar, align 2 221 %call = call i32 @get_scalar1() 222 store i32 %call, ptr %x, align 4 223 call void @end_scalar1() 224 %call1 = call i32 @get_scalar2() 225 store i32 %call1, ptr %y, align 4 226 call void @end_scalar2() 227 %call2 = call i32 @get_scalar3() 228 store i32 %call2, ptr %z, align 4 229 call void @end_scalar3() 230 %call3 = call i32 @get_addrof() 231 store i32 %call3, ptr %ptr, align 4 232 call void @end_addrof() 233 %call4 = call signext i16 @get_small_nonchar() 234 store i16 %call4, ptr %small2, align 2 235 call void @end_small_nonchar() 236 %call5 = call i32 @get_large_nonchar() 237 store i32 %call5, ptr %large2, align 4 238 call void @end_large_nonchar() 239 %call7 = call signext i8 @get_small_char() 240 store i8 %call7, ptr %small, align 1 241 call void @end_small_char() 242 %call9 = call signext i8 @get_large_char() 243 store i8 %call9, ptr %large, align 1 244 call void @end_large_char() 245 %call11 = call signext i8 @get_struct_large_char() 246 store i8 %call11, ptr %a, align 1 247 call void @end_struct_large_char() 248 %call13 = call signext i8 @get_struct_small_char() 249 store i8 %call13, ptr %b, align 1 250 call void @end_struct_small_char() 251 %call16 = call i32 @get_struct_large_nonchar() 252 store i32 %call16, ptr %c, align 4 253 call void @end_struct_large_nonchar() 254 %call19 = call signext i16 @get_struct_small_nonchar() 255 store i16 %call19, ptr %d, align 2 256 call void @end_struct_small_nonchar() 257 %0 = load i32, ptr %x, align 4 258 %1 = load i32, ptr %y, align 4 259 %2 = load i32, ptr %z, align 4 260 %3 = load i64, ptr %a, align 1 261 %4 = load i16, ptr %b, align 1 262 %5 = load i32, ptr %d, align 1 263 call void @takes_all(i64 %3, i16 %4, ptr byval(%struct.struct_large_nonchar) align 4 %c, i32 %5, ptr %large, ptr %small, ptr %large2, ptr %small2, ptr %ptr, i32 %0, i32 %1, i32 %2) 264 ret void 265} 266 267define void @layout_sspreq() sspreq { 268entry: 269; Expected stack layout for sspreq is the same as sspstrong 270; 271; CHECK: layout_sspreq: 272 273; CHECK: bl get_scalar1 274; CHECK: str r0, [sp, #76] 275; CHECK: bl end_scalar1 276 277; CHECK: bl get_scalar2 278; CHECK: str r0, [sp, #72] 279; CHECK: bl end_scalar2 280 281; CHECK: bl get_scalar3 282; CHECK: str r0, [sp, #68] 283; CHECK: bl end_scalar3 284 285; CHECK: bl get_addrof 286; CHECK: str r0, [sp, #80] 287; CHECK: bl end_addrof 288 289; CHECK: get_small_nonchar 290; CHECK: strh r0, [sp, #92] 291; CHECK: bl end_small_nonchar 292 293; CHECK: bl get_large_nonchar 294; CHECK: str r0, [sp, #144] 295; CHECK: bl end_large_nonchar 296 297; CHECK: bl get_small_char 298; CHECK: strb r0, [sp, #90] 299; CHECK: bl end_small_char 300 301; CHECK: bl get_large_char 302; CHECK: strb r0, [sp, #136] 303; CHECK: bl end_large_char 304 305; CHECK: bl get_struct_large_char 306; CHECK: strb r0, [sp, #128] 307; CHECK: bl end_struct_large_char 308 309; CHECK: bl get_struct_small_char 310; CHECK: strb r0, [sp, #88] 311; CHECK: bl end_struct_small_char 312 313; CHECK: bl get_struct_large_nonchar 314; CHECK: str r0, [sp, #96] 315; CHECK: bl end_struct_large_nonchar 316 317; CHECK: bl get_struct_small_nonchar 318; CHECK: strh r0, [sp, #84] 319; CHECK: bl end_struct_small_nonchar 320 %x = alloca i32, align 4 321 %y = alloca i32, align 4 322 %z = alloca i32, align 4 323 %ptr = alloca i32, align 4 324 %small2 = alloca [2 x i16], align 2 325 %large2 = alloca [8 x i32], align 16 326 %small = alloca [2 x i8], align 1 327 %large = alloca [8 x i8], align 1 328 %a = alloca %struct.struct_large_char, align 1 329 %b = alloca %struct.struct_small_char, align 1 330 %c = alloca %struct.struct_large_nonchar, align 8 331 %d = alloca %struct.struct_small_nonchar, align 2 332 %call = call i32 @get_scalar1() 333 store i32 %call, ptr %x, align 4 334 call void @end_scalar1() 335 %call1 = call i32 @get_scalar2() 336 store i32 %call1, ptr %y, align 4 337 call void @end_scalar2() 338 %call2 = call i32 @get_scalar3() 339 store i32 %call2, ptr %z, align 4 340 call void @end_scalar3() 341 %call3 = call i32 @get_addrof() 342 store i32 %call3, ptr %ptr, align 4 343 call void @end_addrof() 344 %call4 = call signext i16 @get_small_nonchar() 345 store i16 %call4, ptr %small2, align 2 346 call void @end_small_nonchar() 347 %call5 = call i32 @get_large_nonchar() 348 store i32 %call5, ptr %large2, align 4 349 call void @end_large_nonchar() 350 %call7 = call signext i8 @get_small_char() 351 store i8 %call7, ptr %small, align 1 352 call void @end_small_char() 353 %call9 = call signext i8 @get_large_char() 354 store i8 %call9, ptr %large, align 1 355 call void @end_large_char() 356 %call11 = call signext i8 @get_struct_large_char() 357 store i8 %call11, ptr %a, align 1 358 call void @end_struct_large_char() 359 %call13 = call signext i8 @get_struct_small_char() 360 store i8 %call13, ptr %b, align 1 361 call void @end_struct_small_char() 362 %call16 = call i32 @get_struct_large_nonchar() 363 store i32 %call16, ptr %c, align 4 364 call void @end_struct_large_nonchar() 365 %call19 = call signext i16 @get_struct_small_nonchar() 366 store i16 %call19, ptr %d, align 2 367 call void @end_struct_small_nonchar() 368 %0 = load i32, ptr %x, align 4 369 %1 = load i32, ptr %y, align 4 370 %2 = load i32, ptr %z, align 4 371 %3 = load i64, ptr %a, align 1 372 %4 = load i16, ptr %b, align 1 373 %5 = load i32, ptr %d, align 1 374 call void @takes_all(i64 %3, i16 %4, ptr byval(%struct.struct_large_nonchar) align 4 %c, i32 %5, ptr %large, ptr %small, ptr %large2, ptr %small2, ptr %ptr, i32 %0, i32 %1, i32 %2) 375 ret void 376} 377 378define void @struct_with_protectable_arrays() sspstrong { 379entry: 380; Check to ensure that a structure which contains a small array followed by a 381; large array is assigned to the stack properly as a large object. 382; CHECK: struct_with_protectable_arrays: 383; CHECK: bl get_struct_small_char 384; CHECK: strb r0, [sp, #68] 385; CHECK: bl end_struct_small_char 386; CHECK: bl get_struct_large_char2 387; CHECK: strb r0, [sp, #106] 388; CHECK: bl end_struct_large_char2 389 %a = alloca %struct.struct_small_char, align 4 390 %b = alloca %struct.struct_large_char2, align 4 391 %d1 = alloca %struct.struct_large_nonchar, align 8 392 %d2 = alloca %struct.struct_small_nonchar, align 2 393 %call = call signext i8 @get_struct_small_char() 394 store i8 %call, ptr %a, align 1 395 call void @end_struct_small_char() 396 %call1 = call signext i8 @get_struct_large_char2() 397 %foo2 = getelementptr inbounds %struct.struct_large_char2, ptr %b, i32 0, i32 1 398 store i8 %call1, ptr %foo2, align 1 399 call void @end_struct_large_char2() 400 %0 = load i64, ptr %b, align 1 401 %1 = load i16, ptr %a, align 1 402 %2 = load i32, ptr %d2, align 1 403 call void @takes_all(i64 %0, i16 %1, ptr byval(%struct.struct_large_nonchar) align 4 %d1, i32 %2, ptr null, ptr null, ptr null, ptr null, ptr null, i32 0, i32 0, i32 0) 404 ret void 405} 406 407declare i32 @get_scalar1() 408declare void @end_scalar1() 409 410declare i32 @get_scalar2() 411declare void @end_scalar2() 412 413declare i32 @get_scalar3() 414declare void @end_scalar3() 415 416declare i32 @get_addrof() 417declare void @end_addrof() 418 419declare signext i16 @get_small_nonchar() 420declare void @end_small_nonchar() 421 422declare i32 @get_large_nonchar() 423declare void @end_large_nonchar() 424 425declare signext i8 @get_small_char() 426declare void @end_small_char() 427 428declare signext i8 @get_large_char() 429declare void @end_large_char() 430 431declare signext i8 @get_struct_large_char() 432declare void @end_struct_large_char() 433 434declare signext i8 @get_struct_large_char2() 435declare void @end_struct_large_char2() 436 437declare signext i8 @get_struct_small_char() 438declare void @end_struct_small_char() 439 440declare i32 @get_struct_large_nonchar() 441declare void @end_struct_large_nonchar() 442 443declare signext i16 @get_struct_small_nonchar() 444declare void @end_struct_small_nonchar() 445 446declare void @takes_all(i64, i16, ptr byval(%struct.struct_large_nonchar) align 8, i32, ptr, ptr, ptr, ptr, ptr, i32, i32, i32) 447