Skip to content

Commit bf64220

Browse files
committed
std.MultiArrayList: add workaround for LLVM bug
1 parent 05f3048 commit bf64220

File tree

1 file changed

+91
-3
lines changed

1 file changed

+91
-3
lines changed

lib/std/multi_array_list.zig

Lines changed: 91 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -263,9 +263,18 @@ pub fn MultiArrayList(comptime S: type) type {
263263
}
264264

265265
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+
}
269278
}
270279

271280
fn allocatedBytes(self: Self) []align(@alignOf(S)) u8 {
@@ -357,3 +366,82 @@ test "basic usage" {
357366
testing.expectEqualStrings("zigzag", list.items(.b)[1]);
358367
testing.expectEqualStrings("fizzbuzz", list.items(.b)[2]);
359368
}
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

Comments
 (0)