@@ -263,9 +263,18 @@ pub fn MultiArrayList(comptime S: type) type {
263
263
}
264
264
265
265
fn capacityInBytes (capacity : usize ) usize {
266
- const sizes_vector : std .meta .Vector (sizes.bytes.len , usize ) = sizes .bytes ;
267
- const capacity_vector = @splat (sizes .bytes .len , capacity );
268
- return @reduce (.Add , capacity_vector * sizes_vector );
266
+ // TODO move this workaround of LLVM SIMD bugs into the Zig frontend.
267
+ if (std .Target .current .cpu .arch == .aarch64 ) {
268
+ var sum : usize = 0 ;
269
+ for (sizes .bytes ) | size | {
270
+ sum += capacity * size ;
271
+ }
272
+ return sum ;
273
+ } else {
274
+ const sizes_vector : std .meta .Vector (sizes.bytes.len , usize ) = sizes .bytes ;
275
+ const capacity_vector = @splat (sizes .bytes .len , capacity );
276
+ return @reduce (.Add , capacity_vector * sizes_vector );
277
+ }
269
278
}
270
279
271
280
fn allocatedBytes (self : Self ) []align (@alignOf (S )) u8 {
@@ -357,3 +366,82 @@ test "basic usage" {
357
366
testing .expectEqualStrings ("zigzag" , list .items (.b )[1 ]);
358
367
testing .expectEqualStrings ("fizzbuzz" , list .items (.b )[2 ]);
359
368
}
369
+
370
+ // This was observed to fail on aarch64 with LLVM 11, when the capacityInBytes
371
+ // function used the @reduce code path.
372
+ test "regression test for @reduce bug" {
373
+ const ally = std .testing .allocator ;
374
+ var list = MultiArrayList (struct {
375
+ tag : std.zig.Token.Tag ,
376
+ start : u32 ,
377
+ }){};
378
+ defer list .deinit (ally );
379
+
380
+ try list .ensureCapacity (ally , 20 );
381
+
382
+ try list .append (ally , .{ .tag = .keyword_const , .start = 0 });
383
+ try list .append (ally , .{ .tag = .identifier , .start = 6 });
384
+ try list .append (ally , .{ .tag = .equal , .start = 10 });
385
+ try list .append (ally , .{ .tag = .builtin , .start = 12 });
386
+ try list .append (ally , .{ .tag = .l_paren , .start = 19 });
387
+ try list .append (ally , .{ .tag = .string_literal , .start = 20 });
388
+ try list .append (ally , .{ .tag = .r_paren , .start = 25 });
389
+ try list .append (ally , .{ .tag = .semicolon , .start = 26 });
390
+ try list .append (ally , .{ .tag = .keyword_pub , .start = 29 });
391
+ try list .append (ally , .{ .tag = .keyword_fn , .start = 33 });
392
+ try list .append (ally , .{ .tag = .identifier , .start = 36 });
393
+ try list .append (ally , .{ .tag = .l_paren , .start = 40 });
394
+ try list .append (ally , .{ .tag = .r_paren , .start = 41 });
395
+ try list .append (ally , .{ .tag = .identifier , .start = 43 });
396
+ try list .append (ally , .{ .tag = .bang , .start = 51 });
397
+ try list .append (ally , .{ .tag = .identifier , .start = 52 });
398
+ try list .append (ally , .{ .tag = .l_brace , .start = 57 });
399
+ try list .append (ally , .{ .tag = .identifier , .start = 63 });
400
+ try list .append (ally , .{ .tag = .period , .start = 66 });
401
+ try list .append (ally , .{ .tag = .identifier , .start = 67 });
402
+ try list .append (ally , .{ .tag = .period , .start = 70 });
403
+ try list .append (ally , .{ .tag = .identifier , .start = 71 });
404
+ try list .append (ally , .{ .tag = .l_paren , .start = 75 });
405
+ try list .append (ally , .{ .tag = .string_literal , .start = 76 });
406
+ try list .append (ally , .{ .tag = .comma , .start = 113 });
407
+ try list .append (ally , .{ .tag = .period , .start = 115 });
408
+ try list .append (ally , .{ .tag = .l_brace , .start = 116 });
409
+ try list .append (ally , .{ .tag = .r_brace , .start = 117 });
410
+ try list .append (ally , .{ .tag = .r_paren , .start = 118 });
411
+ try list .append (ally , .{ .tag = .semicolon , .start = 119 });
412
+ try list .append (ally , .{ .tag = .r_brace , .start = 121 });
413
+ try list .append (ally , .{ .tag = .eof , .start = 123 });
414
+
415
+ const tags = list .items (.tag );
416
+ std .testing .expectEqual (tags [1 ], .identifier );
417
+ std .testing .expectEqual (tags [2 ], .equal );
418
+ std .testing .expectEqual (tags [3 ], .builtin );
419
+ std .testing .expectEqual (tags [4 ], .l_paren );
420
+ std .testing .expectEqual (tags [5 ], .string_literal );
421
+ std .testing .expectEqual (tags [6 ], .r_paren );
422
+ std .testing .expectEqual (tags [7 ], .semicolon );
423
+ std .testing .expectEqual (tags [8 ], .keyword_pub );
424
+ std .testing .expectEqual (tags [9 ], .keyword_fn );
425
+ std .testing .expectEqual (tags [10 ], .identifier );
426
+ std .testing .expectEqual (tags [11 ], .l_paren );
427
+ std .testing .expectEqual (tags [12 ], .r_paren );
428
+ std .testing .expectEqual (tags [13 ], .identifier );
429
+ std .testing .expectEqual (tags [14 ], .bang );
430
+ std .testing .expectEqual (tags [15 ], .identifier );
431
+ std .testing .expectEqual (tags [16 ], .l_brace );
432
+ std .testing .expectEqual (tags [17 ], .identifier );
433
+ std .testing .expectEqual (tags [18 ], .period );
434
+ std .testing .expectEqual (tags [19 ], .identifier );
435
+ std .testing .expectEqual (tags [20 ], .period );
436
+ std .testing .expectEqual (tags [21 ], .identifier );
437
+ std .testing .expectEqual (tags [22 ], .l_paren );
438
+ std .testing .expectEqual (tags [23 ], .string_literal );
439
+ std .testing .expectEqual (tags [24 ], .comma );
440
+ std .testing .expectEqual (tags [25 ], .period );
441
+ std .testing .expectEqual (tags [26 ], .l_brace );
442
+ std .testing .expectEqual (tags [27 ], .r_brace );
443
+ std .testing .expectEqual (tags [28 ], .r_paren );
444
+ std .testing .expectEqual (tags [29 ], .semicolon );
445
+ std .testing .expectEqual (tags [30 ], .r_brace );
446
+ std .testing .expectEqual (tags [31 ], .eof );
447
+ }
0 commit comments