From ca3cf93b21bc77535fbaa7ca6aa411654dcfe069 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 3 May 2023 19:12:53 -0700 Subject: [PATCH] stage2: move most simple values to InternPool --- src/Air.zig | 3 + src/InternPool.zig | 31 ++ src/Module.zig | 50 ++- src/Sema.zig | 134 +++--- src/TypedValue.zig | 57 --- src/Zir.zig | 3 + src/codegen.zig | 4 +- src/codegen/c.zig | 2 +- src/codegen/llvm.zig | 4 +- src/codegen/spirv.zig | 6 +- src/type.zig | 32 +- src/value.zig | 944 ++++++++++++++++-------------------------- 12 files changed, 524 insertions(+), 746 deletions(-) diff --git a/src/Air.zig b/src/Air.zig index 1bc9d949e2..4124788605 100644 --- a/src/Air.zig +++ b/src/Air.zig @@ -899,8 +899,10 @@ pub const Inst = struct { type_info_type = @enumToInt(InternPool.Index.type_info_type), manyptr_u8_type = @enumToInt(InternPool.Index.manyptr_u8_type), manyptr_const_u8_type = @enumToInt(InternPool.Index.manyptr_const_u8_type), + manyptr_const_u8_sentinel_0_type = @enumToInt(InternPool.Index.manyptr_const_u8_sentinel_0_type), single_const_pointer_to_comptime_int_type = @enumToInt(InternPool.Index.single_const_pointer_to_comptime_int_type), const_slice_u8_type = @enumToInt(InternPool.Index.const_slice_u8_type), + const_slice_u8_sentinel_0_type = @enumToInt(InternPool.Index.const_slice_u8_sentinel_0_type), anyerror_void_error_union_type = @enumToInt(InternPool.Index.anyerror_void_error_union_type), generic_poison_type = @enumToInt(InternPool.Index.generic_poison_type), var_args_param_type = @enumToInt(InternPool.Index.var_args_param_type), @@ -908,6 +910,7 @@ pub const Inst = struct { undef = @enumToInt(InternPool.Index.undef), zero = @enumToInt(InternPool.Index.zero), zero_usize = @enumToInt(InternPool.Index.zero_usize), + zero_u8 = @enumToInt(InternPool.Index.zero_u8), one = @enumToInt(InternPool.Index.one), one_usize = @enumToInt(InternPool.Index.one_usize), calling_convention_c = @enumToInt(InternPool.Index.calling_convention_c), diff --git a/src/InternPool.zig b/src/InternPool.zig index 146a880493..6345d36f26 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -318,8 +318,10 @@ pub const Index = enum(u32) { type_info_type, manyptr_u8_type, manyptr_const_u8_type, + manyptr_const_u8_sentinel_0_type, single_const_pointer_to_comptime_int_type, const_slice_u8_type, + const_slice_u8_sentinel_0_type, anyerror_void_error_union_type, generic_poison_type, var_args_param_type, @@ -331,6 +333,8 @@ pub const Index = enum(u32) { zero, /// `0` (usize) zero_usize, + /// `0` (u8) + zero_u8, /// `1` (comptime_int) one, /// `1` (usize) @@ -489,24 +493,43 @@ pub const static_keys = [_]Key{ .size = .Many, } }, + // manyptr_const_u8_type .{ .ptr_type = .{ .elem_type = .u8_type, .size = .Many, .is_const = true, } }, + // manyptr_const_u8_sentinel_0_type + .{ .ptr_type = .{ + .elem_type = .u8_type, + .sentinel = .zero_u8, + .size = .Many, + .is_const = true, + } }, + .{ .ptr_type = .{ .elem_type = .comptime_int_type, .size = .One, .is_const = true, } }, + // const_slice_u8_type .{ .ptr_type = .{ .elem_type = .u8_type, .size = .Slice, .is_const = true, } }, + // const_slice_u8_sentinel_0_type + .{ .ptr_type = .{ + .elem_type = .u8_type, + .sentinel = .zero_u8, + .size = .Slice, + .is_const = true, + } }, + + // anyerror_void_error_union_type .{ .error_union_type = .{ .error_set_type = .anyerror_type, .payload_type = .void_type, @@ -541,6 +564,14 @@ pub const static_keys = [_]Key{ }, } }, + .{ .int = .{ + .ty = .u8_type, + .big_int = .{ + .limbs = &.{0}, + .positive = true, + }, + } }, + .{ .int = .{ .ty = .comptime_int_type, .big_int = .{ diff --git a/src/Module.zig b/src/Module.zig index 77c20fbcc6..5c84b123c1 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -4847,31 +4847,37 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { decl.owns_tv = false; var queue_linker_work = false; var is_extern = false; - switch (decl_tv.val.tag()) { - .variable => { - const variable = decl_tv.val.castTag(.variable).?.data; - if (variable.owner_decl == decl_index) { - decl.owns_tv = true; - queue_linker_work = true; - - const copied_init = try variable.init.copy(decl_arena_allocator); - variable.init = copied_init; - } - }, - .extern_fn => { - const extern_fn = decl_tv.val.castTag(.extern_fn).?.data; - if (extern_fn.owner_decl == decl_index) { - decl.owns_tv = true; - queue_linker_work = true; - is_extern = true; - } - }, - + switch (decl_tv.val.ip_index) { .generic_poison => unreachable, - .unreachable_value => unreachable, + .none => switch (decl_tv.val.tag()) { + .variable => { + const variable = decl_tv.val.castTag(.variable).?.data; + if (variable.owner_decl == decl_index) { + decl.owns_tv = true; + queue_linker_work = true; - .function => {}, + const copied_init = try variable.init.copy(decl_arena_allocator); + variable.init = copied_init; + } + }, + .extern_fn => { + const extern_fn = decl_tv.val.castTag(.extern_fn).?.data; + if (extern_fn.owner_decl == decl_index) { + decl.owns_tv = true; + queue_linker_work = true; + is_extern = true; + } + }, + .unreachable_value => unreachable, + + .function => {}, + + else => { + log.debug("send global const to linker: {*} ({s})", .{ decl, decl.name }); + queue_linker_work = true; + }, + }, else => { log.debug("send global const to linker: {*} ({s})", .{ decl, decl.name }); queue_linker_work = true; diff --git a/src/Sema.zig b/src/Sema.zig index ea8258717b..65475104aa 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -1569,6 +1569,7 @@ fn analyzeBodyInner( }, .condbr => blk: { if (!block.is_comptime) break sema.zirCondbr(block, inst); + const mod = sema.mod; // Same as condbr_inline. TODO https://github.com/ziglang/zig/issues/8220 const inst_data = datas[inst].pl_node; const cond_src: LazySrcLoc = .{ .node_offset_if_cond = inst_data.src_node }; @@ -1579,7 +1580,7 @@ fn analyzeBodyInner( if (err == error.AnalysisFail and block.comptime_reason != null) try block.comptime_reason.?.explain(sema, sema.err); return err; }; - const inline_body = if (cond.val.toBool()) then_body else else_body; + const inline_body = if (cond.val.toBool(mod)) then_body else else_body; try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src); const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse @@ -1591,6 +1592,7 @@ fn analyzeBodyInner( } }, .condbr_inline => blk: { + const mod = sema.mod; const inst_data = datas[inst].pl_node; const cond_src: LazySrcLoc = .{ .node_offset_if_cond = inst_data.src_node }; const extra = sema.code.extraData(Zir.Inst.CondBr, inst_data.payload_index); @@ -1600,7 +1602,7 @@ fn analyzeBodyInner( if (err == error.AnalysisFail and block.comptime_reason != null) try block.comptime_reason.?.explain(sema, sema.err); return err; }; - const inline_body = if (cond.val.toBool()) then_body else else_body; + const inline_body = if (cond.val.toBool(mod)) then_body else else_body; try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src); const old_runtime_index = block.runtime_index; @@ -1634,7 +1636,7 @@ fn analyzeBodyInner( if (err == error.AnalysisFail and block.comptime_reason != null) try block.comptime_reason.?.explain(sema, sema.err); return err; }; - if (is_non_err_val.toBool()) { + if (is_non_err_val.toBool(mod)) { break :blk try sema.analyzeErrUnionPayload(block, src, err_union_ty, err_union, operand_src, false); } const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse @@ -1647,6 +1649,7 @@ fn analyzeBodyInner( }, .try_ptr => blk: { if (!block.is_comptime) break :blk try sema.zirTryPtr(block, inst); + const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); const operand_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node }; @@ -1660,7 +1663,7 @@ fn analyzeBodyInner( if (err == error.AnalysisFail and block.comptime_reason != null) try block.comptime_reason.?.explain(sema, sema.err); return err; }; - if (is_non_err_val.toBool()) { + if (is_non_err_val.toBool(mod)) { break :blk try sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false); } const break_data = (try sema.analyzeBodyBreak(block, inline_body)) orelse @@ -1741,11 +1744,12 @@ fn resolveConstBool( zir_ref: Zir.Inst.Ref, reason: []const u8, ) !bool { + const mod = sema.mod; const air_inst = try sema.resolveInst(zir_ref); const wanted_type = Type.bool; const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src); const val = try sema.resolveConstValue(block, src, coerced_inst, reason); - return val.toBool(); + return val.toBool(mod); } pub fn resolveConstString( @@ -1843,9 +1847,12 @@ fn resolveConstMaybeUndefVal( reason: []const u8, ) CompileError!Value { if (try sema.resolveMaybeUndefValAllowVariables(inst)) |val| { - switch (val.tag()) { - .variable => return sema.failWithNeededComptime(block, src, reason), + switch (val.ip_index) { .generic_poison => return error.GenericPoison, + .none => switch (val.tag()) { + .variable => return sema.failWithNeededComptime(block, src, reason), + else => return val, + }, else => return val, } } @@ -1862,10 +1869,13 @@ fn resolveConstValue( reason: []const u8, ) CompileError!Value { if (try sema.resolveMaybeUndefValAllowVariables(air_ref)) |val| { - switch (val.tag()) { - .undef => return sema.failWithUseOfUndef(block, src), - .variable => return sema.failWithNeededComptime(block, src, reason), + switch (val.ip_index) { .generic_poison => return error.GenericPoison, + .none => switch (val.tag()) { + .undef => return sema.failWithUseOfUndef(block, src), + .variable => return sema.failWithNeededComptime(block, src, reason), + else => return val, + }, else => return val, } } @@ -1900,12 +1910,11 @@ fn resolveMaybeUndefVal( const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null; switch (val.ip_index) { .generic_poison => return error.GenericPoison, - else => return val, .none => switch (val.tag()) { .variable => return null, - .generic_poison => return error.GenericPoison, else => return val, }, + else => return val, } } @@ -1919,12 +1928,18 @@ fn resolveMaybeUndefValIntable( ) CompileError!?Value { const val = (try sema.resolveMaybeUndefValAllowVariables(inst)) orelse return null; var check = val; - while (true) switch (check.tag()) { - .variable, .decl_ref, .decl_ref_mut, .comptime_field_ptr => return null, - .field_ptr => check = check.castTag(.field_ptr).?.data.container_ptr, - .elem_ptr => check = check.castTag(.elem_ptr).?.data.array_ptr, - .eu_payload_ptr, .opt_payload_ptr => check = check.cast(Value.Payload.PayloadPtr).?.data.container_ptr, + while (true) switch (check.ip_index) { .generic_poison => return error.GenericPoison, + .none => switch (check.tag()) { + .variable, .decl_ref, .decl_ref_mut, .comptime_field_ptr => return null, + .field_ptr => check = check.castTag(.field_ptr).?.data.container_ptr, + .elem_ptr => check = check.castTag(.elem_ptr).?.data.array_ptr, + .eu_payload_ptr, .opt_payload_ptr => check = check.cast(Value.Payload.PayloadPtr).?.data.container_ptr, + else => { + try sema.resolveLazyValue(val); + return val; + }, + }, else => { try sema.resolveLazyValue(val); return val; @@ -6208,12 +6223,13 @@ fn popErrorReturnTrace( operand: Air.Inst.Ref, saved_error_trace_index: Air.Inst.Ref, ) CompileError!void { + const mod = sema.mod; var is_non_error: ?bool = null; var is_non_error_inst: Air.Inst.Ref = undefined; if (operand != .none) { is_non_error_inst = try sema.analyzeIsNonErr(block, src, operand); if (try sema.resolveDefinedValue(block, src, is_non_error_inst)) |cond_val| - is_non_error = cond_val.toBool(); + is_non_error = cond_val.toBool(mod); } else is_non_error = true; // no operand means pop unconditionally if (is_non_error == true) { @@ -7222,7 +7238,7 @@ fn analyzeInlineCallArg( if (err == error.AnalysisFail and param_block.comptime_reason != null) try param_block.comptime_reason.?.explain(sema, sema.err); return err; }; - switch (arg_val.tag()) { + switch (arg_val.ip_index) { .generic_poison, .generic_poison_type => { // This function is currently evaluated as part of an as-of-yet unresolvable // parameter or return type. @@ -7261,7 +7277,7 @@ fn analyzeInlineCallArg( if (err == error.AnalysisFail and param_block.comptime_reason != null) try param_block.comptime_reason.?.explain(sema, sema.err); return err; }; - switch (arg_val.tag()) { + switch (arg_val.ip_index) { .generic_poison, .generic_poison_type => { // This function is currently evaluated as part of an as-of-yet unresolvable // parameter or return type. @@ -7443,13 +7459,13 @@ fn instantiateGenericCall( arg_ty.hashWithHasher(&hasher, mod); generic_args[i] = .{ .ty = arg_ty, - .val = Value.initTag(.generic_poison), + .val = Value.generic_poison, .is_anytype = true, }; } else { generic_args[i] = .{ .ty = arg_ty, - .val = Value.initTag(.generic_poison), + .val = Value.generic_poison, .is_anytype = false, }; } @@ -7815,7 +7831,7 @@ fn resolveGenericInstantiationType( } else { child_sema.comptime_args[arg_i] = .{ .ty = copied_arg_ty, - .val = Value.initTag(.generic_poison), + .val = Value.generic_poison, }; } @@ -8780,9 +8796,9 @@ fn resolveGenericBody( switch (err) { error.GenericPoison => { if (dest_ty.ip_index == .type_type) { - return Value.initTag(.generic_poison_type); + return Value.generic_poison_type; } else { - return Value.initTag(.generic_poison); + return Value.generic_poison; } }, else => |e| return e, @@ -9394,7 +9410,7 @@ fn zirParam( if (is_comptime) { // If this is a comptime parameter we can add a constant generic_poison // since this is also a generic parameter. - const result = try sema.addConstant(param_ty, Value.initTag(.generic_poison)); + const result = try sema.addConstant(param_ty, Value.generic_poison); sema.inst_map.putAssumeCapacityNoClobber(inst, result); } else { // Otherwise we need a dummy runtime instruction. @@ -11819,8 +11835,9 @@ fn validateSwitchItemBool( src_node_offset: i32, switch_prong_src: Module.SwitchProngSrc, ) CompileError!void { + const mod = sema.mod; const item_val = (try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none)).val; - if (item_val.toBool()) { + if (item_val.toBool(mod)) { true_count.* += 1; } else { false_count.* += 1; @@ -15462,7 +15479,7 @@ fn cmpSelf( } else { if (resolved_type.zigTypeTag(mod) == .Bool) { // We can lower bool eq/neq more efficiently. - return sema.runtimeBoolCmp(block, src, op, casted_rhs, lhs_val.toBool(), rhs_src); + return sema.runtimeBoolCmp(block, src, op, casted_rhs, lhs_val.toBool(mod), rhs_src); } break :src rhs_src; } @@ -15472,7 +15489,7 @@ fn cmpSelf( if (resolved_type.zigTypeTag(mod) == .Bool) { if (try sema.resolveMaybeUndefVal(casted_rhs)) |rhs_val| { if (rhs_val.isUndef()) return sema.addConstUndef(Type.bool); - return sema.runtimeBoolCmp(block, src, op, casted_lhs, rhs_val.toBool(), lhs_src); + return sema.runtimeBoolCmp(block, src, op, casted_lhs, rhs_val.toBool(mod), lhs_src); } } break :src lhs_src; @@ -16815,6 +16832,7 @@ fn zirBoolNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air const tracy = trace(@src()); defer tracy.end(); + const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[inst].un_node; const src = inst_data.src(); const operand_src: LazySrcLoc = .{ .node_offset_un_op = inst_data.src_node }; @@ -16824,7 +16842,7 @@ fn zirBoolNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air if (try sema.resolveMaybeUndefVal(operand)) |val| { return if (val.isUndef()) sema.addConstUndef(Type.bool) - else if (val.toBool()) + else if (val.toBool(mod)) Air.Inst.Ref.bool_false else Air.Inst.Ref.bool_true; @@ -16842,6 +16860,7 @@ fn zirBoolBr( const tracy = trace(@src()); defer tracy.end(); + const mod = sema.mod; const datas = sema.code.instructions.items(.data); const inst_data = datas[inst].bool_br; const lhs = try sema.resolveInst(inst_data.lhs); @@ -16851,9 +16870,9 @@ fn zirBoolBr( const gpa = sema.gpa; if (try sema.resolveDefinedValue(parent_block, lhs_src, lhs)) |lhs_val| { - if (is_bool_or and lhs_val.toBool()) { + if (is_bool_or and lhs_val.toBool(mod)) { return Air.Inst.Ref.bool_true; - } else if (!is_bool_or and !lhs_val.toBool()) { + } else if (!is_bool_or and !lhs_val.toBool(mod)) { return Air.Inst.Ref.bool_false; } // comptime-known left-hand side. No need for a block here; the result @@ -16897,9 +16916,9 @@ fn zirBoolBr( const result = sema.finishCondBr(parent_block, &child_block, &then_block, &else_block, lhs, block_inst); if (!sema.typeOf(rhs_result).isNoReturn()) { if (try sema.resolveDefinedValue(rhs_block, sema.src, rhs_result)) |rhs_val| { - if (is_bool_or and rhs_val.toBool()) { + if (is_bool_or and rhs_val.toBool(mod)) { return Air.Inst.Ref.bool_true; - } else if (!is_bool_or and !rhs_val.toBool()) { + } else if (!is_bool_or and !rhs_val.toBool(mod)) { return Air.Inst.Ref.bool_false; } } @@ -17053,7 +17072,7 @@ fn zirCondbr( const cond = try sema.coerce(parent_block, Type.bool, uncasted_cond, cond_src); if (try sema.resolveDefinedValue(parent_block, cond_src, cond)) |cond_val| { - const body = if (cond_val.toBool()) then_body else else_body; + const body = if (cond_val.toBool(mod)) then_body else else_body; try sema.maybeErrorUnwrapCondbr(parent_block, body, extra.data.condition, cond_src); // We use `analyzeBodyInner` since we want to propagate any possible @@ -17126,7 +17145,7 @@ fn zirTry(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError! const is_non_err = try sema.analyzeIsNonErrComptimeOnly(parent_block, operand_src, err_union); if (is_non_err != .none) { const is_non_err_val = (try sema.resolveDefinedValue(parent_block, operand_src, is_non_err)).?; - if (is_non_err_val.toBool()) { + if (is_non_err_val.toBool(mod)) { return sema.analyzeErrUnionPayload(parent_block, src, err_union_ty, err_union, operand_src, false); } // We can analyze the body directly in the parent block because we know there are @@ -17173,7 +17192,7 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr const is_non_err = try sema.analyzeIsNonErrComptimeOnly(parent_block, operand_src, err_union); if (is_non_err != .none) { const is_non_err_val = (try sema.resolveDefinedValue(parent_block, operand_src, is_non_err)).?; - if (is_non_err_val.toBool()) { + if (is_non_err_val.toBool(mod)) { return sema.analyzeErrUnionPayloadPtr(parent_block, src, operand, false, false); } // We can analyze the body directly in the parent block because we know there are @@ -18509,11 +18528,12 @@ fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air } fn zirBoolToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { + const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[inst].un_node; const operand = try sema.resolveInst(inst_data.operand); if (try sema.resolveMaybeUndefVal(operand)) |val| { if (val.isUndef()) return sema.addConstUndef(Type.u1); - if (val.toBool()) return sema.addConstant(Type.u1, Value.one); + if (val.toBool(mod)) return sema.addConstant(Type.u1, Value.one); return sema.addConstant(Type.u1, Value.zero); } return block.addUnOp(.bool_to_int, operand); @@ -18811,12 +18831,12 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in const ty = try Type.ptr(sema.arena, mod, .{ .size = ptr_size, - .mutable = !is_const_val.toBool(), - .@"volatile" = is_volatile_val.toBool(), + .mutable = !is_const_val.toBool(mod), + .@"volatile" = is_volatile_val.toBool(mod), .@"align" = abi_align, .@"addrspace" = address_space_val.toEnum(std.builtin.AddressSpace), .pointee_type = try elem_ty.copy(sema.arena), - .@"allowzero" = is_allowzero_val.toBool(), + .@"allowzero" = is_allowzero_val.toBool(mod), .sentinel = actual_sentinel, }); return sema.addType(ty); @@ -18932,7 +18952,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in return sema.fail(block, src, "non-packed struct does not support backing integer type", .{}); } - return try sema.reifyStruct(block, inst, src, layout, backing_int_val, fields_val, name_strategy, is_tuple_val.toBool()); + return try sema.reifyStruct(block, inst, src, layout, backing_int_val, fields_val, name_strategy, is_tuple_val.toBool(mod)); }, .Enum => { const struct_val: []const Value = union_val.val.castTag(.aggregate).?.data; @@ -18961,7 +18981,7 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in const enum_ty_payload = try new_decl_arena_allocator.create(Type.Payload.EnumFull); enum_ty_payload.* = .{ .base = .{ - .tag = if (!is_exhaustive_val.toBool()) + .tag = if (!is_exhaustive_val.toBool(mod)) .enum_nonexhaustive else .enum_full, @@ -19295,9 +19315,9 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in // alignment: comptime_int, const alignment_val = struct_val[1]; // is_generic: bool, - const is_generic = struct_val[2].toBool(); + const is_generic = struct_val[2].toBool(mod); // is_var_args: bool, - const is_var_args = struct_val[3].toBool(); + const is_var_args = struct_val[3].toBool(mod); // return_type: ?type, const return_type_val = struct_val[4]; // args: []const Param, @@ -19339,9 +19359,9 @@ fn zirReify(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, in const arg_val = arg.castTag(.aggregate).?.data; // TODO use reflection instead of magic numbers here // is_generic: bool, - const arg_is_generic = arg_val[0].toBool(); + const arg_is_generic = arg_val[0].toBool(mod); // is_noalias: bool, - const arg_is_noalias = arg_val[1].toBool(); + const arg_is_noalias = arg_val[1].toBool(mod); // type: ?type, const param_type_opt_val = arg_val[2]; @@ -19455,9 +19475,9 @@ fn reifyStruct( if (layout == .Packed) { if (abi_align != 0) return sema.fail(block, src, "alignment in a packed struct field must be set to 0", .{}); - if (is_comptime_val.toBool()) return sema.fail(block, src, "packed struct fields cannot be marked comptime", .{}); + if (is_comptime_val.toBool(mod)) return sema.fail(block, src, "packed struct fields cannot be marked comptime", .{}); } - if (layout == .Extern and is_comptime_val.toBool()) { + if (layout == .Extern and is_comptime_val.toBool(mod)) { return sema.fail(block, src, "extern struct fields cannot be marked comptime", .{}); } @@ -19499,7 +19519,7 @@ fn reifyStruct( opt_val; break :blk try payload_val.copy(new_decl_arena_allocator); } else Value.initTag(.unreachable_value); - if (is_comptime_val.toBool() and default_val.tag() == .unreachable_value) { + if (is_comptime_val.toBool(mod) and default_val.tag() == .unreachable_value) { return sema.fail(block, src, "comptime field without default initialization value", .{}); } @@ -19508,7 +19528,7 @@ fn reifyStruct( .ty = field_ty, .abi_align = abi_align, .default_val = default_val, - .is_comptime = is_comptime_val.toBool(), + .is_comptime = is_comptime_val.toBool(mod), .offset = undefined, }; @@ -21446,7 +21466,7 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C const elems = try sema.gpa.alloc(Value, vec_len); for (elems, 0..) |*elem, i| { const pred_elem_val = pred_val.elemValueBuffer(sema.mod, i, &buf); - const should_choose_a = pred_elem_val.toBool(); + const should_choose_a = pred_elem_val.toBool(mod); if (should_choose_a) { elem.* = a_val.elemValueBuffer(sema.mod, i, &buf); } else { @@ -22956,7 +22976,7 @@ fn resolveExternOptions( .name = name, .library_name = library_name, .linkage = linkage, - .is_thread_local = is_thread_local_val.toBool(), + .is_thread_local = is_thread_local_val.toBool(mod), }; } @@ -31760,8 +31780,10 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type { .enum_literal_type, .manyptr_u8_type, .manyptr_const_u8_type, + .manyptr_const_u8_sentinel_0_type, .single_const_pointer_to_comptime_int_type, .const_slice_u8_type, + .const_slice_u8_sentinel_0_type, .anyerror_void_error_union_type, .generic_poison_type, .var_args_param_type, @@ -31771,6 +31793,7 @@ pub fn resolveTypeFields(sema: *Sema, ty: Type) CompileError!Type { .undef => unreachable, .zero => unreachable, .zero_usize => unreachable, + .zero_u8 => unreachable, .one => unreachable, .one_usize => unreachable, .calling_convention_c => unreachable, @@ -34225,12 +34248,9 @@ fn intFitsInType( switch (val.tag()) { .zero, .undef, - .bool_false, => return true, - .one, - .bool_true, - => switch (ty.zigTypeTag(mod)) { + .one => switch (ty.zigTypeTag(mod)) { .Int => { const info = ty.intInfo(mod); return switch (info.signedness) { diff --git a/src/TypedValue.zig b/src/TypedValue.zig index dc556942c3..7302f42e57 100644 --- a/src/TypedValue.zig +++ b/src/TypedValue.zig @@ -77,66 +77,14 @@ pub fn print( return writer.writeAll("(variable)"); while (true) switch (val.tag()) { - .u1_type => return writer.writeAll("u1"), - .u8_type => return writer.writeAll("u8"), - .i8_type => return writer.writeAll("i8"), - .u16_type => return writer.writeAll("u16"), - .i16_type => return writer.writeAll("i16"), - .u29_type => return writer.writeAll("u29"), - .u32_type => return writer.writeAll("u32"), - .i32_type => return writer.writeAll("i32"), - .u64_type => return writer.writeAll("u64"), - .i64_type => return writer.writeAll("i64"), - .u128_type => return writer.writeAll("u128"), - .i128_type => return writer.writeAll("i128"), - .isize_type => return writer.writeAll("isize"), - .usize_type => return writer.writeAll("usize"), - .c_char_type => return writer.writeAll("c_char"), - .c_short_type => return writer.writeAll("c_short"), - .c_ushort_type => return writer.writeAll("c_ushort"), - .c_int_type => return writer.writeAll("c_int"), - .c_uint_type => return writer.writeAll("c_uint"), - .c_long_type => return writer.writeAll("c_long"), - .c_ulong_type => return writer.writeAll("c_ulong"), - .c_longlong_type => return writer.writeAll("c_longlong"), - .c_ulonglong_type => return writer.writeAll("c_ulonglong"), - .c_longdouble_type => return writer.writeAll("c_longdouble"), - .f16_type => return writer.writeAll("f16"), - .f32_type => return writer.writeAll("f32"), - .f64_type => return writer.writeAll("f64"), - .f80_type => return writer.writeAll("f80"), - .f128_type => return writer.writeAll("f128"), - .anyopaque_type => return writer.writeAll("anyopaque"), - .bool_type => return writer.writeAll("bool"), - .void_type => return writer.writeAll("void"), - .type_type => return writer.writeAll("type"), - .anyerror_type => return writer.writeAll("anyerror"), - .comptime_int_type => return writer.writeAll("comptime_int"), - .comptime_float_type => return writer.writeAll("comptime_float"), - .noreturn_type => return writer.writeAll("noreturn"), - .null_type => return writer.writeAll("@Type(.Null)"), - .undefined_type => return writer.writeAll("@Type(.Undefined)"), .single_const_pointer_to_comptime_int_type => return writer.writeAll("*const comptime_int"), - .anyframe_type => return writer.writeAll("anyframe"), .const_slice_u8_type => return writer.writeAll("[]const u8"), .const_slice_u8_sentinel_0_type => return writer.writeAll("[:0]const u8"), .anyerror_void_error_union_type => return writer.writeAll("anyerror!void"), - .enum_literal_type => return writer.writeAll("@Type(.EnumLiteral)"), .manyptr_u8_type => return writer.writeAll("[*]u8"), .manyptr_const_u8_type => return writer.writeAll("[*]const u8"), .manyptr_const_u8_sentinel_0_type => return writer.writeAll("[*:0]const u8"), - .atomic_order_type => return writer.writeAll("std.builtin.AtomicOrder"), - .atomic_rmw_op_type => return writer.writeAll("std.builtin.AtomicRmwOp"), - .calling_convention_type => return writer.writeAll("std.builtin.CallingConvention"), - .address_space_type => return writer.writeAll("std.builtin.AddressSpace"), - .float_mode_type => return writer.writeAll("std.builtin.FloatMode"), - .reduce_op_type => return writer.writeAll("std.builtin.ReduceOp"), - .modifier_type => return writer.writeAll("std.builtin.CallModifier"), - .prefetch_options_type => return writer.writeAll("std.builtin.PrefetchOptions"), - .export_options_type => return writer.writeAll("std.builtin.ExportOptions"), - .extern_options_type => return writer.writeAll("std.builtin.ExternOptions"), - .type_info_type => return writer.writeAll("std.builtin.Type"), .empty_struct_value, .aggregate => { if (level == 0) { @@ -221,11 +169,8 @@ pub fn print( .undef => return writer.writeAll("undefined"), .zero => return writer.writeAll("0"), .one => return writer.writeAll("1"), - .void_value => return writer.writeAll("{}"), .unreachable_value => return writer.writeAll("unreachable"), .the_only_possible_value => return writer.writeAll("0"), - .bool_true => return writer.writeAll("true"), - .bool_false => return writer.writeAll("false"), .ty => return val.castTag(.ty).?.data.print(writer, mod), .int_u64 => return std.fmt.formatIntValue(val.castTag(.int_u64).?.data, "", .{}, writer), .int_i64 => return std.fmt.formatIntValue(val.castTag(.int_i64).?.data, "", .{}, writer), @@ -487,8 +432,6 @@ pub fn print( // TODO these should not appear in this function .inferred_alloc => return writer.writeAll("(inferred allocation value)"), .inferred_alloc_comptime => return writer.writeAll("(inferred comptime allocation value)"), - .generic_poison_type => return writer.writeAll("(generic poison type)"), - .generic_poison => return writer.writeAll("(generic poison)"), .runtime_value => return writer.writeAll("[runtime value]"), }; } diff --git a/src/Zir.zig b/src/Zir.zig index 1063377fc7..7b708ab04e 100644 --- a/src/Zir.zig +++ b/src/Zir.zig @@ -2106,8 +2106,10 @@ pub const Inst = struct { type_info_type = @enumToInt(InternPool.Index.type_info_type), manyptr_u8_type = @enumToInt(InternPool.Index.manyptr_u8_type), manyptr_const_u8_type = @enumToInt(InternPool.Index.manyptr_const_u8_type), + manyptr_const_u8_sentinel_0_type = @enumToInt(InternPool.Index.manyptr_const_u8_sentinel_0_type), single_const_pointer_to_comptime_int_type = @enumToInt(InternPool.Index.single_const_pointer_to_comptime_int_type), const_slice_u8_type = @enumToInt(InternPool.Index.const_slice_u8_type), + const_slice_u8_sentinel_0_type = @enumToInt(InternPool.Index.const_slice_u8_sentinel_0_type), anyerror_void_error_union_type = @enumToInt(InternPool.Index.anyerror_void_error_union_type), generic_poison_type = @enumToInt(InternPool.Index.generic_poison_type), var_args_param_type = @enumToInt(InternPool.Index.var_args_param_type), @@ -2115,6 +2117,7 @@ pub const Inst = struct { undef = @enumToInt(InternPool.Index.undef), zero = @enumToInt(InternPool.Index.zero), zero_usize = @enumToInt(InternPool.Index.zero_usize), + zero_u8 = @enumToInt(InternPool.Index.zero_u8), one = @enumToInt(InternPool.Index.one), one_usize = @enumToInt(InternPool.Index.one_usize), calling_convention_c = @enumToInt(InternPool.Index.calling_convention_c), diff --git a/src/codegen.zig b/src/codegen.zig index 295409781e..a3ecf88d50 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -494,7 +494,7 @@ pub fn generateSymbol( return Result.ok; }, .Bool => { - const x: u8 = @boolToInt(typed_value.val.toBool()); + const x: u8 = @boolToInt(typed_value.val.toBool(mod)); try code.append(x); return Result.ok; }, @@ -1213,7 +1213,7 @@ pub fn genTypedValue( } }, .Bool => { - return GenResult.mcv(.{ .immediate = @boolToInt(typed_value.val.toBool()) }); + return GenResult.mcv(.{ .immediate = @boolToInt(typed_value.val.toBool(mod)) }); }, .Optional => { if (typed_value.ty.isPtrLikeOptional(mod)) { diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 2e5e45d54c..327ccb0119 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -1191,7 +1191,7 @@ pub const DeclGen = struct { } }, .Bool => { - if (val.toBool()) { + if (val.toBool(mod)) { return writer.writeAll("true"); } else { return writer.writeAll("false"); diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 232cd9d42f..1a092dff69 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -2793,7 +2793,7 @@ pub const DeclGen = struct { if (std.debug.runtime_safety and false) check: { if (t.zigTypeTag(mod) == .Opaque) break :check; if (!t.hasRuntimeBits(mod)) break :check; - if (!llvm_ty.isSized().toBool()) break :check; + if (!llvm_ty.isSized().toBool(mod)) break :check; const zig_size = t.abiSize(mod); const llvm_size = dg.object.target_data.abiSizeOfType(llvm_ty); @@ -3272,7 +3272,7 @@ pub const DeclGen = struct { switch (tv.ty.zigTypeTag(mod)) { .Bool => { const llvm_type = try dg.lowerType(tv.ty); - return if (tv.val.toBool()) llvm_type.constAllOnes() else llvm_type.constNull(); + return if (tv.val.toBool(mod)) llvm_type.constAllOnes() else llvm_type.constNull(); }, // TODO this duplicates code with Pointer but they should share the handling // of the tv.val.tag() and then Int should do extra constPtrToInt on top diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 3a5f5d6f6a..417a8035b5 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -621,7 +621,7 @@ pub const DeclGen = struct { switch (ty.zigTypeTag(mod)) { .Int => try self.addInt(ty, val), .Float => try self.addFloat(ty, val), - .Bool => try self.addConstBool(val.toBool()), + .Bool => try self.addConstBool(val.toBool(mod)), .Array => switch (val.tag()) { .aggregate => { const elem_vals = val.castTag(.aggregate).?.data; @@ -989,8 +989,8 @@ pub const DeclGen = struct { } }, .Bool => switch (repr) { - .direct => return try self.spv.constBool(result_ty_ref, val.toBool()), - .indirect => return try self.spv.constInt(result_ty_ref, @boolToInt(val.toBool())), + .direct => return try self.spv.constBool(result_ty_ref, val.toBool(mod)), + .indirect => return try self.spv.constInt(result_ty_ref, @boolToInt(val.toBool(mod))), }, .Float => return switch (ty.floatBits(target)) { 16 => try self.spv.resolveId(.{ .float = .{ .ty = result_ty_ref, .value = .{ .float16 = val.toFloat(f16) } } }), diff --git a/src/type.zig b/src/type.zig index 7db7ad316b..7c1414a1eb 100644 --- a/src/type.zig +++ b/src/type.zig @@ -2054,22 +2054,22 @@ pub const Type = struct { pub fn toValue(self: Type, allocator: Allocator) Allocator.Error!Value { if (self.ip_index != .none) return self.ip_index.toValue(); switch (self.tag()) { - .u1 => return Value.initTag(.u1_type), - .u8 => return Value.initTag(.u8_type), - .i8 => return Value.initTag(.i8_type), - .u16 => return Value.initTag(.u16_type), - .u29 => return Value.initTag(.u29_type), - .i16 => return Value.initTag(.i16_type), - .u32 => return Value.initTag(.u32_type), - .i32 => return Value.initTag(.i32_type), - .u64 => return Value.initTag(.u64_type), - .i64 => return Value.initTag(.i64_type), - .single_const_pointer_to_comptime_int => return Value.initTag(.single_const_pointer_to_comptime_int_type), - .const_slice_u8 => return Value.initTag(.const_slice_u8_type), - .const_slice_u8_sentinel_0 => return Value.initTag(.const_slice_u8_sentinel_0_type), - .manyptr_u8 => return Value.initTag(.manyptr_u8_type), - .manyptr_const_u8 => return Value.initTag(.manyptr_const_u8_type), - .manyptr_const_u8_sentinel_0 => return Value.initTag(.manyptr_const_u8_sentinel_0_type), + .u1 => return Value{ .ip_index = .u1_type, .legacy = undefined }, + .u8 => return Value{ .ip_index = .u8_type, .legacy = undefined }, + .i8 => return Value{ .ip_index = .i8_type, .legacy = undefined }, + .u16 => return Value{ .ip_index = .u16_type, .legacy = undefined }, + .u29 => return Value{ .ip_index = .u29_type, .legacy = undefined }, + .i16 => return Value{ .ip_index = .i16_type, .legacy = undefined }, + .u32 => return Value{ .ip_index = .u32_type, .legacy = undefined }, + .i32 => return Value{ .ip_index = .i32_type, .legacy = undefined }, + .u64 => return Value{ .ip_index = .u64_type, .legacy = undefined }, + .i64 => return Value{ .ip_index = .i64_type, .legacy = undefined }, + .single_const_pointer_to_comptime_int => return Value{ .ip_index = .single_const_pointer_to_comptime_int_type, .legacy = undefined }, + .const_slice_u8 => return Value{ .ip_index = .const_slice_u8_type, .legacy = undefined }, + .const_slice_u8_sentinel_0 => return Value{ .ip_index = .const_slice_u8_sentinel_0_type, .legacy = undefined }, + .manyptr_u8 => return Value{ .ip_index = .manyptr_u8_type, .legacy = undefined }, + .manyptr_const_u8 => return Value{ .ip_index = .manyptr_const_u8_type, .legacy = undefined }, + .manyptr_const_u8_sentinel_0 => return Value{ .ip_index = .manyptr_const_u8_sentinel_0_type, .legacy = undefined }, .inferred_alloc_const => unreachable, .inferred_alloc_mut => unreachable, else => return Value.Tag.ty.create(allocator, self), diff --git a/src/value.zig b/src/value.zig index 2f9f395017..396aab2012 100644 --- a/src/value.zig +++ b/src/value.zig @@ -33,58 +33,6 @@ pub const Value = struct { // Keep in sync with tools/stage2_pretty_printers_common.py pub const Tag = enum(usize) { // The first section of this enum are tags that require no payload. - u1_type, - u8_type, - i8_type, - u16_type, - i16_type, - u29_type, - u32_type, - i32_type, - u64_type, - i64_type, - u128_type, - i128_type, - usize_type, - isize_type, - c_char_type, - c_short_type, - c_ushort_type, - c_int_type, - c_uint_type, - c_long_type, - c_ulong_type, - c_longlong_type, - c_ulonglong_type, - c_longdouble_type, - f16_type, - f32_type, - f64_type, - f80_type, - f128_type, - anyopaque_type, - bool_type, - void_type, - type_type, - anyerror_type, - comptime_int_type, - comptime_float_type, - noreturn_type, - anyframe_type, - null_type, - undefined_type, - enum_literal_type, - atomic_order_type, - atomic_rmw_op_type, - calling_convention_type, - address_space_type, - float_mode_type, - reduce_op_type, - modifier_type, - prefetch_options_type, - export_options_type, - extern_options_type, - type_info_type, manyptr_u8_type, manyptr_const_u8_type, manyptr_const_u8_sentinel_0_type, @@ -92,19 +40,14 @@ pub const Value = struct { const_slice_u8_type, const_slice_u8_sentinel_0_type, anyerror_void_error_union_type, - generic_poison_type, undef, zero, one, - void_value, unreachable_value, /// The only possible value for a particular type, which is stored externally. the_only_possible_value, null_value, - bool_true, - bool_false, - generic_poison, empty_struct_value, empty_array, // See last_no_payload_tag below. @@ -197,78 +140,22 @@ pub const Value = struct { pub fn Type(comptime t: Tag) type { return switch (t) { - .u1_type, - .u8_type, - .i8_type, - .u16_type, - .i16_type, - .u29_type, - .u32_type, - .i32_type, - .u64_type, - .i64_type, - .u128_type, - .i128_type, - .usize_type, - .isize_type, - .c_char_type, - .c_short_type, - .c_ushort_type, - .c_int_type, - .c_uint_type, - .c_long_type, - .c_ulong_type, - .c_longlong_type, - .c_ulonglong_type, - .c_longdouble_type, - .f16_type, - .f32_type, - .f64_type, - .f80_type, - .f128_type, - .anyopaque_type, - .bool_type, - .void_type, - .type_type, - .anyerror_type, - .comptime_int_type, - .comptime_float_type, - .noreturn_type, - .null_type, - .undefined_type, .single_const_pointer_to_comptime_int_type, - .anyframe_type, .const_slice_u8_type, .const_slice_u8_sentinel_0_type, .anyerror_void_error_union_type, - .generic_poison_type, - .enum_literal_type, + .undef, .zero, .one, - .void_value, .unreachable_value, .the_only_possible_value, .empty_struct_value, .empty_array, .null_value, - .bool_true, - .bool_false, .manyptr_u8_type, .manyptr_const_u8_type, .manyptr_const_u8_sentinel_0_type, - .atomic_order_type, - .atomic_rmw_op_type, - .calling_convention_type, - .address_space_type, - .float_mode_type, - .reduce_op_type, - .modifier_type, - .prefetch_options_type, - .export_options_type, - .extern_options_type, - .type_info_type, - .generic_poison, => @compileError("Value Tag " ++ @tagName(t) ++ " has no payload"), .int_big_positive, @@ -418,78 +305,22 @@ pub const Value = struct { .legacy = .{ .tag_if_small_enough = self.legacy.tag_if_small_enough }, }; } else switch (self.legacy.ptr_otherwise.tag) { - .u1_type, - .u8_type, - .i8_type, - .u16_type, - .i16_type, - .u29_type, - .u32_type, - .i32_type, - .u64_type, - .i64_type, - .u128_type, - .i128_type, - .usize_type, - .isize_type, - .c_char_type, - .c_short_type, - .c_ushort_type, - .c_int_type, - .c_uint_type, - .c_long_type, - .c_ulong_type, - .c_longlong_type, - .c_ulonglong_type, - .c_longdouble_type, - .f16_type, - .f32_type, - .f64_type, - .f80_type, - .f128_type, - .anyopaque_type, - .bool_type, - .void_type, - .type_type, - .anyerror_type, - .comptime_int_type, - .comptime_float_type, - .noreturn_type, - .null_type, - .undefined_type, .single_const_pointer_to_comptime_int_type, - .anyframe_type, .const_slice_u8_type, .const_slice_u8_sentinel_0_type, .anyerror_void_error_union_type, - .generic_poison_type, - .enum_literal_type, + .undef, .zero, .one, - .void_value, .unreachable_value, .the_only_possible_value, .empty_array, .null_value, - .bool_true, - .bool_false, .empty_struct_value, .manyptr_u8_type, .manyptr_const_u8_type, .manyptr_const_u8_sentinel_0_type, - .atomic_order_type, - .atomic_rmw_op_type, - .calling_convention_type, - .address_space_type, - .float_mode_type, - .reduce_op_type, - .modifier_type, - .prefetch_options_type, - .export_options_type, - .extern_options_type, - .type_info_type, - .generic_poison, => unreachable, .ty, .lazy_align, .lazy_size => { @@ -722,67 +553,13 @@ pub const Value = struct { } var val = start_val; while (true) switch (val.tag()) { - .u1_type => return out_stream.writeAll("u1"), - .u8_type => return out_stream.writeAll("u8"), - .i8_type => return out_stream.writeAll("i8"), - .u16_type => return out_stream.writeAll("u16"), - .u29_type => return out_stream.writeAll("u29"), - .i16_type => return out_stream.writeAll("i16"), - .u32_type => return out_stream.writeAll("u32"), - .i32_type => return out_stream.writeAll("i32"), - .u64_type => return out_stream.writeAll("u64"), - .i64_type => return out_stream.writeAll("i64"), - .u128_type => return out_stream.writeAll("u128"), - .i128_type => return out_stream.writeAll("i128"), - .isize_type => return out_stream.writeAll("isize"), - .usize_type => return out_stream.writeAll("usize"), - .c_char_type => return out_stream.writeAll("c_char"), - .c_short_type => return out_stream.writeAll("c_short"), - .c_ushort_type => return out_stream.writeAll("c_ushort"), - .c_int_type => return out_stream.writeAll("c_int"), - .c_uint_type => return out_stream.writeAll("c_uint"), - .c_long_type => return out_stream.writeAll("c_long"), - .c_ulong_type => return out_stream.writeAll("c_ulong"), - .c_longlong_type => return out_stream.writeAll("c_longlong"), - .c_ulonglong_type => return out_stream.writeAll("c_ulonglong"), - .c_longdouble_type => return out_stream.writeAll("c_longdouble"), - .f16_type => return out_stream.writeAll("f16"), - .f32_type => return out_stream.writeAll("f32"), - .f64_type => return out_stream.writeAll("f64"), - .f80_type => return out_stream.writeAll("f80"), - .f128_type => return out_stream.writeAll("f128"), - .anyopaque_type => return out_stream.writeAll("anyopaque"), - .bool_type => return out_stream.writeAll("bool"), - .void_type => return out_stream.writeAll("void"), - .type_type => return out_stream.writeAll("type"), - .anyerror_type => return out_stream.writeAll("anyerror"), - .comptime_int_type => return out_stream.writeAll("comptime_int"), - .comptime_float_type => return out_stream.writeAll("comptime_float"), - .noreturn_type => return out_stream.writeAll("noreturn"), - .null_type => return out_stream.writeAll("@Type(.Null)"), - .undefined_type => return out_stream.writeAll("@Type(.Undefined)"), .single_const_pointer_to_comptime_int_type => return out_stream.writeAll("*const comptime_int"), - .anyframe_type => return out_stream.writeAll("anyframe"), .const_slice_u8_type => return out_stream.writeAll("[]const u8"), .const_slice_u8_sentinel_0_type => return out_stream.writeAll("[:0]const u8"), .anyerror_void_error_union_type => return out_stream.writeAll("anyerror!void"), - .generic_poison_type => return out_stream.writeAll("(generic poison type)"), - .generic_poison => return out_stream.writeAll("(generic poison)"), - .enum_literal_type => return out_stream.writeAll("@Type(.EnumLiteral)"), .manyptr_u8_type => return out_stream.writeAll("[*]u8"), .manyptr_const_u8_type => return out_stream.writeAll("[*]const u8"), .manyptr_const_u8_sentinel_0_type => return out_stream.writeAll("[*:0]const u8"), - .atomic_order_type => return out_stream.writeAll("std.builtin.AtomicOrder"), - .atomic_rmw_op_type => return out_stream.writeAll("std.builtin.AtomicRmwOp"), - .calling_convention_type => return out_stream.writeAll("std.builtin.CallingConvention"), - .address_space_type => return out_stream.writeAll("std.builtin.AddressSpace"), - .float_mode_type => return out_stream.writeAll("std.builtin.FloatMode"), - .reduce_op_type => return out_stream.writeAll("std.builtin.ReduceOp"), - .modifier_type => return out_stream.writeAll("std.builtin.CallModifier"), - .prefetch_options_type => return out_stream.writeAll("std.builtin.PrefetchOptions"), - .export_options_type => return out_stream.writeAll("std.builtin.ExportOptions"), - .extern_options_type => return out_stream.writeAll("std.builtin.ExternOptions"), - .type_info_type => return out_stream.writeAll("std.builtin.Type"), .empty_struct_value => return out_stream.writeAll("struct {}{}"), .aggregate => { @@ -795,11 +572,8 @@ pub const Value = struct { .undef => return out_stream.writeAll("undefined"), .zero => return out_stream.writeAll("0"), .one => return out_stream.writeAll("1"), - .void_value => return out_stream.writeAll("{}"), .unreachable_value => return out_stream.writeAll("unreachable"), .the_only_possible_value => return out_stream.writeAll("(the only possible value)"), - .bool_true => return out_stream.writeAll("true"), - .bool_false => return out_stream.writeAll("false"), .ty => return val.castTag(.ty).?.data.dump("", options, out_stream), .lazy_align => { try out_stream.writeAll("@alignOf("); @@ -943,74 +717,16 @@ pub const Value = struct { /// Asserts that the value is representable as a type. pub fn toType(self: Value) Type { - if (self.ip_index != .none) { - return .{ - .ip_index = self.ip_index, - .legacy = undefined, - }; - } + if (self.ip_index != .none) return self.ip_index.toType(); return switch (self.tag()) { .ty => self.castTag(.ty).?.data, - .u1_type => Type.u1, - .u8_type => Type.u8, - .i8_type => Type.i8, - .u16_type => Type.u16, - .i16_type => Type.i16, - .u29_type => Type.u29, - .u32_type => Type.u32, - .i32_type => Type.i32, - .u64_type => Type.u64, - .i64_type => Type.i64, - .u128_type => Type.u128, - .i128_type => Type.i128, - .usize_type => Type.usize, - .isize_type => Type.isize, - .c_char_type => Type.c_char, - .c_short_type => Type.c_short, - .c_ushort_type => Type.c_ushort, - .c_int_type => Type.c_int, - .c_uint_type => Type.c_uint, - .c_long_type => Type.c_long, - .c_ulong_type => Type.c_ulong, - .c_longlong_type => Type.c_longlong, - .c_ulonglong_type => Type.c_ulonglong, - .c_longdouble_type => Type.c_longdouble, - .f16_type => Type.f16, - .f32_type => Type.f32, - .f64_type => Type.f64, - .f80_type => Type.f80, - .f128_type => Type.f128, - .anyopaque_type => Type.anyopaque, - .bool_type => Type.bool, - .void_type => Type.void, - .type_type => Type.type, - .anyerror_type => Type.anyerror, - .comptime_int_type => Type.comptime_int, - .comptime_float_type => Type.comptime_float, - .noreturn_type => Type.noreturn, - .null_type => Type.null, - .undefined_type => Type.undefined, .single_const_pointer_to_comptime_int_type => Type.initTag(.single_const_pointer_to_comptime_int), - .anyframe_type => Type.@"anyframe", .const_slice_u8_type => Type.initTag(.const_slice_u8), .const_slice_u8_sentinel_0_type => Type.initTag(.const_slice_u8_sentinel_0), .anyerror_void_error_union_type => Type.initTag(.anyerror_void_error_union), - .generic_poison_type => .{ .ip_index = .generic_poison_type, .legacy = undefined }, - .enum_literal_type => .{ .ip_index = .enum_literal_type, .legacy = undefined }, .manyptr_u8_type => Type.initTag(.manyptr_u8), .manyptr_const_u8_type => Type.initTag(.manyptr_const_u8), .manyptr_const_u8_sentinel_0_type => Type.initTag(.manyptr_const_u8_sentinel_0), - .atomic_order_type => .{ .ip_index = .atomic_order_type, .legacy = undefined }, - .atomic_rmw_op_type => .{ .ip_index = .atomic_rmw_op_type, .legacy = undefined }, - .calling_convention_type => .{ .ip_index = .calling_convention_type, .legacy = undefined }, - .address_space_type => .{ .ip_index = .address_space_type, .legacy = undefined }, - .float_mode_type => .{ .ip_index = .float_mode_type, .legacy = undefined }, - .reduce_op_type => .{ .ip_index = .reduce_op_type, .legacy = undefined }, - .modifier_type => .{ .ip_index = .call_modifier_type, .legacy = undefined }, - .prefetch_options_type => .{ .ip_index = .prefetch_options_type, .legacy = undefined }, - .export_options_type => .{ .ip_index = .export_options_type, .legacy = undefined }, - .extern_options_type => .{ .ip_index = .extern_options_type, .legacy = undefined }, - .type_info_type => .{ .ip_index = .type_info_type, .legacy = undefined }, else => unreachable, }; @@ -1133,58 +849,63 @@ pub const Value = struct { mod: *const Module, opt_sema: ?*Sema, ) Module.CompileError!BigIntConst { - switch (val.tag()) { - .null_value, - .zero, - .bool_false, - .the_only_possible_value, // i0, u0 - => return BigIntMutable.init(&space.limbs, 0).toConst(), + switch (val.ip_index) { + .bool_false => return BigIntMutable.init(&space.limbs, 0).toConst(), + .bool_true => return BigIntMutable.init(&space.limbs, 1).toConst(), + .none => switch (val.tag()) { + .null_value, + .zero, + .the_only_possible_value, // i0, u0 + => return BigIntMutable.init(&space.limbs, 0).toConst(), - .one, - .bool_true, - => return BigIntMutable.init(&space.limbs, 1).toConst(), + .one => return BigIntMutable.init(&space.limbs, 1).toConst(), - .enum_field_index => { - const index = val.castTag(.enum_field_index).?.data; - return BigIntMutable.init(&space.limbs, index).toConst(); + .enum_field_index => { + const index = val.castTag(.enum_field_index).?.data; + return BigIntMutable.init(&space.limbs, index).toConst(); + }, + .runtime_value => { + const sub_val = val.castTag(.runtime_value).?.data; + return sub_val.toBigIntAdvanced(space, mod, opt_sema); + }, + .int_u64 => return BigIntMutable.init(&space.limbs, val.castTag(.int_u64).?.data).toConst(), + .int_i64 => return BigIntMutable.init(&space.limbs, val.castTag(.int_i64).?.data).toConst(), + .int_big_positive => return val.castTag(.int_big_positive).?.asBigInt(), + .int_big_negative => return val.castTag(.int_big_negative).?.asBigInt(), + + .undef => unreachable, + + .lazy_align => { + const ty = val.castTag(.lazy_align).?.data; + if (opt_sema) |sema| { + try sema.resolveTypeLayout(ty); + } + const x = ty.abiAlignment(mod); + return BigIntMutable.init(&space.limbs, x).toConst(); + }, + .lazy_size => { + const ty = val.castTag(.lazy_size).?.data; + if (opt_sema) |sema| { + try sema.resolveTypeLayout(ty); + } + const x = ty.abiSize(mod); + return BigIntMutable.init(&space.limbs, x).toConst(); + }, + + .elem_ptr => { + const elem_ptr = val.castTag(.elem_ptr).?.data; + const array_addr = (try elem_ptr.array_ptr.getUnsignedIntAdvanced(mod, opt_sema)).?; + const elem_size = elem_ptr.elem_ty.abiSize(mod); + const new_addr = array_addr + elem_size * elem_ptr.index; + return BigIntMutable.init(&space.limbs, new_addr).toConst(); + }, + + else => unreachable, }, - .runtime_value => { - const sub_val = val.castTag(.runtime_value).?.data; - return sub_val.toBigIntAdvanced(space, mod, opt_sema); + else => switch (mod.intern_pool.indexToKey(val.ip_index)) { + .int => |int| return int.big_int, + else => unreachable, }, - .int_u64 => return BigIntMutable.init(&space.limbs, val.castTag(.int_u64).?.data).toConst(), - .int_i64 => return BigIntMutable.init(&space.limbs, val.castTag(.int_i64).?.data).toConst(), - .int_big_positive => return val.castTag(.int_big_positive).?.asBigInt(), - .int_big_negative => return val.castTag(.int_big_negative).?.asBigInt(), - - .undef => unreachable, - - .lazy_align => { - const ty = val.castTag(.lazy_align).?.data; - if (opt_sema) |sema| { - try sema.resolveTypeLayout(ty); - } - const x = ty.abiAlignment(mod); - return BigIntMutable.init(&space.limbs, x).toConst(); - }, - .lazy_size => { - const ty = val.castTag(.lazy_size).?.data; - if (opt_sema) |sema| { - try sema.resolveTypeLayout(ty); - } - const x = ty.abiSize(mod); - return BigIntMutable.init(&space.limbs, x).toConst(); - }, - - .elem_ptr => { - const elem_ptr = val.castTag(.elem_ptr).?.data; - const array_addr = (try elem_ptr.array_ptr.getUnsignedIntAdvanced(mod, opt_sema)).?; - const elem_size = elem_ptr.elem_ty.abiSize(mod); - const new_addr = array_addr + elem_size * elem_ptr.index; - return BigIntMutable.init(&space.limbs, new_addr).toConst(); - }, - - else => unreachable, } } @@ -1197,41 +918,46 @@ pub const Value = struct { /// 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 { - switch (val.tag()) { - .zero, - .bool_false, - .the_only_possible_value, // i0, u0 - => return 0, + switch (val.ip_index) { + .bool_false => return 0, + .bool_true => return 1, + .none => switch (val.tag()) { + .zero, + .the_only_possible_value, // i0, u0 + => return 0, - .one, - .bool_true, - => return 1, + .one => return 1, - .int_u64 => return val.castTag(.int_u64).?.data, - .int_i64 => return @intCast(u64, val.castTag(.int_i64).?.data), - .int_big_positive => return val.castTag(.int_big_positive).?.asBigInt().to(u64) catch null, - .int_big_negative => return val.castTag(.int_big_negative).?.asBigInt().to(u64) catch null, + .int_u64 => return val.castTag(.int_u64).?.data, + .int_i64 => return @intCast(u64, val.castTag(.int_i64).?.data), + .int_big_positive => return val.castTag(.int_big_positive).?.asBigInt().to(u64) catch null, + .int_big_negative => return val.castTag(.int_big_negative).?.asBigInt().to(u64) catch null, - .undef => unreachable, + .undef => unreachable, - .lazy_align => { - const ty = val.castTag(.lazy_align).?.data; - if (opt_sema) |sema| { - return (try ty.abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar; - } else { - return ty.abiAlignment(mod); - } + .lazy_align => { + const ty = val.castTag(.lazy_align).?.data; + if (opt_sema) |sema| { + return (try ty.abiAlignmentAdvanced(mod, .{ .sema = sema })).scalar; + } else { + return ty.abiAlignment(mod); + } + }, + .lazy_size => { + const ty = val.castTag(.lazy_size).?.data; + if (opt_sema) |sema| { + return (try ty.abiSizeAdvanced(mod, .{ .sema = sema })).scalar; + } else { + return ty.abiSize(mod); + } + }, + + else => return null, }, - .lazy_size => { - const ty = val.castTag(.lazy_size).?.data; - if (opt_sema) |sema| { - return (try ty.abiSizeAdvanced(mod, .{ .sema = sema })).scalar; - } else { - return ty.abiSize(mod); - } + else => switch (mod.intern_pool.indexToKey(val.ip_index)) { + .int => |int| return int.big_int.to(u64) catch null, + else => unreachable, }, - - else => return null, } } @@ -1242,51 +968,65 @@ pub const Value = struct { /// Asserts the value is an integer and it fits in a i64 pub fn toSignedInt(val: Value, mod: *const Module) i64 { - switch (val.tag()) { - .zero, - .bool_false, - .the_only_possible_value, // i0, u0 - => return 0, + switch (val.ip_index) { + .bool_false => return 0, + .bool_true => return 1, + .none => switch (val.tag()) { + .zero, + .the_only_possible_value, // i0, u0 + => return 0, - .one, - .bool_true, - => return 1, + .one => return 1, - .int_u64 => return @intCast(i64, val.castTag(.int_u64).?.data), - .int_i64 => return val.castTag(.int_i64).?.data, - .int_big_positive => return val.castTag(.int_big_positive).?.asBigInt().to(i64) catch unreachable, - .int_big_negative => return val.castTag(.int_big_negative).?.asBigInt().to(i64) catch unreachable, + .int_u64 => return @intCast(i64, val.castTag(.int_u64).?.data), + .int_i64 => return val.castTag(.int_i64).?.data, + .int_big_positive => return val.castTag(.int_big_positive).?.asBigInt().to(i64) catch unreachable, + .int_big_negative => return val.castTag(.int_big_negative).?.asBigInt().to(i64) catch unreachable, - .lazy_align => { - const ty = val.castTag(.lazy_align).?.data; - return @intCast(i64, ty.abiAlignment(mod)); + .lazy_align => { + const ty = val.castTag(.lazy_align).?.data; + return @intCast(i64, ty.abiAlignment(mod)); + }, + .lazy_size => { + const ty = val.castTag(.lazy_size).?.data; + return @intCast(i64, ty.abiSize(mod)); + }, + + .undef => unreachable, + else => unreachable, }, - .lazy_size => { - const ty = val.castTag(.lazy_size).?.data; - return @intCast(i64, ty.abiSize(mod)); + else => switch (mod.intern_pool.indexToKey(val.ip_index)) { + .int => |int| return int.big_int.to(i64) catch unreachable, + else => unreachable, }, - - .undef => unreachable, - else => unreachable, } } - pub fn toBool(self: Value) bool { - return switch (self.tag()) { - .bool_true, .one => true, - .bool_false, .zero => false, - .int_u64 => switch (self.castTag(.int_u64).?.data) { - 0 => false, - 1 => true, + pub fn toBool(val: Value, mod: *const Module) bool { + switch (val.ip_index) { + .bool_true => return true, + .bool_false => return false, + .none => return switch (val.tag()) { + .one => true, + .zero => false, + + .int_u64 => switch (val.castTag(.int_u64).?.data) { + 0 => false, + 1 => true, + else => unreachable, + }, + .int_i64 => switch (val.castTag(.int_i64).?.data) { + 0 => false, + 1 => true, + else => unreachable, + }, else => unreachable, }, - .int_i64 => switch (self.castTag(.int_i64).?.data) { - 0 => false, - 1 => true, + else => switch (mod.intern_pool.indexToKey(val.ip_index)) { + .int => |int| return !int.big_int.eqZero(), else => unreachable, }, - else => unreachable, - }; + } } fn isDeclRef(val: Value) bool { @@ -1319,7 +1059,7 @@ pub const Value = struct { switch (ty.zigTypeTag(mod)) { .Void => {}, .Bool => { - buffer[0] = @boolToInt(val.toBool()); + buffer[0] = @boolToInt(val.toBool(mod)); }, .Int, .Enum => { const int_info = ty.intInfo(mod); @@ -1442,7 +1182,7 @@ pub const Value = struct { .Little => bit_offset / 8, .Big => buffer.len - bit_offset / 8 - 1, }; - if (val.toBool()) { + if (val.toBool(mod)) { buffer[byte_index] |= (@as(u8, 1) << @intCast(u3, bit_offset % 8)); } else { buffer[byte_index] &= ~(@as(u8, 1) << @intCast(u3, bit_offset % 8)); @@ -1802,90 +1542,117 @@ pub const Value = struct { pub fn clz(val: Value, ty: Type, mod: *const Module) u64 { const ty_bits = ty.intInfo(mod).bits; - switch (val.tag()) { - .zero, .bool_false => return ty_bits, - .one, .bool_true => return ty_bits - 1, + switch (val.ip_index) { + .bool_false => return ty_bits, + .bool_true => return ty_bits - 1, + .none => switch (val.tag()) { + .zero => return ty_bits, + .one => return ty_bits - 1, - .int_u64 => { - const big = @clz(val.castTag(.int_u64).?.data); - return big + ty_bits - 64; - }, - .int_i64 => { - @panic("TODO implement i64 Value clz"); - }, - .int_big_positive => { - const bigint = val.castTag(.int_big_positive).?.asBigInt(); - return bigint.clz(ty_bits); - }, - .int_big_negative => { - @panic("TODO implement int_big_negative Value clz"); - }, + .int_u64 => { + const big = @clz(val.castTag(.int_u64).?.data); + return big + ty_bits - 64; + }, + .int_i64 => { + @panic("TODO implement i64 Value clz"); + }, + .int_big_positive => { + const bigint = val.castTag(.int_big_positive).?.asBigInt(); + return bigint.clz(ty_bits); + }, + .int_big_negative => { + @panic("TODO implement int_big_negative Value clz"); + }, - .the_only_possible_value => { - assert(ty_bits == 0); - return ty_bits; - }, + .the_only_possible_value => { + assert(ty_bits == 0); + return ty_bits; + }, - .lazy_align, .lazy_size => { - var bigint_buf: BigIntSpace = undefined; - const bigint = val.toBigIntAdvanced(&bigint_buf, mod, null) catch unreachable; - return bigint.clz(ty_bits); - }, + .lazy_align, .lazy_size => { + var bigint_buf: BigIntSpace = undefined; + const bigint = val.toBigIntAdvanced(&bigint_buf, mod, null) catch unreachable; + return bigint.clz(ty_bits); + }, - else => unreachable, + else => unreachable, + }, + else => switch (mod.intern_pool.indexToKey(val.ip_index)) { + .int => |int| return int.big_int.clz(ty_bits), + else => unreachable, + }, } } pub fn ctz(val: Value, ty: Type, mod: *const Module) u64 { const ty_bits = ty.intInfo(mod).bits; - switch (val.tag()) { - .zero, .bool_false => return ty_bits, - .one, .bool_true => return 0, + switch (val.ip_index) { + .bool_false => return ty_bits, + .bool_true => return 0, + .none => switch (val.tag()) { + .zero => return ty_bits, + .one => return 0, - .int_u64 => { - const big = @ctz(val.castTag(.int_u64).?.data); - return if (big == 64) ty_bits else big; - }, - .int_i64 => { - @panic("TODO implement i64 Value ctz"); - }, - .int_big_positive => { - const bigint = val.castTag(.int_big_positive).?.asBigInt(); - return bigint.ctz(); - }, - .int_big_negative => { - @panic("TODO implement int_big_negative Value ctz"); - }, + .int_u64 => { + const big = @ctz(val.castTag(.int_u64).?.data); + return if (big == 64) ty_bits else big; + }, + .int_i64 => { + @panic("TODO implement i64 Value ctz"); + }, + .int_big_positive => { + const bigint = val.castTag(.int_big_positive).?.asBigInt(); + return bigint.ctz(); + }, + .int_big_negative => { + @panic("TODO implement int_big_negative Value ctz"); + }, - .the_only_possible_value => { - assert(ty_bits == 0); - return ty_bits; - }, + .the_only_possible_value => { + assert(ty_bits == 0); + return ty_bits; + }, - .lazy_align, .lazy_size => { - var bigint_buf: BigIntSpace = undefined; - const bigint = val.toBigIntAdvanced(&bigint_buf, mod, null) catch unreachable; - return bigint.ctz(); - }, + .lazy_align, .lazy_size => { + var bigint_buf: BigIntSpace = undefined; + const bigint = val.toBigIntAdvanced(&bigint_buf, mod, null) catch unreachable; + return bigint.ctz(); + }, - else => unreachable, + else => unreachable, + }, + else => switch (mod.intern_pool.indexToKey(val.ip_index)) { + .int => |int| return int.big_int.ctz(), + else => unreachable, + }, } } pub fn popCount(val: Value, ty: Type, mod: *const Module) u64 { assert(!val.isUndef()); - switch (val.tag()) { - .zero, .bool_false => return 0, - .one, .bool_true => return 1, + switch (val.ip_index) { + .bool_false => return 0, + .bool_true => return 1, + .none => switch (val.tag()) { + .zero => return 0, + .one => return 1, - .int_u64 => return @popCount(val.castTag(.int_u64).?.data), + .int_u64 => return @popCount(val.castTag(.int_u64).?.data), - else => { - const info = ty.intInfo(mod); + else => { + const info = ty.intInfo(mod); - var buffer: Value.BigIntSpace = undefined; - const int = val.toBigInt(&buffer, mod); - return @intCast(u64, int.popCount(info.bits)); + var buffer: Value.BigIntSpace = undefined; + const int = val.toBigInt(&buffer, mod); + return @intCast(u64, int.popCount(info.bits)); + }, + }, + else => switch (mod.intern_pool.indexToKey(val.ip_index)) { + .int => |int| { + const info = ty.intInfo(mod); + return int.big_int.popCount(info.bits); + }, + else => unreachable, }, } } @@ -1933,37 +1700,42 @@ pub const Value = struct { /// Returns the number of bits the value requires to represent stored in twos complement form. pub fn intBitCountTwosComp(self: Value, mod: *const Module) usize { const target = mod.getTarget(); - switch (self.tag()) { - .zero, - .bool_false, - .the_only_possible_value, - => return 0, + switch (self.ip_index) { + .bool_false => return 0, + .bool_true => return 1, + .none => switch (self.tag()) { + .zero, + .the_only_possible_value, + => return 0, - .one, - .bool_true, - => return 1, + .one => return 1, - .int_u64 => { - const x = self.castTag(.int_u64).?.data; - if (x == 0) return 0; - return @intCast(usize, std.math.log2(x) + 1); + .int_u64 => { + const x = self.castTag(.int_u64).?.data; + if (x == 0) return 0; + return @intCast(usize, std.math.log2(x) + 1); + }, + .int_big_positive => return self.castTag(.int_big_positive).?.asBigInt().bitCountTwosComp(), + .int_big_negative => return self.castTag(.int_big_negative).?.asBigInt().bitCountTwosComp(), + + .decl_ref_mut, + .comptime_field_ptr, + .extern_fn, + .decl_ref, + .function, + .variable, + .eu_payload_ptr, + .opt_payload_ptr, + => return target.ptrBitWidth(), + + else => { + var buffer: BigIntSpace = undefined; + return self.toBigInt(&buffer, mod).bitCountTwosComp(); + }, }, - .int_big_positive => return self.castTag(.int_big_positive).?.asBigInt().bitCountTwosComp(), - .int_big_negative => return self.castTag(.int_big_negative).?.asBigInt().bitCountTwosComp(), - - .decl_ref_mut, - .comptime_field_ptr, - .extern_fn, - .decl_ref, - .function, - .variable, - .eu_payload_ptr, - .opt_payload_ptr, - => return target.ptrBitWidth(), - - else => { - var buffer: BigIntSpace = undefined; - return self.toBigInt(&buffer, mod).bitCountTwosComp(); + else => switch (mod.intern_pool.indexToKey(self.ip_index)) { + .int => |int| return int.big_int.bitCountTwosComp(), + else => unreachable, }, } } @@ -2008,82 +1780,88 @@ pub const Value = struct { mod: *const Module, opt_sema: ?*Sema, ) Module.CompileError!std.math.Order { - return switch (lhs.tag()) { - .zero, - .bool_false, - .the_only_possible_value, - => .eq, + switch (lhs.ip_index) { + .bool_false => return .eq, + .bool_true => return .gt, + .none => return switch (lhs.tag()) { + .zero, + .the_only_possible_value, + => .eq, - .one, - .bool_true, - .decl_ref, - .decl_ref_mut, - .comptime_field_ptr, - .extern_fn, - .function, - .variable, - => .gt, + .one, + .decl_ref, + .decl_ref_mut, + .comptime_field_ptr, + .extern_fn, + .function, + .variable, + => .gt, - .enum_field_index => return std.math.order(lhs.castTag(.enum_field_index).?.data, 0), - .runtime_value => { - // This is needed to correctly handle hashing the value. - // Checks in Sema should prevent direct comparisons from reaching here. - const val = lhs.castTag(.runtime_value).?.data; - return val.orderAgainstZeroAdvanced(mod, opt_sema); + .enum_field_index => return std.math.order(lhs.castTag(.enum_field_index).?.data, 0), + .runtime_value => { + // This is needed to correctly handle hashing the value. + // Checks in Sema should prevent direct comparisons from reaching here. + const val = lhs.castTag(.runtime_value).?.data; + return val.orderAgainstZeroAdvanced(mod, opt_sema); + }, + .int_u64 => std.math.order(lhs.castTag(.int_u64).?.data, 0), + .int_i64 => std.math.order(lhs.castTag(.int_i64).?.data, 0), + .int_big_positive => lhs.castTag(.int_big_positive).?.asBigInt().orderAgainstScalar(0), + .int_big_negative => lhs.castTag(.int_big_negative).?.asBigInt().orderAgainstScalar(0), + + .lazy_align => { + const ty = lhs.castTag(.lazy_align).?.data; + const strat: Type.AbiAlignmentAdvancedStrat = if (opt_sema) |sema| .{ .sema = sema } else .eager; + if (ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) { + error.NeedLazy => unreachable, + else => |e| return e, + }) { + return .gt; + } else { + return .eq; + } + }, + .lazy_size => { + const ty = lhs.castTag(.lazy_size).?.data; + const strat: Type.AbiAlignmentAdvancedStrat = if (opt_sema) |sema| .{ .sema = sema } else .eager; + if (ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) { + error.NeedLazy => unreachable, + else => |e| return e, + }) { + return .gt; + } else { + return .eq; + } + }, + + .float_16 => std.math.order(lhs.castTag(.float_16).?.data, 0), + .float_32 => std.math.order(lhs.castTag(.float_32).?.data, 0), + .float_64 => std.math.order(lhs.castTag(.float_64).?.data, 0), + .float_80 => std.math.order(lhs.castTag(.float_80).?.data, 0), + .float_128 => std.math.order(lhs.castTag(.float_128).?.data, 0), + + .elem_ptr => { + const elem_ptr = lhs.castTag(.elem_ptr).?.data; + switch (try elem_ptr.array_ptr.orderAgainstZeroAdvanced(mod, opt_sema)) { + .lt => unreachable, + .gt => return .gt, + .eq => { + if (elem_ptr.index == 0) { + return .eq; + } else { + return .gt; + } + }, + } + }, + + else => unreachable, }, - .int_u64 => std.math.order(lhs.castTag(.int_u64).?.data, 0), - .int_i64 => std.math.order(lhs.castTag(.int_i64).?.data, 0), - .int_big_positive => lhs.castTag(.int_big_positive).?.asBigInt().orderAgainstScalar(0), - .int_big_negative => lhs.castTag(.int_big_negative).?.asBigInt().orderAgainstScalar(0), - - .lazy_align => { - const ty = lhs.castTag(.lazy_align).?.data; - const strat: Type.AbiAlignmentAdvancedStrat = if (opt_sema) |sema| .{ .sema = sema } else .eager; - if (ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) { - error.NeedLazy => unreachable, - else => |e| return e, - }) { - return .gt; - } else { - return .eq; - } + else => switch (mod.intern_pool.indexToKey(lhs.ip_index)) { + .int => |int| return int.big_int.orderAgainstScalar(0), + else => unreachable, }, - .lazy_size => { - const ty = lhs.castTag(.lazy_size).?.data; - const strat: Type.AbiAlignmentAdvancedStrat = if (opt_sema) |sema| .{ .sema = sema } else .eager; - if (ty.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) { - error.NeedLazy => unreachable, - else => |e| return e, - }) { - return .gt; - } else { - return .eq; - } - }, - - .float_16 => std.math.order(lhs.castTag(.float_16).?.data, 0), - .float_32 => std.math.order(lhs.castTag(.float_32).?.data, 0), - .float_64 => std.math.order(lhs.castTag(.float_64).?.data, 0), - .float_80 => std.math.order(lhs.castTag(.float_80).?.data, 0), - .float_128 => std.math.order(lhs.castTag(.float_128).?.data, 0), - - .elem_ptr => { - const elem_ptr = lhs.castTag(.elem_ptr).?.data; - switch (try elem_ptr.array_ptr.orderAgainstZeroAdvanced(mod, opt_sema)) { - .lt => unreachable, - .gt => return .gt, - .eq => { - if (elem_ptr.index == 0) { - return .eq; - } else { - return .gt; - } - }, - } - }, - - else => unreachable, - }; + } } /// Asserts the value is comparable. @@ -2293,12 +2071,14 @@ pub const Value = struct { mod: *Module, opt_sema: ?*Sema, ) Module.CompileError!bool { + if (a.ip_index != .none or b.ip_index != .none) return a.ip_index == b.ip_index; + const target = mod.getTarget(); const a_tag = a.tag(); const b_tag = b.tag(); if (a_tag == b_tag) switch (a_tag) { .undef => return true, - .void_value, .null_value, .the_only_possible_value, .empty_struct_value => return true, + .null_value, .the_only_possible_value, .empty_struct_value => return true, .enum_literal => { const a_name = a.castTag(.enum_literal).?.data; const b_name = b.castTag(.enum_literal).?.data; @@ -2574,6 +2354,13 @@ pub const Value = struct { /// This function is used by hash maps and so treats floating-point NaNs as equal /// to each other, and not equal to other floating-point values. pub fn hash(val: Value, ty: Type, hasher: *std.hash.Wyhash, mod: *Module) void { + if (val.ip_index != .none) { + // The InternPool data structure hashes based on Key to make interned objects + // unique. An Index can be treated simply as u32 value for the + // purpose of Type/Value hashing and equality. + std.hash.autoHash(hasher, val.ip_index); + return; + } const zig_ty_tag = ty.zigTypeTag(mod); std.hash.autoHash(hasher, zig_ty_tag); if (val.isUndef()) return; @@ -2908,8 +2695,6 @@ pub const Value = struct { .int_i64, .int_big_positive, .int_big_negative, - .bool_false, - .bool_true, .the_only_possible_value, .lazy_align, .lazy_size, @@ -3051,15 +2836,6 @@ pub const Value = struct { .opt_payload => return val.castTag(.opt_payload).?.data.elemValueAdvanced(mod, index, arena, buffer), .eu_payload => return val.castTag(.eu_payload).?.data.elemValueAdvanced(mod, index, arena, buffer), - // These values will implicitly be treated as `repeated`. - .zero, - .one, - .bool_false, - .bool_true, - .int_i64, - .int_u64, - => return val, - else => unreachable, } } @@ -3272,13 +3048,10 @@ pub const Value = struct { // in which case the value 0 is null and other values are non-null. .zero, - .bool_false, .the_only_possible_value, => true, - .one, - .bool_true, - => false, + .one => false, .int_u64, .int_i64, @@ -5419,11 +5192,7 @@ pub const Value = struct { } pub fn isGenericPoison(val: Value) bool { - return switch (val.ip_index) { - .generic_poison => true, - .none => val.tag() == .generic_poison, - else => false, - }; + return val.ip_index == .generic_poison; } /// This type is not copyable since it may contain pointers to its inner data. @@ -5673,10 +5442,13 @@ pub const Value = struct { .legacy = .{ .ptr_otherwise = &negative_one_payload.base }, }; pub const undef = initTag(.undef); - pub const @"void" = initTag(.void_value); + pub const @"void": Value = .{ .ip_index = .void_value, .legacy = undefined }; pub const @"null" = initTag(.null_value); - pub const @"false" = initTag(.bool_false); - pub const @"true" = initTag(.bool_true); + pub const @"false": Value = .{ .ip_index = .bool_false, .legacy = undefined }; + pub const @"true": Value = .{ .ip_index = .bool_true, .legacy = undefined }; + + pub const generic_poison: Value = .{ .ip_index = .generic_poison, .legacy = undefined }; + pub const generic_poison_type: Value = .{ .ip_index = .generic_poison_type, .legacy = undefined }; pub fn makeBool(x: bool) Value { return if (x) Value.true else Value.false;