From 4d88f825bc5eb14aa00446f046ab4714a4fdce70 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 7 May 2023 15:38:31 -0700 Subject: [PATCH] stage2: implement intTagType logic This commit changes a lot of `*const Module` to `*Module` to make it work, since accessing the integer tag type of an enum might need to mutate the InternPool by adding a new integer type into it. An alternate strategy would be to pre-heat the InternPool with the integer tag type when creating an enum type, which would make it so that intTagType could accept a const Module instead of a mutable one, asserting that the InternPool already had the integer tag type. --- src/Module.zig | 29 ++++++------- src/Sema.zig | 14 +++---- src/arch/aarch64/CodeGen.zig | 2 +- src/arch/aarch64/abi.zig | 6 +-- src/arch/arm/CodeGen.zig | 2 +- src/arch/arm/abi.zig | 4 +- src/arch/riscv64/abi.zig | 2 +- src/arch/sparc64/CodeGen.zig | 2 +- src/arch/wasm/CodeGen.zig | 16 ++++---- src/arch/wasm/abi.zig | 4 +- src/arch/x86_64/CodeGen.zig | 4 +- src/arch/x86_64/abi.zig | 4 +- src/codegen.zig | 8 ++-- src/codegen/c.zig | 8 ++-- src/codegen/c/type.zig | 8 ++-- src/codegen/llvm.zig | 30 +++++++------- src/codegen/spirv.zig | 6 +-- src/type.zig | 80 +++++++++++++++++------------------- src/value.zig | 44 ++++++++++---------- 19 files changed, 136 insertions(+), 137 deletions(-) diff --git a/src/Module.zig b/src/Module.zig index 3f5dc8039e..ef38e6ff06 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -944,7 +944,7 @@ pub const Decl = struct { }; } - pub fn getAlignment(decl: Decl, mod: *const Module) u32 { + pub fn getAlignment(decl: Decl, mod: *Module) u32 { assert(decl.has_tv); if (decl.@"align" != 0) { // Explicit alignment. @@ -1053,7 +1053,7 @@ pub const Struct = struct { /// Returns the field alignment. If the struct is packed, returns 0. pub fn alignment( field: Field, - mod: *const Module, + mod: *Module, layout: std.builtin.Type.ContainerLayout, ) u32 { if (field.abi_align != 0) { @@ -1076,7 +1076,7 @@ pub const Struct = struct { } } - pub fn alignmentExtern(field: Field, mod: *const Module) u32 { + pub fn alignmentExtern(field: Field, mod: *Module) u32 { // This logic is duplicated in Type.abiAlignmentAdvanced. const ty_abi_align = field.ty.abiAlignment(mod); @@ -1157,7 +1157,7 @@ pub const Struct = struct { }; } - pub fn packedFieldBitOffset(s: Struct, mod: *const Module, index: usize) u16 { + pub fn packedFieldBitOffset(s: Struct, mod: *Module, index: usize) u16 { assert(s.layout == .Packed); assert(s.haveLayout()); var bit_sum: u64 = 0; @@ -1171,7 +1171,7 @@ pub const Struct = struct { } pub const RuntimeFieldIterator = struct { - module: *const Module, + module: *Module, struct_obj: *const Struct, index: u32 = 0, @@ -1201,7 +1201,7 @@ pub const Struct = struct { } }; - pub fn runtimeFieldIterator(s: *const Struct, module: *const Module) RuntimeFieldIterator { + pub fn runtimeFieldIterator(s: *const Struct, module: *Module) RuntimeFieldIterator { return .{ .struct_obj = s, .module = module, @@ -1353,7 +1353,7 @@ pub const Union = struct { /// Returns the field alignment, assuming the union is not packed. /// Keep implementation in sync with `Sema.unionFieldAlignment`. /// Prefer to call that function instead of this one during Sema. - pub fn normalAlignment(field: Field, mod: *const Module) u32 { + pub fn normalAlignment(field: Field, mod: *Module) u32 { if (field.abi_align == 0) { return field.ty.abiAlignment(mod); } else { @@ -1413,7 +1413,7 @@ pub const Union = struct { }; } - pub fn hasAllZeroBitFieldTypes(u: Union, mod: *const Module) bool { + pub fn hasAllZeroBitFieldTypes(u: Union, mod: *Module) bool { assert(u.haveFieldTypes()); for (u.fields.values()) |field| { if (field.ty.hasRuntimeBits(mod)) return false; @@ -1421,7 +1421,7 @@ pub const Union = struct { return true; } - pub fn mostAlignedField(u: Union, mod: *const Module) u32 { + pub fn mostAlignedField(u: Union, mod: *Module) u32 { assert(u.haveFieldTypes()); var most_alignment: u32 = 0; var most_index: usize = undefined; @@ -1438,7 +1438,7 @@ pub const Union = struct { } /// Returns 0 if the union is represented with 0 bits at runtime. - pub fn abiAlignment(u: Union, mod: *const Module, have_tag: bool) u32 { + pub fn abiAlignment(u: Union, mod: *Module, have_tag: bool) u32 { var max_align: u32 = 0; if (have_tag) max_align = u.tag_ty.abiAlignment(mod); for (u.fields.values()) |field| { @@ -1450,7 +1450,7 @@ pub const Union = struct { return max_align; } - pub fn abiSize(u: Union, mod: *const Module, have_tag: bool) u64 { + pub fn abiSize(u: Union, mod: *Module, have_tag: bool) u64 { return u.getLayout(mod, have_tag).abi_size; } @@ -1481,7 +1481,7 @@ pub const Union = struct { }; } - pub fn getLayout(u: Union, mod: *const Module, have_tag: bool) Layout { + pub fn getLayout(u: Union, mod: *Module, have_tag: bool) Layout { assert(u.haveLayout()); var most_aligned_field: u32 = undefined; var most_aligned_field_size: u64 = undefined; @@ -6988,6 +6988,7 @@ pub const AtomicPtrAlignmentError = error{ FloatTooBig, IntTooBig, BadType, + OutOfMemory, }; pub const AtomicPtrAlignmentDiagnostics = struct { @@ -7001,7 +7002,7 @@ pub const AtomicPtrAlignmentDiagnostics = struct { // TODO this function does not take into account CPU features, which can affect // this value. Audit this! pub fn atomicPtrAlignment( - mod: *const Module, + mod: *Module, ty: Type, diags: *AtomicPtrAlignmentDiagnostics, ) AtomicPtrAlignmentError!u32 { @@ -7080,7 +7081,7 @@ pub fn atomicPtrAlignment( const int_ty = switch (ty.zigTypeTag(mod)) { .Int => ty, - .Enum => ty.intTagType(), + .Enum => try ty.intTagType(mod), .Float => { const bit_count = ty.floatBits(target); if (bit_count > max_atomic_bits) { diff --git a/src/Sema.zig b/src/Sema.zig index ca6f28017b..8725704937 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -8249,7 +8249,6 @@ fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const mod = sema.mod; - const arena = sema.arena; const inst_data = sema.code.instructions.items(.data)[inst].un_node; const src = inst_data.src(); const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; @@ -8278,7 +8277,7 @@ fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A }; const enum_tag_ty = sema.typeOf(enum_tag); - const int_tag_ty = try enum_tag_ty.intTagType().copy(arena); + const int_tag_ty = try enum_tag_ty.intTagType(mod); if (try sema.typeHasOnePossibleValue(enum_tag_ty)) |opv| { return sema.addConstant(int_tag_ty, opv); @@ -8310,7 +8309,7 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A if (try sema.resolveMaybeUndefVal(operand)) |int_val| { if (dest_ty.isNonexhaustiveEnum()) { - const int_tag_ty = dest_ty.intTagType(); + const int_tag_ty = try dest_ty.intTagType(mod); if (try sema.intFitsInType(int_val, int_tag_ty, null)) { return sema.addConstant(dest_ty, int_val); } @@ -16268,7 +16267,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai }, .Enum => { // TODO: look into memoizing this result. - const int_tag_ty = try ty.intTagType().copy(sema.arena); + const int_tag_ty = try ty.intTagType(mod); const is_exhaustive = Value.makeBool(!ty.isNonexhaustiveEnum()); @@ -20354,7 +20353,7 @@ fn zirBitCount( block: *Block, inst: Zir.Inst.Index, air_tag: Air.Inst.Tag, - comptime comptimeOp: fn (val: Value, ty: Type, mod: *const Module) u64, + comptime comptimeOp: fn (val: Value, ty: Type, mod: *Module) u64, ) CompileError!Air.Inst.Ref { const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[inst].un_node; @@ -20755,6 +20754,7 @@ fn checkAtomicPtrOperand( const mod = sema.mod; var diag: Module.AtomicPtrAlignmentDiagnostics = .{}; const alignment = mod.atomicPtrAlignment(elem_ty, &diag) catch |err| switch (err) { + error.OutOfMemory => return error.OutOfMemory, error.FloatTooBig => return sema.fail( block, elem_ty_src, @@ -23462,7 +23462,7 @@ fn validateExternType( return !Type.fnCallingConventionAllowsZigTypes(target, ty.fnCallingConvention()); }, .Enum => { - return sema.validateExternType(ty.intTagType(), position); + return sema.validateExternType(try ty.intTagType(mod), position); }, .Struct, .Union => switch (ty.containerLayout()) { .Extern => return true, @@ -23540,7 +23540,7 @@ fn explainWhyTypeIsNotExtern( } }, .Enum => { - const tag_ty = ty.intTagType(); + const tag_ty = try ty.intTagType(mod); try mod.errNoteNonLazy(src_loc, msg, "enum tag type '{}' is not extern compatible", .{tag_ty.fmt(sema.mod)}); try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position); }, diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index ea3814a20e..970d59a25f 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -4533,7 +4533,7 @@ fn cmp( } }, .Float => return self.fail("TODO ARM cmp floats", .{}), - .Enum => lhs_ty.intTagType(), + .Enum => try lhs_ty.intTagType(mod), .Int => lhs_ty, .Bool => Type.u1, .Pointer => Type.usize, diff --git a/src/arch/aarch64/abi.zig b/src/arch/aarch64/abi.zig index 821afd27ae..1d042b632a 100644 --- a/src/arch/aarch64/abi.zig +++ b/src/arch/aarch64/abi.zig @@ -15,7 +15,7 @@ pub const Class = union(enum) { }; /// For `float_array` the second element will be the amount of floats. -pub fn classifyType(ty: Type, mod: *const Module) Class { +pub fn classifyType(ty: Type, mod: *Module) Class { std.debug.assert(ty.hasRuntimeBitsIgnoreComptime(mod)); var maybe_float_bits: ?u16 = null; @@ -74,7 +74,7 @@ pub fn classifyType(ty: Type, mod: *const Module) Class { } const sret_float_count = 4; -fn countFloats(ty: Type, mod: *const Module, maybe_float_bits: *?u16) u8 { +fn countFloats(ty: Type, mod: *Module, maybe_float_bits: *?u16) u8 { const target = mod.getTarget(); const invalid = std.math.maxInt(u8); switch (ty.zigTypeTag(mod)) { @@ -115,7 +115,7 @@ fn countFloats(ty: Type, mod: *const Module, maybe_float_bits: *?u16) u8 { } } -pub fn getFloatArrayType(ty: Type, mod: *const Module) ?Type { +pub fn getFloatArrayType(ty: Type, mod: *Module) ?Type { switch (ty.zigTypeTag(mod)) { .Union => { const fields = ty.unionFields(); diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig index 967a6dd753..50f6d76c55 100644 --- a/src/arch/arm/CodeGen.zig +++ b/src/arch/arm/CodeGen.zig @@ -4480,7 +4480,7 @@ fn cmp( } }, .Float => return self.fail("TODO ARM cmp floats", .{}), - .Enum => lhs_ty.intTagType(), + .Enum => try lhs_ty.intTagType(mod), .Int => lhs_ty, .Bool => Type.u1, .Pointer => Type.usize, diff --git a/src/arch/arm/abi.zig b/src/arch/arm/abi.zig index eee4b41eef..79ffadf831 100644 --- a/src/arch/arm/abi.zig +++ b/src/arch/arm/abi.zig @@ -24,7 +24,7 @@ pub const Class = union(enum) { pub const Context = enum { ret, arg }; -pub fn classifyType(ty: Type, mod: *const Module, ctx: Context) Class { +pub fn classifyType(ty: Type, mod: *Module, ctx: Context) Class { assert(ty.hasRuntimeBitsIgnoreComptime(mod)); var maybe_float_bits: ?u16 = null; @@ -116,7 +116,7 @@ pub fn classifyType(ty: Type, mod: *const Module, ctx: Context) Class { } const byval_float_count = 4; -fn countFloats(ty: Type, mod: *const Module, maybe_float_bits: *?u16) u32 { +fn countFloats(ty: Type, mod: *Module, maybe_float_bits: *?u16) u32 { const target = mod.getTarget(); const invalid = std.math.maxInt(u32); switch (ty.zigTypeTag(mod)) { diff --git a/src/arch/riscv64/abi.zig b/src/arch/riscv64/abi.zig index ac0d8d3e32..28a69d9136 100644 --- a/src/arch/riscv64/abi.zig +++ b/src/arch/riscv64/abi.zig @@ -7,7 +7,7 @@ const Module = @import("../../Module.zig"); pub const Class = enum { memory, byval, integer, double_integer }; -pub fn classifyType(ty: Type, mod: *const Module) Class { +pub fn classifyType(ty: Type, mod: *Module) Class { const target = mod.getTarget(); std.debug.assert(ty.hasRuntimeBitsIgnoreComptime(mod)); diff --git a/src/arch/sparc64/CodeGen.zig b/src/arch/sparc64/CodeGen.zig index 2cb35460c2..0490db615b 100644 --- a/src/arch/sparc64/CodeGen.zig +++ b/src/arch/sparc64/CodeGen.zig @@ -1436,7 +1436,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { const int_ty = switch (lhs_ty.zigTypeTag(mod)) { .Vector => unreachable, // Handled by cmp_vector. - .Enum => lhs_ty.intTagType(), + .Enum => try lhs_ty.intTagType(mod), .Int => lhs_ty, .Bool => Type.u1, .Pointer => Type.usize, diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index 36b805cf94..237a55984e 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -1393,7 +1393,7 @@ fn resolveCallingConventionValues(func: *CodeGen, fn_ty: Type) InnerError!CallWV return result; } -fn firstParamSRet(cc: std.builtin.CallingConvention, return_type: Type, mod: *const Module) bool { +fn firstParamSRet(cc: std.builtin.CallingConvention, return_type: Type, mod: *Module) bool { switch (cc) { .Unspecified, .Inline => return isByRef(return_type, mod), .C => { @@ -1713,7 +1713,7 @@ fn arch(func: *const CodeGen) std.Target.Cpu.Arch { /// For a given `Type`, will return true when the type will be passed /// by reference, rather than by value -fn isByRef(ty: Type, mod: *const Module) bool { +fn isByRef(ty: Type, mod: *Module) bool { const target = mod.getTarget(); switch (ty.zigTypeTag(mod)) { .Type, @@ -1787,7 +1787,7 @@ const SimdStoreStrategy = enum { /// This means when a given type is 128 bits and either the simd128 or relaxed-simd /// features are enabled, the function will return `.direct`. This would allow to store /// it using a instruction, rather than an unrolled version. -fn determineSimdStoreStrategy(ty: Type, mod: *const Module) SimdStoreStrategy { +fn determineSimdStoreStrategy(ty: Type, mod: *Module) SimdStoreStrategy { std.debug.assert(ty.zigTypeTag(mod) == .Vector); if (ty.bitSize(mod) != 128) return .unrolled; const hasFeature = std.Target.wasm.featureSetHas; @@ -3121,7 +3121,7 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue { else => return func.fail("TODO: lowerConstant for enum tag: {}", .{ty.tag()}), } } else { - const int_tag_ty = ty.intTagType(); + const int_tag_ty = try ty.intTagType(mod); return func.lowerConstant(val, int_tag_ty); } }, @@ -3235,7 +3235,7 @@ fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue { /// Returns a `Value` as a signed 32 bit value. /// It's illegal to provide a value with a type that cannot be represented /// as an integer value. -fn valueAsI32(func: *const CodeGen, val: Value, ty: Type) i32 { +fn valueAsI32(func: *const CodeGen, val: Value, ty: Type) !i32 { const mod = func.bin_file.base.options.module.?; switch (ty.zigTypeTag(mod)) { .Enum => { @@ -3257,7 +3257,7 @@ fn valueAsI32(func: *const CodeGen, val: Value, ty: Type) i32 { else => unreachable, } } else { - const int_tag_ty = ty.intTagType(); + const int_tag_ty = try ty.intTagType(mod); return func.valueAsI32(val, int_tag_ty); } }, @@ -3793,7 +3793,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { for (items, 0..) |ref, i| { const item_val = (try func.air.value(ref, mod)).?; - const int_val = func.valueAsI32(item_val, target_ty); + const int_val = try func.valueAsI32(item_val, target_ty); if (lowest_maybe == null or int_val < lowest_maybe.?) { lowest_maybe = int_val; } @@ -6814,7 +6814,7 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 { return loc.index; } - const int_tag_ty = enum_ty.intTagType(); + const int_tag_ty = try enum_ty.intTagType(mod); if (int_tag_ty.bitSize(mod) > 64) { return func.fail("TODO: Implement @tagName for enums with tag size larger than 64 bits", .{}); diff --git a/src/arch/wasm/abi.zig b/src/arch/wasm/abi.zig index c7819b0fa6..bb5911382b 100644 --- a/src/arch/wasm/abi.zig +++ b/src/arch/wasm/abi.zig @@ -21,7 +21,7 @@ const direct: [2]Class = .{ .direct, .none }; /// Classifies a given Zig type to determine how they must be passed /// or returned as value within a wasm function. /// When all elements result in `.none`, no value must be passed in or returned. -pub fn classifyType(ty: Type, mod: *const Module) [2]Class { +pub fn classifyType(ty: Type, mod: *Module) [2]Class { const target = mod.getTarget(); if (!ty.hasRuntimeBitsIgnoreComptime(mod)) return none; switch (ty.zigTypeTag(mod)) { @@ -93,7 +93,7 @@ pub fn classifyType(ty: Type, mod: *const Module) [2]Class { /// Returns the scalar type a given type can represent. /// Asserts given type can be represented as scalar, such as /// a struct with a single scalar field. -pub fn scalarType(ty: Type, mod: *const Module) Type { +pub fn scalarType(ty: Type, mod: *Module) Type { switch (ty.zigTypeTag(mod)) { .Struct => { switch (ty.containerLayout()) { diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index c5e3410947..1cfed06ff1 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -605,7 +605,7 @@ const FrameAlloc = struct { .ref_count = 0, }; } - fn initType(ty: Type, mod: *const Module) FrameAlloc { + fn initType(ty: Type, mod: *Module) FrameAlloc { return init(.{ .size = ty.abiSize(mod), .alignment = ty.abiAlignment(mod) }); } }; @@ -2309,7 +2309,7 @@ fn allocRegOrMemAdvanced(self: *Self, ty: Type, inst: ?Air.Inst.Index, reg_ok: b return .{ .load_frame = .{ .index = frame_index } }; } -fn regClassForType(ty: Type, mod: *const Module) RegisterManager.RegisterBitSet { +fn regClassForType(ty: Type, mod: *Module) RegisterManager.RegisterBitSet { return switch (ty.zigTypeTag(mod)) { .Float, .Vector => sse, else => gp, diff --git a/src/arch/x86_64/abi.zig b/src/arch/x86_64/abi.zig index ea75a1f4d2..1bae899d33 100644 --- a/src/arch/x86_64/abi.zig +++ b/src/arch/x86_64/abi.zig @@ -12,7 +12,7 @@ pub const Class = enum { float_combine, }; -pub fn classifyWindows(ty: Type, mod: *const Module) Class { +pub fn classifyWindows(ty: Type, mod: *Module) Class { // https://docs.microsoft.com/en-gb/cpp/build/x64-calling-convention?view=vs-2017 // "There's a strict one-to-one correspondence between a function call's arguments // and the registers used for those arguments. Any argument that doesn't fit in 8 @@ -68,7 +68,7 @@ pub const Context = enum { ret, arg, other }; /// There are a maximum of 8 possible return slots. Returned values are in /// the beginning of the array; unused slots are filled with .none. -pub fn classifySystemV(ty: Type, mod: *const Module, ctx: Context) [8]Class { +pub fn classifySystemV(ty: Type, mod: *Module, ctx: Context) [8]Class { const target = mod.getTarget(); const memory_class = [_]Class{ .memory, .none, .none, .none, diff --git a/src/codegen.zig b/src/codegen.zig index 8bd478bf7c..70df1fc17b 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -1241,7 +1241,7 @@ pub fn genTypedValue( if (enum_values.count() != 0) { const tag_val = enum_values.keys()[field_index.data]; return genTypedValue(bin_file, src_loc, .{ - .ty = typed_value.ty.intTagType(), + .ty = try typed_value.ty.intTagType(mod), .val = tag_val, }, owner_decl_index); } else { @@ -1251,7 +1251,7 @@ pub fn genTypedValue( else => unreachable, } } else { - const int_tag_ty = typed_value.ty.intTagType(); + const int_tag_ty = try typed_value.ty.intTagType(mod); return genTypedValue(bin_file, src_loc, .{ .ty = int_tag_ty, .val = typed_value.val, @@ -1303,7 +1303,7 @@ pub fn genTypedValue( return genUnnamedConst(bin_file, src_loc, typed_value, owner_decl_index); } -pub fn errUnionPayloadOffset(payload_ty: Type, mod: *const Module) u64 { +pub fn errUnionPayloadOffset(payload_ty: Type, mod: *Module) u64 { if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) return 0; const payload_align = payload_ty.abiAlignment(mod); const error_align = Type.anyerror.abiAlignment(mod); @@ -1314,7 +1314,7 @@ pub fn errUnionPayloadOffset(payload_ty: Type, mod: *const Module) u64 { } } -pub fn errUnionErrorOffset(payload_ty: Type, mod: *const Module) u64 { +pub fn errUnionErrorOffset(payload_ty: Type, mod: *Module) u64 { if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) return 0; const payload_align = payload_ty.abiAlignment(mod); const error_align = Type.anyerror.abiAlignment(mod); diff --git a/src/codegen/c.zig b/src/codegen/c.zig index b688aada34..3c6f5a9e73 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -1300,7 +1300,7 @@ pub const DeclGen = struct { } }, else => { - const int_tag_ty = ty.intTagType(); + const int_tag_ty = try ty.intTagType(mod); return dg.renderValue(writer, int_tag_ty, val, location); }, } @@ -5198,7 +5198,7 @@ fn fieldLocation( container_ty: Type, field_ptr_ty: Type, field_index: u32, - mod: *const Module, + mod: *Module, ) union(enum) { begin: void, field: CValue, @@ -7722,7 +7722,7 @@ const LowerFnRetTyBuffer = struct { values: [1]Value, payload: Type.Payload.AnonStruct, }; -fn lowerFnRetTy(ret_ty: Type, buffer: *LowerFnRetTyBuffer, mod: *const Module) Type { +fn lowerFnRetTy(ret_ty: Type, buffer: *LowerFnRetTyBuffer, mod: *Module) Type { if (ret_ty.zigTypeTag(mod) == .NoReturn) return Type.noreturn; if (lowersToArray(ret_ty, mod)) { @@ -7740,7 +7740,7 @@ fn lowerFnRetTy(ret_ty: Type, buffer: *LowerFnRetTyBuffer, mod: *const Module) T return if (ret_ty.hasRuntimeBitsIgnoreComptime(mod)) ret_ty else Type.void; } -fn lowersToArray(ty: Type, mod: *const Module) bool { +fn lowersToArray(ty: Type, mod: *Module) bool { return switch (ty.zigTypeTag(mod)) { .Array, .Vector => return true, else => return ty.isAbiInt(mod) and toCIntBits(@intCast(u32, ty.bitSize(mod))) == null, diff --git a/src/codegen/c/type.zig b/src/codegen/c/type.zig index 84ddce6809..0823400858 100644 --- a/src/codegen/c/type.zig +++ b/src/codegen/c/type.zig @@ -292,17 +292,17 @@ pub const CType = extern union { .abi = std.math.log2_int(u32, abi_alignment), }; } - pub fn abiAlign(ty: Type, mod: *const Module) AlignAs { + pub fn abiAlign(ty: Type, mod: *Module) AlignAs { const abi_align = ty.abiAlignment(mod); return init(abi_align, abi_align); } - pub fn fieldAlign(struct_ty: Type, field_i: usize, mod: *const Module) AlignAs { + pub fn fieldAlign(struct_ty: Type, field_i: usize, mod: *Module) AlignAs { return init( struct_ty.structFieldAlign(field_i, mod), struct_ty.structFieldType(field_i).abiAlignment(mod), ); } - pub fn unionPayloadAlign(union_ty: Type, mod: *const Module) AlignAs { + pub fn unionPayloadAlign(union_ty: Type, mod: *Module) AlignAs { const union_obj = union_ty.cast(Type.Payload.Union).?.data; const union_payload_align = union_obj.abiAlignment(mod, false); return init(union_payload_align, union_payload_align); @@ -1897,7 +1897,7 @@ pub const CType = extern union { } } - fn createFromType(store: *Store.Promoted, ty: Type, mod: *const Module, kind: Kind) !CType { + fn createFromType(store: *Store.Promoted, ty: Type, mod: *Module, kind: Kind) !CType { var convert: Convert = undefined; try convert.initType(ty, kind, .{ .imm = .{ .set = &store.set, .mod = mod } }); return createFromConvert(store, ty, mod, kind, &convert); diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 23340b5d34..5f013c38ec 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1527,7 +1527,7 @@ pub const Object = struct { }; const field_index_val = Value.initPayload(&buf_field_index.base); - const int_ty = ty.intTagType(); + const int_ty = try ty.intTagType(mod); const int_info = ty.intInfo(mod); assert(int_info.bits != 0); @@ -2805,7 +2805,7 @@ pub const DeclGen = struct { return dg.context.intType(info.bits); }, .Enum => { - const int_ty = t.intTagType(); + const int_ty = try t.intTagType(mod); const bit_count = int_ty.intInfo(mod).bits; assert(bit_count != 0); return dg.context.intType(bit_count); @@ -4334,7 +4334,9 @@ pub const DeclGen = struct { const mod = dg.module; const int_ty = switch (ty.zigTypeTag(mod)) { .Int => ty, - .Enum => ty.intTagType(), + .Enum => ty.intTagType(mod) catch |err| switch (err) { + error.OutOfMemory => @panic("OOM"), + }, .Float => { if (!is_rmw_xchg) return null; return dg.context.intType(@intCast(c_uint, ty.abiSize(mod) * 8)); @@ -5286,7 +5288,7 @@ pub const FuncGen = struct { const mod = self.dg.module; const scalar_ty = operand_ty.scalarType(mod); const int_ty = switch (scalar_ty.zigTypeTag(mod)) { - .Enum => scalar_ty.intTagType(), + .Enum => try scalar_ty.intTagType(mod), .Int, .Bool, .Pointer, .ErrorSet => scalar_ty, .Optional => blk: { const payload_ty = operand_ty.optionalChild(mod); @@ -8867,7 +8869,7 @@ pub const FuncGen = struct { defer self.gpa.free(fqn); const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_is_named_enum_value_{s}", .{fqn}); - const int_tag_ty = enum_ty.intTagType(); + const int_tag_ty = try enum_ty.intTagType(mod); const param_types = [_]*llvm.Type{try self.dg.lowerType(int_tag_ty)}; const llvm_ret_ty = try self.dg.lowerType(Type.bool); @@ -8950,7 +8952,7 @@ pub const FuncGen = struct { const usize_llvm_ty = try self.dg.lowerType(Type.usize); const slice_alignment = slice_ty.abiAlignment(mod); - const int_tag_ty = enum_ty.intTagType(); + const int_tag_ty = try enum_ty.intTagType(mod); const param_types = [_]*llvm.Type{try self.dg.lowerType(int_tag_ty)}; const fn_type = llvm.functionType(llvm_ret_ty, ¶m_types, param_types.len, .False); @@ -10487,7 +10489,7 @@ fn toLlvmGlobalAddressSpace(wanted_address_space: std.builtin.AddressSpace, targ fn llvmFieldIndex( ty: Type, field_index: usize, - mod: *const Module, + mod: *Module, ptr_pl_buf: *Type.Payload.Pointer, ) ?c_uint { // Detects where we inserted extra padding fields so that we can skip @@ -10564,7 +10566,7 @@ fn llvmFieldIndex( } } -fn firstParamSRet(fn_info: Type.Payload.Function.Data, mod: *const Module) bool { +fn firstParamSRet(fn_info: Type.Payload.Function.Data, mod: *Module) bool { if (!fn_info.return_type.hasRuntimeBitsIgnoreComptime(mod)) return false; const target = mod.getTarget(); @@ -10593,7 +10595,7 @@ fn firstParamSRet(fn_info: Type.Payload.Function.Data, mod: *const Module) bool } } -fn firstParamSRetSystemV(ty: Type, mod: *const Module) bool { +fn firstParamSRetSystemV(ty: Type, mod: *Module) bool { const class = x86_64_abi.classifySystemV(ty, mod, .ret); if (class[0] == .memory) return true; if (class[0] == .x87 and class[2] != .none) return true; @@ -11041,7 +11043,7 @@ fn iterateParamTypes(dg: *DeclGen, fn_info: Type.Payload.Function.Data) ParamTyp fn ccAbiPromoteInt( cc: std.builtin.CallingConvention, - mod: *const Module, + mod: *Module, ty: Type, ) ?std.builtin.Signedness { const target = mod.getTarget(); @@ -11080,7 +11082,7 @@ fn ccAbiPromoteInt( /// This is the one source of truth for whether a type is passed around as an LLVM pointer, /// or as an LLVM value. -fn isByRef(ty: Type, mod: *const Module) bool { +fn isByRef(ty: Type, mod: *Module) bool { // For tuples and structs, if there are more than this many non-void // fields, then we make it byref, otherwise byval. const max_fields_byval = 0; @@ -11159,7 +11161,7 @@ fn isByRef(ty: Type, mod: *const Module) bool { } } -fn isScalar(mod: *const Module, ty: Type) bool { +fn isScalar(mod: *Module, ty: Type) bool { return switch (ty.zigTypeTag(mod)) { .Void, .Bool, @@ -11344,11 +11346,11 @@ fn buildAllocaInner( return alloca; } -fn errUnionPayloadOffset(payload_ty: Type, mod: *const Module) u1 { +fn errUnionPayloadOffset(payload_ty: Type, mod: *Module) u1 { return @boolToInt(Type.anyerror.abiAlignment(mod) > payload_ty.abiAlignment(mod)); } -fn errUnionErrorOffset(payload_ty: Type, mod: *const Module) u1 { +fn errUnionErrorOffset(payload_ty: Type, mod: *Module) u1 { return @boolToInt(Type.anyerror.abiAlignment(mod) <= payload_ty.abiAlignment(mod)); } diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 3842da5f7b..843b67e426 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -745,7 +745,7 @@ pub const DeclGen = struct { .Enum => { const int_val = try val.enumToInt(ty, mod); - const int_ty = ty.intTagType(); + const int_ty = try ty.intTagType(mod); try self.lower(int_ty, int_val); }, @@ -1195,7 +1195,7 @@ pub const DeclGen = struct { return try self.intType(int_info.signedness, int_info.bits); }, .Enum => { - const tag_ty = ty.intTagType(); + const tag_ty = try ty.intTagType(mod); return self.resolveType(tag_ty, repr); }, .Float => { @@ -3090,7 +3090,7 @@ pub const DeclGen = struct { break :blk if (backing_bits <= 32) @as(u32, 1) else 2; }, .Enum => blk: { - const int_ty = cond_ty.intTagType(); + const int_ty = try cond_ty.intTagType(mod); const int_info = int_ty.intInfo(mod); const backing_bits = self.backingIntBits(int_info.bits) orelse { return self.todo("implement composite int switch", .{}); diff --git a/src/type.zig b/src/type.zig index 68ac507037..9c8c1f1591 100644 --- a/src/type.zig +++ b/src/type.zig @@ -1606,7 +1606,7 @@ pub const Type = struct { /// may return false positives. pub fn hasRuntimeBitsAdvanced( ty: Type, - mod: *const Module, + mod: *Module, ignore_comptime_only: bool, strat: AbiAlignmentAdvancedStrat, ) RuntimeBitsError!bool { @@ -1785,7 +1785,7 @@ pub const Type = struct { return enum_simple.fields.count() >= 2; }, .enum_numbered, .enum_nonexhaustive => { - const int_tag_ty = ty.intTagType(); + const int_tag_ty = try ty.intTagType(mod); return int_tag_ty.hasRuntimeBitsAdvanced(mod, ignore_comptime_only, strat); }, @@ -1850,7 +1850,7 @@ pub const Type = struct { /// true if and only if the type has a well-defined memory layout /// readFrom/writeToMemory are supported only for types with a well- /// defined memory layout - pub fn hasWellDefinedLayout(ty: Type, mod: *const Module) bool { + pub fn hasWellDefinedLayout(ty: Type, mod: *Module) bool { if (ty.ip_index != .none) return switch (mod.intern_pool.indexToKey(ty.ip_index)) { .int_type => true, .ptr_type => true, @@ -1952,15 +1952,15 @@ pub const Type = struct { }; } - pub fn hasRuntimeBits(ty: Type, mod: *const Module) bool { + pub fn hasRuntimeBits(ty: Type, mod: *Module) bool { return hasRuntimeBitsAdvanced(ty, mod, false, .eager) catch unreachable; } - pub fn hasRuntimeBitsIgnoreComptime(ty: Type, mod: *const Module) bool { + pub fn hasRuntimeBitsIgnoreComptime(ty: Type, mod: *Module) bool { return hasRuntimeBitsAdvanced(ty, mod, true, .eager) catch unreachable; } - pub fn isFnOrHasRuntimeBits(ty: Type, mod: *const Module) bool { + pub fn isFnOrHasRuntimeBits(ty: Type, mod: *Module) bool { switch (ty.zigTypeTag(mod)) { .Fn => { const fn_info = ty.fnInfo(); @@ -1980,7 +1980,7 @@ pub const Type = struct { } /// Same as `isFnOrHasRuntimeBits` but comptime-only types may return a false positive. - pub fn isFnOrHasRuntimeBitsIgnoreComptime(ty: Type, mod: *const Module) bool { + pub fn isFnOrHasRuntimeBitsIgnoreComptime(ty: Type, mod: *Module) bool { return switch (ty.zigTypeTag(mod)) { .Fn => true, else => return ty.hasRuntimeBitsIgnoreComptime(mod), @@ -2019,11 +2019,11 @@ pub const Type = struct { } /// Returns 0 if the pointer is naturally aligned and the element type is 0-bit. - pub fn ptrAlignment(ty: Type, mod: *const Module) u32 { + pub fn ptrAlignment(ty: Type, mod: *Module) u32 { return ptrAlignmentAdvanced(ty, mod, null) catch unreachable; } - pub fn ptrAlignmentAdvanced(ty: Type, mod: *const Module, opt_sema: ?*Sema) !u32 { + pub fn ptrAlignmentAdvanced(ty: Type, mod: *Module, opt_sema: ?*Sema) !u32 { switch (ty.ip_index) { .none => switch (ty.tag()) { .pointer => { @@ -2072,7 +2072,7 @@ pub const Type = struct { } /// Returns 0 for 0-bit types. - pub fn abiAlignment(ty: Type, mod: *const Module) u32 { + pub fn abiAlignment(ty: Type, mod: *Module) u32 { return (ty.abiAlignmentAdvanced(mod, .eager) catch unreachable).scalar; } @@ -2103,7 +2103,7 @@ pub const Type = struct { /// necessary, possibly returning a CompileError. pub fn abiAlignmentAdvanced( ty: Type, - mod: *const Module, + mod: *Module, strat: AbiAlignmentAdvancedStrat, ) Module.CompileError!AbiAlignmentAdvanced { const target = mod.getTarget(); @@ -2320,7 +2320,7 @@ pub const Type = struct { }, .enum_full, .enum_nonexhaustive, .enum_simple, .enum_numbered => { - const int_tag_ty = ty.intTagType(); + const int_tag_ty = try ty.intTagType(mod); return AbiAlignmentAdvanced{ .scalar = int_tag_ty.abiAlignment(mod) }; }, .@"union" => { @@ -2344,7 +2344,7 @@ pub const Type = struct { fn abiAlignmentAdvancedErrorUnion( ty: Type, - mod: *const Module, + mod: *Module, strat: AbiAlignmentAdvancedStrat, ) Module.CompileError!AbiAlignmentAdvanced { // This code needs to be kept in sync with the equivalent switch prong @@ -2380,7 +2380,7 @@ pub const Type = struct { fn abiAlignmentAdvancedOptional( ty: Type, - mod: *const Module, + mod: *Module, strat: AbiAlignmentAdvancedStrat, ) Module.CompileError!AbiAlignmentAdvanced { const target = mod.getTarget(); @@ -2412,7 +2412,7 @@ pub const Type = struct { pub fn abiAlignmentAdvancedUnion( ty: Type, - mod: *const Module, + mod: *Module, strat: AbiAlignmentAdvancedStrat, union_obj: *Module.Union, have_tag: bool, @@ -2477,7 +2477,7 @@ pub const Type = struct { /// Asserts the type has the ABI size already resolved. /// Types that return false for hasRuntimeBits() return 0. - pub fn abiSize(ty: Type, mod: *const Module) u64 { + pub fn abiSize(ty: Type, mod: *Module) u64 { return (abiSizeAdvanced(ty, mod, .eager) catch unreachable).scalar; } @@ -2494,7 +2494,7 @@ pub const Type = struct { /// necessary, possibly returning a CompileError. pub fn abiSizeAdvanced( ty: Type, - mod: *const Module, + mod: *Module, strat: AbiAlignmentAdvancedStrat, ) Module.CompileError!AbiSizeAdvanced { const target = mod.getTarget(); @@ -2661,7 +2661,7 @@ pub const Type = struct { }, .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => { - const int_tag_ty = ty.intTagType(); + const int_tag_ty = try ty.intTagType(mod); return AbiSizeAdvanced{ .scalar = int_tag_ty.abiSize(mod) }; }, .@"union" => { @@ -2754,7 +2754,7 @@ pub const Type = struct { pub fn abiSizeAdvancedUnion( ty: Type, - mod: *const Module, + mod: *Module, strat: AbiAlignmentAdvancedStrat, union_obj: *Module.Union, have_tag: bool, @@ -2773,7 +2773,7 @@ pub const Type = struct { fn abiSizeAdvancedOptional( ty: Type, - mod: *const Module, + mod: *Module, strat: AbiAlignmentAdvancedStrat, ) Module.CompileError!AbiSizeAdvanced { const child_ty = ty.optionalChild(mod); @@ -2821,7 +2821,7 @@ pub const Type = struct { ); } - pub fn bitSize(ty: Type, mod: *const Module) u64 { + pub fn bitSize(ty: Type, mod: *Module) u64 { return bitSizeAdvanced(ty, mod, null) catch unreachable; } @@ -2830,7 +2830,7 @@ pub const Type = struct { /// the type is fully resolved, and there will be no error, guaranteed. pub fn bitSizeAdvanced( ty: Type, - mod: *const Module, + mod: *Module, opt_sema: ?*Sema, ) Module.CompileError!u64 { const target = mod.getTarget(); @@ -2950,7 +2950,7 @@ pub const Type = struct { }, .enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => { - const int_tag_ty = ty.intTagType(); + const int_tag_ty = try ty.intTagType(mod); return try bitSizeAdvanced(int_tag_ty, mod, opt_sema); }, @@ -3464,11 +3464,11 @@ pub const Type = struct { return union_obj.fields.getIndex(name); } - pub fn unionHasAllZeroBitFieldTypes(ty: Type, mod: *const Module) bool { + pub fn unionHasAllZeroBitFieldTypes(ty: Type, mod: *Module) bool { return ty.cast(Payload.Union).?.data.hasAllZeroBitFieldTypes(mod); } - pub fn unionGetLayout(ty: Type, mod: *const Module) Module.Union.Layout { + pub fn unionGetLayout(ty: Type, mod: *Module) Module.Union.Layout { switch (ty.tag()) { .@"union" => { const union_obj = ty.castTag(.@"union").?.data; @@ -4428,24 +4428,18 @@ pub const Type = struct { } /// Asserts the type is an enum or a union. - pub fn intTagType(ty: Type) Type { + pub fn intTagType(ty: Type, mod: *Module) !Type { switch (ty.tag()) { .enum_full, .enum_nonexhaustive => return ty.cast(Payload.EnumFull).?.data.tag_ty, .enum_numbered => return ty.castTag(.enum_numbered).?.data.tag_ty, .enum_simple => { - @panic("TODO move enum_simple to use the intern pool"); - //const enum_simple = ty.castTag(.enum_simple).?.data; - //const field_count = enum_simple.fields.count(); - //const bits: u16 = if (field_count == 0) 0 else std.math.log2_int_ceil(usize, field_count); - //buffer.* = .{ - // .base = .{ .tag = .int_unsigned }, - // .data = bits, - //}; - //return Type.initPayload(&buffer.base); + const enum_simple = ty.castTag(.enum_simple).?.data; + const field_count = enum_simple.fields.count(); + const bits: u16 = if (field_count == 0) 0 else std.math.log2_int_ceil(usize, field_count); + return mod.intType(.unsigned, bits); }, .union_tagged => { - @panic("TODO move union_tagged to use the intern pool"); - //return ty.castTag(.union_tagged).?.data.tag_ty.intTagType(buffer), + return ty.castTag(.union_tagged).?.data.tag_ty.intTagType(mod); }, else => unreachable, } @@ -4628,7 +4622,7 @@ pub const Type = struct { } } - pub fn structFieldAlign(ty: Type, index: usize, mod: *const Module) u32 { + pub fn structFieldAlign(ty: Type, index: usize, mod: *Module) u32 { switch (ty.tag()) { .@"struct" => { const struct_obj = ty.castTag(.@"struct").?.data; @@ -4718,7 +4712,7 @@ pub const Type = struct { } } - pub fn packedStructFieldByteOffset(ty: Type, field_index: usize, mod: *const Module) u32 { + pub fn packedStructFieldByteOffset(ty: Type, field_index: usize, mod: *Module) u32 { const struct_obj = ty.castTag(.@"struct").?.data; assert(struct_obj.layout == .Packed); comptime assert(Type.packed_struct_layout_version == 2); @@ -4750,7 +4744,7 @@ pub const Type = struct { offset: u64 = 0, big_align: u32 = 0, struct_obj: *Module.Struct, - module: *const Module, + module: *Module, pub fn next(it: *StructOffsetIterator) ?FieldOffset { const mod = it.module; @@ -4779,7 +4773,7 @@ pub const Type = struct { /// Get an iterator that iterates over all the struct field, returning the field and /// offset of that field. Asserts that the type is a non-packed struct. - pub fn iterateStructOffsets(ty: Type, mod: *const Module) StructOffsetIterator { + pub fn iterateStructOffsets(ty: Type, mod: *Module) StructOffsetIterator { const struct_obj = ty.castTag(.@"struct").?.data; assert(struct_obj.haveLayout()); assert(struct_obj.layout != .Packed); @@ -4787,7 +4781,7 @@ pub const Type = struct { } /// Supports structs and unions. - pub fn structFieldOffset(ty: Type, index: usize, mod: *const Module) u64 { + pub fn structFieldOffset(ty: Type, index: usize, mod: *Module) u64 { switch (ty.tag()) { .@"struct" => { const struct_obj = ty.castTag(.@"struct").?.data; @@ -5226,7 +5220,7 @@ pub const Type = struct { pub const VectorIndex = InternPool.Key.PtrType.VectorIndex; - pub fn alignment(data: Data, mod: *const Module) u32 { + pub fn alignment(data: Data, mod: *Module) u32 { if (data.@"align" != 0) return data.@"align"; return abiAlignment(data.pointee_type, mod); } diff --git a/src/value.zig b/src/value.zig index 49ca651a79..402e0981d3 100644 --- a/src/value.zig +++ b/src/value.zig @@ -694,7 +694,7 @@ pub const Value = struct { }, .enum_simple => { // Field index and integer values are the same. - const tag_ty = ty.intTagType(); + const tag_ty = try ty.intTagType(mod); return mod.intValue(tag_ty, field_index); }, else => unreachable, @@ -722,7 +722,9 @@ pub const Value = struct { // auto-numbered enum break :field_index @intCast(u32, val.toUnsignedInt(mod)); } - const int_tag_ty = ty.intTagType(); + const int_tag_ty = ty.intTagType(mod) catch |err| switch (err) { + error.OutOfMemory => @panic("OOM"), // TODO handle this failure + }; break :field_index @intCast(u32, values.getIndexContext(val, .{ .ty = int_tag_ty, .mod = mod }).?); }, }; @@ -737,7 +739,7 @@ pub const Value = struct { } /// Asserts the value is an integer. - pub fn toBigInt(val: Value, space: *BigIntSpace, mod: *const Module) BigIntConst { + pub fn toBigInt(val: Value, space: *BigIntSpace, mod: *Module) BigIntConst { return val.toBigIntAdvanced(space, mod, null) catch unreachable; } @@ -745,7 +747,7 @@ pub const Value = struct { pub fn toBigIntAdvanced( val: Value, space: *BigIntSpace, - mod: *const Module, + mod: *Module, opt_sema: ?*Sema, ) Module.CompileError!BigIntConst { return switch (val.ip_index) { @@ -801,13 +803,13 @@ pub const Value = struct { /// If the value fits in a u64, return it, otherwise null. /// Asserts not undefined. - pub fn getUnsignedInt(val: Value, mod: *const Module) ?u64 { + pub fn getUnsignedInt(val: Value, mod: *Module) ?u64 { return getUnsignedIntAdvanced(val, mod, null) catch unreachable; } /// If the value fits in a u64, return it, otherwise null. /// Asserts not undefined. - pub fn getUnsignedIntAdvanced(val: Value, mod: *const Module, opt_sema: ?*Sema) !?u64 { + pub fn getUnsignedIntAdvanced(val: Value, mod: *Module, opt_sema: ?*Sema) !?u64 { switch (val.ip_index) { .bool_false => return 0, .bool_true => return 1, @@ -847,12 +849,12 @@ pub const Value = struct { } /// Asserts the value is an integer and it fits in a u64 - pub fn toUnsignedInt(val: Value, mod: *const Module) u64 { + pub fn toUnsignedInt(val: Value, mod: *Module) u64 { return getUnsignedInt(val, mod).?; } /// Asserts the value is an integer and it fits in a i64 - pub fn toSignedInt(val: Value, mod: *const Module) i64 { + pub fn toSignedInt(val: Value, mod: *Module) i64 { switch (val.ip_index) { .bool_false => return 0, .bool_true => return 1, @@ -1405,7 +1407,7 @@ pub const Value = struct { } } - pub fn clz(val: Value, ty: Type, mod: *const Module) u64 { + pub fn clz(val: Value, ty: Type, mod: *Module) u64 { const ty_bits = ty.intInfo(mod).bits; return switch (val.ip_index) { .bool_false => ty_bits, @@ -1435,7 +1437,7 @@ pub const Value = struct { }; } - pub fn ctz(val: Value, ty: Type, mod: *const Module) u64 { + pub fn ctz(val: Value, ty: Type, mod: *Module) u64 { const ty_bits = ty.intInfo(mod).bits; return switch (val.ip_index) { .bool_false => ty_bits, @@ -1468,7 +1470,7 @@ pub const Value = struct { }; } - pub fn popCount(val: Value, ty: Type, mod: *const Module) u64 { + pub fn popCount(val: Value, ty: Type, mod: *Module) u64 { assert(!val.isUndef()); switch (val.ip_index) { .bool_false => return 0, @@ -1527,7 +1529,7 @@ pub const Value = struct { /// Asserts the value is an integer and not undefined. /// Returns the number of bits the value requires to represent stored in twos complement form. - pub fn intBitCountTwosComp(self: Value, mod: *const Module) usize { + pub fn intBitCountTwosComp(self: Value, mod: *Module) usize { const target = mod.getTarget(); return switch (self.ip_index) { .bool_false => 0, @@ -1593,13 +1595,13 @@ pub const Value = struct { }; } - pub fn orderAgainstZero(lhs: Value, mod: *const Module) std.math.Order { + pub fn orderAgainstZero(lhs: Value, mod: *Module) std.math.Order { return orderAgainstZeroAdvanced(lhs, mod, null) catch unreachable; } pub fn orderAgainstZeroAdvanced( lhs: Value, - mod: *const Module, + mod: *Module, opt_sema: ?*Sema, ) Module.CompileError!std.math.Order { switch (lhs.ip_index) { @@ -1683,13 +1685,13 @@ pub const Value = struct { } /// Asserts the value is comparable. - pub fn order(lhs: Value, rhs: Value, mod: *const Module) std.math.Order { + pub fn order(lhs: Value, rhs: Value, mod: *Module) std.math.Order { return orderAdvanced(lhs, rhs, mod, null) catch unreachable; } /// Asserts the value is comparable. /// If opt_sema is null then this function asserts things are resolved and cannot fail. - pub fn orderAdvanced(lhs: Value, rhs: Value, mod: *const Module, opt_sema: ?*Sema) !std.math.Order { + pub fn orderAdvanced(lhs: Value, rhs: Value, mod: *Module, opt_sema: ?*Sema) !std.math.Order { const lhs_against_zero = try lhs.orderAgainstZeroAdvanced(mod, opt_sema); const rhs_against_zero = try rhs.orderAgainstZeroAdvanced(mod, opt_sema); switch (lhs_against_zero) { @@ -1734,7 +1736,7 @@ pub const Value = struct { /// Asserts the value is comparable. Does not take a type parameter because it supports /// comparisons between heterogeneous types. - pub fn compareHetero(lhs: Value, op: std.math.CompareOperator, rhs: Value, mod: *const Module) bool { + pub fn compareHetero(lhs: Value, op: std.math.CompareOperator, rhs: Value, mod: *Module) bool { return compareHeteroAdvanced(lhs, op, rhs, mod, null) catch unreachable; } @@ -1742,7 +1744,7 @@ pub const Value = struct { lhs: Value, op: std.math.CompareOperator, rhs: Value, - mod: *const Module, + mod: *Module, opt_sema: ?*Sema, ) !bool { if (lhs.pointerDecl()) |lhs_decl| { @@ -2047,7 +2049,7 @@ pub const Value = struct { .Enum => { const a_val = try a.enumToInt(ty, mod); const b_val = try b.enumToInt(ty, mod); - const int_ty = ty.intTagType(); + const int_ty = try ty.intTagType(mod); return eqlAdvanced(a_val, int_ty, b_val, int_ty, mod, opt_sema); }, .Array, .Vector => { @@ -2462,7 +2464,7 @@ pub const Value = struct { }; } - fn hashInt(int_val: Value, hasher: *std.hash.Wyhash, mod: *const Module) void { + fn hashInt(int_val: Value, hasher: *std.hash.Wyhash, mod: *Module) void { var buffer: BigIntSpace = undefined; const big = int_val.toBigInt(&buffer, mod); std.hash.autoHash(hasher, big.positive); @@ -2471,7 +2473,7 @@ pub const Value = struct { } } - fn hashPtr(ptr_val: Value, hasher: *std.hash.Wyhash, mod: *const Module) void { + fn hashPtr(ptr_val: Value, hasher: *std.hash.Wyhash, mod: *Module) void { switch (ptr_val.tag()) { .decl_ref, .decl_ref_mut,