authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-02-25 15:53:28-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-02-25 15:53:28-05:00
log81a47dc874d8468db7120e1733acd122f90d8eab
tree97921a5f1f37300756e7dcbce9dbfad347574d3e
parent26196be344e971c26ed044a39b68d0420cd94b90
parent477be90c0c18a473c5b0c84c0fbcc9ce41e47738
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #14725 from jacobly0/more-ctype

CBE: more `CType` improvements

3 files changed, 156 insertions(+), 140 deletions(-)

src/codegen/c.zig+95-64
...@@ -82,15 +82,20 @@ pub const LazyFnMap = std.AutoArrayHashMapUnmanaged(LazyFnKey, LazyFnValue);...@@ -82,15 +82,20 @@ pub const LazyFnMap = std.AutoArrayHashMapUnmanaged(LazyFnKey, LazyFnValue);
8282
83const LoopDepth = u16;83const LoopDepth = u16;
84const Local = struct {84const Local = struct {
85 ty: Type,85 cty_idx: CType.Index,
86 alignment: u32,
87 /// How many loops the last definition was nested in.86 /// How many loops the last definition was nested in.
88 loop_depth: LoopDepth,87 loop_depth: LoopDepth,
88 alignas: CType.AlignAs,
89
90 pub fn getType(local: Local) LocalType {
91 return .{ .cty_idx = local.cty_idx, .alignas = local.alignas };
92 }
89};93};
9094
91const LocalIndex = u16;95const LocalIndex = u16;
92const LocalsList = std.ArrayListUnmanaged(LocalIndex);96const LocalType = struct { cty_idx: CType.Index, alignas: CType.AlignAs };
93const LocalsMap = std.ArrayHashMapUnmanaged(Type, LocalsList, Type.HashContext32, true);97const LocalsList = std.AutoArrayHashMapUnmanaged(LocalIndex, void);
98const LocalsMap = std.AutoArrayHashMapUnmanaged(LocalType, LocalsList);
94const LocalsStack = std.ArrayListUnmanaged(LocalsMap);99const LocalsStack = std.ArrayListUnmanaged(LocalsMap);
95100
96const ValueRenderLocation = enum {101const ValueRenderLocation = enum {
...@@ -296,10 +301,6 @@ pub const Function = struct {...@@ -296,10 +301,6 @@ pub const Function = struct {
296 /// Needed for memory used by the keys of free_locals_stack entries.301 /// Needed for memory used by the keys of free_locals_stack entries.
297 arena: std.heap.ArenaAllocator,302 arena: std.heap.ArenaAllocator,
298303
299 fn tyHashCtx(f: Function) Type.HashContext32 {
300 return .{ .mod = f.object.dg.module };
301 }
302
303 fn resolveInst(f: *Function, inst: Air.Inst.Ref) !CValue {304 fn resolveInst(f: *Function, inst: Air.Inst.Ref) !CValue {
304 const gop = try f.value_map.getOrPut(inst);305 const gop = try f.value_map.getOrPut(inst);
305 if (gop.found_existing) return gop.value_ptr.*;306 if (gop.found_existing) return gop.value_ptr.*;
...@@ -339,10 +340,11 @@ pub const Function = struct {...@@ -339,10 +340,11 @@ pub const Function = struct {
339 /// Skips the reuse logic.340 /// Skips the reuse logic.
340 fn allocLocalValue(f: *Function, ty: Type, alignment: u32) !CValue {341 fn allocLocalValue(f: *Function, ty: Type, alignment: u32) !CValue {
341 const gpa = f.object.dg.gpa;342 const gpa = f.object.dg.gpa;
343 const target = f.object.dg.module.getTarget();
342 try f.locals.append(gpa, .{344 try f.locals.append(gpa, .{
343 .ty = ty,345 .cty_idx = try f.typeToIndex(ty, .complete),
344 .alignment = alignment,
345 .loop_depth = @intCast(LoopDepth, f.free_locals_stack.items.len - 1),346 .loop_depth = @intCast(LoopDepth, f.free_locals_stack.items.len - 1),
347 .alignas = CType.AlignAs.init(alignment, ty.abiAlignment(target)),
346 });348 });
347 return .{ .new_local = @intCast(LocalIndex, f.locals.items.len - 1) };349 return .{ .new_local = @intCast(LocalIndex, f.locals.items.len - 1) };
348 }350 }
...@@ -355,14 +357,15 @@ pub const Function = struct {...@@ -355,14 +357,15 @@ pub const Function = struct {
355357
356 /// Only allocates the local; does not print anything.358 /// Only allocates the local; does not print anything.
357 fn allocAlignedLocal(f: *Function, ty: Type, _: CQualifiers, alignment: u32) !CValue {359 fn allocAlignedLocal(f: *Function, ty: Type, _: CQualifiers, alignment: u32) !CValue {
358 if (f.getFreeLocals().getPtrContext(ty, f.tyHashCtx())) |locals_list| {360 const target = f.object.dg.module.getTarget();
359 for (locals_list.items, 0..) |local_index, i| {361 if (f.getFreeLocals().getPtr(.{
360 const local = &f.locals.items[local_index];362 .cty_idx = try f.typeToIndex(ty, .complete),
361 if (local.alignment >= alignment) {363 .alignas = CType.AlignAs.init(alignment, ty.abiAlignment(target)),
362 local.loop_depth = @intCast(LoopDepth, f.free_locals_stack.items.len - 1);364 })) |locals_list| {
363 _ = locals_list.swapRemove(i);365 if (locals_list.popOrNull()) |local_entry| {
364 return .{ .new_local = local_index };366 const local = &f.locals.items[local_entry.key];
365 }367 local.loop_depth = @intCast(LoopDepth, f.free_locals_stack.items.len - 1);
368 return .{ .new_local = local_entry.key };
366 }369 }
367 }370 }
368371
...@@ -1695,22 +1698,34 @@ pub const DeclGen = struct {...@@ -1695,22 +1698,34 @@ pub const DeclGen = struct {
1695 qualifiers: CQualifiers,1698 qualifiers: CQualifiers,
1696 alignment: u32,1699 alignment: u32,
1697 kind: CType.Kind,1700 kind: CType.Kind,
1701 ) error{ OutOfMemory, AnalysisFail }!void {
1702 const target = dg.module.getTarget();
1703 const alignas = CType.AlignAs.init(alignment, ty.abiAlignment(target));
1704 try dg.renderCTypeAndName(w, try dg.typeToIndex(ty, kind), name, qualifiers, alignas);
1705 }
1706
1707 fn renderCTypeAndName(
1708 dg: *DeclGen,
1709 w: anytype,
1710 cty_idx: CType.Index,
1711 name: CValue,
1712 qualifiers: CQualifiers,
1713 alignas: CType.AlignAs,
1698 ) error{ OutOfMemory, AnalysisFail }!void {1714 ) error{ OutOfMemory, AnalysisFail }!void {
1699 const store = &dg.ctypes.set;1715 const store = &dg.ctypes.set;
1700 const module = dg.module;1716 const module = dg.module;
17011717
1702 if (alignment != 0) switch (std.math.order(alignment, ty.abiAlignment(dg.module.getTarget()))) {1718 switch (std.math.order(alignas.@"align", alignas.abi)) {
1703 .lt => try w.print("zig_under_align({}) ", .{alignment}),1719 .lt => try w.print("zig_under_align({}) ", .{alignas.getAlign()}),
1704 .eq => {},1720 .eq => {},
1705 .gt => try w.print("zig_align({}) ", .{alignment}),1721 .gt => try w.print("zig_align({}) ", .{alignas.getAlign()}),
1706 };1722 }
17071723
1708 const idx = try dg.typeToIndex(ty, kind);
1709 const trailing =1724 const trailing =
1710 try renderTypePrefix(dg.decl_index, store.*, module, w, idx, .suffix, qualifiers);1725 try renderTypePrefix(dg.decl_index, store.*, module, w, cty_idx, .suffix, qualifiers);
1711 try w.print("{}", .{trailing});1726 try w.print("{}", .{trailing});
1712 try dg.writeCValue(w, name);1727 try dg.writeCValue(w, name);
1713 try renderTypeSuffix(dg.decl_index, store.*, module, w, idx, .suffix, .{});1728 try renderTypeSuffix(dg.decl_index, store.*, module, w, cty_idx, .suffix, .{});
1714 }1729 }
17151730
1716 fn declIsGlobal(dg: *DeclGen, tv: TypedValue) bool {1731 fn declIsGlobal(dg: *DeclGen, tv: TypedValue) bool {
...@@ -2589,36 +2604,27 @@ pub fn genFunc(f: *Function) !void {...@@ -2589,36 +2604,27 @@ pub fn genFunc(f: *Function) !void {
2589 if (value) continue; // static2604 if (value) continue; // static
2590 const local = f.locals.items[local_index];2605 const local = f.locals.items[local_index];
2591 log.debug("inserting local {d} into free_locals", .{local_index});2606 log.debug("inserting local {d} into free_locals", .{local_index});
2592 const gop = try free_locals.getOrPutContext(gpa, local.ty, f.tyHashCtx());2607 const gop = try free_locals.getOrPut(gpa, local.getType());
2593 if (!gop.found_existing) gop.value_ptr.* = .{};2608 if (!gop.found_existing) gop.value_ptr.* = .{};
2594 try gop.value_ptr.append(gpa, local_index);2609 try gop.value_ptr.putNoClobber(gpa, local_index, {});
2595 }2610 }
25962611
2597 const SortContext = struct {2612 const SortContext = struct {
2598 target: std.Target,2613 keys: []const LocalType,
2599 keys: []const Type,
26002614
2601 pub fn lessThan(ctx: @This(), a_index: usize, b_index: usize) bool {2615 pub fn lessThan(ctx: @This(), lhs_index: usize, rhs_index: usize) bool {
2602 const a_ty = ctx.keys[a_index];2616 const lhs_ty = ctx.keys[lhs_index];
2603 const b_ty = ctx.keys[b_index];2617 const rhs_ty = ctx.keys[rhs_index];
2604 return b_ty.abiAlignment(ctx.target) < a_ty.abiAlignment(ctx.target);2618 return lhs_ty.alignas.getAlign() > rhs_ty.alignas.getAlign();
2605 }2619 }
2606 };2620 };
2607 const target = o.dg.module.getTarget();2621 free_locals.sort(SortContext{ .keys = free_locals.keys() });
2608 free_locals.sort(SortContext{ .target = target, .keys = free_locals.keys() });
26092622
2610 const w = o.code_header.writer();2623 const w = o.code_header.writer();
2611 for (free_locals.values()) |list| {2624 for (free_locals.values()) |list| {
2612 for (list.items) |local_index| {2625 for (list.keys()) |local_index| {
2613 const local = f.locals.items[local_index];2626 const local = f.locals.items[local_index];
2614 try o.dg.renderTypeAndName(2627 try o.dg.renderCTypeAndName(w, local.cty_idx, .{ .local = local_index }, .{}, local.alignas);
2615 w,
2616 local.ty,
2617 .{ .local = local_index },
2618 .{},
2619 local.alignment,
2620 .complete,
2621 );
2622 try w.writeAll(";\n ");2628 try w.writeAll(";\n ");
2623 }2629 }
2624 }2630 }
...@@ -4486,13 +4492,13 @@ fn airLoop(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4486,13 +4492,13 @@ fn airLoop(f: *Function, inst: Air.Inst.Index) !CValue {
4486 const new_free_locals = f.getFreeLocals();4492 const new_free_locals = f.getFreeLocals();
4487 var it = new_free_locals.iterator();4493 var it = new_free_locals.iterator();
4488 while (it.next()) |entry| {4494 while (it.next()) |entry| {
4489 const gop = try old_free_locals.getOrPutContext(gpa, entry.key_ptr.*, f.tyHashCtx());4495 const gop = try old_free_locals.getOrPut(gpa, entry.key_ptr.*);
4490 if (gop.found_existing) {4496 if (gop.found_existing) {
4491 try gop.value_ptr.appendSlice(gpa, entry.value_ptr.items);4497 try gop.value_ptr.ensureUnusedCapacity(gpa, entry.value_ptr.count());
4492 } else {4498 for (entry.value_ptr.keys()) |local_index| {
4493 gop.value_ptr.* = entry.value_ptr.*;4499 gop.value_ptr.putAssumeCapacityNoClobber(local_index, {});
4494 entry.value_ptr.* = .{};4500 }
4495 }4501 } else gop.value_ptr.* = entry.value_ptr.move();
4496 }4502 }
4497 deinitFreeLocalsMap(gpa, new_free_locals);4503 deinitFreeLocalsMap(gpa, new_free_locals);
4498 new_free_locals.* = old_free_locals.move();4504 new_free_locals.* = old_free_locals.move();
...@@ -4522,6 +4528,10 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4522,6 +4528,10 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue {
4522 // that we can notice and use them in the else branch. Any new locals must4528 // that we can notice and use them in the else branch. Any new locals must
4523 // necessarily be free already after the then branch is complete.4529 // necessarily be free already after the then branch is complete.
4524 const pre_locals_len = @intCast(LocalIndex, f.locals.items.len);4530 const pre_locals_len = @intCast(LocalIndex, f.locals.items.len);
4531 // Remember how many allocs there were before entering the then branch so
4532 // that we can notice and make sure not to use them in the else branch.
4533 // Any new allocs must be removed from the free list.
4534 const pre_allocs_len = @intCast(LocalIndex, f.allocs.count());
4525 const pre_clone_depth = f.free_locals_clone_depth;4535 const pre_clone_depth = f.free_locals_clone_depth;
4526 f.free_locals_clone_depth = @intCast(LoopDepth, f.free_locals_stack.items.len);4536 f.free_locals_clone_depth = @intCast(LoopDepth, f.free_locals_stack.items.len);
45274537
...@@ -4552,7 +4562,7 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4552,7 +4562,7 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue {
4552 try die(f, inst, Air.indexToRef(operand));4562 try die(f, inst, Air.indexToRef(operand));
4553 }4563 }
45544564
4555 try noticeBranchFrees(f, pre_locals_len, inst);4565 try noticeBranchFrees(f, pre_locals_len, pre_allocs_len, inst);
45564566
4557 if (needs_else) {4567 if (needs_else) {
4558 try genBody(f, else_body);4568 try genBody(f, else_body);
...@@ -4627,6 +4637,10 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4627,6 +4637,10 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
4627 // we can notice and use them in subsequent branches. Any new locals must4637 // we can notice and use them in subsequent branches. Any new locals must
4628 // necessarily be free already after the previous branch is complete.4638 // necessarily be free already after the previous branch is complete.
4629 const pre_locals_len = @intCast(LocalIndex, f.locals.items.len);4639 const pre_locals_len = @intCast(LocalIndex, f.locals.items.len);
4640 // Remember how many allocs there were before entering each branch so that
4641 // we can notice and make sure not to use them in subsequent branches.
4642 // Any new allocs must be removed from the free list.
4643 const pre_allocs_len = @intCast(LocalIndex, f.allocs.count());
4630 const pre_clone_depth = f.free_locals_clone_depth;4644 const pre_clone_depth = f.free_locals_clone_depth;
4631 f.free_locals_clone_depth = @intCast(LoopDepth, f.free_locals_stack.items.len);4645 f.free_locals_clone_depth = @intCast(LoopDepth, f.free_locals_stack.items.len);
46324646
...@@ -4647,7 +4661,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4647,7 +4661,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
4647 try genBody(f, case_body);4661 try genBody(f, case_body);
4648 }4662 }
46494663
4650 try noticeBranchFrees(f, pre_locals_len, inst);4664 try noticeBranchFrees(f, pre_locals_len, pre_allocs_len, inst);
4651 } else {4665 } else {
4652 for (liveness.deaths[case_i]) |operand| {4666 for (liveness.deaths[case_i]) |operand| {
4653 try die(f, inst, Air.indexToRef(operand));4667 try die(f, inst, Air.indexToRef(operand));
...@@ -7441,21 +7455,16 @@ fn freeLocal(f: *Function, inst: Air.Inst.Index, local_index: LocalIndex, ref_in...@@ -7441,21 +7455,16 @@ fn freeLocal(f: *Function, inst: Air.Inst.Index, local_index: LocalIndex, ref_in
7441 const local = &f.locals.items[local_index];7455 const local = &f.locals.items[local_index];
7442 log.debug("%{d}: freeing t{d} (operand %{d})", .{ inst, local_index, ref_inst });7456 log.debug("%{d}: freeing t{d} (operand %{d})", .{ inst, local_index, ref_inst });
7443 if (local.loop_depth < f.free_locals_clone_depth) return;7457 if (local.loop_depth < f.free_locals_clone_depth) return;
7444 const gop = try f.free_locals_stack.items[local.loop_depth].getOrPutContext(7458 const gop = try f.free_locals_stack.items[local.loop_depth].getOrPut(gpa, local.getType());
7445 gpa,
7446 local.ty,
7447 f.tyHashCtx(),
7448 );
7449 if (!gop.found_existing) gop.value_ptr.* = .{};7459 if (!gop.found_existing) gop.value_ptr.* = .{};
7450 if (std.debug.runtime_safety) {7460 if (std.debug.runtime_safety) {
7451 // If this trips, it means a local is being inserted into the
7452 // free_locals map while it already exists in the map, which is not
7453 // allowed.
7454 assert(mem.indexOfScalar(LocalIndex, gop.value_ptr.items, local_index) == null);
7455 // If this trips, an unfreeable allocation was attempted to be freed.7461 // If this trips, an unfreeable allocation was attempted to be freed.
7456 assert(!f.allocs.contains(local_index));7462 assert(!f.allocs.contains(local_index));
7457 }7463 }
7458 try gop.value_ptr.append(gpa, local_index);7464 // If this trips, it means a local is being inserted into the
7465 // free_locals map while it already exists in the map, which is not
7466 // allowed.
7467 try gop.value_ptr.putNoClobber(gpa, local_index, {});
7459}7468}
74607469
7461const BigTomb = struct {7470const BigTomb = struct {
...@@ -7504,14 +7513,36 @@ fn deinitFreeLocalsMap(gpa: mem.Allocator, map: *LocalsMap) void {...@@ -7504,14 +7513,36 @@ fn deinitFreeLocalsMap(gpa: mem.Allocator, map: *LocalsMap) void {
7504 map.deinit(gpa);7513 map.deinit(gpa);
7505}7514}
75067515
7507fn noticeBranchFrees(f: *Function, pre_locals_len: LocalIndex, inst: Air.Inst.Index) !void {7516fn noticeBranchFrees(
7517 f: *Function,
7518 pre_locals_len: LocalIndex,
7519 pre_allocs_len: LocalIndex,
7520 inst: Air.Inst.Index,
7521) !void {
7522 const free_locals = f.getFreeLocals();
7523
7508 for (f.locals.items[pre_locals_len..], pre_locals_len..) |*local, local_i| {7524 for (f.locals.items[pre_locals_len..], pre_locals_len..) |*local, local_i| {
7509 const local_index = @intCast(LocalIndex, local_i);7525 const local_index = @intCast(LocalIndex, local_i);
7510 if (f.allocs.contains(local_index)) continue; // allocs are not freeable7526 if (f.allocs.contains(local_index)) {
7527 if (std.debug.runtime_safety) {
7528 // new allocs are no longer freeable, so make sure they aren't in the free list
7529 if (free_locals.getPtr(local.getType())) |locals_list| {
7530 assert(!locals_list.contains(local_index));
7531 }
7532 }
7533 continue;
7534 }
75117535
7512 // free more deeply nested locals from other branches at current depth7536 // free more deeply nested locals from other branches at current depth
7513 assert(local.loop_depth >= f.free_locals_stack.items.len - 1);7537 assert(local.loop_depth >= f.free_locals_stack.items.len - 1);
7514 local.loop_depth = @intCast(LoopDepth, f.free_locals_stack.items.len - 1);7538 local.loop_depth = @intCast(LoopDepth, f.free_locals_stack.items.len - 1);
7515 try freeLocal(f, inst, local_index, 0);7539 try freeLocal(f, inst, local_index, 0);
7516 }7540 }
7541
7542 for (f.allocs.keys()[pre_allocs_len..]) |local_i| {
7543 const local_index = @intCast(LocalIndex, local_i);
7544 const local = &f.locals.items[local_index];
7545 // new allocs are no longer freeable, so remove them from the free list
7546 if (free_locals.getPtr(local.getType())) |locals_list| _ = locals_list.swapRemove(local_index);
7547 }
7517}7548}
src/codegen/c/type.zig+59-76
...@@ -251,38 +251,6 @@ pub const CType = extern union {...@@ -251,38 +251,6 @@ pub const CType = extern union {
251 type: Index,251 type: Index,
252 alignas: AlignAs,252 alignas: AlignAs,
253 };253 };
254 pub const AlignAs = struct {
255 @"align": std.math.Log2Int(u32),
256 abi: std.math.Log2Int(u32),
257
258 pub fn init(alignment: u32, abi_alignment: u32) AlignAs {
259 assert(std.math.isPowerOfTwo(alignment));
260 assert(std.math.isPowerOfTwo(abi_alignment));
261 return .{
262 .@"align" = std.math.log2_int(u32, alignment),
263 .abi = std.math.log2_int(u32, abi_alignment),
264 };
265 }
266 pub fn abiAlign(ty: Type, target: Target) AlignAs {
267 const abi_align = ty.abiAlignment(target);
268 return init(abi_align, abi_align);
269 }
270 pub fn fieldAlign(struct_ty: Type, field_i: usize, target: Target) AlignAs {
271 return init(
272 struct_ty.structFieldAlign(field_i, target),
273 struct_ty.structFieldType(field_i).abiAlignment(target),
274 );
275 }
276 pub fn unionPayloadAlign(union_ty: Type, target: Target) AlignAs {
277 const union_obj = union_ty.cast(Type.Payload.Union).?.data;
278 const union_payload_align = union_obj.abiAlignment(target, false);
279 return init(union_payload_align, union_payload_align);
280 }
281
282 pub fn getAlign(self: AlignAs) u32 {
283 return @as(u32, 1) << self.@"align";
284 }
285 };
286 };254 };
287255
288 pub const Unnamed = struct {256 pub const Unnamed = struct {
...@@ -311,13 +279,57 @@ pub const CType = extern union {...@@ -311,13 +279,57 @@ pub const CType = extern union {
311 };279 };
312 };280 };
313281
282 pub const AlignAs = struct {
283 @"align": std.math.Log2Int(u32),
284 abi: std.math.Log2Int(u32),
285
286 pub fn init(alignment: u32, abi_alignment: u32) AlignAs {
287 const actual_align = if (alignment != 0) alignment else abi_alignment;
288 assert(std.math.isPowerOfTwo(actual_align));
289 assert(std.math.isPowerOfTwo(abi_alignment));
290 return .{
291 .@"align" = std.math.log2_int(u32, actual_align),
292 .abi = std.math.log2_int(u32, abi_alignment),
293 };
294 }
295 pub fn abiAlign(ty: Type, target: Target) AlignAs {
296 const abi_align = ty.abiAlignment(target);
297 return init(abi_align, abi_align);
298 }
299 pub fn fieldAlign(struct_ty: Type, field_i: usize, target: Target) AlignAs {
300 return init(
301 struct_ty.structFieldAlign(field_i, target),
302 struct_ty.structFieldType(field_i).abiAlignment(target),
303 );
304 }
305 pub fn unionPayloadAlign(union_ty: Type, target: Target) AlignAs {
306 const union_obj = union_ty.cast(Type.Payload.Union).?.data;
307 const union_payload_align = union_obj.abiAlignment(target, false);
308 return init(union_payload_align, union_payload_align);
309 }
310
311 pub fn getAlign(self: AlignAs) u32 {
312 return @as(u32, 1) << self.@"align";
313 }
314 };
315
314 pub const Index = u32;316 pub const Index = u32;
315 pub const Store = struct {317 pub const Store = struct {
316 arena: std.heap.ArenaAllocator.State = .{},318 arena: std.heap.ArenaAllocator.State = .{},
317 set: Set = .{},319 set: Set = .{},
318320
319 pub const Set = struct {321 pub const Set = struct {
320 pub const Map = std.ArrayHashMapUnmanaged(CType, void, HashContext32, true);322 pub const Map = std.ArrayHashMapUnmanaged(CType, void, HashContext, true);
323 const HashContext = struct {
324 store: *const Set,
325
326 pub fn hash(self: @This(), cty: CType) Map.Hash {
327 return @truncate(Map.Hash, cty.hash(self.store.*));
328 }
329 pub fn eql(_: @This(), lhs: CType, rhs: CType, _: usize) bool {
330 return lhs.eql(rhs);
331 }
332 };
321333
322 map: Map = .{},334 map: Map = .{},
323335
...@@ -328,7 +340,7 @@ pub const CType = extern union {...@@ -328,7 +340,7 @@ pub const CType = extern union {
328340
329 pub fn indexToHash(self: Set, index: Index) Map.Hash {341 pub fn indexToHash(self: Set, index: Index) Map.Hash {
330 if (index < Tag.no_payload_count)342 if (index < Tag.no_payload_count)
331 return (HashContext32{ .store = &self }).hash(self.indexToCType(index));343 return (HashContext{ .store = &self }).hash(self.indexToCType(index));
332 return self.map.entries.items(.hash)[index - Tag.no_payload_count];344 return self.map.entries.items(.hash)[index - Tag.no_payload_count];
333 }345 }
334346
...@@ -905,7 +917,7 @@ pub const CType = extern union {...@@ -905,7 +917,7 @@ pub const CType = extern union {
905 self.storage.anon.fields[0] = .{917 self.storage.anon.fields[0] = .{
906 .name = "array",918 .name = "array",
907 .type = array_idx,919 .type = array_idx,
908 .alignas = Payload.Fields.AlignAs.abiAlign(ty, lookup.getTarget()),920 .alignas = AlignAs.abiAlign(ty, lookup.getTarget()),
909 };921 };
910 self.initAnon(kind, fwd_idx, 1);922 self.initAnon(kind, fwd_idx, 1);
911 } else self.init(switch (kind) {923 } else self.init(switch (kind) {
...@@ -1004,12 +1016,12 @@ pub const CType = extern union {...@@ -1004,12 +1016,12 @@ pub const CType = extern union {
1004 self.storage.anon.fields[0] = .{1016 self.storage.anon.fields[0] = .{
1005 .name = "ptr",1017 .name = "ptr",
1006 .type = ptr_idx,1018 .type = ptr_idx,
1007 .alignas = Payload.Fields.AlignAs.abiAlign(ptr_ty, target),1019 .alignas = AlignAs.abiAlign(ptr_ty, target),
1008 };1020 };
1009 self.storage.anon.fields[1] = .{1021 self.storage.anon.fields[1] = .{
1010 .name = "len",1022 .name = "len",
1011 .type = Tag.uintptr_t.toIndex(),1023 .type = Tag.uintptr_t.toIndex(),
1012 .alignas = Payload.Fields.AlignAs.abiAlign(Type.usize, target),1024 .alignas = AlignAs.abiAlign(Type.usize, target),
1013 };1025 };
1014 self.initAnon(kind, fwd_idx, 2);1026 self.initAnon(kind, fwd_idx, 2);
1015 } else self.init(switch (kind) {1027 } else self.init(switch (kind) {
...@@ -1125,7 +1137,7 @@ pub const CType = extern union {...@@ -1125,7 +1137,7 @@ pub const CType = extern union {
1125 self.storage.anon.fields[field_count] = .{1137 self.storage.anon.fields[field_count] = .{
1126 .name = "payload",1138 .name = "payload",
1127 .type = payload_idx.?,1139 .type = payload_idx.?,
1128 .alignas = Payload.Fields.AlignAs.unionPayloadAlign(ty, target),1140 .alignas = AlignAs.unionPayloadAlign(ty, target),
1129 };1141 };
1130 field_count += 1;1142 field_count += 1;
1131 }1143 }
...@@ -1133,7 +1145,7 @@ pub const CType = extern union {...@@ -1133,7 +1145,7 @@ pub const CType = extern union {
1133 self.storage.anon.fields[field_count] = .{1145 self.storage.anon.fields[field_count] = .{
1134 .name = "tag",1146 .name = "tag",
1135 .type = tag_idx.?,1147 .type = tag_idx.?,
1136 .alignas = Payload.Fields.AlignAs.abiAlign(tag_ty.?, target),1148 .alignas = AlignAs.abiAlign(tag_ty.?, target),
1137 };1149 };
1138 field_count += 1;1150 field_count += 1;
1139 }1151 }
...@@ -1158,11 +1170,7 @@ pub const CType = extern union {...@@ -1158,11 +1170,7 @@ pub const CType = extern union {
1158 const field_ty = ty.structFieldType(field_i);1170 const field_ty = ty.structFieldType(field_i);
1159 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;1171 if (!field_ty.hasRuntimeBitsIgnoreComptime()) continue;
11601172
1161 const field_align = Payload.Fields.AlignAs.fieldAlign(1173 const field_align = AlignAs.fieldAlign(ty, field_i, target);
1162 ty,
1163 field_i,
1164 target,
1165 );
1166 if (field_align.@"align" < field_align.abi) {1174 if (field_align.@"align" < field_align.abi) {
1167 is_packed = true;1175 is_packed = true;
1168 if (!lookup.isMutable()) break;1176 if (!lookup.isMutable()) break;
...@@ -1235,12 +1243,12 @@ pub const CType = extern union {...@@ -1235,12 +1243,12 @@ pub const CType = extern union {
1235 self.storage.anon.fields[0] = .{1243 self.storage.anon.fields[0] = .{
1236 .name = "payload",1244 .name = "payload",
1237 .type = payload_idx,1245 .type = payload_idx,
1238 .alignas = Payload.Fields.AlignAs.abiAlign(payload_ty, target),1246 .alignas = AlignAs.abiAlign(payload_ty, target),
1239 };1247 };
1240 self.storage.anon.fields[1] = .{1248 self.storage.anon.fields[1] = .{
1241 .name = "is_null",1249 .name = "is_null",
1242 .type = Tag.bool.toIndex(),1250 .type = Tag.bool.toIndex(),
1243 .alignas = Payload.Fields.AlignAs.abiAlign(Type.bool, target),1251 .alignas = AlignAs.abiAlign(Type.bool, target),
1244 };1252 };
1245 self.initAnon(kind, fwd_idx, 2);1253 self.initAnon(kind, fwd_idx, 2);
1246 } else self.init(switch (kind) {1254 } else self.init(switch (kind) {
...@@ -1273,12 +1281,12 @@ pub const CType = extern union {...@@ -1273,12 +1281,12 @@ pub const CType = extern union {
1273 self.storage.anon.fields[0] = .{1281 self.storage.anon.fields[0] = .{
1274 .name = "payload",1282 .name = "payload",
1275 .type = payload_idx,1283 .type = payload_idx,
1276 .alignas = Payload.Fields.AlignAs.abiAlign(payload_ty, target),1284 .alignas = AlignAs.abiAlign(payload_ty, target),
1277 };1285 };
1278 self.storage.anon.fields[1] = .{1286 self.storage.anon.fields[1] = .{
1279 .name = "error",1287 .name = "error",
1280 .type = error_idx,1288 .type = error_idx,
1281 .alignas = Payload.Fields.AlignAs.abiAlign(error_ty, target),1289 .alignas = AlignAs.abiAlign(error_ty, target),
1282 };1290 };
1283 self.initAnon(kind, fwd_idx, 2);1291 self.initAnon(kind, fwd_idx, 2);
1284 } else self.init(switch (kind) {1292 } else self.init(switch (kind) {
...@@ -1551,7 +1559,7 @@ pub const CType = extern union {...@@ -1551,7 +1559,7 @@ pub const CType = extern union {
1551 .complete, .parameter, .payload => .complete,1559 .complete, .parameter, .payload => .complete,
1552 .global => .global,1560 .global => .global,
1553 }).?,1561 }).?,
1554 .alignas = Payload.Fields.AlignAs.fieldAlign(ty, field_i, target),1562 .alignas = AlignAs.fieldAlign(ty, field_i, target),
1555 };1563 };
1556 }1564 }
15571565
...@@ -1635,28 +1643,6 @@ pub const CType = extern union {...@@ -1635,28 +1643,6 @@ pub const CType = extern union {
1635 }1643 }
1636 }1644 }
16371645
1638 pub const HashContext64 = struct {
1639 store: *const Store.Set,
1640
1641 pub fn hash(self: @This(), cty: CType) u64 {
1642 return cty.hash(self.store.*);
1643 }
1644 pub fn eql(_: @This(), lhs: CType, rhs: CType) bool {
1645 return lhs.eql(rhs);
1646 }
1647 };
1648
1649 pub const HashContext32 = struct {
1650 store: *const Store.Set,
1651
1652 pub fn hash(self: @This(), cty: CType) u32 {
1653 return @truncate(u32, cty.hash(self.store.*));
1654 }
1655 pub fn eql(_: @This(), lhs: CType, rhs: CType, _: usize) bool {
1656 return lhs.eql(rhs);
1657 }
1658 };
1659
1660 pub const TypeAdapter64 = struct {1646 pub const TypeAdapter64 = struct {
1661 kind: Kind,1647 kind: Kind,
1662 lookup: Convert.Lookup,1648 lookup: Convert.Lookup,
...@@ -1719,7 +1705,7 @@ pub const CType = extern union {...@@ -1719,7 +1705,7 @@ pub const CType = extern union {
1719 else => unreachable,1705 else => unreachable,
1720 },1706 },
1721 mem.span(c_field.name),1707 mem.span(c_field.name),
1722 ) or Payload.Fields.AlignAs.fieldAlign(ty, field_i, target).@"align" !=1708 ) or AlignAs.fieldAlign(ty, field_i, target).@"align" !=
1723 c_field.alignas.@"align") return false;1709 c_field.alignas.@"align") return false;
1724 }1710 }
1725 return true;1711 return true;
...@@ -1840,10 +1826,7 @@ pub const CType = extern union {...@@ -1840,10 +1826,7 @@ pub const CType = extern union {
1840 .Union => ty.unionFields().keys()[field_i],1826 .Union => ty.unionFields().keys()[field_i],
1841 else => unreachable,1827 else => unreachable,
1842 });1828 });
1843 autoHash(1829 autoHash(hasher, AlignAs.fieldAlign(ty, field_i, target).@"align");
1844 hasher,
1845 Payload.Fields.AlignAs.fieldAlign(ty, field_i, target).@"align",
1846 );
1847 }1830 }
1848 },1831 },
18491832
test/behavior/vector.zig+2
...@@ -1247,6 +1247,7 @@ test "load packed vector element" {...@@ -1247,6 +1247,7 @@ test "load packed vector element" {
1247 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1247 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1248 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1248 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1249 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1249 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1250 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
12501251
1251 var x: @Vector(2, u15) = .{ 1, 4 };1252 var x: @Vector(2, u15) = .{ 1, 4 };
1252 try expect((&x[0]).* == 1);1253 try expect((&x[0]).* == 1);
...@@ -1259,6 +1260,7 @@ test "store packed vector element" {...@@ -1259,6 +1260,7 @@ test "store packed vector element" {
1259 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1260 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1260 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1261 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1261 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1262 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1263 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
12621264
1263 var v = @Vector(4, u1){ 1, 1, 1, 1 };1265 var v = @Vector(4, u1){ 1, 1, 1, 1 };
1264 try expectEqual(@Vector(4, u1){ 1, 1, 1, 1 }, v);1266 try expectEqual(@Vector(4, u1){ 1, 1, 1, 1 }, v);