| ... | ... | @@ -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 | } |