| ... | @@ -263,9 +263,18 @@ pub fn MultiArrayList(comptime S: type) type { | ... | @@ -263,9 +263,18 @@ pub fn MultiArrayList(comptime S: type) type { |
| 263 | } | 263 | } |
| 264 | | 264 | |
| 265 | fn capacityInBytes(capacity: usize) usize { | 265 | fn capacityInBytes(capacity: usize) usize { |
| 266 | const sizes_vector: std.meta.Vector(sizes.bytes.len, usize) = sizes.bytes; | 266 | // TODO move this workaround of LLVM SIMD bugs into the Zig frontend. |
| 267 | const capacity_vector = @splat(sizes.bytes.len, capacity); | 267 | if (std.Target.current.cpu.arch == .aarch64) { |
| 268 | return @reduce(.Add, capacity_vector * sizes_vector); | 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 | fn allocatedBytes(self: Self) []align(@alignOf(S)) u8 { | 280 | fn allocatedBytes(self: Self) []align(@alignOf(S)) u8 { |
| ... | @@ -357,3 +366,82 @@ test "basic usage" { | ... | @@ -357,3 +366,82 @@ test "basic usage" { |
| 357 | testing.expectEqualStrings("zigzag", list.items(.b)[1]); | 366 | testing.expectEqualStrings("zigzag", list.items(.b)[1]); |
| 358 | testing.expectEqualStrings("fizzbuzz", list.items(.b)[2]); | 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 | } |