From 738a3d33608c831016a512460f62dbc9e74733c4 Mon Sep 17 00:00:00 2001 From: Matthew Lugg Date: Thu, 12 Feb 2026 12:30:21 +0000 Subject: [PATCH] compiler: get everything building Several backends are crashing right now. I'll need to fix at least the C backend before this branch is ready to PR. --- lib/std/zig/target.zig | 11 +- src/codegen/aarch64/Select.zig | 89 ++++++------- src/codegen/c.zig | 143 ++++++++------------- src/codegen/c/Type.zig | 59 ++++----- src/codegen/riscv64/CodeGen.zig | 53 ++++---- src/codegen/sparc64/CodeGen.zig | 22 ++-- src/codegen/spirv/CodeGen.zig | 115 ++++++++--------- src/codegen/wasm/CodeGen.zig | 219 +++++++++++--------------------- src/link/MachO/Atom.zig | 2 +- src/link/MachO/ZigObject.zig | 2 +- src/link/MachO/file.zig | 2 +- src/link/Wasm.zig | 4 +- src/link/Wasm/Flush.zig | 6 +- src/link/tapi/parse.zig | 2 +- 14 files changed, 300 insertions(+), 429 deletions(-) diff --git a/lib/std/zig/target.zig b/lib/std/zig/target.zig index d0331a160d..988686b8ab 100644 --- a/lib/std/zig/target.zig +++ b/lib/std/zig/target.zig @@ -518,10 +518,13 @@ pub fn intAlignment(target: *const std.Target, bits: u16) u16 { 33...64 => 8, else => 16, }, - else => return @min( - std.math.ceilPowerOfTwoPromote(u16, @as(u16, @intCast((@as(u17, bits) + 7) / 8))), - target.cMaxIntAlignment(), - ), + else => switch (bits) { + 0 => 1, + else => @min( + std.math.ceilPowerOfTwoPromote(u16, @intCast((@as(u17, bits) + 7) / 8)), + target.cMaxIntAlignment(), + ), + }, }; } diff --git a/src/codegen/aarch64/Select.zig b/src/codegen/aarch64/Select.zig index a95faca765..ba136872b1 100644 --- a/src/codegen/aarch64/Select.zig +++ b/src/codegen/aarch64/Select.zig @@ -2791,9 +2791,9 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, } else return isel.fail("invalid constraint: '{s}'", .{constraint}); } - const clobbers_val: Value = .fromInterned(unwrapped_asm.clobbers); + const clobbers_val: Constant = .fromInterned(unwrapped_asm.clobbers); const clobbers_ty = clobbers_val.typeOf(zcu); - var clobbers_bigint_buf: Value.BigIntSpace = undefined; + var clobbers_bigint_buf: Constant.BigIntSpace = undefined; const clobbers_bigint = clobbers_val.toBigInt(&clobbers_bigint_buf, zcu); for (0..clobbers_ty.structFieldCount(zcu)) |field_index| { assert(clobbers_ty.fieldType(field_index, zcu).toIntern() == .bool_type); @@ -2818,7 +2818,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, for (0..clobbers_ty.structFieldCount(zcu)) |field_index| { const limb_bits = @bitSizeOf(std.math.big.Limb); if (field_index / limb_bits >= clobbers_bigint.limbs.len) continue; // field is false - switch (@as(u1, @truncate(clobbers_bigint.limbs[field_index / limb_bits] >> field_index % limb_bits))) { + switch (@as(u1, @truncate(clobbers_bigint.limbs[field_index / limb_bits] >> @intCast(field_index % limb_bits)))) { 0 => continue, // field is false 1 => {}, // field is true } @@ -2871,7 +2871,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, for (0..clobbers_ty.structFieldCount(zcu)) |field_index| { const limb_bits = @bitSizeOf(std.math.big.Limb); if (field_index / limb_bits >= clobbers_bigint.limbs.len) continue; // field is false - switch (@as(u1, @truncate(clobbers_bigint.limbs[field_index / limb_bits] >> field_index % limb_bits))) { + switch (@as(u1, @truncate(clobbers_bigint.limbs[field_index / limb_bits] >> @intCast(field_index % limb_bits)))) { 0 => continue, // field is false 1 => {}, // field is true } @@ -3283,8 +3283,8 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, } else if (dst_ty.isSliceAtRuntime(zcu) and src_ty.isSliceAtRuntime(zcu)) { try dst_vi.value.move(isel, ty_op.operand); } else if (dst_tag == .error_union and src_tag == .error_union) { - assert(dst_ty.errorUnionSet(zcu).hasRuntimeBitsIgnoreComptime(zcu) == - src_ty.errorUnionSet(zcu).hasRuntimeBitsIgnoreComptime(zcu)); + assert(dst_ty.errorUnionSet(zcu).hasRuntimeBits(zcu) == + src_ty.errorUnionSet(zcu).hasRuntimeBits(zcu)); if (dst_ty.errorUnionPayload(zcu).toIntern() == src_ty.errorUnionPayload(zcu).toIntern()) { try dst_vi.value.move(isel, ty_op.operand); } else return isel.fail("bad {t} {f} {f}", .{ air_tag, isel.fmtType(dst_ty), isel.fmtType(src_ty) }); @@ -4562,7 +4562,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, } if (case.ranges.len == 0 and case.items.len == 1 and Constant.fromInterned( case.items[0].toInterned().?, - ).orderAgainstZero(zcu).compare(.eq)) { + ).compareHetero(.eq, .zero_comptime_int, zcu)) { try isel.emit(.cbnz( cond_reg, @intCast((isel.instructions.items.len + 1 - next_label) << 2), @@ -6893,11 +6893,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, var field_it = loaded_struct.iterateRuntimeOrder(ip); while (field_it.next()) |field_index| { const field_ty: ZigType = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); - field_offset = field_ty.structFieldAlignment( - loaded_struct.fieldAlign(ip, field_index), - loaded_struct.layout, - zcu, - ).forward(field_offset); + field_offset = loaded_struct.field_offsets.get(ip)[field_index]; const field_size = field_ty.abiSize(zcu); if (field_size == 0) continue; var agg_part_it = agg_vi.value.field(agg_ty, field_offset, field_size); @@ -6905,7 +6901,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, try agg_part_vi.?.move(isel, elems[field_index]); field_offset += field_size; } - assert(loaded_struct.flagsUnordered(ip).alignment.forward(field_offset) == agg_vi.value.size(isel)); + assert(loaded_struct.alignment.forward(field_offset) == agg_vi.value.size(isel)); }, .tuple_type => |tuple_type| { const elems: []const Air.Inst.Ref = @@ -6947,23 +6943,23 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, const union_layout = ZigType.getUnionLayout(loaded_union, zcu); if (union_layout.tag_size > 0) unused_tag: { - const loaded_tag = loaded_union.loadTagType(ip); + const loaded_tag = ip.loadEnumType(loaded_union.enum_tag_type); var tag_it = union_vi.value.field(union_ty, union_layout.tagOffset(), union_layout.tag_size); const tag_vi = try tag_it.only(isel); const tag_ra = try tag_vi.?.defReg(isel) orelse break :unused_tag; switch (union_layout.tag_size) { 0 => unreachable, - 1...4 => try isel.movImmediate(tag_ra.w(), @as(u32, switch (loaded_tag.values.len) { + 1...4 => try isel.movImmediate(tag_ra.w(), @as(u32, switch (loaded_tag.field_values.len) { 0 => extra.field_index, - else => switch (ip.indexToKey(loaded_tag.values.get(ip)[extra.field_index]).int.storage) { + else => switch (ip.indexToKey(loaded_tag.field_values.get(ip)[extra.field_index]).int.storage) { .u64 => |imm| @intCast(imm), .i64 => |imm| @bitCast(@as(i32, @intCast(imm))), else => unreachable, }, })), - 5...8 => try isel.movImmediate(tag_ra.x(), switch (loaded_tag.values.len) { + 5...8 => try isel.movImmediate(tag_ra.x(), switch (loaded_tag.field_values.len) { 0 => extra.field_index, - else => switch (ip.indexToKey(loaded_tag.values.get(ip)[extra.field_index]).int.storage) { + else => switch (ip.indexToKey(loaded_tag.field_values.get(ip)[extra.field_index]).int.storage) { .u64 => |imm| imm, .i64 => |imm| @bitCast(imm), else => unreachable, @@ -10391,7 +10387,7 @@ pub const Value = struct { switch (loaded_struct.layout) { .auto, .@"extern" => {}, .@"packed" => continue :type_key .{ - .int_type = ip.indexToKey(loaded_struct.backingIntTypeUnordered(ip)).int_type, + .int_type = ip.indexToKey(loaded_struct.packed_backing_int_type).int_type, }, } const min_part_log2_stride: u5 = if (size > 16) 4 else if (size > 8) 3 else 0; @@ -10406,7 +10402,7 @@ pub const Value = struct { var field_it = loaded_struct.iterateRuntimeOrder(ip); while (field_it.next()) |field_index| { const field_ty: ZigType = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); - const field_begin = switch (loaded_struct.fieldAlign(ip, field_index)) { + const field_begin = switch (loaded_struct.field_aligns.getOrNone(ip, field_index)) { .none => field_ty.abiAlignment(zcu), else => |field_align| field_align, }.forward(field_end); @@ -10504,7 +10500,7 @@ pub const Value = struct { }, .union_type => { const loaded_union = ip.loadUnionType(ty.toIntern()); - switch (loaded_union.flagsUnordered(ip).layout) { + switch (loaded_union.layout) { .auto, .@"extern" => {}, .@"packed" => continue :type_key .{ .int_type = .{ .signedness = .unsigned, @@ -10539,12 +10535,13 @@ pub const Value = struct { const field_signedness = field_signedness: switch (field) { .tag => { if (offset >= field_begin and offset + size <= field_begin + field_size) { - ty = .fromInterned(loaded_union.enum_tag_ty); + ty = .fromInterned(loaded_union.enum_tag_type); ty_size = field_size; offset -= field_begin; - continue :type_key ip.indexToKey(loaded_union.enum_tag_ty); + continue :type_key ip.indexToKey(loaded_union.enum_tag_type); } - break :field_signedness ip.indexToKey(loaded_union.loadTagType(ip).tag_ty).int_type.signedness; + const loaded_enum = ip.loadEnumType(loaded_union.enum_tag_type); + break :field_signedness ip.indexToKey(loaded_enum.int_tag_type).int_type.signedness; }, .payload => null, }; @@ -10574,7 +10571,7 @@ pub const Value = struct { } }, .opaque_type, .func_type => continue :type_key .{ .simple_type = .anyopaque }, - .enum_type => continue :type_key ip.indexToKey(ip.loadEnumType(ty.toIntern()).tag_ty), + .enum_type => continue :type_key ip.indexToKey(ip.loadEnumType(ty.toIntern()).int_tag_type), .error_set_type, .inferred_error_set_type, => continue :type_key .{ .simple_type = .anyerror }, @@ -10740,7 +10737,7 @@ pub const Value = struct { .storage = .{ .u64 = 0 }, } }, }, - .int => |int| break :free storage: switch (int.storage) { + .int => |int| break :free switch (int.storage) { .u64 => |imm| try isel.movImmediate(switch (size) { else => unreachable, 1...4 => mat.ra.w(), @@ -10772,12 +10769,6 @@ pub const Value = struct { } try isel.movImmediate(mat.ra.x(), imm); }, - .lazy_align => |ty| continue :storage .{ - .u64 = ZigType.fromInterned(ty).abiAlignment(zcu).toByteUnits().?, - }, - .lazy_size => |ty| continue :storage .{ - .u64 = ZigType.fromInterned(ty).abiSize(zcu), - }, }, .err => |err| continue :constant_key .{ .int = .{ .ty = err.ty, @@ -11084,13 +11075,9 @@ pub const Value = struct { var field_offset: u64 = 0; var field_it = loaded_struct.iterateRuntimeOrder(ip); while (field_it.next()) |field_index| { - if (loaded_struct.fieldIsComptime(ip, field_index)) continue; + if (loaded_struct.field_is_comptime_bits.get(ip, field_index)) continue; const field_ty: ZigType = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); - field_offset = field_ty.structFieldAlignment( - loaded_struct.fieldAlign(ip, field_index), - loaded_struct.layout, - zcu, - ).forward(field_offset); + field_offset = loaded_struct.field_offsets.get(ip)[field_index]; const field_size = field_ty.abiSize(zcu); if (offset >= field_offset and offset + size <= field_offset + field_size) { offset -= field_offset; @@ -11132,7 +11119,7 @@ pub const Value = struct { .un => |un| { const loaded_union = ip.loadUnionType(un.ty); const union_layout = ZigType.getUnionLayout(loaded_union, zcu); - if (loaded_union.hasTag(ip)) { + if (loaded_union.has_runtime_tag) { const tag_offset = union_layout.tagOffset(); if (offset >= tag_offset and offset + size <= tag_offset + union_layout.tag_size) { offset -= tag_offset; @@ -11477,13 +11464,9 @@ fn writeKeyToMemory(isel: *Select, constant_key: InternPool.Key, buffer: []u8) e var field_offset: u64 = 0; var field_it = loaded_struct.iterateRuntimeOrder(ip); while (field_it.next()) |field_index| { - if (loaded_struct.fieldIsComptime(ip, field_index)) continue; + if (loaded_struct.field_is_comptime_bits.get(ip, field_index)) continue; const field_ty: ZigType = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); - field_offset = field_ty.structFieldAlignment( - loaded_struct.fieldAlign(ip, field_index), - loaded_struct.layout, - zcu, - ).forward(field_offset); + field_offset = loaded_struct.field_offsets.get(ip)[field_index]; const field_size = field_ty.abiSize(zcu); if (!try isel.writeToMemory(.fromInterned(switch (aggregate.storage) { .bytes => unreachable, @@ -12082,7 +12065,7 @@ pub const CallAbiIterator = struct { const zcu = isel.pt.zcu; const ip = &zcu.intern_pool; - if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) return null; + if (!ty.hasRuntimeBits(zcu)) return null; try isel.values.ensureUnusedCapacity(zcu.gpa, Value.max_parts); const wip_vi = isel.initValue(ty); type_key: switch (ip.indexToKey(ty.toIntern())) { @@ -12186,7 +12169,7 @@ pub const CallAbiIterator = struct { switch (loaded_struct.layout) { .auto, .@"extern" => {}, .@"packed" => continue :type_key .{ - .int_type = ip.indexToKey(loaded_struct.backingIntTypeUnordered(ip)).int_type, + .int_type = ip.indexToKey(loaded_struct.packed_backing_int_type).int_type, }, } const size = wip_vi.size(isel); @@ -12210,7 +12193,7 @@ pub const CallAbiIterator = struct { const field_end = next_field_end; const next_field_begin = if (field_it.next()) |field_index| next_field_begin: { const field_ty: ZigType = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); - const next_field_begin = switch (loaded_struct.fieldAlign(ip, field_index)) { + const next_field_begin = switch (loaded_struct.field_aligns.getOrNone(ip, field_index)) { .none => field_ty.abiAlignment(zcu), else => |field_align| field_align, }.forward(field_end); @@ -12276,7 +12259,7 @@ pub const CallAbiIterator = struct { }, .union_type => { const loaded_union = ip.loadUnionType(ty.toIntern()); - switch (loaded_union.flagsUnordered(ip).layout) { + switch (loaded_union.layout) { .auto, .@"extern" => {}, .@"packed" => continue :type_key .{ .int_type = .{ .signedness = .unsigned, @@ -12309,7 +12292,9 @@ pub const CallAbiIterator = struct { } }, .opaque_type, .func_type => continue :type_key .{ .simple_type = .anyopaque }, - .enum_type => continue :type_key ip.indexToKey(ip.loadEnumType(ty.toIntern()).tag_ty), + .enum_type => continue :type_key .{ + .int_type = ip.indexToKey(ip.loadEnumType(ty.toIntern()).int_tag_type).int_type, + }, .error_set_type, .inferred_error_set_type, => continue :type_key .{ .simple_type = .anyerror }, @@ -12414,8 +12399,8 @@ pub const CallAbiIterator = struct { const ip = &zcu.intern_pool; var common_fdt: ?FundamentalDataType = null; for (0.., loaded_struct.field_types.get(ip)) |field_index, field_ty| { - if (loaded_struct.fieldIsComptime(ip, field_index)) continue; - if (loaded_struct.fieldAlign(ip, field_index) != .none) return null; + if (loaded_struct.field_is_comptime_bits.get(ip, field_index)) continue; + if (loaded_struct.field_aligns.getOrNone(ip, field_index) != .none) return null; if (!ZigType.fromInterned(field_ty).hasRuntimeBits(zcu)) continue; const fdt = homogeneousAggregateBaseType(zcu, field_ty); if (common_fdt == null) common_fdt = fdt else if (fdt != common_fdt) return null; diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 879dc0e45a..c8904405e2 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -1052,17 +1052,7 @@ pub const DeclGen = struct { .func, .enum_literal, => unreachable, // non-runtime values - .int => |int| switch (int.storage) { - .u64, .i64, .big_int => try w.print("{f}", .{try dg.fmtIntLiteralDec(val, location)}), - .lazy_align, .lazy_size => { - try w.writeAll("(("); - try dg.renderCType(w, ctype); - try w.print("){f})", .{try dg.fmtIntLiteralHex( - try pt.intValue(.usize, val.toUnsignedInt(zcu)), - .Other, - )}); - }, - }, + .int => try w.print("{f}", .{try dg.fmtIntLiteralDec(val, location)}), .err => |err| try dg.renderErrorName(w, err.name), .error_union => |error_union| switch (ctype.info(ctype_pool)) { .basic => switch (error_union.val) { @@ -1338,7 +1328,7 @@ pub const DeclGen = struct { const comptime_val = tuple.values.get(ip)[field_index]; if (comptime_val != .none) continue; const field_ty: Type = .fromInterned(tuple.types.get(ip)[field_index]); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!field_ty.hasRuntimeBits(zcu)) continue; if (!empty) try w.writeByte(','); @@ -1373,7 +1363,7 @@ pub const DeclGen = struct { var need_comma = false; while (field_it.next()) |field_index| { const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!field_ty.hasRuntimeBits(zcu)) continue; if (need_comma) try w.writeByte(','); need_comma = true; @@ -1396,7 +1386,7 @@ pub const DeclGen = struct { const loaded_union = ip.loadUnionType(ty.toIntern()); if (un.tag == .none) { const backing_ty = try ty.externUnionBackingType(pt); - assert(loaded_union.flagsUnordered(ip).layout == .@"extern"); + assert(loaded_union.layout == .@"extern"); if (location == .StaticInitializer) { return dg.fail("TODO: C backend: implement extern union backing type rendering in static initializers", .{}); } @@ -1418,9 +1408,9 @@ pub const DeclGen = struct { const field_index = zcu.unionTagFieldIndex(loaded_union, Value.fromInterned(un.tag)).?; const field_ty: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); - const field_name = loaded_union.loadTagType(ip).names.get(ip)[field_index]; + const field_name = ip.loadEnumType(loaded_union.enum_tag_type).field_names.get(ip)[field_index]; - const has_tag = loaded_union.hasTag(ip); + const has_tag = loaded_union.has_runtime_tag; if (has_tag) try w.writeByte('{'); const aggregate = ctype.info(ctype_pool).aggregate; for (0..if (has_tag) aggregate.fields.len else 1) |outer_field_index| { @@ -1597,7 +1587,7 @@ pub const DeclGen = struct { var need_comma = false; while (field_it.next()) |field_index| { const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!field_ty.hasRuntimeBits(zcu)) continue; if (need_comma) try w.writeByte(','); need_comma = true; @@ -1620,7 +1610,7 @@ pub const DeclGen = struct { for (0..tuple_info.types.len) |field_index| { if (tuple_info.values.get(ip)[field_index] != .none) continue; const field_ty: Type = .fromInterned(tuple_info.types.get(ip)[field_index]); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!field_ty.hasRuntimeBits(zcu)) continue; if (need_comma) try w.writeByte(','); need_comma = true; @@ -1630,7 +1620,7 @@ pub const DeclGen = struct { }, .union_type => { const loaded_union = ip.loadUnionType(ty.toIntern()); - switch (loaded_union.flagsUnordered(ip).layout) { + switch (loaded_union.layout) { .auto, .@"extern" => { if (!location.isInitializer()) { try w.writeByte('('); @@ -1638,7 +1628,7 @@ pub const DeclGen = struct { try w.writeByte(')'); } - const has_tag = loaded_union.hasTag(ip); + const has_tag = loaded_union.has_runtime_tag; if (has_tag) try w.writeByte('{'); const aggregate = ctype.info(ctype_pool).aggregate; for (0..if (has_tag) aggregate.fields.len else 1) |outer_field_index| { @@ -1649,7 +1639,7 @@ pub const DeclGen = struct { .payload) { .tag => try dg.renderUndefValue( w, - .fromInterned(loaded_union.enum_tag_ty), + .fromInterned(loaded_union.enum_tag_type), initializer_type, ), .payload => { @@ -1760,6 +1750,7 @@ pub const DeclGen = struct { .opt, .aggregate, .un, + .bitpack, .memoized_call, => unreachable, // values, not types }, @@ -2797,7 +2788,7 @@ pub fn genLazyFn(o: *Object, lazy_ctype_pool: *const CType.Pool, lazy_fn: LazyFn } }); try w.print("case {f}: {{", .{ - try o.dg.fmtIntLiteralDec(try tag_val.intFromEnum(enum_ty, pt), .Other), + try o.dg.fmtIntLiteralDec(tag_val.intFromEnum(zcu), .Other), }); o.indent(); try o.newline(); @@ -3599,10 +3590,7 @@ fn airPtrElemVal(f: *Function, inst: Air.Inst.Index) !CValue { const zcu = f.object.dg.pt.zcu; const inst_ty = f.typeOfIndex(inst); const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; - if (!inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) { - try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); - return .none; - } + assert(inst_ty.hasRuntimeBits(zcu)); const ptr = try f.resolveInst(bin_op.lhs); const index = try f.resolveInst(bin_op.rhs); @@ -3629,7 +3617,7 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { const inst_ty = f.typeOfIndex(inst); const ptr_ty = f.typeOf(bin_op.lhs); - const elem_has_bits = ptr_ty.indexableElem(zcu).hasRuntimeBitsIgnoreComptime(zcu); + assert(ptr_ty.indexableElem(zcu).hasRuntimeBits(zcu)); const ptr = try f.resolveInst(bin_op.lhs); const index = try f.resolveInst(bin_op.rhs); @@ -3643,16 +3631,14 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { try w.writeByte('('); try f.renderType(w, inst_ty); try w.writeByte(')'); - if (elem_has_bits) try w.writeByte('&'); - if (elem_has_bits and ptr_ty.ptrSize(zcu) == .one) { + try w.writeByte('&'); + if (ptr_ty.ptrSize(zcu) == .one) { // It's a pointer to an array, so we need to de-reference. try f.writeCValueDeref(w, ptr); } else try f.writeCValue(w, ptr, .Other); - if (elem_has_bits) { - try w.writeByte('['); - try f.writeCValue(w, index, .Other); - try w.writeByte(']'); - } + try w.writeByte('['); + try f.writeCValue(w, index, .Other); + try w.writeByte(']'); try a.end(f, w); return local; } @@ -3661,10 +3647,7 @@ fn airSliceElemVal(f: *Function, inst: Air.Inst.Index) !CValue { const zcu = f.object.dg.pt.zcu; const inst_ty = f.typeOfIndex(inst); const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; - if (!inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) { - try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); - return .none; - } + assert(inst_ty.hasRuntimeBits(zcu)); const slice = try f.resolveInst(bin_op.lhs); const index = try f.resolveInst(bin_op.rhs); @@ -3692,7 +3675,7 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { const inst_ty = f.typeOfIndex(inst); const slice_ty = f.typeOf(bin_op.lhs); const elem_ty = slice_ty.childType(zcu); - const elem_has_bits = elem_ty.hasRuntimeBitsIgnoreComptime(zcu); + assert(elem_ty.hasRuntimeBits(zcu)); const slice = try f.resolveInst(bin_op.lhs); const index = try f.resolveInst(bin_op.rhs); @@ -3703,13 +3686,11 @@ fn airSliceElemPtr(f: *Function, inst: Air.Inst.Index) !CValue { const a = try Assignment.start(f, w, try f.ctypeFromType(inst_ty, .complete)); try f.writeCValue(w, local, .Other); try a.assign(f, w); - if (elem_has_bits) try w.writeByte('&'); + try w.writeByte('&'); try f.writeCValueMember(w, slice, .{ .identifier = "ptr" }); - if (elem_has_bits) { - try w.writeByte('['); - try f.writeCValue(w, index, .Other); - try w.writeByte(']'); - } + try w.writeByte('['); + try f.writeCValue(w, index, .Other); + try w.writeByte(']'); try a.end(f, w); return local; } @@ -3718,10 +3699,7 @@ fn airArrayElemVal(f: *Function, inst: Air.Inst.Index) !CValue { const zcu = f.object.dg.pt.zcu; const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const inst_ty = f.typeOfIndex(inst); - if (!inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) { - try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); - return .none; - } + assert(inst_ty.hasRuntimeBits(zcu)); const array = try f.resolveInst(bin_op.lhs); const index = try f.resolveInst(bin_op.rhs); @@ -3853,10 +3831,7 @@ fn airLoad(f: *Function, inst: Air.Inst.Index) !CValue { // bit-pointers we see here are vector element pointers. assert(ptr_info.packed_offset.host_size == 0 or ptr_info.flags.vector_index != .none); - if (!src_ty.hasRuntimeBitsIgnoreComptime(zcu)) { - try reap(f, inst, &.{ty_op.operand}); - return .none; - } + assert(src_ty.hasRuntimeBits(zcu)); const operand = try f.resolveInst(ty_op.operand); @@ -4456,7 +4431,7 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue { const inst_ty = f.typeOfIndex(inst); const inst_scalar_ty = inst_ty.scalarType(zcu); const elem_ty = inst_scalar_ty.indexableElem(zcu); - if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) return f.moveCValue(inst, inst_ty, lhs); + assert(elem_ty.hasRuntimeBits(zcu)); const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete); const local = try f.allocLocal(inst, inst_ty); @@ -4787,7 +4762,7 @@ fn lowerBlock(f: *Function, inst: Air.Inst.Index, body: []const Air.Inst.Index) const w = &f.object.code.writer; const inst_ty = f.typeOfIndex(inst); - const result = if (inst_ty.hasRuntimeBitsIgnoreComptime(zcu) and !f.liveness.isUnused(inst)) + const result = if (inst_ty.hasRuntimeBits(zcu) and !f.liveness.isUnused(inst)) try f.allocLocal(inst, inst_ty) else .none; @@ -4853,7 +4828,7 @@ fn lowerTry( const liveness_condbr = f.liveness.getCondBr(inst); const w = &f.object.code.writer; const payload_ty = err_union_ty.errorUnionPayload(zcu); - const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(zcu); + const payload_has_bits = payload_ty.hasRuntimeBits(zcu); if (!err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) { try w.writeAll("if ("); @@ -5393,7 +5368,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { const result = result: { const w = &f.object.code.writer; const inst_ty = f.typeOfIndex(inst); - const inst_local = if (inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) local: { + const inst_local = if (inst_ty.hasRuntimeBits(zcu)) local: { const inst_local = try f.allocLocalValue(.{ .ctype = try f.ctypeFromType(inst_ty, .complete), .alignas = CType.AlignAs.fromAbiAlignment(inst_ty.abiAlignment(zcu)), @@ -5820,12 +5795,12 @@ fn fieldLocation( .struct_type => { const loaded_struct = ip.loadStructType(container_ty.toIntern()); return switch (loaded_struct.layout) { - .auto, .@"extern" => if (!container_ty.hasRuntimeBitsIgnoreComptime(zcu)) + .auto, .@"extern" => if (!container_ty.hasRuntimeBits(zcu)) .begin - else if (!field_ptr_ty.childType(zcu).hasRuntimeBitsIgnoreComptime(zcu)) - .{ .byte_offset = loaded_struct.offsets.get(ip)[field_index] } + else if (!field_ptr_ty.childType(zcu).hasRuntimeBits(zcu)) + .{ .byte_offset = loaded_struct.field_offsets.get(ip)[field_index] } else - .{ .field = .{ .identifier = loaded_struct.fieldName(ip, field_index).toSlice(ip) } }, + .{ .field = .{ .identifier = loaded_struct.field_names.get(ip)[field_index].toSlice(ip) } }, .@"packed" => if (field_ptr_ty.ptrInfo(zcu).packed_offset.host_size == 0) .{ .byte_offset = @divExact(zcu.structPackedFieldBitOffset(loaded_struct, field_index) + container_ptr_ty.ptrInfo(zcu).packed_offset.bit_offset, 8) } @@ -5833,24 +5808,24 @@ fn fieldLocation( .begin, }; }, - .tuple_type => return if (!container_ty.hasRuntimeBitsIgnoreComptime(zcu)) + .tuple_type => return if (!container_ty.hasRuntimeBits(zcu)) .begin - else if (!field_ptr_ty.childType(zcu).hasRuntimeBitsIgnoreComptime(zcu)) + else if (!field_ptr_ty.childType(zcu).hasRuntimeBits(zcu)) .{ .byte_offset = container_ty.structFieldOffset(field_index, zcu) } else .{ .field = .{ .field = field_index } }, .union_type => { const loaded_union = ip.loadUnionType(container_ty.toIntern()); - switch (loaded_union.flagsUnordered(ip).layout) { + switch (loaded_union.layout) { .auto, .@"extern" => { const field_ty: Type = .fromInterned(loaded_union.field_types.get(ip)[field_index]); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) + if (!field_ty.hasRuntimeBits(zcu)) return if (loaded_union.has_runtime_tag and !container_ty.unionHasAllZeroBitFieldTypes(zcu)) .{ .field = .{ .identifier = "payload" } } else .begin; - const field_name = loaded_union.loadTagType(ip).names.get(ip)[field_index]; - return .{ .field = if (loaded_union.hasTag(ip)) + const field_name = ip.loadEnumType(loaded_union.enum_tag_type).field_names.get(ip)[field_index]; + return .{ .field = if (loaded_union.has_runtime_tag) .{ .payload_identifier = field_name.toSlice(ip) } else .{ .identifier = field_name.toSlice(ip) } }; @@ -5996,10 +5971,7 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { const extra = f.air.extraData(Air.StructField, ty_pl.payload).data; const inst_ty = f.typeOfIndex(inst); - if (!inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) { - try reap(f, inst, &.{extra.struct_operand}); - return .none; - } + assert(inst_ty.hasRuntimeBits(zcu)); const struct_byval = try f.resolveInst(extra.struct_operand); try reap(f, inst, &.{extra.struct_operand}); @@ -6014,9 +5986,9 @@ fn airStructFieldVal(f: *Function, inst: Air.Inst.Index) !CValue { .struct_type => .{ .identifier = struct_ty.structFieldName(extra.field_index, zcu).unwrap().?.toSlice(ip) }, .union_type => name: { const union_type = ip.loadUnionType(struct_ty.toIntern()); - const enum_tag_ty: Type = .fromInterned(union_type.enum_tag_ty); + const enum_tag_ty: Type = .fromInterned(union_type.enum_tag_type); const field_name_str = enum_tag_ty.enumFieldName(extra.field_index, zcu).toSlice(ip); - if (union_type.hasTag(ip)) { + if (union_type.has_runtime_tag) { break :name .{ .payload_identifier = field_name_str }; } else { break :name .{ .identifier = field_name_str }; @@ -6161,7 +6133,7 @@ fn airWrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue { const inst_ty = f.typeOfIndex(inst); const payload_ty = inst_ty.errorUnionPayload(zcu); - const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(zcu); + const repr_is_err = !payload_ty.hasRuntimeBits(zcu); const err_ty = inst_ty.errorUnionSet(zcu); const err = try f.resolveInst(ty_op.operand); try reap(f, inst, &.{ty_op.operand}); @@ -6210,7 +6182,7 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { try reap(f, inst, &.{ty_op.operand}); // First, set the non-error value. - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_ty.hasRuntimeBits(zcu)) { const a = try Assignment.start(f, w, try f.ctypeFromType(operand_ty, .complete)); try f.writeCValueDeref(w, operand); try a.assign(f, w); @@ -6262,13 +6234,13 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { const inst_ty = f.typeOfIndex(inst); const payload_ty = inst_ty.errorUnionPayload(zcu); const payload = try f.resolveInst(ty_op.operand); - const repr_is_err = !payload_ty.hasRuntimeBitsIgnoreComptime(zcu); + assert(payload_ty.hasRuntimeBits(zcu)); const err_ty = inst_ty.errorUnionSet(zcu); try reap(f, inst, &.{ty_op.operand}); const w = &f.object.code.writer; const local = try f.allocLocal(inst, inst_ty); - if (!repr_is_err) { + { const a = try Assignment.start(f, w, try f.ctypeFromType(payload_ty, .complete)); try f.writeCValueMember(w, local, .{ .identifier = "payload" }); try a.assign(f, w); @@ -6277,10 +6249,7 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { } { const a = try Assignment.start(f, w, try f.ctypeFromType(err_ty, .complete)); - if (repr_is_err) - try f.writeCValue(w, local, .Other) - else - try f.writeCValueMember(w, local, .{ .identifier = "error" }); + try f.writeCValueMember(w, local, .{ .identifier = "error" }); try a.assign(f, w); try f.object.dg.renderValue(w, try pt.intValue(try pt.errorIntType(), 0), .Other); try a.end(f, w); @@ -7411,10 +7380,10 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { var field_it = loaded_struct.iterateRuntimeOrder(ip); while (field_it.next()) |field_index| { const field_ty: Type = .fromInterned(loaded_struct.field_types.get(ip)[field_index]); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!field_ty.hasRuntimeBits(zcu)) continue; const a = try Assignment.start(f, w, try f.ctypeFromType(field_ty, .complete)); - try f.writeCValueMember(w, local, .{ .identifier = loaded_struct.fieldName(ip, field_index).toSlice(ip) }); + try f.writeCValueMember(w, local, .{ .identifier = loaded_struct.field_names.get(ip)[field_index].toSlice(ip) }); try a.assign(f, w); try f.writeCValue(w, resolved_elements[field_index], .Other); try a.end(f, w); @@ -7426,7 +7395,7 @@ fn airAggregateInit(f: *Function, inst: Air.Inst.Index) !CValue { .tuple_type => |tuple_info| for (0..tuple_info.types.len) |field_index| { if (tuple_info.values.get(ip)[field_index] != .none) continue; const field_ty: Type = .fromInterned(tuple_info.types.get(ip)[field_index]); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!field_ty.hasRuntimeBits(zcu)) continue; const a = try Assignment.start(f, w, try f.ctypeFromType(field_ty, .complete)); try f.writeCValueMember(w, local, .{ .field = field_index }); @@ -7449,13 +7418,13 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { const union_ty = f.typeOfIndex(inst); const loaded_union = ip.loadUnionType(union_ty.toIntern()); - const field_name = loaded_union.loadTagType(ip).names.get(ip)[extra.field_index]; + const field_name = ip.loadEnumType(loaded_union.enum_tag_type).field_names.get(ip)[extra.field_index]; const payload_ty = f.typeOf(extra.init); const payload = try f.resolveInst(extra.init); try reap(f, inst, &.{extra.init}); const w = &f.object.code.writer; - if (loaded_union.flagsUnordered(ip).layout == .@"packed") return f.moveCValue(inst, union_ty, payload); + if (loaded_union.layout == .@"packed") return f.moveCValue(inst, union_ty, payload); const local = try f.allocLocal(inst, union_ty); @@ -7466,7 +7435,7 @@ fn airUnionInit(f: *Function, inst: Air.Inst.Index) !CValue { const a = try Assignment.start(f, w, try f.ctypeFromType(tag_ty, .complete)); try f.writeCValueMember(w, local, .{ .identifier = "tag" }); try a.assign(f, w); - try w.print("{f}", .{try f.fmtIntLiteralDec(try tag_val.intFromEnum(tag_ty, pt))}); + try w.print("{f}", .{try f.fmtIntLiteralDec(tag_val.intFromEnum(zcu))}); try a.end(f, w); break :field .{ .payload_identifier = field_name.toSlice(ip) }; } else .{ .identifier = field_name.toSlice(ip) }; diff --git a/src/codegen/c/Type.zig b/src/codegen/c/Type.zig index f28dd48a17..a7442a1d49 100644 --- a/src/codegen/c/Type.zig +++ b/src/codegen/c/Type.zig @@ -2558,7 +2558,7 @@ pub const Pool = struct { .tag = .@"struct", .name = .{ .index = ip_index }, }); - if (kind.isForward()) return if (ty.hasRuntimeBitsIgnoreComptime(zcu)) + if (kind.isForward()) return if (ty.hasRuntimeBits(zcu)) fwd_decl else .void; @@ -2584,9 +2584,9 @@ pub const Pool = struct { kind.noParameter(), ); if (field_ctype.index == .void) continue; - const field_name = try pool.string(allocator, loaded_struct.fieldName(ip, field_index).toSlice(ip)); + const field_name = try pool.string(allocator, loaded_struct.field_names.get(ip)[field_index].toSlice(ip)); const field_alignas = AlignAs.fromAlignment(.{ - .@"align" = loaded_struct.fieldAlign(ip, field_index), + .@"align" = loaded_struct.field_aligns.getOrNone(ip, field_index), .abi = field_type.abiAlignment(zcu), }); pool.addHashedExtraAssumeCapacityTo(scratch, &hasher, Field, .{ @@ -2613,7 +2613,7 @@ pub const Pool = struct { .@"packed" => return pool.fromType( allocator, scratch, - Type.fromInterned(loaded_struct.backingIntTypeUnordered(ip)), + .fromInterned(loaded_struct.packed_backing_int_type), pt, mod, kind, @@ -2682,17 +2682,17 @@ pub const Pool = struct { }, .union_type => { const loaded_union = ip.loadUnionType(ip_index); - switch (loaded_union.flagsUnordered(ip).layout) { + switch (loaded_union.layout) { .auto, .@"extern" => { const fwd_decl = try pool.getFwdDecl(allocator, .{ .tag = if (loaded_union.has_runtime_tag) .@"struct" else .@"union", .name = .{ .index = ip_index }, }); - if (kind.isForward()) return if (ty.hasRuntimeBitsIgnoreComptime(zcu)) + if (kind.isForward()) return if (ty.hasRuntimeBits(zcu)) fwd_decl else .void; - const loaded_tag = loaded_union.loadTagType(ip); + const loaded_tag = ip.loadEnumType(loaded_union.enum_tag_type); const scratch_top = scratch.items.len; defer scratch.shrinkRetainingCapacity(scratch_top); try scratch.ensureUnusedCapacity( @@ -2718,10 +2718,10 @@ pub const Pool = struct { if (field_ctype.index == .void) continue; const field_name = try pool.string( allocator, - loaded_tag.names.get(ip)[field_index].toSlice(ip), + loaded_tag.field_names.get(ip)[field_index].toSlice(ip), ); const field_alignas = AlignAs.fromAlignment(.{ - .@"align" = loaded_union.fieldAlign(ip, field_index), + .@"align" = loaded_union.field_aligns.getOrNone(ip, field_index), .abi = field_type.abiAlignment(zcu), }); pool.addHashedExtraAssumeCapacityTo(scratch, &hasher, Field, .{ @@ -2753,24 +2753,22 @@ pub const Pool = struct { try pool.ensureUnusedCapacity(allocator, 2); var struct_fields: [2]Info.Field = undefined; var struct_fields_len: usize = 0; - if (loaded_tag.tag_ty != .comptime_int_type) { - const tag_type = Type.fromInterned(loaded_tag.tag_ty); - const tag_ctype: CType = try pool.fromType( - allocator, - scratch, - tag_type, - pt, - mod, - kind.noParameter(), - ); - if (tag_ctype.index != .void) { - struct_fields[struct_fields_len] = .{ - .name = .{ .index = .tag }, - .ctype = tag_ctype, - .alignas = AlignAs.fromAbiAlignment(tag_type.abiAlignment(zcu)), - }; - struct_fields_len += 1; - } + const tag_type = Type.fromInterned(loaded_tag.int_tag_type); + const tag_ctype: CType = try pool.fromType( + allocator, + scratch, + tag_type, + pt, + mod, + kind.noParameter(), + ); + if (tag_ctype.index != .void) { + struct_fields[struct_fields_len] = .{ + .name = .{ .index = .tag }, + .ctype = tag_ctype, + .alignas = AlignAs.fromAbiAlignment(tag_type.abiAlignment(zcu)), + }; + struct_fields_len += 1; } if (fields_len > 0) { const payload_ctype = payload_ctype: { @@ -2823,12 +2821,14 @@ pub const Pool = struct { .enum_type => return pool.fromType( allocator, scratch, - Type.fromInterned(ip.loadEnumType(ip_index).tag_ty), + .fromInterned(ip.loadEnumType(ip_index).int_tag_type), pt, mod, kind, ), - .func_type => |func_info| if (func_info.is_generic) return .void else { + .func_type => |func_info| { + if (!ty.fnHasRuntimeBits(zcu)) return .void; + const scratch_top = scratch.items.len; defer scratch.shrinkRetainingCapacity(scratch_top); try scratch.ensureUnusedCapacity(allocator, func_info.param_types.len); @@ -2894,6 +2894,7 @@ pub const Pool = struct { .opt, .aggregate, .un, + .bitpack, .memoized_call, => unreachable, // values, not types }, diff --git a/src/codegen/riscv64/CodeGen.zig b/src/codegen/riscv64/CodeGen.zig index 1f5b6224d7..3ad6faf805 100644 --- a/src/codegen/riscv64/CodeGen.zig +++ b/src/codegen/riscv64/CodeGen.zig @@ -3257,7 +3257,7 @@ fn airOptionalPayload(func: *Func, inst: Air.Inst.Index) !void { const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const result: MCValue = result: { const pl_ty = func.typeOfIndex(inst); - if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .none; + if (!pl_ty.hasRuntimeBits(zcu)) break :result .none; const opt_mcv = try func.resolveInst(ty_op.operand); if (func.reuseOperand(inst, ty_op.operand, 0, opt_mcv)) { @@ -3331,7 +3331,7 @@ fn airUnwrapErrErr(func: *Func, inst: Air.Inst.Index) !void { break :result .{ .immediate = 0 }; } - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_ty.hasRuntimeBits(zcu)) { break :result operand; } @@ -3384,7 +3384,7 @@ fn genUnwrapErrUnionPayloadMir( const payload_ty = err_union_ty.errorUnionPayload(zcu); const result: MCValue = result: { - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .none; + if (!payload_ty.hasRuntimeBits(zcu)) break :result .none; const payload_off: u31 = @intCast(errUnionPayloadOffset(payload_ty, zcu)); switch (err_union) { @@ -3547,7 +3547,7 @@ fn airWrapErrUnionPayload(func: *Func, inst: Air.Inst.Index) !void { const operand = try func.resolveInst(ty_op.operand); const result: MCValue = result: { - if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .{ .immediate = 0 }; + if (!pl_ty.hasRuntimeBits(zcu)) break :result .{ .immediate = 0 }; const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(eu_ty, zcu)); const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, zcu)); @@ -3571,7 +3571,7 @@ fn airWrapErrUnionErr(func: *Func, inst: Air.Inst.Index) !void { const err_ty = eu_ty.errorUnionSet(zcu); const result: MCValue = result: { - if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result try func.resolveInst(ty_op.operand); + if (!pl_ty.hasRuntimeBits(zcu)) break :result try func.resolveInst(ty_op.operand); const frame_index = try func.allocFrameIndex(FrameAlloc.initSpill(eu_ty, zcu)); const pl_off: i32 = @intCast(errUnionPayloadOffset(pl_ty, zcu)); @@ -3761,7 +3761,7 @@ fn airSliceElemVal(func: *Func, inst: Air.Inst.Index) !void { const result: MCValue = result: { const elem_ty = func.typeOfIndex(inst); - if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .none; + assert(elem_ty.hasRuntimeBits(zcu)); const slice_ty = func.typeOf(bin_op.lhs); const slice_ptr_field_type = slice_ty.slicePtrFieldType(zcu); @@ -3914,7 +3914,7 @@ fn airPtrElemVal(func: *Func, inst: Air.Inst.Index) !void { const result: MCValue = if (!is_volatile and func.liveness.isUnused(inst)) .unreach else result: { const elem_ty = base_ptr_ty.indexableElem(zcu); - if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .none; + assert(elem_ty.hasRuntimeBits(zcu)); const base_ptr_mcv = try func.resolveInst(bin_op.lhs); const base_ptr_lock: ?RegisterLock = switch (base_ptr_mcv) { .register => |reg| func.register_manager.lockRegAssumeUnused(reg), @@ -4617,7 +4617,7 @@ fn airStructFieldVal(func: *Func, inst: Air.Inst.Index) !void { const src_mcv = try func.resolveInst(operand); const struct_ty = func.typeOf(operand); const field_ty = struct_ty.fieldType(index, zcu); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) break :result .none; + assert(field_ty.hasRuntimeBits(zcu)); const field_off: u32 = switch (struct_ty.containerLayout(zcu)) { .auto, .@"extern" => @intCast(struct_ty.structFieldOffset(index, zcu) * 8), @@ -5126,7 +5126,6 @@ fn airCmp(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { const bin_op = func.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const pt = func.pt; const zcu = pt.zcu; - const ip = &zcu.intern_pool; const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: { const lhs_ty = func.typeOf(bin_op.lhs); @@ -5140,28 +5139,23 @@ fn airCmp(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { .optional, .@"struct", => { - const int_ty = switch (lhs_ty.zigTypeTag(zcu)) { + const int_ty: Type = switch (lhs_ty.zigTypeTag(zcu)) { .@"enum" => lhs_ty.intTagType(zcu), .int => lhs_ty, - .bool => Type.u1, - .pointer => Type.u64, - .error_set => Type.anyerror, + .bool => .u1, + .pointer => .u64, + .error_set => .anyerror, .optional => blk: { const payload_ty = lhs_ty.optionalChild(zcu); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { - break :blk Type.u1; + if (!payload_ty.hasRuntimeBits(zcu)) { + break :blk .u1; } else if (lhs_ty.isPtrLikeOptional(zcu)) { - break :blk Type.u64; + break :blk .u64; } else { return func.fail("TODO riscv cmp non-pointer optionals", .{}); } }, - .@"struct" => blk: { - const struct_obj = ip.loadStructType(lhs_ty.toIntern()); - assert(struct_obj.layout == .@"packed"); - const backing_index = struct_obj.backingIntTypeUnordered(ip); - break :blk Type.fromInterned(backing_index); - }, + .@"struct", .@"union" => lhs_ty.bitpackBackingInt(zcu), else => unreachable, }; @@ -5925,8 +5919,7 @@ fn airBr(func: *Func, inst: Air.Inst.Index) !void { const br = func.air.instructions.items(.data)[@intFromEnum(inst)].br; const block_ty = func.typeOfIndex(br.block_inst); - const block_unused = - !block_ty.hasRuntimeBitsIgnoreComptime(zcu) or func.liveness.isUnused(br.block_inst); + const block_unused = !block_ty.hasRuntimeBits(zcu) or func.liveness.isUnused(br.block_inst); const block_tracking = func.inst_tracking.getPtr(br.block_inst).?; const block_data = func.blocks.getPtr(br.block_inst).?; const first_br = block_data.relocs.items.len == 0; @@ -8249,7 +8242,7 @@ fn resolveCallingConventionValues( // Return values if (ret_ty.zigTypeTag(zcu) == .noreturn) { result.return_value = InstTracking.init(.unreach); - } else if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + } else if (!ret_ty.hasRuntimeBits(zcu)) { result.return_value = InstTracking.init(.none); } else { var ret_tracking: [2]InstTracking = undefined; @@ -8300,7 +8293,7 @@ fn resolveCallingConventionValues( var param_float_reg_i: usize = 0; for (param_types, result.args) |ty, *arg| { - if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!ty.hasRuntimeBits(zcu)) { assert(cc == .auto); arg.* = .none; continue; @@ -8415,10 +8408,10 @@ fn hasFeature(func: *Func, feature: Target.riscv.Feature) bool { } pub fn errUnionPayloadOffset(payload_ty: Type, zcu: *Zcu) u64 { - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) return 0; + if (!payload_ty.hasRuntimeBits(zcu)) return 0; const payload_align = payload_ty.abiAlignment(zcu); const error_align = Type.anyerror.abiAlignment(zcu); - if (payload_align.compare(.gte, error_align) or !payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (payload_align.compare(.gte, error_align) or !payload_ty.hasRuntimeBits(zcu)) { return 0; } else { return payload_align.forward(Type.anyerror.abiSize(zcu)); @@ -8426,10 +8419,10 @@ pub fn errUnionPayloadOffset(payload_ty: Type, zcu: *Zcu) u64 { } pub fn errUnionErrorOffset(payload_ty: Type, zcu: *Zcu) u64 { - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) return 0; + if (!payload_ty.hasRuntimeBits(zcu)) return 0; const payload_align = payload_ty.abiAlignment(zcu); const error_align = Type.anyerror.abiAlignment(zcu); - if (payload_align.compare(.gte, error_align) and payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (payload_align.compare(.gte, error_align) and payload_ty.hasRuntimeBits(zcu)) { return error_align.forward(payload_ty.abiSize(zcu)); } else { return 0; diff --git a/src/codegen/sparc64/CodeGen.zig b/src/codegen/sparc64/CodeGen.zig index a246df12c5..3b38d6319a 100644 --- a/src/codegen/sparc64/CodeGen.zig +++ b/src/codegen/sparc64/CodeGen.zig @@ -1102,7 +1102,7 @@ fn airBlock(self: *Self, inst: Air.Inst.Index) !void { fn lowerBlock(self: *Self, inst: Air.Inst.Index, body: []const Air.Inst.Index) !void { try self.blocks.putNoClobber(self.gpa, inst, .{ // A block is a setup to be able to jump to the end. - .relocs = .{}, + .relocs = .empty, // It also acts as a receptacle for break operands. // Here we use `MCValue.none` to represent a null value so that the first // break instruction will choose a MCValue for the block result and overwrite @@ -1376,19 +1376,19 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { const rhs = try self.resolveInst(bin_op.rhs); const lhs_ty = self.typeOf(bin_op.lhs); - const int_ty = switch (lhs_ty.zigTypeTag(zcu)) { + const int_ty: Type = switch (lhs_ty.zigTypeTag(zcu)) { .vector => unreachable, // Handled by cmp_vector. .@"enum" => lhs_ty.intTagType(zcu), .int => lhs_ty, - .bool => Type.u1, - .pointer => Type.usize, - .error_set => Type.u16, + .bool => .u1, + .pointer => .usize, + .error_set => .u16, .optional => blk: { const payload_ty = lhs_ty.optionalChild(zcu); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { - break :blk Type.u1; + if (!payload_ty.hasRuntimeBits(zcu)) { + break :blk .u1; } else if (lhs_ty.isPtrLikeOptional(zcu)) { - break :blk Type.usize; + break :blk .usize; } else { return self.fail("TODO SPARCv9 cmp non-pointer optionals", .{}); } @@ -3452,8 +3452,8 @@ fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) if (err_ty.errorSetIsEmpty(zcu)) { return error_union_mcv; } - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { - return MCValue.none; + if (!payload_ty.hasRuntimeBits(zcu)) { + return .none; } const payload_offset: u32 = @intCast(errUnionPayloadOffset(payload_ty, zcu)); @@ -4481,7 +4481,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue { const ty = self.typeOf(ref); // If the type has no codegen bits, no need to store it. - if (!ty.hasRuntimeBitsIgnoreComptime(pt.zcu)) return .none; + if (!ty.hasRuntimeBits(pt.zcu)) return .none; if (ref.toIndex()) |inst| { return self.getResolvedInstValue(inst); diff --git a/src/codegen/spirv/CodeGen.zig b/src/codegen/spirv/CodeGen.zig index d303af6d61..34a7f99ce4 100644 --- a/src/codegen/spirv/CodeGen.zig +++ b/src/codegen/spirv/CodeGen.zig @@ -208,7 +208,7 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { try cg.args.ensureUnusedCapacity(gpa, fn_info.param_types.len); for (fn_info.param_types.get(ip)) |param_ty_index| { const param_ty: Type = .fromInterned(param_ty_index); - if (!param_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!param_ty.hasRuntimeBits(zcu)) continue; const param_type_id = try cg.resolveType(param_ty, .direct); const arg_result_id = cg.module.allocId(); @@ -884,7 +884,7 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { return try cg.constructComposite(comp_ty_id, &constituents); }, .enum_tag => { - const int_val = try val.intFromEnum(ty, pt); + const int_val = val.intFromEnum(zcu); const int_ty = ty.intTagType(zcu); break :cache try cg.constant(int_ty, int_val, repr); }, @@ -959,18 +959,7 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { }, .struct_type => { const struct_type = zcu.typeToStruct(ty).?; - - if (struct_type.layout == .@"packed") { - // TODO: composite int - // TODO: endianness - const bits: u16 = @intCast(ty.bitSize(zcu)); - const bytes = std.mem.alignForward(u16, cg.module.backingIntBits(bits).@"0", 8) / 8; - var limbs: [8]u8 = undefined; - @memset(&limbs, 0); - val.writeToPackedMemory(pt, limbs[0..bytes], 0) catch unreachable; - const backing_ty: Type = .fromInterned(struct_type.backingIntTypeUnordered(ip)); - return try cg.constInt(backing_ty, @as(u64, @bitCast(limbs))); - } + assert(struct_type.layout != .@"packed"); // packed structs use `bitpack` var types = std.array_list.Managed(Type).init(gpa); defer types.deinit(); @@ -981,7 +970,7 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { var it = struct_type.iterateRuntimeOrder(ip); while (it.next()) |field_index| { const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!field_ty.hasRuntimeBits(zcu)) { // This is a zero-bit field - we only needed it for the alignment. continue; } @@ -1001,20 +990,24 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { else => unreachable, }, .un => |un| { + assert(ty.containerLayout(zcu) != .@"packed"); // packed unions use `bitpack` if (un.tag == .none) { - assert(ty.containerLayout(zcu) == .@"packed"); // TODO - const int_ty = try pt.intType(.unsigned, @intCast(ty.bitSize(zcu))); - return try cg.constInt(int_ty, Value.toUnsignedInt(.fromInterned(un.val), zcu)); + @panic("TODO"); } const active_field = ty.unionTagFieldIndex(.fromInterned(un.tag), zcu).?; const union_obj = zcu.typeToUnion(ty).?; const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[active_field]); - const payload = if (field_ty.hasRuntimeBitsIgnoreComptime(zcu)) + const payload = if (field_ty.hasRuntimeBits(zcu)) try cg.constant(field_ty, .fromInterned(un.val), .direct) else null; return try cg.unionInit(ty, active_field, payload); }, + .bitpack => |bitpack| { + const int_val: Value = .fromInterned(bitpack.backing_int_val); + break :cache try cg.constant(int_val.typeOf(zcu), int_val, repr); + }, + .memoized_call => unreachable, } }; @@ -1255,17 +1248,16 @@ fn resolveTypeName(cg: *CodeGen, ty: Type) ![]const u8 { fn resolveUnionType(cg: *CodeGen, ty: Type) !Id { const gpa = cg.module.gpa; const zcu = cg.module.zcu; - const ip = &zcu.intern_pool; const union_obj = zcu.typeToUnion(ty).?; - if (union_obj.flagsUnordered(ip).layout == .@"packed") { + if (union_obj.layout == .@"packed") { return try cg.module.intType(.unsigned, @intCast(ty.bitSize(zcu))); } const layout = cg.unionLayout(ty); if (!layout.has_payload) { // No payload, so represent this as just the tag type. - return try cg.resolveType(.fromInterned(union_obj.enum_tag_ty), .indirect); + return try cg.resolveType(.fromInterned(union_obj.enum_tag_type), .indirect); } var member_types: [4]Id = undefined; @@ -1274,7 +1266,7 @@ fn resolveUnionType(cg: *CodeGen, ty: Type) !Id { const u8_ty_id = try cg.resolveType(.u8, .direct); if (layout.tag_size != 0) { - const tag_ty_id = try cg.resolveType(.fromInterned(union_obj.enum_tag_ty), .indirect); + const tag_ty_id = try cg.resolveType(.fromInterned(union_obj.enum_tag_type), .indirect); member_types[layout.tag_index] = tag_ty_id; member_names[layout.tag_index] = "(tag)"; } @@ -1315,7 +1307,7 @@ fn resolveUnionType(cg: *CodeGen, ty: Type) !Id { fn resolveFnReturnType(cg: *CodeGen, ret_ty: Type) !Id { const zcu = cg.module.zcu; - if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!ret_ty.hasRuntimeBits(zcu)) { // If the return type is an error set or an error union, then we make this // anyerror return type instead, so that it can be coerced into a function // pointer type which has anyerror as the return type. @@ -1389,7 +1381,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { return cg.fail("array type of {} elements is too large", .{ty.arrayLenIncludingSentinel(zcu)}); }; - if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!elem_ty.hasRuntimeBits(zcu)) { assert(repr == .indirect); if (target.os.tag != .opencl) return cg.fail("cannot generate opaque type", .{}); return try cg.module.opaqueType("zero-sized-array"); @@ -1453,7 +1445,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { var param_index: usize = 0; for (fn_info.param_types.get(ip)) |param_ty_index| { const param_ty: Type = .fromInterned(param_ty_index); - if (!param_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!param_ty.hasRuntimeBits(zcu)) continue; param_ty_ids[param_index] = try cg.resolveType(param_ty, .direct); param_index += 1; @@ -1518,7 +1510,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { }; if (struct_type.layout == .@"packed") { - return try cg.resolveType(.fromInterned(struct_type.backingIntTypeUnordered(ip)), .direct); + return try cg.resolveType(.fromInterned(struct_type.packed_backing_int_type), .direct); } var member_types = std.array_list.Managed(Id).init(gpa); @@ -1533,9 +1525,9 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { var it = struct_type.iterateRuntimeOrder(ip); while (it.next()) |field_index| { const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!field_ty.hasRuntimeBits(zcu)) continue; - const field_name = struct_type.fieldName(ip, field_index); + const field_name = struct_type.field_names.get(ip)[field_index]; try member_types.append(try cg.resolveType(field_ty, .indirect)); try member_names.append(field_name.toSlice(ip)); try member_offsets.append(@intCast(ty.structFieldOffset(field_index, zcu))); @@ -1556,7 +1548,7 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { }, .optional => { const payload_ty = ty.optionalChild(zcu); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_ty.hasRuntimeBits(zcu)) { // Just use a bool. // Note: Always generate the bool with indirect format, to save on some sanity // Perform the conversion to a direct bool when the field is extracted. @@ -1653,7 +1645,7 @@ fn errorUnionLayout(cg: *CodeGen, payload_ty: Type) ErrorUnionLayout { const error_first = error_align.compare(.gt, payload_align); return .{ - .payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(zcu), + .payload_has_bits = payload_ty.hasRuntimeBits(zcu), .error_first = error_first, }; } @@ -3724,7 +3716,6 @@ fn cmp( const gpa = cg.module.gpa; const pt = cg.pt; const zcu = cg.module.zcu; - const ip = &zcu.intern_pool; const scalar_ty = lhs.ty.scalarType(zcu); const is_vector = lhs.ty.isVector(zcu); @@ -3737,7 +3728,7 @@ fn cmp( }, .@"struct" => { const struct_ty = zcu.typeToPackedStruct(scalar_ty).?; - const ty: Type = .fromInterned(struct_ty.backingIntTypeUnordered(ip)); + const ty: Type = .fromInterned(struct_ty.packed_backing_int_type); return try cg.cmp(op, lhs.pun(ty), rhs.pun(ty)); }, .error_set => { @@ -3778,7 +3769,7 @@ fn cmp( const payload_ty = ty.optionalChild(zcu); if (ty.optionalReprIsPayload(zcu)) { - assert(payload_ty.hasRuntimeBitsIgnoreComptime(zcu)); + assert(payload_ty.hasRuntimeBits(zcu)); assert(!payload_ty.isSlice(zcu)); return try cg.cmp(op, lhs.pun(payload_ty), rhs.pun(payload_ty)); @@ -3787,12 +3778,12 @@ fn cmp( const lhs_id = try lhs.materialize(cg); const rhs_id = try rhs.materialize(cg); - const lhs_valid_id = if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) + const lhs_valid_id = if (payload_ty.hasRuntimeBits(zcu)) try cg.extractField(.bool, lhs_id, 1) else try cg.convertToDirect(.bool, lhs_id); - const rhs_valid_id = if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) + const rhs_valid_id = if (payload_ty.hasRuntimeBits(zcu)) try cg.extractField(.bool, rhs_id, 1) else try cg.convertToDirect(.bool, rhs_id); @@ -3800,7 +3791,7 @@ fn cmp( const lhs_valid: Temporary = .init(.bool, lhs_valid_id); const rhs_valid: Temporary = .init(.bool, rhs_valid_id); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_ty.hasRuntimeBits(zcu)) { return try cg.cmp(op, lhs_valid, rhs_valid); } @@ -4138,7 +4129,7 @@ fn airArrayToSlice(cg: *CodeGen, inst: Air.Inst.Index) !?Id { const array_ptr_id = try cg.resolve(ty_op.operand); const len_id = try cg.constInt(.usize, array_ty.arrayLen(zcu)); - const elem_ptr_id = if (!array_ty.hasRuntimeBitsIgnoreComptime(zcu)) + const elem_ptr_id = if (!array_ty.hasRuntimeBits(zcu)) // Note: The pointer is something like *opaque{}, so we need to bitcast it to the element type. try cg.bitCast(elem_ptr_ty, array_ptr_ty, array_ptr_id) else @@ -4174,12 +4165,12 @@ fn airAggregateInit(cg: *CodeGen, inst: Air.Inst.Index) !?Id { .@"struct" => { if (zcu.typeToPackedStruct(result_ty)) |struct_type| { comptime assert(Type.packed_struct_layout_version == 2); - const backing_int_ty: Type = .fromInterned(struct_type.backingIntTypeUnordered(ip)); + const backing_int_ty: Type = .fromInterned(struct_type.packed_backing_int_type); var running_int_id = try cg.constInt(backing_int_ty, 0); var running_bits: u16 = 0; for (struct_type.field_types.get(ip), elements) |field_ty_ip, element| { const field_ty: Type = .fromInterned(field_ty_ip); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!field_ty.hasRuntimeBits(zcu)) continue; const field_id = try cg.resolve(element); const ty_bit_size: u16 = @intCast(field_ty.bitSize(zcu)); const field_int_ty = try cg.pt.intType(.unsigned, ty_bit_size); @@ -4239,7 +4230,7 @@ fn airAggregateInit(cg: *CodeGen, inst: Air.Inst.Index) !?Id { const field_index = it.next().?; if ((try result_ty.structFieldValueComptime(pt, i)) != null) continue; const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); - assert(field_ty.hasRuntimeBitsIgnoreComptime(zcu)); + assert(field_ty.hasRuntimeBits(zcu)); const id = try cg.resolve(element); types[index] = field_ty; @@ -4399,10 +4390,7 @@ fn airPtrElemPtr(cg: *CodeGen, inst: Air.Inst.Index) !?Id { const elem_ty = src_ptr_ty.childType(zcu); const ptr_id = try cg.resolve(bin_op.lhs); - if (!elem_ty.hasRuntimeBitsIgnoreComptime(zcu)) { - const dst_ptr_ty = cg.typeOfIndex(inst); - return try cg.bitCast(dst_ptr_ty, src_ptr_ty, ptr_id); - } + assert(elem_ty.hasRuntimeBits(zcu)); const index_id = try cg.resolve(bin_op.rhs); return try cg.ptrElemPtr(src_ptr_ty, ptr_id, index_id); @@ -4526,13 +4514,13 @@ fn unionInit( const zcu = cg.module.zcu; const ip = &zcu.intern_pool; const union_ty = zcu.typeToUnion(ty).?; - const tag_ty: Type = .fromInterned(union_ty.enum_tag_ty); + const tag_ty: Type = .fromInterned(union_ty.enum_tag_type); const layout = cg.unionLayout(ty); const payload_ty: Type = .fromInterned(union_ty.field_types.get(ip)[active_field]); - if (union_ty.flagsUnordered(ip).layout == .@"packed") { - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (union_ty.layout == .@"packed") { + if (!payload_ty.hasRuntimeBits(zcu)) { const int_ty = try pt.intType(.unsigned, @intCast(ty.bitSize(zcu))); return cg.constInt(int_ty, 0); } @@ -4558,7 +4546,7 @@ fn unionInit( const tag_int = if (layout.tag_size != 0) blk: { const tag_val = try pt.enumValueFieldIndex(tag_ty, active_field); - const tag_int_val = try tag_val.intFromEnum(tag_ty, pt); + const tag_int_val = tag_val.intFromEnum(zcu); break :blk tag_int_val.toUnsignedInt(zcu); } else 0; @@ -4577,7 +4565,7 @@ fn unionInit( try cg.store(tag_ty, ptr_id, tag_id, .{}); } - if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (payload_ty.hasRuntimeBits(zcu)) { const layout_payload_ty_id = try cg.resolveType(layout.payload_ty, .indirect); const pl_ptr_ty_id = try cg.module.ptrType(layout_payload_ty_id, .function); const pl_ptr_id = try cg.accessChain(pl_ptr_ty_id, tmp_id, &.{layout.payload_index}); @@ -4613,7 +4601,7 @@ fn airUnionInit(cg: *CodeGen, inst: Air.Inst.Index) !?Id { const union_obj = zcu.typeToUnion(ty).?; const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[extra.field_index]); - const payload = if (field_ty.hasRuntimeBitsIgnoreComptime(zcu)) + const payload = if (field_ty.hasRuntimeBits(zcu)) try cg.resolve(extra.init) else null; @@ -4631,7 +4619,7 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id { const field_index = struct_field.field_index; const field_ty = object_ty.fieldType(field_index, zcu); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) return null; + assert(field_ty.hasRuntimeBits(zcu)); switch (object_ty.zigTypeTag(zcu)) { .@"struct" => switch (object_ty.containerLayout(zcu)) { @@ -5332,7 +5320,7 @@ fn airRet(cg: *CodeGen, inst: Air.Inst.Index) !void { const zcu = cg.module.zcu; const operand = cg.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const ret_ty = cg.typeOf(operand); - if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!ret_ty.hasRuntimeBits(zcu)) { const fn_info = zcu.typeToFunc(zcu.navValue(cg.owner_nav).typeOf(zcu)).?; if (Type.fromInterned(fn_info.return_type).isError(zcu)) { // Functions with an empty error set are emitted with an error code @@ -5356,7 +5344,7 @@ fn airRetLoad(cg: *CodeGen, inst: Air.Inst.Index) !void { const ptr_ty = cg.typeOf(un_op); const ret_ty = ptr_ty.childType(zcu); - if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!ret_ty.hasRuntimeBits(zcu)) { const fn_info = zcu.typeToFunc(zcu.navValue(cg.owner_nav).typeOf(zcu)).?; if (Type.fromInterned(fn_info.return_type).isError(zcu)) { // Functions with an empty error set are emitted with an error code @@ -5573,7 +5561,7 @@ fn airIsNull(cg: *CodeGen, inst: Air.Inst.Index, is_pointer: bool, pred: enum { const is_non_null_id = blk: { if (is_pointer) { - if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (payload_ty.hasRuntimeBits(zcu)) { const storage_class = cg.module.storageClass(operand_ty.ptrAddressSpace(zcu)); const bool_indirect_ty_id = try cg.resolveType(.bool, .indirect); const bool_ptr_ty_id = try cg.module.ptrType(bool_indirect_ty_id, storage_class); @@ -5584,7 +5572,7 @@ fn airIsNull(cg: *CodeGen, inst: Air.Inst.Index, is_pointer: bool, pred: enum { break :blk try cg.load(.bool, operand_id, .{}); } - break :blk if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) + break :blk if (payload_ty.hasRuntimeBits(zcu)) try cg.extractField(.bool, operand_id, 1) else // Optional representation is bool indicating whether the optional is set @@ -5653,7 +5641,7 @@ fn airUnwrapOptional(cg: *CodeGen, inst: Air.Inst.Index) !?Id { const optional_ty = cg.typeOf(ty_op.operand); const payload_ty = cg.typeOfIndex(inst); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) return null; + if (!payload_ty.hasRuntimeBits(zcu)) return null; if (optional_ty.optionalReprIsPayload(zcu)) { return operand_id; @@ -5672,7 +5660,7 @@ fn airUnwrapOptionalPtr(cg: *CodeGen, inst: Air.Inst.Index) !?Id { const result_ty = cg.typeOfIndex(inst); const result_ty_id = try cg.resolveType(result_ty, .direct); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_ty.hasRuntimeBits(zcu)) { // There is no payload, but we still need to return a valid pointer. // We can just return anything here, so just return a pointer to the operand. return try cg.bitCast(result_ty, operand_ty, operand_id); @@ -5691,9 +5679,7 @@ fn airWrapOptional(cg: *CodeGen, inst: Air.Inst.Index) !?Id { const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const payload_ty = cg.typeOf(ty_op.operand); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { - return try cg.constBool(true, .indirect); - } + assert(payload_ty.hasRuntimeBits(zcu)); const operand_id = try cg.resolve(ty_op.operand); @@ -5789,8 +5775,7 @@ fn airSwitchBr(cg: *CodeGen, inst: Air.Inst.Index) !void { const int_val: u64 = switch (cond_ty.zigTypeTag(zcu)) { .bool, .int => if (cond_ty.isSignedInt(zcu)) @bitCast(value.toSignedInt(zcu)) else value.toUnsignedInt(zcu), .@"enum" => blk: { - // TODO: figure out of cond_ty is correct (something with enum literals) - break :blk (try value.intFromEnum(cond_ty, pt)).toUnsignedInt(zcu); // TODO: composite integer constants + break :blk value.intFromEnum(zcu).toUnsignedInt(zcu); // TODO: composite integer constants }, .error_set => value.getErrorInt(zcu), .pointer => value.toUnsignedInt(zcu), @@ -6067,7 +6052,7 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie // before starting to emit OpFunctionCall instructions. Hence the // temporary params buffer. const arg_ty = cg.typeOf(arg); - if (!arg_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!arg_ty.hasRuntimeBits(zcu)) continue; const arg_id = try cg.resolve(arg); params[n_params] = arg_id; @@ -6081,7 +6066,7 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie .id_ref_3 = params[0..n_params], }); - if (cg.liveness.isUnused(inst) or !Type.fromInterned(return_type).hasRuntimeBitsIgnoreComptime(zcu)) { + if (cg.liveness.isUnused(inst) or !Type.fromInterned(return_type).hasRuntimeBits(zcu)) { return null; } diff --git a/src/codegen/wasm/CodeGen.zig b/src/codegen/wasm/CodeGen.zig index 6b5cd3c1c5..a8f374772e 100644 --- a/src/codegen/wasm/CodeGen.zig +++ b/src/codegen/wasm/CodeGen.zig @@ -759,7 +759,7 @@ fn resolveInst(cg: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue { const zcu = pt.zcu; const val = (try cg.air.value(ref, pt)).?; const ty = cg.typeOf(ref); - if (!ty.hasRuntimeBitsIgnoreComptime(zcu) and !ty.isInt(zcu) and !ty.isError(zcu)) { + if (!ty.hasRuntimeBits(zcu) and !ty.isInt(zcu) and !ty.isError(zcu)) { gop.value_ptr.* = .none; return .none; } @@ -773,7 +773,7 @@ fn resolveInst(cg: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue { const result: WValue = if (isByRef(ty, zcu, cg.target)) .{ .uav_ref = .{ .ip_index = val.toIntern() } } else - try cg.lowerConstant(val, ty); + try cg.lowerConstant(val); gop.value_ptr.* = result; return result; @@ -786,7 +786,7 @@ fn resolveValue(cg: *CodeGen, val: Value) InnerError!WValue { return if (isByRef(ty, zcu, cg.target)) .{ .uav_ref = .{ .ip_index = val.toIntern() } } else - try cg.lowerConstant(val, ty); + try cg.lowerConstant(val); } /// NOTE: if result == .stack, it will be stored in .local @@ -980,7 +980,6 @@ fn addExtraAssumeCapacity(cg: *CodeGen, extra: anytype) error{OutOfMemory}!u32 { /// For `std.builtin.CallingConvention.auto`. pub fn typeToValtype(ty: Type, zcu: *const Zcu, target: *const std.Target) std.wasm.Valtype { - const ip = &zcu.intern_pool; return switch (ty.zigTypeTag(zcu)) { .float => switch (ty.floatBits(target)) { 16 => .i32, // stored/loaded as u16 @@ -994,25 +993,13 @@ pub fn typeToValtype(ty: Type, zcu: *const Zcu, target: *const std.Target) std.w 33...64 => .i64, else => .i32, }, - .@"struct" => blk: { - if (zcu.typeToPackedStruct(ty)) |packed_struct| { - const backing_int_ty = Type.fromInterned(packed_struct.backingIntTypeUnordered(ip)); - break :blk typeToValtype(backing_int_ty, zcu, target); - } else { - break :blk .i32; - } - }, .vector => switch (CodeGen.determineSimdStoreStrategy(ty, zcu, target)) { .direct => .v128, .unrolled => .i32, }, - .@"union" => switch (ty.containerLayout(zcu)) { - .@"packed" => switch (ty.bitSize(zcu)) { - 0...32 => .i32, - 33...64 => .i64, - else => .i32, - }, - else => .i32, + .@"union", .@"struct" => switch (ty.containerLayout(zcu)) { + .@"packed" => typeToValtype(ty.bitpackBackingInt(zcu), zcu, target), + .auto, .@"extern" => .i32, }, else => .i32, // all represented as reference/immediate }; @@ -1185,7 +1172,7 @@ pub fn generate( const fn_ty = zcu.navValue(cg.owner_nav).typeOf(zcu); const fn_info = zcu.typeToFunc(fn_ty).?; const ret_ty: Type = .fromInterned(fn_info.return_type); - const any_returns = !firstParamSRet(fn_info.cc, ret_ty, zcu, target) and ret_ty.hasRuntimeBitsIgnoreComptime(zcu); + const any_returns = !firstParamSRet(fn_info.cc, ret_ty, zcu, target) and ret_ty.hasRuntimeBits(zcu); var cc_result = try resolveCallingConventionValues(zcu, fn_ty, target); defer cc_result.deinit(gpa); @@ -1244,7 +1231,7 @@ fn generateInner(cg: *CodeGen, any_returns: bool) InnerError!Mir { if (any_returns and cg.air.instructions.len > 0) { const inst: Air.Inst.Index = @enumFromInt(cg.air.instructions.len - 1); const last_inst_ty = cg.typeOfIndex(inst); - if (!last_inst_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!last_inst_ty.hasRuntimeBits(zcu)) { try cg.addTag(.@"unreachable"); } } @@ -1316,7 +1303,7 @@ fn resolveCallingConventionValues( switch (cc) { .auto => { for (fn_info.param_types.get(ip)) |ty| { - if (!Type.fromInterned(ty).hasRuntimeBitsIgnoreComptime(zcu)) { + if (!Type.fromInterned(ty).hasRuntimeBits(zcu)) { continue; } @@ -1326,7 +1313,7 @@ fn resolveCallingConventionValues( }, .wasm_mvp => { for (fn_info.param_types.get(ip)) |ty| { - if (!Type.fromInterned(ty).hasRuntimeBitsIgnoreComptime(zcu)) { + if (!Type.fromInterned(ty).hasRuntimeBits(zcu)) { continue; } switch (abi.classifyType(.fromInterned(ty), zcu)) { @@ -1357,7 +1344,7 @@ pub fn firstParamSRet( zcu: *const Zcu, target: *const std.Target, ) bool { - if (!return_type.hasRuntimeBitsIgnoreComptime(zcu)) return false; + if (!return_type.hasRuntimeBits(zcu)) return false; switch (cc) { .@"inline" => unreachable, .auto => return isByRef(return_type, zcu, target), @@ -1457,7 +1444,7 @@ fn restoreStackPointer(cg: *CodeGen) !void { fn allocStack(cg: *CodeGen, ty: Type) !WValue { const pt = cg.pt; const zcu = pt.zcu; - assert(ty.hasRuntimeBitsIgnoreComptime(zcu)); + assert(ty.hasRuntimeBits(zcu)); if (cg.initial_stack_value == .none) { try cg.initializeStack(); } @@ -1491,7 +1478,7 @@ fn allocStackPtr(cg: *CodeGen, inst: Air.Inst.Index) !WValue { try cg.initializeStack(); } - if (!pointee_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!pointee_ty.hasRuntimeBits(zcu)) { return cg.allocStack(Type.usize); // create a value containing just the stack pointer. } @@ -1676,7 +1663,6 @@ fn ptrSize(cg: *const CodeGen) u16 { /// For a given `Type`, will return true when the type will be passed /// by reference, rather than by value fn isByRef(ty: Type, zcu: *const Zcu, target: *const std.Target) bool { - const ip = &zcu.intern_pool; switch (ty.zigTypeTag(zcu)) { .type, .comptime_int, @@ -1697,20 +1683,10 @@ fn isByRef(ty: Type, zcu: *const Zcu, target: *const std.Target) bool { .array, .frame, - => return ty.hasRuntimeBitsIgnoreComptime(zcu), - .@"union" => { - if (zcu.typeToUnion(ty)) |union_obj| { - if (union_obj.flagsUnordered(ip).layout == .@"packed") { - return ty.abiSize(zcu) > 8; - } - } - return ty.hasRuntimeBitsIgnoreComptime(zcu); - }, - .@"struct" => { - if (zcu.typeToPackedStruct(ty)) |packed_struct| { - return isByRef(Type.fromInterned(packed_struct.backingIntTypeUnordered(ip)), zcu, target); - } - return ty.hasRuntimeBitsIgnoreComptime(zcu); + => return ty.hasRuntimeBits(zcu), + .@"struct", .@"union" => switch (ty.containerLayout(zcu)) { + .@"packed" => return isByRef(ty.bitpackBackingInt(zcu), zcu, target), + .@"extern", .auto => return ty.hasRuntimeBits(zcu), }, .vector => return determineSimdStoreStrategy(ty, zcu, target) == .unrolled, .int => return ty.intInfo(zcu).bits > 64, @@ -1718,7 +1694,7 @@ fn isByRef(ty: Type, zcu: *const Zcu, target: *const std.Target) bool { .float => return ty.floatBits(target) > 64, .error_union => { const pl_ty = ty.errorUnionPayload(zcu); - if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!pl_ty.hasRuntimeBits(zcu)) { return false; } return true; @@ -1727,7 +1703,7 @@ fn isByRef(ty: Type, zcu: *const Zcu, target: *const std.Target) bool { if (ty.isPtrLikeOptional(zcu)) return false; const pl_type = ty.optionalChild(zcu); if (pl_type.zigTypeTag(zcu) == .error_set) return false; - return pl_type.hasRuntimeBitsIgnoreComptime(zcu); + return pl_type.hasRuntimeBits(zcu); }, .pointer => { // Slices act like struct and will be passed by reference @@ -2069,7 +2045,7 @@ fn airRet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { // to the stack instead if (cg.return_value != .none) { try cg.store(cg.return_value, operand, ret_ty, 0); - } else if (fn_info.cc == .wasm_mvp and ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + } else if (fn_info.cc == .wasm_mvp and ret_ty.hasRuntimeBits(zcu)) { switch (abi.classifyType(ret_ty, zcu)) { .direct => |scalar_type| { assert(!abi.lowerAsDoubleI64(scalar_type, zcu)); @@ -2082,7 +2058,7 @@ fn airRet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { .indirect => unreachable, } } else { - if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu) and ret_ty.isError(zcu)) { + if (!ret_ty.hasRuntimeBits(zcu) and ret_ty.isError(zcu)) { try cg.addImm32(0); } else { try cg.emitWValue(operand); @@ -2121,7 +2097,7 @@ fn airRetLoad(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { const ret_ty = cg.typeOf(un_op).childType(zcu); const fn_info = zcu.typeToFunc(zcu.navValue(cg.owner_nav).typeOf(zcu)).?; - if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!ret_ty.hasRuntimeBits(zcu)) { if (ret_ty.isError(zcu)) { try cg.addImm32(0); } @@ -2177,7 +2153,7 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie const arg_val = try cg.resolveInst(arg); const arg_ty = cg.typeOf(arg); - if (!arg_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!arg_ty.hasRuntimeBits(zcu)) continue; try cg.lowerArg(zcu.typeToFunc(fn_ty).?.cc, arg_ty, arg_val); } @@ -2199,7 +2175,7 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie } const result_value = result_value: { - if (!ret_ty.hasRuntimeBitsIgnoreComptime(zcu) and !ret_ty.isError(zcu)) { + if (!ret_ty.hasRuntimeBits(zcu) and !ret_ty.isError(zcu)) { break :result_value .none; } else if (first_param_sret) { break :result_value sret; @@ -2320,12 +2296,12 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr const zcu = pt.zcu; const abi_size = ty.abiSize(zcu); - if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) return; + if (!ty.hasRuntimeBits(zcu)) return; switch (ty.zigTypeTag(zcu)) { .error_union => { const pl_ty = ty.errorUnionPayload(zcu); - if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!pl_ty.hasRuntimeBits(zcu)) { return cg.store(lhs, rhs, Type.anyerror, offset); } @@ -2338,7 +2314,7 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr return cg.store(lhs, rhs, Type.usize, offset); } const pl_ty = ty.optionalChild(zcu); - if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!pl_ty.hasRuntimeBits(zcu)) { return cg.store(lhs, rhs, Type.u8, offset); } if (pl_ty.zigTypeTag(zcu) == .error_set) { @@ -2438,7 +2414,7 @@ fn airLoad(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { const ptr_ty = cg.typeOf(ty_op.operand); const ptr_info = ptr_ty.ptrInfo(zcu); - if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) return cg.finishAir(inst, .none, &.{ty_op.operand}); + if (!ty.hasRuntimeBits(zcu)) return cg.finishAir(inst, .none, &.{ty_op.operand}); const result = result: { if (isByRef(ty, zcu, cg.target)) { @@ -3089,7 +3065,7 @@ fn lowerPtr(cg: *CodeGen, ptr_val: InternPool.Index, prev_offset: u64) InnerErro return switch (ptr.base_addr) { .nav => |nav| return .{ .nav_ref = .{ .nav_index = nav, .offset = @intCast(offset) } }, .uav => |uav| return .{ .uav_ref = .{ .ip_index = uav.val, .offset = @intCast(offset), .orig_ptr_ty = uav.orig_ty } }, - .int => return cg.lowerConstant(try pt.intValue(Type.usize, offset), Type.usize), + .int => return cg.lowerConstant(try pt.intValue(.usize, offset)), .eu_payload => |eu_ptr| try cg.lowerPtr( eu_ptr, offset + codegen.errUnionPayloadOffset( @@ -3126,10 +3102,11 @@ fn lowerPtr(cg: *CodeGen, ptr_val: InternPool.Index, prev_offset: u64) InnerErro }; } -/// Asserts that `isByRef` returns `false` for `ty`. -fn lowerConstant(cg: *CodeGen, val: Value, ty: Type) InnerError!WValue { +/// Asserts that `isByRef` returns `false` for `val.typeOf(zcu)`. +fn lowerConstant(cg: *CodeGen, val: Value) InnerError!WValue { const pt = cg.pt; const zcu = pt.zcu; + const ty = val.typeOf(zcu); assert(!isByRef(ty, zcu, cg.target)); const ip = &zcu.intern_pool; if (val.isUndef(zcu)) return cg.emitUndefined(ty); @@ -3191,31 +3168,22 @@ fn lowerConstant(cg: *CodeGen, val: Value, ty: Type) InnerError!WValue { }, .error_union => |error_union| { const err_int_ty = try pt.errorIntType(); - const err_ty, const err_val = switch (error_union.val) { - .err_name => |err_name| .{ - ty.errorUnionSet(zcu), - Value.fromInterned(try pt.intern(.{ .err = .{ - .ty = ty.errorUnionSet(zcu).toIntern(), - .name = err_name, - } })), - }, - .payload => .{ - err_int_ty, - try pt.intValue(err_int_ty, 0), - }, + const err_val: Value = switch (error_union.val) { + .err_name => |err_name| .fromInterned(try pt.intern(.{ .err = .{ + .ty = ty.errorUnionSet(zcu).toIntern(), + .name = err_name, + } })), + .payload => try pt.intValue(err_int_ty, 0), }; const payload_type = ty.errorUnionPayload(zcu); - if (!payload_type.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_type.hasRuntimeBits(zcu)) { // We use the error type directly as the type. - return cg.lowerConstant(err_val, err_ty); + return cg.lowerConstant(err_val); } return cg.fail("Wasm TODO: lowerConstant error union with non-zero-bit payload type", .{}); }, - .enum_tag => |enum_tag| { - const int_tag_ty = ip.typeOf(enum_tag.int); - return cg.lowerConstant(Value.fromInterned(enum_tag.int), Type.fromInterned(int_tag_ty)); - }, + .enum_tag => |enum_tag| return cg.lowerConstant(.fromInterned(enum_tag.int)), .float => |float| switch (float.storage) { .f16 => |f16_val| return .{ .imm32 = @as(u16, @bitCast(f16_val)) }, .f32 => |f32_val| return .{ .float32 = f32_val }, @@ -3225,9 +3193,8 @@ fn lowerConstant(cg: *CodeGen, val: Value, ty: Type) InnerError!WValue { .slice => unreachable, // isByRef == true .ptr => return cg.lowerPtr(val.toIntern(), 0), .opt => if (ty.optionalReprIsPayload(zcu)) { - const pl_ty = ty.optionalChild(zcu); if (val.optionalValue(zcu)) |payload| { - return cg.lowerConstant(payload, pl_ty); + return cg.lowerConstant(payload); } else { return .{ .imm32 = 0 }; } @@ -3242,33 +3209,11 @@ fn lowerConstant(cg: *CodeGen, val: Value, ty: Type) InnerError!WValue { val.writeToMemory(pt, &buf) catch unreachable; return cg.storeSimdImmd(buf); }, - .struct_type => { - const struct_type = ip.loadStructType(ty.toIntern()); - // non-packed structs are not handled in this function because they - // are by-ref types. - assert(struct_type.layout == .@"packed"); - var buf: [8]u8 = .{0} ** 8; // zero the buffer so we do not read 0xaa as integer - val.writeToPackedMemory(pt, &buf, 0) catch unreachable; - const backing_int_ty = Type.fromInterned(struct_type.backingIntTypeUnordered(ip)); - const int_val = try pt.intValue( - backing_int_ty, - mem.readInt(u64, &buf, .little), - ); - return cg.lowerConstant(int_val, backing_int_ty); - }, + .struct_type => unreachable, // packed structs use `bitpack` else => unreachable, }, - .un => { - const int_type = try pt.intType(.unsigned, @intCast(ty.bitSize(zcu))); - - var buf: [8]u8 = .{0} ** 8; // zero the buffer so we do not read 0xaa as integer - val.writeToPackedMemory(pt, &buf, 0) catch unreachable; - const int_val = try pt.intValue( - int_type, - mem.readInt(u64, &buf, .little), - ); - return cg.lowerConstant(int_val, int_type); - }, + .un => unreachable, // packed unions use `bitpack` + .bitpack => |bitpack| return cg.lowerConstant(.fromInterned(bitpack.backing_int_val)), .memoized_call => unreachable, } } @@ -3283,7 +3228,6 @@ fn storeSimdImmd(cg: *CodeGen, value: [16]u8) !WValue { fn emitUndefined(cg: *CodeGen, ty: Type) InnerError!WValue { const zcu = cg.pt.zcu; - const ip = &zcu.intern_pool; switch (ty.zigTypeTag(zcu)) { .bool, .error_set => return .{ .imm32 = 0xaaaaaaaa }, .int, .@"enum" => switch (ty.intInfo(zcu).bits) { @@ -3311,17 +3255,9 @@ fn emitUndefined(cg: *CodeGen, ty: Type) InnerError!WValue { .error_union => { return .{ .imm32 = 0xaaaaaaaa }; }, - .@"struct" => { - const packed_struct = zcu.typeToPackedStruct(ty).?; - return cg.emitUndefined(Type.fromInterned(packed_struct.backingIntTypeUnordered(ip))); - }, - .@"union" => switch (ty.containerLayout(zcu)) { - .@"packed" => switch (ty.bitSize(zcu)) { - 0...32 => return .{ .imm32 = 0xaaaaaaaa }, - 33...64 => return .{ .imm64 = 0xaaaaaaaaaaaaaaaa }, - else => unreachable, - }, - else => unreachable, + .@"struct", .@"union" => { + const backing_int_ty = ty.bitpackBackingInt(zcu); + return cg.emitUndefined(backing_int_ty); }, else => return cg.fail("Wasm TODO: emitUndefined for type: {t}\n", .{ty.zigTypeTag(zcu)}), } @@ -3335,7 +3271,7 @@ fn airBlock(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, block_ty: Type, body: []const Air.Inst.Index) InnerError!void { const zcu = cg.pt.zcu; // if wasm_block_ty is non-empty, we create a register to store the temporary value - const block_result: WValue = if (block_ty.hasRuntimeBitsIgnoreComptime(zcu)) + const block_result: WValue = if (block_ty.hasRuntimeBits(zcu)) try cg.allocLocal(block_ty) else .none; @@ -3449,7 +3385,7 @@ fn cmp(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: std.math.CompareOpe const zcu = cg.pt.zcu; if (ty.zigTypeTag(zcu) == .optional and !ty.optionalReprIsPayload(zcu)) { const payload_ty = ty.optionalChild(zcu); - if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (payload_ty.hasRuntimeBits(zcu)) { // When we hit this case, we must check the value of optionals // that are not pointers. This means first checking against non-null for // both lhs and rhs, as well as checking the payload are matching of lhs and rhs @@ -3792,7 +3728,6 @@ fn structFieldPtr( fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { const pt = cg.pt; const zcu = pt.zcu; - const ip = &zcu.intern_pool; const ty_pl = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const struct_field = cg.air.extraData(Air.StructField, ty_pl.payload).data; @@ -3800,14 +3735,14 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { const operand = try cg.resolveInst(struct_field.struct_operand); const field_index = struct_field.field_index; const field_ty = struct_ty.fieldType(field_index, zcu); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) return cg.finishAir(inst, .none, &.{struct_field.struct_operand}); + if (!field_ty.hasRuntimeBits(zcu)) return cg.finishAir(inst, .none, &.{struct_field.struct_operand}); const result: WValue = switch (struct_ty.containerLayout(zcu)) { .@"packed" => switch (struct_ty.zigTypeTag(zcu)) { .@"struct" => result: { const packed_struct = zcu.typeToPackedStruct(struct_ty).?; const offset = zcu.structPackedFieldBitOffset(packed_struct, field_index); - const backing_ty = Type.fromInterned(packed_struct.backingIntTypeUnordered(ip)); + const backing_ty = Type.fromInterned(packed_struct.packed_backing_int_type); const host_bits = backing_ty.intInfo(zcu).bits; const const_wvalue: WValue = if (33 <= host_bits and host_bits <= 64) @@ -3885,7 +3820,7 @@ fn airSwitchBr(cg: *CodeGen, inst: Air.Inst.Index, is_dispatch_loop: bool) Inner const switch_br = cg.air.unwrapSwitch(inst); const target_ty = cg.typeOf(switch_br.operand); - assert(target_ty.hasRuntimeBitsIgnoreComptime(zcu)); + assert(target_ty.hasRuntimeBits(zcu)); // swap target value with placeholder local, for dispatching const target = if (is_dispatch_loop) target: { @@ -4119,7 +4054,7 @@ fn airIsErr(cg: *CodeGen, inst: Air.Inst.Index, opcode: std.wasm.Opcode, op_kind } try cg.emitWValue(operand); - if (op_kind == .ptr or pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (op_kind == .ptr or pl_ty.hasRuntimeBits(zcu)) { try cg.addMemArg(.i32_load16_u, .{ .offset = operand.offset() + @as(u32, @intCast(errUnionErrorOffset(pl_ty, zcu))), .alignment = @intCast(Type.anyerror.abiAlignment(zcu).toByteUnits().?), @@ -4146,7 +4081,7 @@ fn airUnwrapErrUnionPayload(cg: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) const payload_ty = eu_ty.errorUnionPayload(zcu); const result: WValue = result: { - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_ty.hasRuntimeBits(zcu)) { if (op_is_ptr) { break :result cg.reuseOperand(ty_op.operand, operand); } else { @@ -4166,7 +4101,7 @@ fn airUnwrapErrUnionPayload(cg: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) } /// E!T -> E op_is_ptr == false -/// *(E!T) -> E op_is_prt == true +/// *(E!T) -> E op_is_ptr == true /// NOTE: op_is_ptr will not change return type fn airUnwrapErrUnionError(cg: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) InnerError!void { const zcu = cg.pt.zcu; @@ -4186,7 +4121,7 @@ fn airUnwrapErrUnionError(cg: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) I if (op_is_ptr or isByRef(eu_ty, zcu, cg.target)) { break :result try cg.load(operand, Type.anyerror, err_offset); } else { - assert(!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)); + assert(!payload_ty.hasRuntimeBits(zcu)); break :result cg.reuseOperand(ty_op.operand, operand); } }; @@ -4202,7 +4137,7 @@ fn airWrapErrUnionPayload(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { const pl_ty = cg.typeOf(ty_op.operand); const result = result: { - if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!pl_ty.hasRuntimeBits(zcu)) { break :result cg.reuseOperand(ty_op.operand, operand); } @@ -4232,7 +4167,7 @@ fn airWrapErrUnionErr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { const pl_ty = err_ty.errorUnionPayload(zcu); const result = result: { - if (!pl_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!pl_ty.hasRuntimeBits(zcu)) { break :result cg.reuseOperand(ty_op.operand, operand); } @@ -4348,7 +4283,7 @@ fn isNull(cg: *CodeGen, operand: WValue, optional_ty: Type, opcode: std.wasm.Opc if (!optional_ty.optionalReprIsPayload(zcu)) { // When payload is zero-bits, we can treat operand as a value, rather than // a pointer to the stack value - if (payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (payload_ty.hasRuntimeBits(zcu)) { const offset = std.math.cast(u32, payload_ty.abiSize(zcu)) orelse { return cg.fail("Optional type {f} too big to fit into stack frame", .{optional_ty.fmt(pt)}); }; @@ -4373,7 +4308,7 @@ fn airOptionalPayload(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; const opt_ty = cg.typeOf(ty_op.operand); const payload_ty = cg.typeOfIndex(inst); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_ty.hasRuntimeBits(zcu)) { return cg.finishAir(inst, .none, &.{ty_op.operand}); } @@ -4398,7 +4333,7 @@ fn airOptionalPayloadPtr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { const result = result: { const payload_ty = opt_ty.optionalChild(zcu); - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu) or opt_ty.optionalReprIsPayload(zcu)) { + if (!payload_ty.hasRuntimeBits(zcu) or opt_ty.optionalReprIsPayload(zcu)) { break :result cg.reuseOperand(ty_op.operand, operand); } @@ -4438,7 +4373,7 @@ fn airWrapOptional(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { const zcu = pt.zcu; const result = result: { - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_ty.hasRuntimeBits(zcu)) { const non_null_bit = try cg.allocStack(Type.u1); try cg.emitWValue(non_null_bit); try cg.addImm32(1); @@ -4606,7 +4541,7 @@ fn airArrayToSlice(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { const slice_local = try cg.allocStack(slice_ty); // store the array ptr in the slice - if (array_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (array_ty.hasRuntimeBits(zcu)) { try cg.store(slice_local, operand, Type.usize, 0); } @@ -5105,7 +5040,7 @@ fn airShuffleOne(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { try cg.emitWValue(dest_alloc); const elem_val = switch (mask_elem.unwrap()) { .elem => |idx| try cg.load(operand, elem_ty, @intCast(elem_size * idx)), - .value => |val| try cg.lowerConstant(.fromInterned(val), elem_ty), + .value => |val| try cg.lowerConstant(.fromInterned(val)), }; try cg.store(.stack, elem_val, elem_ty, @intCast(dest_alloc.offset() + elem_size * out_idx)); } @@ -5246,7 +5181,7 @@ fn airAggregateInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { } const packed_struct = zcu.typeToPackedStruct(result_ty).?; const field_types = packed_struct.field_types; - const backing_type = Type.fromInterned(packed_struct.backingIntTypeUnordered(ip)); + const backing_type = Type.fromInterned(packed_struct.packed_backing_int_type); // ensure the result is zero'd const result = try cg.allocLocal(backing_type); @@ -5259,7 +5194,7 @@ fn airAggregateInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { var current_bit: u16 = 0; for (elements, 0..) |elem, elem_index| { const field_ty = Type.fromInterned(field_types.get(ip)[elem_index]); - if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!field_ty.hasRuntimeBits(zcu)) continue; const shift_val: WValue = if (backing_type.bitSize(zcu) <= 32) .{ .imm32 = current_bit } @@ -5332,13 +5267,13 @@ fn airUnionInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { const layout = union_ty.unionGetLayout(zcu); const union_obj = zcu.typeToUnion(union_ty).?; const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[extra.field_index]); - const field_name = union_obj.loadTagType(ip).names.get(ip)[extra.field_index]; + const field_name = ip.loadEnumType(union_obj.enum_tag_type).field_names.get(ip)[extra.field_index]; const tag_int = blk: { - const tag_ty = union_ty.unionTagTypeRuntime(zcu).?; + const tag_ty = union_ty.unionTagTypeHypothetical(zcu); const enum_field_index = tag_ty.enumFieldIndex(field_name, zcu).?; const tag_val = try pt.enumValueFieldIndex(tag_ty, enum_field_index); - break :blk try cg.lowerConstant(tag_val, tag_ty); + break :blk try cg.lowerConstant(tag_val); }; if (layout.payload_size == 0) { if (layout.tag_size == 0) { @@ -5360,7 +5295,7 @@ fn airUnionInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { } if (layout.tag_size > 0) { - try cg.store(result_ptr, tag_int, Type.fromInterned(union_obj.enum_tag_ty), 0); + try cg.store(result_ptr, tag_int, .fromInterned(union_obj.enum_tag_type), 0); } } else { try cg.store(result_ptr, payload, field_ty, 0); @@ -5368,7 +5303,7 @@ fn airUnionInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { try cg.store( result_ptr, tag_int, - Type.fromInterned(union_obj.enum_tag_ty), + .fromInterned(union_obj.enum_tag_type), @intCast(layout.payload_size), ); } @@ -5415,7 +5350,7 @@ fn airWasmMemoryGrow(cg: *CodeGen, inst: Air.Inst.Index) !void { fn cmpOptionals(cg: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: std.math.CompareOperator) InnerError!WValue { const zcu = cg.pt.zcu; - assert(operand_ty.hasRuntimeBitsIgnoreComptime(zcu)); + assert(operand_ty.hasRuntimeBits(zcu)); assert(op == .eq or op == .neq); const payload_ty = operand_ty.optionalChild(zcu); assert(!isByRef(payload_ty, zcu, cg.target)); @@ -5669,7 +5604,7 @@ fn airErrUnionPayloadPtrSet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void ); const result = result: { - if (!payload_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!payload_ty.hasRuntimeBits(zcu)) { break :result cg.reuseOperand(ty_op.operand, operand); } @@ -6458,7 +6393,7 @@ fn lowerTry( const zcu = cg.pt.zcu; const pl_ty = err_union_ty.errorUnionPayload(zcu); - const pl_has_bits = pl_ty.hasRuntimeBitsIgnoreComptime(zcu); + const pl_has_bits = pl_ty.hasRuntimeBits(zcu); if (!err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) { // Block we can jump out of when error is not set @@ -7096,13 +7031,13 @@ fn callIntrinsic( // Lower all arguments to the stack before we call our function for (args, 0..) |arg, arg_i| { assert(!(want_sret_param and arg == .stack)); - assert(Type.fromInterned(param_types[arg_i]).hasRuntimeBitsIgnoreComptime(zcu)); + assert(Type.fromInterned(param_types[arg_i]).hasRuntimeBits(zcu)); try cg.lowerArg(.{ .wasm_mvp = .{} }, Type.fromInterned(param_types[arg_i]), arg); } try cg.addInst(.{ .tag = .call_intrinsic, .data = .{ .intrinsic = intrinsic } }); - if (!return_type.hasRuntimeBitsIgnoreComptime(zcu)) { + if (!return_type.hasRuntimeBits(zcu)) { return .none; } else if (want_sret_param) { return sret; diff --git a/src/link/MachO/Atom.zig b/src/link/MachO/Atom.zig index 8f0f801949..df9dc381ab 100644 --- a/src/link/MachO/Atom.zig +++ b/src/link/MachO/Atom.zig @@ -561,7 +561,7 @@ fn reportUndefSymbol(self: Atom, rel: Relocation, macho_file: *MachO) !bool { defer macho_file.undefs_mutex.unlock(io); const gop = try macho_file.undefs.getOrPut(gpa, file.getGlobals()[rel.target]); if (!gop.found_existing) { - gop.value_ptr.* = .{ .refs = .{} }; + gop.value_ptr.* = .{ .refs = .empty }; } try gop.value_ptr.refs.append(gpa, .{ .index = self.atom_index, .file = self.file }); return true; diff --git a/src/link/MachO/ZigObject.zig b/src/link/MachO/ZigObject.zig index b17dc09907..5d71e46eaa 100644 --- a/src/link/MachO/ZigObject.zig +++ b/src/link/MachO/ZigObject.zig @@ -150,7 +150,7 @@ fn newAtom(self: *ZigObject, allocator: Allocator, name: MachO.String, macho_fil atom.name = name; const relocs_index = @as(u32, @intCast(self.relocs.items.len)); - self.relocs.addOneAssumeCapacity().* = .{}; + self.relocs.addOneAssumeCapacity().* = .empty; atom.addExtra(.{ .rel_index = relocs_index, .rel_count = 0 }, macho_file); return index; diff --git a/src/link/MachO/file.zig b/src/link/MachO/file.zig index cd687a4941..4f6f70debe 100644 --- a/src/link/MachO/file.zig +++ b/src/link/MachO/file.zig @@ -258,7 +258,7 @@ pub const File = union(enum) { const gop = try macho_file.dupes.getOrPut(gpa, file.getGlobals()[i]); if (!gop.found_existing) { - gop.value_ptr.* = .{}; + gop.value_ptr.* = .empty; } try gop.value_ptr.append(gpa, file.getIndex()); } diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index a9e7f35c21..1975ad9ba9 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -4226,7 +4226,7 @@ fn convertZcuFnType( if (CodeGen.firstParamSRet(cc, return_type, zcu, target)) { try params_buffer.append(gpa, .i32); // memory address is always a 32-bit handle - } else if (return_type.hasRuntimeBitsIgnoreComptime(zcu)) { + } else if (return_type.hasRuntimeBits(zcu)) { if (cc == .wasm_mvp) { switch (abi.classifyType(return_type, zcu)) { .direct => |scalar_ty| { @@ -4245,7 +4245,7 @@ fn convertZcuFnType( // param types for (params) |param_type_ip| { const param_type = Zcu.Type.fromInterned(param_type_ip); - if (!param_type.hasRuntimeBitsIgnoreComptime(zcu)) continue; + if (!param_type.hasRuntimeBits(zcu)) continue; switch (cc) { .wasm_mvp => { diff --git a/src/link/Wasm/Flush.zig b/src/link/Wasm/Flush.zig index 8197d35b72..5d19f5b159 100644 --- a/src/link/Wasm/Flush.zig +++ b/src/link/Wasm/Flush.zig @@ -154,7 +154,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { .type_index = try wasm.internFunctionType(.auto, &.{int_tag_ty.ip_index}, .slice_const_u8_sentinel_0, target), .table_index = @intCast(wasm.tag_name_offs.items.len), } }; - const tag_names = ip.loadEnumType(data.ip_index).names; + const tag_names = ip.loadEnumType(data.ip_index).field_names; for (tag_names.get(ip)) |tag_name| { const slice = tag_name.toSlice(ip); try wasm.tag_name_offs.append(gpa, @intCast(wasm.tag_name_bytes.items.len)); @@ -1869,7 +1869,7 @@ fn emitTagNameFunction( const zcu = comp.zcu.?; const ip = &zcu.intern_pool; const enum_type = ip.loadEnumType(enum_type_ip); - const tag_values = enum_type.values.get(ip); + const tag_values = enum_type.field_values.get(ip); const slice_abi_size = 8; const encoded_alignment = @ctz(@as(u32, 4)); @@ -1908,7 +1908,7 @@ fn emitTagNameFunction( return; } - const int_info = Zcu.Type.intInfo(.fromInterned(enum_type.tag_ty), zcu); + const int_info = Zcu.Type.intInfo(.fromInterned(enum_type.int_tag_type), zcu); const outer_block_type: std.wasm.BlockType = switch (int_info.bits) { 0...32 => .i32, 33...64 => .i64, diff --git a/src/link/tapi/parse.zig b/src/link/tapi/parse.zig index 4483d359eb..487b609bca 100644 --- a/src/link/tapi/parse.zig +++ b/src/link/tapi/parse.zig @@ -530,7 +530,7 @@ const Parser = struct { fn leaf_value(self: *Parser) ParseError!*Node { const node = try self.allocator.create(Node.Value); errdefer self.allocator.destroy(node); - node.* = .{ .string_value = .{} }; + node.* = .{ .string_value = .empty }; node.base.tree = self.tree; node.base.start = self.token_it.pos; errdefer node.string_value.deinit(self.allocator);