From c6f3e9d79cf849623e6c4f25e02e17cdfab07b7c Mon Sep 17 00:00:00 2001 From: mlugg Date: Mon, 25 Mar 2024 19:02:21 +0000 Subject: Zcu.Decl: remove `ty` field `Decl` can no longer store un-interned values, so this field is now unnecessary. The type can instead be fetched with the new `typeOf` helper method, which just gets the type of the Decl's `Value`. --- src/Module.zig | 51 +++++++++++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 26 deletions(-) (limited to 'src/Module.zig') diff --git a/src/Module.zig b/src/Module.zig index 7d91ceb7d1..9cbb2cc89a 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -330,9 +330,6 @@ const ValueArena = struct { pub const Decl = struct { name: InternPool.NullTerminatedString, - /// The most recent Type of the Decl after a successful semantic analysis. - /// Populated when `has_tv`. - ty: Type, /// The most recent Value of the Decl after a successful semantic analysis. /// Populated when `has_tv`. val: Value, @@ -487,20 +484,28 @@ pub const Decl = struct { zcu.namespacePtr(decl.src_namespace).fullyQualifiedName(zcu, decl.name); } - pub fn typedValue(decl: Decl) error{AnalysisFail}!TypedValue { + pub fn typeOf(decl: Decl, zcu: *const Zcu) Type { + assert(decl.has_tv); + return Type.fromInterned(zcu.intern_pool.typeOf(decl.val.toIntern())); + } + + pub fn typedValue(decl: Decl, zcu: *const Zcu) error{AnalysisFail}!TypedValue { if (!decl.has_tv) return error.AnalysisFail; - return TypedValue{ .ty = decl.ty, .val = decl.val }; + return .{ + .ty = decl.typeOf(zcu), + .val = decl.val, + }; } pub fn internValue(decl: *Decl, zcu: *Zcu) Allocator.Error!InternPool.Index { assert(decl.has_tv); - const ip_index = try decl.val.intern(decl.ty, zcu); + const ip_index = try decl.val.intern(decl.typeOf(zcu), zcu); decl.val = Value.fromInterned(ip_index); return ip_index; } pub fn isFunction(decl: Decl, zcu: *const Zcu) !bool { - const tv = try decl.typedValue(); + const tv = try decl.typedValue(zcu); return tv.ty.zigTypeTag(zcu) == .Fn; } @@ -590,7 +595,7 @@ pub const Decl = struct { @tagName(decl.analysis), }); if (decl.has_tv) { - std.debug.print(" ty={} val={}", .{ decl.ty, decl.val }); + std.debug.print(" val={}", .{decl.val}); } std.debug.print("\n", .{}); } @@ -615,7 +620,7 @@ pub const Decl = struct { pub fn getAlignment(decl: Decl, zcu: *Zcu) Alignment { assert(decl.has_tv); if (decl.alignment != .none) return decl.alignment; - return decl.ty.abiAlignment(zcu); + return decl.typeOf(zcu).abiAlignment(zcu); } /// Upgrade a `LazySrcLoc` to a `SrcLoc` based on the `Decl` provided. @@ -3525,7 +3530,6 @@ fn semaFile(mod: *Module, file: *File) SemaError!void { new_decl.src_line = 0; new_decl.is_pub = true; new_decl.is_exported = false; - new_decl.ty = Type.type; new_decl.alignment = .none; new_decl.@"linksection" = .none; new_decl.alive = true; // This Decl corresponds to a File and is therefore always alive. @@ -3594,7 +3598,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { const old_has_tv = decl.has_tv; // The following values are ignored if `!old_has_tv` - const old_ty = decl.ty; + const old_ty = decl.typeOf(mod); const old_val = decl.val; const old_align = decl.alignment; const old_linksection = decl.@"linksection"; @@ -3716,7 +3720,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { return sema.fail(&block_scope, ty_src, "type {} has no namespace", .{ty.fmt(mod)}); } - decl.ty = Type.fromInterned(InternPool.Index.type_type); decl.val = ty.toValue(); decl.alignment = .none; decl.@"linksection" = .none; @@ -3760,7 +3763,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { }, } - decl.ty = decl_tv.ty; decl.val = Value.fromInterned((try decl_tv.val.intern(decl_tv.ty, mod))); // Function linksection, align, and addrspace were already set by Sema if (!is_func) { @@ -3806,10 +3808,10 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { decl.analysis = .complete; const result: SemaDeclResult = if (old_has_tv) .{ - .invalidate_decl_val = !decl.ty.eql(old_ty, mod) or - !decl.val.eql(old_val, decl.ty, mod) or + .invalidate_decl_val = !decl_tv.ty.eql(old_ty, mod) or + !decl.val.eql(old_val, decl_tv.ty, mod) or is_inline != old_is_inline, - .invalidate_decl_ref = !decl.ty.eql(old_ty, mod) or + .invalidate_decl_ref = !decl_tv.ty.eql(old_ty, mod) or decl.alignment != old_align or decl.@"linksection" != old_linksection or decl.@"addrspace" != old_addrspace or @@ -3819,11 +3821,11 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { .invalidate_decl_ref = true, }; - const has_runtime_bits = queue_linker_work and (is_func or try sema.typeHasRuntimeBits(decl.ty)); + const has_runtime_bits = queue_linker_work and (is_func or try sema.typeHasRuntimeBits(decl_tv.ty)); if (has_runtime_bits) { // Needed for codegen_decl which will call updateDecl and then the // codegen backend wants full access to the Decl Type. - try sema.resolveTypeFully(decl.ty); + try sema.resolveTypeFully(decl_tv.ty); try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl_index }); @@ -3850,7 +3852,7 @@ fn semaAnonOwnerDecl(zcu: *Zcu, decl_index: Decl.Index) !SemaDeclResult { log.debug("semaAnonOwnerDecl '{d}'", .{@intFromEnum(decl_index)}); - switch (decl.ty.zigTypeTag(zcu)) { + switch (decl.typeOf(zcu).zigTypeTag(zcu)) { .Fn => @panic("TODO: update fn instance"), .Type => {}, else => unreachable, @@ -4479,7 +4481,7 @@ pub fn finalizeAnonDecl(mod: *Module, decl_index: Decl.Index) Allocator.Error!vo // if the Decl is referenced by an instruction or another constant. Otherwise, // the Decl will be garbage collected by the `codegen_decl` task instead of sent // to the linker. - if (mod.declPtr(decl_index).ty.isFnOrHasRuntimeBits(mod)) { + if (mod.declPtr(decl_index).typeOf(mod).isFnOrHasRuntimeBits(mod)) { try mod.comp.anon_work_queue.writeItem(.{ .codegen_decl = decl_index }); } } @@ -4563,7 +4565,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato // the runtime-known parameters only, not to be confused with the // generic_owner function type, which potentially has more parameters, // including comptime parameters. - const fn_ty = decl.ty; + const fn_ty = decl.typeOf(mod); const fn_ty_info = mod.typeToFunc(fn_ty).?; var sema: Sema = .{ @@ -4812,7 +4814,6 @@ pub fn allocateNewDecl( .src_line = undefined, .has_tv = false, .owns_tv = false, - .ty = undefined, .val = undefined, .alignment = undefined, .@"linksection" = .none, @@ -4889,7 +4890,6 @@ pub fn initNewAnonDecl( new_decl.name = name; new_decl.src_line = src_line; - new_decl.ty = typed_value.ty; new_decl.val = typed_value.val; new_decl.alignment = .none; new_decl.@"linksection" = .none; @@ -5419,7 +5419,7 @@ pub fn populateTestFunctions( try mod.ensureDeclAnalyzed(decl_index); } const decl = mod.declPtr(decl_index); - const test_fn_ty = decl.ty.slicePtrFieldType(mod).childType(mod); + const test_fn_ty = decl.typeOf(mod).slicePtrFieldType(mod).childType(mod); const array_decl_index = d: { // Add mod.test_functions to an array decl then make the test_functions @@ -5463,7 +5463,7 @@ pub fn populateTestFunctions( // func try mod.intern(.{ .ptr = .{ .ty = try mod.intern(.{ .ptr_type = .{ - .child = test_decl.ty.toIntern(), + .child = test_decl.typeOf(mod).toIntern(), .flags = .{ .is_const = true, }, @@ -5515,7 +5515,6 @@ pub fn populateTestFunctions( // Since we are replacing the Decl's value we must perform cleanup on the // previous value. - decl.ty = new_ty; decl.val = new_val; decl.has_tv = true; } -- cgit v1.2.3 From 5ec6e3036b2772e6efc08726b22c560dedd556bc Mon Sep 17 00:00:00 2001 From: mlugg Date: Mon, 25 Mar 2024 23:08:59 +0000 Subject: Sema: introduce separate `MutableValue` representation for comptime-mutable memory Perhaps someday, we will make Sema operate on mutable values more generally. For now, it makes sense to split out this representation, since it is only used in comptime pointer accesses. There are some currently unused methods on `MutableValue` which will be used once I rewrite the comptime pointer access logic to be less terrible. The commit following this one will - at long last - delete the legacy Value representation --- src/Module.zig | 2 +- src/Sema.zig | 657 +++++++++++++++++--------------------------------- src/Value.zig | 8 +- src/mutable_value.zig | 508 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 734 insertions(+), 441 deletions(-) create mode 100644 src/mutable_value.zig (limited to 'src/Module.zig') diff --git a/src/Module.zig b/src/Module.zig index 9cbb2cc89a..a11194c103 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -3598,7 +3598,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { const old_has_tv = decl.has_tv; // The following values are ignored if `!old_has_tv` - const old_ty = decl.typeOf(mod); + const old_ty = if (old_has_tv) decl.typeOf(mod) else undefined; const old_val = decl.val; const old_align = decl.alignment; const old_linksection = decl.@"linksection"; diff --git a/src/Sema.zig b/src/Sema.zig index 826988ee34..7db1462787 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -139,8 +139,7 @@ const MaybeComptimeAlloc = struct { }; const ComptimeAlloc = struct { - ty: Type, - val: Value, + val: MutableValue, is_const: bool, /// `.none` indicates that the alignment is the natural alignment of `val`. alignment: Alignment, @@ -153,8 +152,7 @@ const ComptimeAlloc = struct { fn newComptimeAlloc(sema: *Sema, block: *Block, ty: Type, alignment: Alignment) !ComptimeAllocIndex { const idx = sema.comptime_allocs.items.len; try sema.comptime_allocs.append(sema.gpa, .{ - .ty = ty, - .val = Value.fromInterned(try sema.mod.intern(.{ .undef = ty.toIntern() })), + .val = .{ .interned = try sema.mod.intern(.{ .undef = ty.toIntern() }) }, .is_const = false, .alignment = alignment, .runtime_index = block.runtime_index, @@ -175,6 +173,7 @@ const log = std.log.scoped(.sema); const Sema = @This(); const Value = @import("Value.zig"); +const MutableValue = @import("mutable_value.zig").MutableValue; const Type = @import("type.zig").Type; const TypedValue = @import("TypedValue.zig"); const Air = @import("Air.zig"); @@ -3762,10 +3761,10 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro if (!sema.isComptimeMutablePtr(ptr_val)) break :already_ct; const alloc_index = mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr.addr.comptime_alloc; const ct_alloc = sema.getComptimeAlloc(alloc_index); - const interned = try ct_alloc.val.intern(ct_alloc.ty, mod); + const interned = try ct_alloc.val.intern(mod, sema.arena); if (Value.fromInterned(interned).canMutateComptimeVarState(mod)) { // Preserve the comptime alloc, just make the pointer const. - ct_alloc.val = Value.fromInterned(interned); + ct_alloc.val = .{ .interned = interned }; ct_alloc.is_const = true; return sema.makePtrConst(block, alloc); } else { @@ -4030,7 +4029,7 @@ fn finishResolveComptimeKnownAllocPtr( const alloc_index = existing_comptime_alloc orelse a: { const idx = try sema.newComptimeAlloc(block, alloc_ty.childType(zcu), alloc_ty.ptrAlignment(zcu)); const alloc = sema.getComptimeAlloc(idx); - alloc.val = Value.fromInterned(result_val); + alloc.val = .{ .interned = result_val }; break :a idx; }; sema.getComptimeAlloc(alloc_index).is_const = true; @@ -4193,7 +4192,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com .anon_decl => |a| a.val, .comptime_alloc => |i| val: { const alloc = sema.getComptimeAlloc(i); - break :val try alloc.val.intern(alloc.ty, mod); + break :val try alloc.val.intern(mod, sema.arena); }, else => unreachable, }; @@ -5597,7 +5596,7 @@ fn storeToInferredAllocComptime( } }); } else { const alloc_index = try sema.newComptimeAlloc(block, operand_ty, iac.alignment); - sema.getComptimeAlloc(alloc_index).val = operand_val; + sema.getComptimeAlloc(alloc_index).val = .{ .interned = operand_val.toIntern() }; iac.ptr = try zcu.intern(.{ .ptr = .{ .ty = alloc_ty.toIntern(), .addr = .{ .comptime_alloc = alloc_index }, @@ -30655,21 +30654,22 @@ fn storePtrVal( .opv => {}, .direct => |val_ptr| { if (mut_kit.root == .comptime_field) { - val_ptr.* = Value.fromInterned((try val_ptr.intern(operand_ty, mod))); - if (!operand_val.eql(val_ptr.*, operand_ty, mod)) { + val_ptr.* = .{ .interned = try val_ptr.intern(mod, sema.arena) }; + if (operand_val.toIntern() != val_ptr.interned) { // TODO use failWithInvalidComptimeFieldStore return sema.fail(block, src, "value stored in comptime field does not match the default value of the field", .{}); } return; } - val_ptr.* = Value.fromInterned((try operand_val.intern(operand_ty, mod))); + val_ptr.* = .{ .interned = operand_val.toIntern() }; }, .reinterpret => |reinterpret| { try sema.resolveTypeLayout(mut_kit.ty); const abi_size = try sema.usizeCast(block, src, mut_kit.ty.abiSize(mod)); const buffer = try sema.gpa.alloc(u8, abi_size); defer sema.gpa.free(buffer); - reinterpret.val_ptr.*.writeToMemory(mut_kit.ty, mod, buffer) catch |err| switch (err) { + const interned_old = Value.fromInterned(try reinterpret.val_ptr.intern(mod, sema.arena)); + interned_old.writeToMemory(mut_kit.ty, mod, buffer) catch |err| switch (err) { error.OutOfMemory => return error.OutOfMemory, error.ReinterpretDeclRef => unreachable, error.IllDefinedMemoryLayout => unreachable, // Sema was supposed to emit a compile error already @@ -30693,7 +30693,7 @@ fn storePtrVal( error.IllDefinedMemoryLayout => unreachable, error.Unimplemented => return sema.fail(block, src, "TODO: implement readFromMemory for type '{}'", .{mut_kit.ty.fmt(mod)}), }; - reinterpret.val_ptr.* = Value.fromInterned((try val.intern(mut_kit.ty, mod))); + reinterpret.val_ptr.* = .{ .interned = val.toIntern() }; }, .bad_decl_ty, .bad_ptr_ty => { // TODO show the decl declaration site in a note and explain whether the decl @@ -30718,11 +30718,11 @@ const ComptimePtrMutationKit = struct { opv, /// The pointer type matches the actual comptime Value so a direct /// modification is possible. - direct: *Value, + direct: *MutableValue, /// The largest parent Value containing pointee and having a well-defined memory layout. /// This is used for bitcasting, if direct dereferencing failed. reinterpret: struct { - val_ptr: *Value, + val_ptr: *MutableValue, byte_offset: usize, /// If set, write the operand to packed memory write_packed: bool = false, @@ -30754,15 +30754,15 @@ fn beginComptimePtrMutation( .decl, .anon_decl, .int => unreachable, // isComptimeMutablePtr has been checked already .comptime_alloc => |alloc_index| { const alloc = sema.getComptimeAlloc(alloc_index); - return sema.beginComptimePtrMutationInner(block, src, alloc.ty, &alloc.val, ptr_elem_ty, .{ .alloc = alloc_index }); + return sema.beginComptimePtrMutationInner(block, src, alloc.val.typeOf(mod), &alloc.val, ptr_elem_ty, .{ .alloc = alloc_index }); }, .comptime_field => |comptime_field| { - const duped = try sema.arena.create(Value); - duped.* = Value.fromInterned(comptime_field); + const duped = try sema.arena.create(MutableValue); + duped.* = .{ .interned = comptime_field }; return sema.beginComptimePtrMutationInner( block, src, - Type.fromInterned(mod.intern_pool.typeOf(comptime_field)), + duped.typeOf(mod), duped, ptr_elem_ty, .comptime_field, @@ -30775,36 +30775,28 @@ fn beginComptimePtrMutation( .opv => unreachable, .direct => |val_ptr| { const payload_ty = parent.ty.errorUnionPayload(mod); - if (val_ptr.ip_index == .none and val_ptr.tag() == .eu_payload) { - return ComptimePtrMutationKit{ - .root = parent.root, - .pointee = .{ .direct = &val_ptr.castTag(.eu_payload).?.data }, - .ty = payload_ty, - }; - } else { + try val_ptr.unintern(mod, sema.arena, false, false); + if (val_ptr.* == .interned) { // An error union has been initialized to undefined at comptime and now we // are for the first time setting the payload. We must change the - // representation of the error union from `undef` to `opt_payload`. - - const payload = try sema.arena.create(Value.Payload.SubValue); - payload.* = .{ - .base = .{ .tag = .eu_payload }, - .data = Value.fromInterned((try mod.intern(.{ .undef = payload_ty.toIntern() }))), - }; - - val_ptr.* = Value.initPayload(&payload.base); - - return ComptimePtrMutationKit{ - .root = parent.root, - .pointee = .{ .direct = &payload.data }, - .ty = payload_ty, - }; + // representation of the error union to `eu_payload`. + const child = try sema.arena.create(MutableValue); + child.* = .{ .interned = try mod.intern(.{ .undef = payload_ty.toIntern() }) }; + val_ptr.* = .{ .eu_payload = .{ + .ty = parent.ty.toIntern(), + .child = child, + } }; } + return .{ + .root = parent.root, + .pointee = .{ .direct = val_ptr.eu_payload.child }, + .ty = payload_ty, + }; }, .bad_decl_ty, .bad_ptr_ty => return parent, // Even though the parent value type has well-defined memory layout, our // pointer type does not. - .reinterpret => return ComptimePtrMutationKit{ + .reinterpret => return .{ .root = parent.root, .pointee = .bad_ptr_ty, .ty = eu_ty, @@ -30818,46 +30810,28 @@ fn beginComptimePtrMutation( .opv => unreachable, .direct => |val_ptr| { const payload_ty = parent.ty.optionalChild(mod); - switch (val_ptr.ip_index) { - .none => return ComptimePtrMutationKit{ - .root = parent.root, - .pointee = .{ .direct = &val_ptr.castTag(.opt_payload).?.data }, - .ty = payload_ty, - }, - else => { - const payload_val = switch (mod.intern_pool.indexToKey(val_ptr.ip_index)) { - .undef => try mod.intern(.{ .undef = payload_ty.toIntern() }), - .opt => |opt| switch (opt.val) { - .none => try mod.intern(.{ .undef = payload_ty.toIntern() }), - else => |payload| payload, - }, - else => unreachable, - }; - - // An optional has been initialized to undefined at comptime and now we - // are for the first time setting the payload. We must change the - // representation of the optional from `undef` to `opt_payload`. - - const payload = try sema.arena.create(Value.Payload.SubValue); - payload.* = .{ - .base = .{ .tag = .opt_payload }, - .data = Value.fromInterned(payload_val), - }; - - val_ptr.* = Value.initPayload(&payload.base); - - return ComptimePtrMutationKit{ - .root = parent.root, - .pointee = .{ .direct = &payload.data }, - .ty = payload_ty, - }; - }, + try val_ptr.unintern(mod, sema.arena, false, false); + if (val_ptr.* == .interned) { + // An optional has been initialized to undefined at comptime and now we + // are for the first time setting the payload. We must change the + // representation of the optional to `opt_payload`. + const child = try sema.arena.create(MutableValue); + child.* = .{ .interned = try mod.intern(.{ .undef = payload_ty.toIntern() }) }; + val_ptr.* = .{ .opt_payload = .{ + .ty = parent.ty.toIntern(), + .child = child, + } }; } + return .{ + .root = parent.root, + .pointee = .{ .direct = val_ptr.opt_payload.child }, + .ty = payload_ty, + }; }, .bad_decl_ty, .bad_ptr_ty => return parent, // Even though the parent value type has well-defined memory layout, our // pointer type does not. - .reinterpret => return ComptimePtrMutationKit{ + .reinterpret => return .{ .root = parent.root, .pointee = .bad_ptr_ty, .ty = opt_ty, @@ -30916,106 +30890,28 @@ fn beginComptimePtrMutation( }; } - switch (val_ptr.ip_index) { - .none => switch (val_ptr.tag()) { - .bytes => { - // An array is memory-optimized to store a slice of bytes, but we are about - // to modify an individual field and the representation has to change. - // If we wanted to avoid this, there would need to be special detection - // elsewhere to identify when writing a value to an array element that is stored - // using the `bytes` tag, and handle it without making a call to this function. - const arena = sema.arena; - - const bytes = val_ptr.castTag(.bytes).?.data; - const dest_len = parent.ty.arrayLenIncludingSentinel(mod); - // bytes.len may be one greater than dest_len because of the case when - // assigning `[N:S]T` to `[N]T`. This is allowed; the sentinel is omitted. - assert(bytes.len >= dest_len); - const elems = try arena.alloc(Value, @intCast(dest_len)); - for (elems, 0..) |*elem, i| { - elem.* = try mod.intValue(elem_ty, bytes[i]); - } - - val_ptr.* = try Value.Tag.aggregate.create(arena, elems); - - return beginComptimePtrMutationInner( - sema, - block, - src, - elem_ty, - &elems[@intCast(elem_ptr.index)], - ptr_elem_ty, - parent.root, - ); - }, - .repeated => { - // An array is memory-optimized to store only a single element value, and - // that value is understood to be the same for the entire length of the array. - // However, now we want to modify an individual field and so the - // representation has to change. If we wanted to avoid this, there would - // need to be special detection elsewhere to identify when writing a value to an - // array element that is stored using the `repeated` tag, and handle it - // without making a call to this function. - const arena = sema.arena; - - const repeated_val = try val_ptr.castTag(.repeated).?.data.intern(parent.ty.childType(mod), mod); - const array_len_including_sentinel = - try sema.usizeCast(block, src, parent.ty.arrayLenIncludingSentinel(mod)); - const elems = try arena.alloc(Value, array_len_including_sentinel); - @memset(elems, Value.fromInterned(repeated_val)); - - val_ptr.* = try Value.Tag.aggregate.create(arena, elems); - - return beginComptimePtrMutationInner( - sema, - block, - src, - elem_ty, - &elems[@intCast(elem_ptr.index)], - ptr_elem_ty, - parent.root, - ); - }, - - .aggregate => return beginComptimePtrMutationInner( - sema, - block, - src, - elem_ty, - &val_ptr.castTag(.aggregate).?.data[@intCast(elem_ptr.index)], - ptr_elem_ty, - parent.root, - ), + try val_ptr.unintern(mod, sema.arena, false, false); + + const aggregate = switch (val_ptr.*) { + .interned, + .bytes, + .repeated, + .eu_payload, + .opt_payload, + .slice, + .un, + => unreachable, + .aggregate => |*a| a, + }; - else => unreachable, - }, - else => switch (mod.intern_pool.indexToKey(val_ptr.toIntern())) { - .undef => { - // An array has been initialized to undefined at comptime and now we - // are for the first time setting an element. We must change the representation - // of the array from `undef` to `array`. - const arena = sema.arena; - - const array_len_including_sentinel = - try sema.usizeCast(block, src, parent.ty.arrayLenIncludingSentinel(mod)); - const elems = try arena.alloc(Value, array_len_including_sentinel); - @memset(elems, Value.fromInterned((try mod.intern(.{ .undef = elem_ty.toIntern() })))); - - val_ptr.* = try Value.Tag.aggregate.create(arena, elems); - - return beginComptimePtrMutationInner( - sema, - block, - src, - elem_ty, - &elems[@intCast(elem_ptr.index)], - ptr_elem_ty, - parent.root, - ); - }, - else => unreachable, - }, - } + return sema.beginComptimePtrMutationInner( + block, + src, + elem_ty, + &aggregate.elems[@intCast(elem_ptr.index)], + ptr_elem_ty, + parent.root, + ); }, else => { if (elem_ptr.index != 0) { @@ -31039,7 +30935,7 @@ fn beginComptimePtrMutation( if (!base_elem_ty.hasWellDefinedLayout(mod)) { // Even though the parent value type has well-defined memory layout, our // pointer type does not. - return ComptimePtrMutationKit{ + return .{ .root = parent.root, .pointee = .bad_ptr_ty, .ty = base_elem_ty, @@ -31049,7 +30945,7 @@ fn beginComptimePtrMutation( const elem_abi_size_u64 = try sema.typeAbiSize(base_elem_ty); const elem_abi_size = try sema.usizeCast(block, src, elem_abi_size_u64); const elem_idx = try sema.usizeCast(block, src, elem_ptr.index); - return ComptimePtrMutationKit{ + return .{ .root = parent.root, .pointee = .{ .reinterpret = .{ .val_ptr = reinterpret.val_ptr, @@ -31068,56 +30964,68 @@ fn beginComptimePtrMutation( var parent = try sema.beginComptimePtrMutation(block, src, Value.fromInterned(field_ptr.base), base_child_ty); switch (parent.pointee) { .opv => unreachable, - .direct => |val_ptr| switch (val_ptr.ip_index) { - .empty_struct => { - const duped = try sema.arena.create(Value); - duped.* = val_ptr.*; - return beginComptimePtrMutationInner( - sema, - block, - src, - parent.ty.structFieldType(field_index, mod), - duped, - ptr_elem_ty, - parent.root, - ); - }, - .none => switch (val_ptr.tag()) { - .aggregate => return beginComptimePtrMutationInner( - sema, + .direct => |val_ptr| { + try val_ptr.unintern(mod, sema.arena, false, false); + switch (val_ptr.*) { + .interned, + .eu_payload, + .opt_payload, + .repeated, + .bytes, + => unreachable, + .aggregate => |*a| return sema.beginComptimePtrMutationInner( block, src, parent.ty.structFieldType(field_index, mod), - &val_ptr.castTag(.aggregate).?.data[field_index], + &a.elems[field_index], ptr_elem_ty, parent.root, ), - .repeated => { - const arena = sema.arena; - - const elems = try arena.alloc(Value, parent.ty.structFieldCount(mod)); - @memset(elems, val_ptr.castTag(.repeated).?.data); - val_ptr.* = try Value.Tag.aggregate.create(arena, elems); - - return beginComptimePtrMutationInner( - sema, + .slice => |*s| switch (field_index) { + Value.slice_ptr_index => return sema.beginComptimePtrMutationInner( block, src, - parent.ty.structFieldType(field_index, mod), - &elems[field_index], + parent.ty.slicePtrFieldType(mod), + s.ptr, ptr_elem_ty, parent.root, - ); + ), + Value.slice_len_index => return sema.beginComptimePtrMutationInner( + block, + src, + Type.usize, + s.len, + ptr_elem_ty, + parent.root, + ), + else => unreachable, }, - .@"union" => { - const payload = &val_ptr.castTag(.@"union").?.data; + .un => |*un| { const layout = base_child_ty.containerLayout(mod); const tag_type = base_child_ty.unionTagTypeHypothetical(mod); const hypothetical_tag = try mod.enumValueFieldIndex(tag_type, field_index); - if (layout == .auto or (payload.tag != null and hypothetical_tag.eql(payload.tag.?, tag_type, mod))) { + if (un.tag == .none and un.payload.* == .interned and un.payload.interned == .undef) { + // A union has been initialized to undefined at comptime and now we + // are for the first time setting the payload. We must change the + // tag implicitly. + const payload_ty = parent.ty.structFieldType(field_index, mod); + un.tag = hypothetical_tag.toIntern(); + un.payload.* = .{ .interned = try mod.intern(.{ .undef = payload_ty.toIntern() }) }; + return beginComptimePtrMutationInner( + sema, + block, + src, + payload_ty, + un.payload, + ptr_elem_ty, + parent.root, + ); + } + + if (layout == .auto or hypothetical_tag.toIntern() == un.tag) { // We need to set the active field of the union. - payload.tag = hypothetical_tag; + un.tag = hypothetical_tag.toIntern(); const field_ty = parent.ty.structFieldType(field_index, mod); return beginComptimePtrMutationInner( @@ -31125,7 +31033,7 @@ fn beginComptimePtrMutation( block, src, field_ty, - &payload.val, + un.payload, ptr_elem_ty, parent.root, ); @@ -31133,11 +31041,10 @@ fn beginComptimePtrMutation( // Writing to a different field (a different or unknown tag is active) requires reinterpreting // memory of the entire union, which requires knowing its abiSize. try sema.resolveTypeLayout(parent.ty); - // This union value no longer has a well-defined tag type. // The reinterpretation will read it back out as .none. - payload.val = try payload.val.unintern(sema.arena, mod); - return ComptimePtrMutationKit{ + try un.payload.unintern(mod, sema.arena, false, false); + return .{ .root = parent.root, .pointee = .{ .reinterpret = .{ .val_ptr = val_ptr, @@ -31148,119 +31055,12 @@ fn beginComptimePtrMutation( }; } }, - .slice => switch (field_index) { - Value.slice_ptr_index => return beginComptimePtrMutationInner( - sema, - block, - src, - parent.ty.slicePtrFieldType(mod), - &val_ptr.castTag(.slice).?.data.ptr, - ptr_elem_ty, - parent.root, - ), - - Value.slice_len_index => return beginComptimePtrMutationInner( - sema, - block, - src, - Type.usize, - &val_ptr.castTag(.slice).?.data.len, - ptr_elem_ty, - parent.root, - ), - - else => unreachable, - }, - else => unreachable, - }, - else => switch (mod.intern_pool.indexToKey(val_ptr.toIntern())) { - .undef => { - // A struct or union has been initialized to undefined at comptime and now we - // are for the first time setting a field. We must change the representation - // of the struct/union from `undef` to `struct`/`union`. - const arena = sema.arena; - - switch (parent.ty.zigTypeTag(mod)) { - .Struct => { - const fields = try arena.alloc(Value, parent.ty.structFieldCount(mod)); - for (fields, 0..) |*field, i| field.* = Value.fromInterned((try mod.intern(.{ - .undef = parent.ty.structFieldType(i, mod).toIntern(), - }))); - - val_ptr.* = try Value.Tag.aggregate.create(arena, fields); - - return beginComptimePtrMutationInner( - sema, - block, - src, - parent.ty.structFieldType(field_index, mod), - &fields[field_index], - ptr_elem_ty, - parent.root, - ); - }, - .Union => { - const payload = try arena.create(Value.Payload.Union); - const tag_ty = parent.ty.unionTagTypeHypothetical(mod); - const payload_ty = parent.ty.structFieldType(field_index, mod); - payload.* = .{ .data = .{ - .tag = try mod.enumValueFieldIndex(tag_ty, field_index), - .val = Value.fromInterned((try mod.intern(.{ .undef = payload_ty.toIntern() }))), - } }; - - val_ptr.* = Value.initPayload(&payload.base); - - return beginComptimePtrMutationInner( - sema, - block, - src, - payload_ty, - &payload.data.val, - ptr_elem_ty, - parent.root, - ); - }, - .Pointer => { - assert(parent.ty.isSlice(mod)); - const ptr_ty = parent.ty.slicePtrFieldType(mod); - val_ptr.* = try Value.Tag.slice.create(arena, .{ - .ptr = Value.fromInterned((try mod.intern(.{ .undef = ptr_ty.toIntern() }))), - .len = Value.fromInterned((try mod.intern(.{ .undef = .usize_type }))), - }); - - switch (field_index) { - Value.slice_ptr_index => return beginComptimePtrMutationInner( - sema, - block, - src, - ptr_ty, - &val_ptr.castTag(.slice).?.data.ptr, - ptr_elem_ty, - parent.root, - ), - Value.slice_len_index => return beginComptimePtrMutationInner( - sema, - block, - src, - Type.usize, - &val_ptr.castTag(.slice).?.data.len, - ptr_elem_ty, - parent.root, - ), - - else => unreachable, - } - }, - else => unreachable, - } - }, - else => unreachable, - }, + } }, .reinterpret => |reinterpret| { const field_offset_u64 = base_child_ty.structFieldOffset(field_index, mod); const field_offset = try sema.usizeCast(block, src, field_offset_u64); - return ComptimePtrMutationKit{ + return .{ .root = parent.root, .pointee = .{ .reinterpret = .{ .val_ptr = reinterpret.val_ptr, @@ -31280,7 +31080,7 @@ fn beginComptimePtrMutationInner( block: *Block, src: LazySrcLoc, decl_ty: Type, - decl_val: *Value, + decl_val: *MutableValue, ptr_elem_ty: Type, root: ComptimePtrMutationKit.Root, ) CompileError!ComptimePtrMutationKit { @@ -31288,7 +31088,13 @@ fn beginComptimePtrMutationInner( const target = mod.getTarget(); const coerce_ok = (try sema.coerceInMemoryAllowed(block, ptr_elem_ty, decl_ty, true, target, src, src)) == .ok; - decl_val.* = try decl_val.unintern(sema.arena, mod); + const old_decl_val = decl_val.*; + try decl_val.unintern(mod, sema.arena, false, false); + if (decl_val.* == .un and decl_val.un.tag == .none and decl_val.un.payload.* == .interned and decl_val.un.payload.interned == .undef) { + // HACKHACK: undefined union - re-intern it for now + // `unintern` probably should just leave these as is, but I'm leaving it until I rewrite comptime pointer access. + decl_val.* = old_decl_val; + } if (coerce_ok) { return ComptimePtrMutationKit{ @@ -31334,21 +31140,16 @@ fn beginComptimePtrMutationInner( }; } -const TypedValueAndOffset = struct { - tv: TypedValue, - byte_offset: usize, -}; - const ComptimePtrLoadKit = struct { /// The Value and Type corresponding to the pointee of the provided pointer. /// If a direct dereference is not possible, this is null. - pointee: ?TypedValue, + pointee: ?MutableValue, /// The largest parent Value containing `pointee` and having a well-defined memory layout. /// This is used for bitcasting, if direct dereferencing failed (i.e. `pointee` is null). - parent: ?TypedValueAndOffset, - /// Whether the `pointee` could be mutated by further - /// semantic analysis and a copy must be performed. - is_mutable: bool, + parent: ?struct { + val: MutableValue, + byte_offset: usize, + }, /// If the root decl could not be used as `parent`, this is the type that /// caused that by not having a well-defined layout ty_without_well_defined_layout: ?Type, @@ -31375,53 +31176,41 @@ fn beginComptimePtrLoad( .ptr => |ptr| switch (ptr.addr) { .decl => |decl_index| blk: { const decl = mod.declPtr(decl_index); - const decl_tv = try decl.typedValue(mod); try sema.declareDependency(.{ .decl_val = decl_index }); if (decl.val.getVariable(mod) != null) return error.RuntimeLoad; - + const decl_val: MutableValue = .{ .interned = decl.val.toIntern() }; const layout_defined = decl.typeOf(mod).hasWellDefinedLayout(mod); break :blk ComptimePtrLoadKit{ - .parent = if (layout_defined) .{ .tv = decl_tv, .byte_offset = 0 } else null, - .pointee = decl_tv, - .is_mutable = false, + .parent = if (layout_defined) .{ .val = decl_val, .byte_offset = 0 } else null, + .pointee = decl_val, .ty_without_well_defined_layout = if (!layout_defined) decl.typeOf(mod) else null, }; }, .comptime_alloc => |alloc_index| kit: { const alloc = sema.getComptimeAlloc(alloc_index); - const alloc_tv: TypedValue = .{ - .ty = alloc.ty, - .val = alloc.val, - }; - const layout_defined = alloc.ty.hasWellDefinedLayout(mod); + const alloc_ty = alloc.val.typeOf(mod); + const layout_defined = alloc_ty.hasWellDefinedLayout(mod); break :kit .{ - .parent = if (layout_defined) .{ .tv = alloc_tv, .byte_offset = 0 } else null, - .pointee = alloc_tv, - .is_mutable = true, - .ty_without_well_defined_layout = if (!layout_defined) alloc.ty else null, + .parent = if (layout_defined) .{ .val = alloc.val, .byte_offset = 0 } else null, + .pointee = alloc.val, + .ty_without_well_defined_layout = if (!layout_defined) alloc_ty else null, }; }, .anon_decl => |anon_decl| blk: { const decl_val = anon_decl.val; if (Value.fromInterned(decl_val).getVariable(mod) != null) return error.RuntimeLoad; const decl_ty = Type.fromInterned(ip.typeOf(decl_val)); - const decl_tv: TypedValue = .{ .ty = decl_ty, .val = Value.fromInterned(decl_val) }; + const decl_mv: MutableValue = .{ .interned = decl_val }; const layout_defined = decl_ty.hasWellDefinedLayout(mod); break :blk ComptimePtrLoadKit{ - .parent = if (layout_defined) .{ .tv = decl_tv, .byte_offset = 0 } else null, - .pointee = decl_tv, - .is_mutable = false, + .parent = if (layout_defined) .{ .val = decl_mv, .byte_offset = 0 } else null, + .pointee = decl_mv, .ty_without_well_defined_layout = if (!layout_defined) decl_ty else null, }; }, .int => return error.RuntimeLoad, .eu_payload, .opt_payload => |container_ptr| blk: { const container_ty = Type.fromInterned(ip.typeOf(container_ptr)).childType(mod); - const payload_ty = switch (ptr.addr) { - .eu_payload => container_ty.errorUnionPayload(mod), - .opt_payload => container_ty.optionalChild(mod), - else => unreachable, - }; var deref = try sema.beginComptimePtrLoad(block, src, Value.fromInterned(container_ptr), container_ty); // eu_payload and opt_payload never have a well-defined layout @@ -31430,15 +31219,14 @@ fn beginComptimePtrLoad( deref.ty_without_well_defined_layout = container_ty; } - if (deref.pointee) |*tv| { + if (deref.pointee) |pointee| { + const pointee_ty = pointee.typeOf(mod); const coerce_in_mem_ok = - (try sema.coerceInMemoryAllowed(block, container_ty, tv.ty, false, target, src, src)) == .ok or - (try sema.coerceInMemoryAllowed(block, tv.ty, container_ty, false, target, src, src)) == .ok; + (try sema.coerceInMemoryAllowed(block, container_ty, pointee_ty, false, target, src, src)) == .ok or + (try sema.coerceInMemoryAllowed(block, pointee_ty, container_ty, false, target, src, src)) == .ok; if (coerce_in_mem_ok) { - const payload_val = switch (tv.val.ip_index) { - .none => tv.val.cast(Value.Payload.SubValue).?.data, - .null_value => return sema.fail(block, src, "attempt to use null value", .{}), - else => Value.fromInterned(switch (ip.indexToKey(tv.val.toIntern())) { + deref.pointee = switch (pointee) { + .interned => |ip_index| .{ .interned = switch (ip.indexToKey(ip_index)) { .error_union => |error_union| switch (error_union.val) { .err_name => |err_name| return sema.fail( block, @@ -31453,23 +31241,20 @@ fn beginComptimePtrLoad( else => |payload| payload, }, else => unreachable, - }), + } }, + .eu_payload, .opt_payload => |p| p.child.*, + else => unreachable, }; - tv.* = TypedValue{ .ty = payload_ty, .val = payload_val }; break :blk deref; } } deref.pointee = null; break :blk deref; }, - .comptime_field => |comptime_field| blk: { - const field_ty = Type.fromInterned(ip.typeOf(comptime_field)); - break :blk ComptimePtrLoadKit{ - .parent = null, - .pointee = .{ .ty = field_ty, .val = Value.fromInterned(comptime_field) }, - .is_mutable = false, - .ty_without_well_defined_layout = field_ty, - }; + .comptime_field => |field_val| .{ + .parent = null, + .pointee = .{ .interned = field_val }, + .ty_without_well_defined_layout = Type.fromInterned(ip.typeOf(field_val)), }, .elem => |elem_ptr| blk: { const elem_ty = Type.fromInterned(ip.typeOf(elem_ptr.base)).elemType2(mod); @@ -31502,30 +31287,37 @@ fn beginComptimePtrLoad( // If we're loading an elem that was derived from a different type // than the true type of the underlying decl, we cannot deref directly - const ty_matches = if (deref.pointee != null and deref.pointee.?.ty.isArrayOrVector(mod)) x: { - const deref_elem_ty = deref.pointee.?.ty.childType(mod); - break :x (try sema.coerceInMemoryAllowed(block, deref_elem_ty, elem_ty, false, target, src, src)) == .ok or - (try sema.coerceInMemoryAllowed(block, elem_ty, deref_elem_ty, false, target, src, src)) == .ok; + const ty_matches = if (deref.pointee) |pointee| match: { + const ty = pointee.typeOf(mod); + if (!ty.isArrayOrVector(mod)) break :match false; + const deref_elem_ty = ty.childType(mod); + if ((try sema.coerceInMemoryAllowed(block, deref_elem_ty, elem_ty, false, target, src, src)) == .ok) break :match true; + if ((try sema.coerceInMemoryAllowed(block, elem_ty, deref_elem_ty, false, target, src, src)) == .ok) break :match true; + break :match false; } else false; if (!ty_matches) { deref.pointee = null; break :blk deref; } - var array_tv = deref.pointee.?; - const check_len = array_tv.ty.arrayLenIncludingSentinel(mod); + var array_val = deref.pointee.?; + const check_len = array_val.typeOf(mod).arrayLenIncludingSentinel(mod); if (maybe_array_ty) |load_ty| { // It's possible that we're loading a [N]T, in which case we'd like to slice // the pointee array directly from our parent array. if (load_ty.isArrayOrVector(mod) and load_ty.childType(mod).eql(elem_ty, mod)) { const len = try sema.usizeCast(block, src, load_ty.arrayLenIncludingSentinel(mod)); const elem_idx = try sema.usizeCast(block, src, elem_ptr.index); - deref.pointee = if (elem_ptr.index + len <= check_len) TypedValue{ - .ty = try mod.arrayType(.{ - .len = len, - .child = elem_ty.toIntern(), - }), - .val = try array_tv.val.sliceArray(sema, elem_idx, elem_idx + len), + deref.pointee = if (elem_ptr.index + len <= check_len) switch (array_val) { + .aggregate => |a| .{ .aggregate = .{ + .ty = (try mod.arrayType(.{ .len = len, .child = elem_ty.toIntern() })).toIntern(), + .elems = a.elems[elem_idx..][0..len], + } }, + else => .{ + .interned = (try (Value.fromInterned( + try array_val.intern(mod, sema.arena), + ).sliceArray(sema, elem_idx, elem_idx + len))).toIntern(), + }, } else null; break :blk deref; } @@ -31536,18 +31328,12 @@ fn beginComptimePtrLoad( break :blk deref; } if (elem_ptr.index == check_len - 1) { - if (array_tv.ty.sentinel(mod)) |sent| { - deref.pointee = TypedValue{ - .ty = elem_ty, - .val = sent, - }; + if (array_val.typeOf(mod).sentinel(mod)) |sent| { + deref.pointee = .{ .interned = sent.toIntern() }; break :blk deref; } } - deref.pointee = TypedValue{ - .ty = elem_ty, - .val = try array_tv.val.elemValue(mod, @intCast(elem_ptr.index)), - }; + deref.pointee = try array_val.getElem(mod, @intCast(elem_ptr.index)); break :blk deref; }, .field => |field_ptr| blk: { @@ -31571,37 +31357,17 @@ fn beginComptimePtrLoad( deref.ty_without_well_defined_layout = container_ty; } - const tv = deref.pointee orelse { - deref.pointee = null; - break :blk deref; - }; + const pointee = deref.pointee orelse break :blk deref; + const pointee_ty = pointee.typeOf(mod); const coerce_in_mem_ok = - (try sema.coerceInMemoryAllowed(block, container_ty, tv.ty, false, target, src, src)) == .ok or - (try sema.coerceInMemoryAllowed(block, tv.ty, container_ty, false, target, src, src)) == .ok; + (try sema.coerceInMemoryAllowed(block, container_ty, pointee_ty, false, target, src, src)) == .ok or + (try sema.coerceInMemoryAllowed(block, pointee_ty, container_ty, false, target, src, src)) == .ok; if (!coerce_in_mem_ok) { deref.pointee = null; break :blk deref; } - if (container_ty.isSlice(mod)) { - deref.pointee = switch (field_index) { - Value.slice_ptr_index => TypedValue{ - .ty = container_ty.slicePtrFieldType(mod), - .val = tv.val.slicePtr(mod), - }, - Value.slice_len_index => TypedValue{ - .ty = Type.usize, - .val = Value.fromInterned(ip.indexToKey(try tv.val.intern(tv.ty, mod)).slice.len), - }, - else => unreachable, - }; - } else { - const field_ty = container_ty.structFieldType(field_index, mod); - deref.pointee = TypedValue{ - .ty = field_ty, - .val = try tv.val.fieldValue(mod, field_index), - }; - } + deref.pointee = try pointee.getElem(mod, field_index); break :blk deref; }, }, @@ -31612,9 +31378,9 @@ fn beginComptimePtrLoad( else => unreachable, }; - if (deref.pointee) |tv| { - if (deref.parent == null and tv.ty.hasWellDefinedLayout(mod)) { - deref.parent = .{ .tv = tv, .byte_offset = 0 }; + if (deref.pointee) |val| { + if (deref.parent == null and val.typeOf(mod).hasWellDefinedLayout(mod)) { + deref.parent = .{ .val = val, .byte_offset = 0 }; } } return deref; @@ -38289,17 +38055,18 @@ fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value else => |e| return e, }; - if (deref.pointee) |tv| { + if (deref.pointee) |pointee| { + const uncoerced_val = Value.fromInterned(try pointee.intern(mod, sema.arena)); + const ty = Type.fromInterned(mod.intern_pool.typeOf(uncoerced_val.toIntern())); const coerce_in_mem_ok = - (try sema.coerceInMemoryAllowed(block, load_ty, tv.ty, false, target, src, src)) == .ok or - (try sema.coerceInMemoryAllowed(block, tv.ty, load_ty, false, target, src, src)) == .ok; + (try sema.coerceInMemoryAllowed(block, load_ty, ty, false, target, src, src)) == .ok or + (try sema.coerceInMemoryAllowed(block, ty, load_ty, false, target, src, src)) == .ok; if (coerce_in_mem_ok) { // We have a Value that lines up in virtual memory exactly with what we want to load, // and it is in-memory coercible to load_ty. It may be returned without modifications. // Move mutable decl values to the InternPool and assert other decls are already in // the InternPool. - const uncoerced_val = if (deref.is_mutable) try tv.val.intern(tv.ty, mod) else tv.val.toIntern(); - const coerced_val = try mod.getCoerced(Value.fromInterned(uncoerced_val), load_ty); + const coerced_val = try mod.getCoerced(uncoerced_val, load_ty); return .{ .val = coerced_val }; } } @@ -38313,21 +38080,35 @@ fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value const load_sz = try sema.typeAbiSize(load_ty); // Try the smaller bit-cast first, since that's more efficient than using the larger `parent` - if (deref.pointee) |tv| if (load_sz <= try sema.typeAbiSize(tv.ty)) - return DerefResult{ .val = (try sema.bitCastVal(block, src, tv.val, tv.ty, load_ty, 0)) orelse return .runtime_load }; + if (deref.pointee) |pointee| { + const val_ip_index = try pointee.intern(mod, sema.arena); + const val = Value.fromInterned(val_ip_index); + const ty = Type.fromInterned(mod.intern_pool.typeOf(val_ip_index)); + if (load_sz <= try sema.typeAbiSize(ty)) { + return .{ .val = (try sema.bitCastVal(block, src, val, ty, load_ty, 0)) orelse return .runtime_load }; + } + } // If that fails, try to bit-cast from the largest parent value with a well-defined layout - if (deref.parent) |parent| if (load_sz + parent.byte_offset <= try sema.typeAbiSize(parent.tv.ty)) - return DerefResult{ .val = (try sema.bitCastVal(block, src, parent.tv.val, parent.tv.ty, load_ty, parent.byte_offset)) orelse return .runtime_load }; + if (deref.parent) |parent| { + const parent_ip_index = try parent.val.intern(mod, sema.arena); + const parent_val = Value.fromInterned(parent_ip_index); + const parent_ty = Type.fromInterned(mod.intern_pool.typeOf(parent_ip_index)); + if (load_sz + parent.byte_offset <= try sema.typeAbiSize(parent_ty)) { + return .{ .val = (try sema.bitCastVal(block, src, parent_val, parent_ty, load_ty, parent.byte_offset)) orelse return .runtime_load }; + } + } if (deref.ty_without_well_defined_layout) |bad_ty| { // We got no parent for bit-casting, or the parent we got was too small. Either way, the problem // is that some type we encountered when de-referencing does not have a well-defined layout. - return DerefResult{ .needed_well_defined = bad_ty }; + return .{ .needed_well_defined = bad_ty }; } else { // If all encountered types had well-defined layouts, the parent is the root decl and it just // wasn't big enough for the load. - return DerefResult{ .out_of_bounds = deref.parent.?.tv.ty }; + const parent_ip_index = try deref.parent.?.val.intern(mod, sema.arena); + const parent_ty = Type.fromInterned(mod.intern_pool.typeOf(parent_ip_index)); + return .{ .out_of_bounds = parent_ty }; } } diff --git a/src/Value.zig b/src/Value.zig index c220f6d0d9..af24d68d7c 100644 --- a/src/Value.zig +++ b/src/Value.zig @@ -1627,7 +1627,9 @@ pub fn maybeElemValueFull(val: Value, sema: ?*Sema, mod: *Module, index: usize) .ptr => |ptr| switch (ptr.addr) { .decl => |decl| mod.declPtr(decl).val.maybeElemValueFull(sema, mod, index), .anon_decl => |anon_decl| Value.fromInterned(anon_decl.val).maybeElemValueFull(sema, mod, index), - .comptime_alloc => |idx| if (sema) |s| s.getComptimeAlloc(idx).val.maybeElemValueFull(sema, mod, index) else null, + .comptime_alloc => |idx| if (sema) |s| Value.fromInterned( + try s.getComptimeAlloc(idx).val.intern(mod, s.arena), + ).maybeElemValueFull(sema, mod, index) else null, .int, .eu_payload => null, .opt_payload => |base| Value.fromInterned(base).maybeElemValueFull(sema, mod, index), .comptime_field => |field_val| Value.fromInterned(field_val).maybeElemValueFull(sema, mod, index), @@ -1697,7 +1699,9 @@ pub fn sliceArray( else => switch (mod.intern_pool.indexToKey(val.toIntern())) { .ptr => |ptr| switch (ptr.addr) { .decl => |decl| try mod.declPtr(decl).val.sliceArray(sema, start, end), - .comptime_alloc => |idx| sema.getComptimeAlloc(idx).val.sliceArray(sema, start, end), + .comptime_alloc => |idx| try Value.fromInterned( + try sema.getComptimeAlloc(idx).val.intern(mod, sema.arena), + ).sliceArray(sema, start, end), .comptime_field => |comptime_field| Value.fromInterned(comptime_field) .sliceArray(sema, start, end), .elem => |elem| Value.fromInterned(elem.base) diff --git a/src/mutable_value.zig b/src/mutable_value.zig new file mode 100644 index 0000000000..327c354108 --- /dev/null +++ b/src/mutable_value.zig @@ -0,0 +1,508 @@ +const std = @import("std"); +const assert = std.debug.assert; +const Allocator = std.mem.Allocator; +const Zcu = @import("Module.zig"); +const InternPool = @import("InternPool.zig"); +const Type = @import("type.zig").Type; +const Value = @import("Value.zig"); + +/// We use a tagged union here because while it wastes a few bytes for some tags, having a fixed +/// size for the type makes the common `aggregate` representation more efficient. +/// For aggregates, the sentinel value, if any, *is* stored. +pub const MutableValue = union(enum) { + /// An interned value. + interned: InternPool.Index, + /// An error union value which is a payload (not an error). + eu_payload: SubValue, + /// An optional value which is a payload (not `null`). + opt_payload: SubValue, + /// An aggregate consisting of a single repeated value. + repeated: SubValue, + /// An aggregate of `u8` consisting of "plain" bytes (no lazy or undefined elements). + bytes: Bytes, + /// An aggregate with arbitrary sub-values. + aggregate: Aggregate, + /// A slice, containing a pointer and length. + slice: Slice, + /// An instance of a union. + un: Union, + + pub const SubValue = struct { + ty: InternPool.Index, + child: *MutableValue, + }; + pub const Bytes = struct { + ty: InternPool.Index, + data: []u8, + }; + pub const Aggregate = struct { + ty: InternPool.Index, + elems: []MutableValue, + }; + pub const Slice = struct { + ty: InternPool.Index, + /// Must have the appropriate many-ptr type. + /// TODO: we want this to be an `InternPool.Index`, but `Sema.beginComptimePtrMutation` doesn't support it. + ptr: *MutableValue, + /// Must be of type `usize`. + /// TODO: we want this to be an `InternPool.Index`, but `Sema.beginComptimePtrMutation` doesn't support it. + len: *MutableValue, + }; + pub const Union = struct { + ty: InternPool.Index, + tag: InternPool.Index, + payload: *MutableValue, + }; + + pub fn intern(mv: MutableValue, zcu: *Zcu, arena: Allocator) Allocator.Error!InternPool.Index { + const ip = &zcu.intern_pool; + const gpa = zcu.gpa; + return switch (mv) { + .interned => |ip_index| ip_index, + .eu_payload => |sv| try ip.get(gpa, .{ .error_union = .{ + .ty = sv.ty, + .val = .{ .payload = try sv.child.intern(zcu, arena) }, + } }), + .opt_payload => |sv| try ip.get(gpa, .{ .opt = .{ + .ty = sv.ty, + .val = try sv.child.intern(zcu, arena), + } }), + .repeated => |sv| try ip.get(gpa, .{ .aggregate = .{ + .ty = sv.ty, + .storage = .{ .repeated_elem = try sv.child.intern(zcu, arena) }, + } }), + .bytes => |b| try ip.get(gpa, .{ .aggregate = .{ + .ty = b.ty, + .storage = .{ .bytes = b.data }, + } }), + .aggregate => |a| { + const elems = try arena.alloc(InternPool.Index, a.elems.len); + for (a.elems, elems) |mut_elem, *interned_elem| { + interned_elem.* = try mut_elem.intern(zcu, arena); + } + return ip.get(gpa, .{ .aggregate = .{ + .ty = a.ty, + .storage = .{ .elems = elems }, + } }); + }, + .slice => |s| try ip.get(gpa, .{ .slice = .{ + .ty = s.ty, + .ptr = try s.ptr.intern(zcu, arena), + .len = try s.len.intern(zcu, arena), + } }), + .un => |u| try ip.get(gpa, .{ .un = .{ + .ty = u.ty, + .tag = u.tag, + .val = try u.payload.intern(zcu, arena), + } }), + }; + } + + /// Un-interns the top level of this `MutableValue`, if applicable. + /// * Non-error error unions use `eu_payload` + /// * Non-null optionals use `eu_payload + /// * Slices use `slice` + /// * Unions use `un` + /// * Aggregates use `repeated` or `bytes` or `aggregate` + /// If `!allow_bytes`, the `bytes` representation will not be used. + /// If `!allow_repeated`, the `repeated` representation will not be used. + pub fn unintern( + mv: *MutableValue, + zcu: *Zcu, + arena: Allocator, + allow_bytes: bool, + allow_repeated: bool, + ) Allocator.Error!void { + const ip = &zcu.intern_pool; + const gpa = zcu.gpa; + switch (mv.*) { + .interned => |ip_index| switch (ip.indexToKey(ip_index)) { + .opt => |opt| if (opt.val != .none) { + const mut_payload = try arena.create(MutableValue); + mut_payload.* = .{ .interned = opt.val }; + mv.* = .{ .opt_payload = .{ + .ty = opt.ty, + .child = mut_payload, + } }; + }, + .error_union => |eu| switch (eu.val) { + .err_name => {}, + .payload => |payload| { + const mut_payload = try arena.create(MutableValue); + mut_payload.* = .{ .interned = payload }; + mv.* = .{ .eu_payload = .{ + .ty = eu.ty, + .child = mut_payload, + } }; + }, + }, + .slice => |slice| { + const ptr = try arena.create(MutableValue); + const len = try arena.create(MutableValue); + ptr.* = .{ .interned = slice.ptr }; + len.* = .{ .interned = slice.len }; + mv.* = .{ .slice = .{ + .ty = slice.ty, + .ptr = ptr, + .len = len, + } }; + }, + .un => |un| { + const payload = try arena.create(MutableValue); + payload.* = .{ .interned = un.val }; + mv.* = .{ .un = .{ + .ty = un.ty, + .tag = un.tag, + .payload = payload, + } }; + }, + .aggregate => |agg| switch (agg.storage) { + .bytes => |bytes| { + assert(bytes.len == ip.aggregateTypeLenIncludingSentinel(agg.ty)); + assert(ip.childType(agg.ty) == .u8_type); + if (allow_bytes) { + const arena_bytes = try arena.alloc(u8, bytes.len); + @memcpy(arena_bytes, bytes); + mv.* = .{ .bytes = .{ + .ty = agg.ty, + .data = arena_bytes, + } }; + } else { + const mut_elems = try arena.alloc(MutableValue, bytes.len); + for (bytes, mut_elems) |b, *mut_elem| { + mut_elem.* = .{ .interned = try ip.get(gpa, .{ .int = .{ + .ty = .u8_type, + .storage = .{ .u64 = b }, + } }) }; + } + mv.* = .{ .aggregate = .{ + .ty = agg.ty, + .elems = mut_elems, + } }; + } + }, + .elems => |elems| { + assert(elems.len == ip.aggregateTypeLenIncludingSentinel(agg.ty)); + const mut_elems = try arena.alloc(MutableValue, elems.len); + for (elems, mut_elems) |interned_elem, *mut_elem| { + mut_elem.* = .{ .interned = interned_elem }; + } + mv.* = .{ .aggregate = .{ + .ty = agg.ty, + .elems = mut_elems, + } }; + }, + .repeated_elem => |val| { + if (allow_repeated) { + const repeated_val = try arena.create(MutableValue); + repeated_val.* = .{ .interned = val }; + mv.* = .{ .repeated = .{ + .ty = agg.ty, + .child = repeated_val, + } }; + } else { + const len = ip.aggregateTypeLenIncludingSentinel(agg.ty); + const mut_elems = try arena.alloc(MutableValue, @intCast(len)); + @memset(mut_elems, .{ .interned = val }); + mv.* = .{ .aggregate = .{ + .ty = agg.ty, + .elems = mut_elems, + } }; + } + }, + }, + .undef => |ty_ip| switch (Type.fromInterned(ty_ip).zigTypeTag(zcu)) { + .Struct, .Array, .Vector => |type_tag| { + const ty = Type.fromInterned(ty_ip); + const opt_sent = ty.sentinel(zcu); + if (type_tag == .Struct or opt_sent != null or !allow_repeated) { + const len_no_sent = ip.aggregateTypeLen(ty_ip); + const elems = try arena.alloc(MutableValue, @intCast(len_no_sent + @intFromBool(opt_sent != null))); + switch (type_tag) { + .Array, .Vector => { + const elem_ty = ip.childType(ty_ip); + const undef_elem = try ip.get(gpa, .{ .undef = elem_ty }); + @memset(elems[0..@intCast(len_no_sent)], .{ .interned = undef_elem }); + }, + .Struct => for (elems[0..@intCast(len_no_sent)], 0..) |*mut_elem, i| { + const field_ty = ty.structFieldType(i, zcu).toIntern(); + mut_elem.* = .{ .interned = try ip.get(gpa, .{ .undef = field_ty }) }; + }, + else => unreachable, + } + if (opt_sent) |s| elems[@intCast(len_no_sent)] = .{ .interned = s.toIntern() }; + mv.* = .{ .aggregate = .{ + .ty = ty_ip, + .elems = elems, + } }; + } else { + const repeated_val = try arena.create(MutableValue); + repeated_val.* = .{ + .interned = try ip.get(gpa, .{ .undef = ip.childType(ty_ip) }), + }; + mv.* = .{ .repeated = .{ + .ty = ty_ip, + .child = repeated_val, + } }; + } + }, + .Union => { + const payload = try arena.create(MutableValue); + // HACKHACK: this logic is silly, but Sema detects it and reverts the change where needed. + // See comment at the top of `Sema.beginComptimePtrMutationInner`. + payload.* = .{ .interned = .undef }; + mv.* = .{ .un = .{ + .ty = ty_ip, + .tag = .none, + .payload = payload, + } }; + }, + .Pointer => { + const ptr_ty = ip.indexToKey(ty_ip).ptr_type; + if (ptr_ty.flags.size != .Slice) return; + const ptr = try arena.create(MutableValue); + const len = try arena.create(MutableValue); + ptr.* = .{ .interned = try ip.get(gpa, .{ .undef = ip.slicePtrType(ty_ip) }) }; + len.* = .{ .interned = try ip.get(gpa, .{ .undef = .usize_type }) }; + mv.* = .{ .slice = .{ + .ty = ty_ip, + .ptr = ptr, + .len = len, + } }; + }, + else => {}, + }, + else => {}, + }, + .bytes => |bytes| if (!allow_bytes) { + const elems = try arena.alloc(MutableValue, bytes.data.len); + for (bytes.data, elems) |byte, *interned_byte| { + interned_byte.* = .{ .interned = try ip.get(gpa, .{ .int = .{ + .ty = .u8_type, + .storage = .{ .u64 = byte }, + } }) }; + } + mv.* = .{ .aggregate = .{ + .ty = bytes.ty, + .elems = elems, + } }; + }, + else => {}, + } + } + + /// Get a pointer to the `MutableValue` associated with a field/element. + /// The returned pointer can be safety mutated through to modify the field value. + /// The returned pointer is valid until the representation of `mv` changes. + /// This function does *not* support accessing the ptr/len field of slices. + pub fn elem( + mv: *MutableValue, + zcu: *Zcu, + arena: Allocator, + field_idx: usize, + ) Allocator.Error!*MutableValue { + const ip = &zcu.intern_pool; + const gpa = zcu.gpa; + // Convert to the `aggregate` representation. + switch (mv) { + .eu_payload, .opt_payload, .slice, .un => unreachable, + .interned => { + try mv.unintern(zcu, arena, false, false); + }, + .bytes => |bytes| { + const elems = try arena.alloc(MutableValue, bytes.data.len); + for (bytes.data, elems) |byte, interned_byte| { + interned_byte.* = try ip.get(gpa, .{ .int = .{ + .ty = .u8_type, + .storage = .{ .u64 = byte }, + } }); + } + mv.* = .{ .aggregate = .{ + .ty = bytes.ty, + .elems = elems, + } }; + }, + .repeated => |repeated| { + const len = ip.aggregateTypeLenIncludingSentinel(repeated.ty); + const elems = try arena.alloc(MutableValue, @intCast(len)); + @memset(elems, repeated.child.*); + mv.* = .{ .aggregate = .{ + .ty = repeated.ty, + .elems = elems, + } }; + }, + .aggregate => {}, + } + return &mv.aggregate.elems[field_idx]; + } + + /// Modify a single field of a `MutableValue` which represents an aggregate or slice, leaving others + /// untouched. When an entire field must be modified, this should be used in preference to `elemPtr` + /// to allow for an optimal representation. + /// For slices, uses `Value.slice_ptr_index` and `Value.slice_len_index`. + pub fn setElem( + mv: *MutableValue, + zcu: *Zcu, + arena: Allocator, + field_idx: usize, + field_val: MutableValue, + ) Allocator.Error!void { + const ip = &zcu.intern_pool; + const is_trivial_int = field_val.isTrivialInt(zcu); + try mv.unintern(arena, is_trivial_int, true); + switch (mv) { + .interned, + .eu_payload, + .opt_payload, + .un, + => unreachable, + .slice => |*s| switch (field_idx) { + Value.slice_ptr_index => s.ptr = field_val, + Value.slice_len_index => s.len = field_val, + }, + .bytes => |b| { + assert(is_trivial_int); + assert(field_val.typeOf() == Type.u8); + b.data[field_idx] = Value.fromInterned(field_val.interned).toUnsignedInt(zcu); + }, + .repeated => |r| { + if (field_val.eqlTrivial(r.child.*)) return; + // We must switch to either the `aggregate` or the `bytes` representation. + const len_inc_sent = ip.aggregateTypeLenIncludingSentinel(r.ty); + if (ip.zigTypeTag(r.ty) != .Struct and + is_trivial_int and + Type.fromInterned(r.ty).childType(zcu) == .u8_type and + r.child.isTrivialInt(zcu)) + { + // We can use the `bytes` representation. + const bytes = try arena.alloc(u8, @intCast(len_inc_sent)); + const repeated_byte = Value.fromInterned(r.child.interned).getUnsignedInt(zcu); + @memset(bytes, repeated_byte); + bytes[field_idx] = Value.fromInterned(field_val.interned).getUnsignedInt(zcu); + mv.* = .{ .bytes = .{ + .ty = r.ty, + .data = bytes, + } }; + } else { + // We must use the `aggregate` representation. + const mut_elems = try arena.alloc(u8, @intCast(len_inc_sent)); + @memset(mut_elems, r.child.*); + mut_elems[field_idx] = field_val; + mv.* = .{ .aggregate = .{ + .ty = r.ty, + .elems = mut_elems, + } }; + } + }, + .aggregate => |a| { + a.elems[field_idx] = field_val; + const is_struct = ip.zigTypeTag(a.ty) == .Struct; + // Attempt to switch to a more efficient representation. + const is_repeated = for (a.elems) |e| { + if (!e.eqlTrivial(field_val)) break false; + } else true; + if (is_repeated) { + // Switch to `repeated` repr + const mut_repeated = try arena.create(MutableValue); + mut_repeated.* = field_val; + mv.* = .{ .repeated = .{ + .ty = a.ty, + .child = mut_repeated, + } }; + } else if (!is_struct and is_trivial_int and Type.fromInterned(a.ty).childType(zcu).toIntern() == .u8_type) { + // See if we can switch to `bytes` repr + for (a.elems) |e| { + switch (e) { + else => break, + .interned => |ip_index| switch (ip.indexToKey(ip_index)) { + else => break, + .int => |int| switch (int.storage) { + .u64, .i64, .big_int => {}, + .lazy_align, .lazy_size => break, + }, + }, + } + } else { + const bytes = try arena.alloc(u8, a.elems.len); + for (a.elems, bytes) |elem_val, *b| { + b.* = Value.fromInterned(elem_val.interned).toUnsignedInt(zcu); + } + mv.* = .{ .bytes = .{ + .ty = a.ty, + .data = bytes, + } }; + } + } + }, + } + } + + /// Get the value of a single field of a `MutableValue` which represents an aggregate or slice. + /// For slices, uses `Value.slice_ptr_index` and `Value.slice_len_index`. + pub fn getElem( + mv: MutableValue, + zcu: *Zcu, + field_idx: usize, + ) Allocator.Error!MutableValue { + return switch (mv) { + .eu_payload, + .opt_payload, + => unreachable, + .interned => |ip_index| { + const ty = Type.fromInterned(zcu.intern_pool.typeOf(ip_index)); + switch (ty.zigTypeTag(zcu)) { + .Array, .Vector => return .{ .interned = (try Value.fromInterned(ip_index).elemValue(zcu, field_idx)).toIntern() }, + .Struct, .Union => return .{ .interned = (try Value.fromInterned(ip_index).fieldValue(zcu, field_idx)).toIntern() }, + .Pointer => { + assert(ty.isSlice(zcu)); + return switch (field_idx) { + Value.slice_ptr_index => .{ .interned = Value.fromInterned(ip_index).slicePtr(zcu).toIntern() }, + Value.slice_len_index => .{ .interned = switch (zcu.intern_pool.indexToKey(ip_index)) { + .undef => try zcu.intern(.{ .undef = .usize_type }), + .slice => |s| s.len, + else => unreachable, + } }, + else => unreachable, + }; + }, + else => unreachable, + } + }, + .un => |un| { + // TODO assert the tag is correct + return un.payload.*; + }, + .slice => |s| switch (field_idx) { + Value.slice_ptr_index => s.ptr.*, + Value.slice_len_index => s.len.*, + else => unreachable, + }, + .bytes => |b| .{ .interned = try zcu.intern(.{ .int = .{ + .ty = .u8_type, + .storage = .{ .u64 = b.data[field_idx] }, + } }) }, + .repeated => |r| r.child.*, + .aggregate => |a| a.elems[field_idx], + }; + } + + fn isTrivialInt(mv: MutableValue, zcu: *Zcu) bool { + return switch (mv) { + else => false, + .interned => |ip_index| switch (zcu.intern_pool.indexToKey(ip_index)) { + else => false, + .int => |int| switch (int.storage) { + .u64, .i64, .big_int => true, + .lazy_align, .lazy_size => false, + }, + }, + }; + } + + pub fn typeOf(mv: MutableValue, zcu: *Zcu) Type { + return switch (mv) { + .interned => |ip_index| Type.fromInterned(zcu.intern_pool.typeOf(ip_index)), + inline else => |x| Type.fromInterned(x.ty), + }; + } +}; -- cgit v1.2.3 From 884d957b6c291961536c10401f60264da26cba30 Mon Sep 17 00:00:00 2001 From: mlugg Date: Tue, 26 Mar 2024 00:05:08 +0000 Subject: compiler: eliminate legacy Value representation Good riddance! Most of these changes are trivial. There's a fix for a minor bug this exposed in `Value.readFromPackedMemory`, but aside from that, it's all just things like changing `intern` calls to `toIntern`. --- src/Module.zig | 11 +- src/Sema.zig | 116 +++---- src/TypedValue.zig | 609 ++++++++++++++-------------------- src/Value.zig | 783 ++++++++++---------------------------------- src/arch/wasm/CodeGen.zig | 2 +- src/arch/x86_64/CodeGen.zig | 2 +- src/codegen.zig | 2 +- src/codegen/c.zig | 4 +- src/codegen/llvm.zig | 2 +- src/type.zig | 2 +- 10 files changed, 476 insertions(+), 1057 deletions(-) (limited to 'src/Module.zig') diff --git a/src/Module.zig b/src/Module.zig index a11194c103..4391472fa5 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -497,13 +497,6 @@ pub const Decl = struct { }; } - pub fn internValue(decl: *Decl, zcu: *Zcu) Allocator.Error!InternPool.Index { - assert(decl.has_tv); - const ip_index = try decl.val.intern(decl.typeOf(zcu), zcu); - decl.val = Value.fromInterned(ip_index); - return ip_index; - } - pub fn isFunction(decl: Decl, zcu: *const Zcu) !bool { const tv = try decl.typedValue(zcu); return tv.ty.zigTypeTag(zcu) == .Fn; @@ -3763,7 +3756,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { }, } - decl.val = Value.fromInterned((try decl_tv.val.intern(decl_tv.ty, mod))); + decl.val = decl_tv.val; // Function linksection, align, and addrspace were already set by Sema if (!is_func) { decl.alignment = blk: { @@ -5624,8 +5617,6 @@ pub fn markDeclAlive(mod: *Module, decl: *Decl) Allocator.Error!void { if (decl.alive) return; decl.alive = true; - _ = try decl.internValue(mod); - // This is the first time we are marking this Decl alive. We must // therefore recurse into its value and mark any Decl it references // as also alive, so that any Decl referenced does not get garbage collected. diff --git a/src/Sema.zig b/src/Sema.zig index 7db1462787..0d387faacf 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -7835,7 +7835,7 @@ fn analyzeCall( if (is_comptime_call) { const result_val = try sema.resolveConstValue(block, .unneeded, result, undefined); - const result_interned = try result_val.intern2(sema.fn_ret_ty, mod); + const result_interned = result_val.toIntern(); // Transform ad-hoc inferred error set types into concrete error sets. const result_transformed = try sema.resolveAdHocInferredErrorSet(block, call_src, result_interned); @@ -7856,8 +7856,7 @@ fn analyzeCall( } if (try sema.resolveValue(result)) |result_val| { - const result_interned = try result_val.intern2(sema.fn_ret_ty, mod); - const result_transformed = try sema.resolveAdHocInferredErrorSet(block, call_src, result_interned); + const result_transformed = try sema.resolveAdHocInferredErrorSet(block, call_src, result_val.toIntern()); break :res2 Air.internedToRef(result_transformed); } @@ -8042,7 +8041,7 @@ fn analyzeInlineCallArg( // when the hash function is called. const resolved_arg_val = try ics.caller().resolveLazyValue(arg_val); should_memoize.* = should_memoize.* and !resolved_arg_val.canMutateComptimeVarState(mod); - memoized_arg_values[arg_i.*] = try resolved_arg_val.intern(Type.fromInterned(param_ty), mod); + memoized_arg_values[arg_i.*] = resolved_arg_val.toIntern(); } else { ics.callee().inst_map.putAssumeCapacityNoClobber(inst, casted_arg); } @@ -8081,7 +8080,7 @@ fn analyzeInlineCallArg( // when the hash function is called. const resolved_arg_val = try ics.caller().resolveLazyValue(arg_val); should_memoize.* = should_memoize.* and !resolved_arg_val.canMutateComptimeVarState(mod); - memoized_arg_values[arg_i.*] = try resolved_arg_val.intern(ics.caller().typeOf(uncasted_arg), mod); + memoized_arg_values[arg_i.*] = resolved_arg_val.toIntern(); } else { if (zir_tags[@intFromEnum(inst)] == .param_anytype_comptime) { _ = try ics.caller().resolveConstValue(arg_block, arg_src, uncasted_arg, .{ @@ -14270,7 +14269,7 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air. const elems = try sema.arena.alloc(InternPool.Index, vec_len); for (elems, 0..) |*elem, i| { const elem_val = try val.elemValue(mod, i); - elem.* = try (try elem_val.bitwiseNot(scalar_type, sema.arena, mod)).intern(scalar_type, mod); + elem.* = (try elem_val.bitwiseNot(scalar_type, sema.arena, mod)).toIntern(); } return Air.internedToRef((try mod.intern(.{ .aggregate = .{ .ty = operand_type.toIntern(), @@ -14521,7 +14520,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai } }; const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, operand_src); const coerced_elem_val = try sema.resolveConstValue(block, operand_src, coerced_elem_val_inst, undefined); - element_vals[elem_i] = try coerced_elem_val.intern(resolved_elem_ty, mod); + element_vals[elem_i] = coerced_elem_val.toIntern(); } while (elem_i < result_len) : (elem_i += 1) { const rhs_elem_i = elem_i - lhs_len; @@ -14534,7 +14533,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai } }; const coerced_elem_val_inst = try sema.coerce(block, resolved_elem_ty, elem_val_inst, operand_src); const coerced_elem_val = try sema.resolveConstValue(block, operand_src, coerced_elem_val_inst, undefined); - element_vals[elem_i] = try coerced_elem_val.intern(resolved_elem_ty, mod); + element_vals[elem_i] = coerced_elem_val.toIntern(); } return sema.addConstantMaybeRef(try mod.intern(.{ .aggregate = .{ .ty = result_ty.toIntern(), @@ -15813,7 +15812,7 @@ fn intRem( for (result_data, 0..) |*scalar, i| { const lhs_elem = try lhs.elemValue(mod, i); const rhs_elem = try rhs.elemValue(mod, i); - scalar.* = try (try sema.intRemScalar(lhs_elem, rhs_elem, scalar_ty)).intern(scalar_ty, mod); + scalar.* = (try sema.intRemScalar(lhs_elem, rhs_elem, scalar_ty)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = ty.toIntern(), @@ -17753,7 +17752,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const info = ty.intInfo(mod); const field_values = .{ // signedness: Signedness, - try (try mod.enumValueFieldIndex(signedness_ty, @intFromEnum(info.signedness))).intern(signedness_ty, mod), + (try mod.enumValueFieldIndex(signedness_ty, @intFromEnum(info.signedness))).toIntern(), // bits: u16, (try mod.intValue(Type.u16, info.bits)).toIntern(), }; @@ -17823,7 +17822,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const field_values = .{ // size: Size, - try (try mod.enumValueFieldIndex(ptr_size_ty, @intFromEnum(info.flags.size))).intern(ptr_size_ty, mod), + (try mod.enumValueFieldIndex(ptr_size_ty, @intFromEnum(info.flags.size))).toIntern(), // is_const: bool, Value.makeBool(info.flags.is_const).toIntern(), // is_volatile: bool, @@ -17831,7 +17830,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai // alignment: comptime_int, alignment.toIntern(), // address_space: AddressSpace - try (try mod.enumValueFieldIndex(addrspace_ty, @intFromEnum(info.flags.address_space))).intern(addrspace_ty, mod), + (try mod.enumValueFieldIndex(addrspace_ty, @intFromEnum(info.flags.address_space))).toIntern(), // child: type, info.child, // is_allowzero: bool, @@ -19975,8 +19974,8 @@ fn unionInit( const tag_val = try mod.enumValueFieldIndex(tag_ty, field_index); return Air.internedToRef((try mod.intern(.{ .un = .{ .ty = union_ty.toIntern(), - .tag = try tag_val.intern(tag_ty, mod), - .val = try init_val.intern(field_ty, mod), + .tag = tag_val.toIntern(), + .val = init_val.toIntern(), } }))); } @@ -20099,8 +20098,8 @@ fn zirStructInit( if (try sema.resolveValue(init_inst)) |val| { const struct_val = Value.fromInterned((try mod.intern(.{ .un = .{ .ty = resolved_ty.toIntern(), - .tag = try tag_val.intern(tag_ty, mod), - .val = try val.intern(field_ty, mod), + .tag = tag_val.toIntern(), + .val = val.toIntern(), } }))); const final_val_inst = try sema.coerce(block, result_ty, Air.internedToRef(struct_val.toIntern()), src); const final_val = (try sema.resolveValue(final_val_inst)).?; @@ -20400,7 +20399,7 @@ fn structInitAnon( return sema.failWithOwnedErrorMsg(block, msg); } if (try sema.resolveValue(init)) |init_val| { - field_val.* = try init_val.intern(Type.fromInterned(field_ty.*), mod); + field_val.* = init_val.toIntern(); } else { field_val.* = .none; runtime_index = @intCast(i_usize); @@ -20577,13 +20576,9 @@ fn zirArrayInit( const runtime_index = opt_runtime_index orelse { const elem_vals = try sema.arena.alloc(InternPool.Index, resolved_args.len); - for (elem_vals, resolved_args, 0..) |*val, arg, i| { - const elem_ty = if (is_tuple) - array_ty.structFieldType(i, mod) - else - array_ty.elemType2(mod); + for (elem_vals, resolved_args) |*val, arg| { // We checked that all args are comptime above. - val.* = try ((sema.resolveValue(arg) catch unreachable).?).intern(elem_ty, mod); + val.* = (sema.resolveValue(arg) catch unreachable).?.toIntern(); } const arr_val = try mod.intern(.{ .aggregate = .{ .ty = array_ty.toIntern(), @@ -20998,7 +20993,7 @@ fn maybeConstantUnaryMath( const elems = try sema.arena.alloc(InternPool.Index, vec_len); for (elems, 0..) |*elem, i| { const elem_val = try val.elemValue(sema.mod, i); - elem.* = try (try eval(elem_val, scalar_ty, sema.arena, sema.mod)).intern(scalar_ty, mod); + elem.* = (try eval(elem_val, scalar_ty, sema.arena, sema.mod)).toIntern(); } return Air.internedToRef((try mod.intern(.{ .aggregate = .{ .ty = result_ty.toIntern(), @@ -23216,7 +23211,8 @@ fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const elems = try sema.arena.alloc(InternPool.Index, operand_ty.vectorLen(mod)); for (elems, 0..) |*elem, i| { const elem_val = try val.elemValue(mod, i); - elem.* = try (try elem_val.intTrunc(operand_scalar_ty, sema.arena, dest_info.signedness, dest_info.bits, mod)).intern(dest_scalar_ty, mod); + const uncoerced_elem = try elem_val.intTrunc(operand_scalar_ty, sema.arena, dest_info.signedness, dest_info.bits, mod); + elem.* = (try mod.getCoerced(uncoerced_elem, dest_scalar_ty)).toIntern(); } return Air.internedToRef((try mod.intern(.{ .aggregate = .{ .ty = dest_ty.toIntern(), @@ -23330,7 +23326,7 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const elems = try sema.arena.alloc(InternPool.Index, vec_len); for (elems, 0..) |*elem, i| { const elem_val = try val.elemValue(mod, i); - elem.* = try (try elem_val.byteSwap(scalar_ty, mod, sema.arena)).intern(scalar_ty, mod); + elem.* = (try elem_val.byteSwap(scalar_ty, mod, sema.arena)).toIntern(); } return Air.internedToRef((try mod.intern(.{ .aggregate = .{ .ty = operand_ty.toIntern(), @@ -23378,7 +23374,7 @@ fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! const elems = try sema.arena.alloc(InternPool.Index, vec_len); for (elems, 0..) |*elem, i| { const elem_val = try val.elemValue(mod, i); - elem.* = try (try elem_val.bitReverse(scalar_ty, mod, sema.arena)).intern(scalar_ty, mod); + elem.* = (try elem_val.bitReverse(scalar_ty, mod, sema.arena)).toIntern(); } return Air.internedToRef((try mod.intern(.{ .aggregate = .{ .ty = operand_ty.toIntern(), @@ -24311,7 +24307,7 @@ fn analyzeShuffle( } const int = mask_elem_val.toSignedInt(mod); const unsigned: u32 = @intCast(if (int >= 0) int else ~int); - values[i] = try (try (if (int >= 0) a_val else b_val).elemValue(mod, unsigned)).intern(elem_ty, mod); + values[i] = (try (if (int >= 0) a_val else b_val).elemValue(mod, unsigned)).toIntern(); } return Air.internedToRef((try mod.intern(.{ .aggregate = .{ .ty = res_ty.toIntern(), @@ -24417,7 +24413,7 @@ fn zirSelect(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) C for (elems, 0..) |*elem, i| { const pred_elem_val = try pred_val.elemValue(mod, i); const should_choose_a = pred_elem_val.toBool(); - elem.* = try (try (if (should_choose_a) a_val else b_val).elemValue(mod, i)).intern(elem_ty, mod); + elem.* = (try (if (should_choose_a) a_val else b_val).elemValue(mod, i)).toIntern(); } return Air.internedToRef((try mod.intern(.{ .aggregate = .{ @@ -27789,7 +27785,7 @@ fn structFieldPtrByIndex( const val = try mod.intern(.{ .ptr = .{ .ty = ptr_field_ty.toIntern(), .addr = .{ .field = .{ - .base = try struct_ptr_val.intern(struct_ptr_ty, mod), + .base = struct_ptr_val.toIntern(), .index = field_index, } }, } }); @@ -31611,7 +31607,7 @@ fn coerceCompatiblePtrs( } // The comptime Value representation is compatible with both types. return Air.internedToRef( - (try mod.getCoerced(Value.fromInterned((try val.intern(inst_ty, mod))), dest_ty)).toIntern(), + (try mod.getCoerced(val, dest_ty)).toIntern(), ); } try sema.requireRuntimeBlock(block, inst_src, null); @@ -31948,7 +31944,7 @@ fn coerceArrayLike( ref.* = coerced; if (runtime_src == null) { if (try sema.resolveValue(coerced)) |elem_val| { - val.* = try elem_val.intern(dest_elem_ty, mod); + val.* = elem_val.toIntern(); } else { runtime_src = elem_src; } @@ -32013,7 +32009,7 @@ fn coerceTupleToArray( ref.* = coerced; if (runtime_src == null) { if (try sema.resolveValue(coerced)) |elem_val| { - val.* = try elem_val.intern(dest_elem_ty, mod); + val.* = elem_val.toIntern(); } else { runtime_src = elem_src; } @@ -33250,10 +33246,7 @@ fn analyzeSlice( }; if (!new_ptr_val.isUndef(mod)) { - return Air.internedToRef((try mod.getCoerced( - Value.fromInterned((try new_ptr_val.intern(new_ptr_ty, mod))), - return_ty, - )).toIntern()); + return Air.internedToRef((try mod.getCoerced(new_ptr_val, return_ty)).toIntern()); } // Special case: @as([]i32, undefined)[x..x] @@ -33765,7 +33758,7 @@ fn wrapErrorUnionPayload( if (try sema.resolveValue(coerced)) |val| { return Air.internedToRef((try mod.intern(.{ .error_union = .{ .ty = dest_ty.toIntern(), - .val = .{ .payload = try val.intern(dest_payload_ty, mod) }, + .val = .{ .payload = val.toIntern() }, } }))); } try sema.requireRuntimeBlock(block, inst_src, null); @@ -36941,15 +36934,14 @@ fn semaStructFieldInits( }); }; - const field_init = try default_val.intern(field_ty, mod); - if (Value.fromInterned(field_init).canMutateComptimeVarState(mod)) { + if (Value.fromInterned(default_val.toIntern()).canMutateComptimeVarState(mod)) { const init_src = mod.fieldSrcLoc(decl_index, .{ .index = field_i, .range = .value, }).lazy; return sema.fail(&block_scope, init_src, "field default value contains reference to comptime-mutable memory", .{}); } - struct_type.field_inits.get(ip)[field_i] = field_init; + struct_type.field_inits.get(ip)[field_i] = default_val.toIntern(); } } } @@ -37756,7 +37748,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { return sema.failWithOwnedErrorMsg(null, msg); } if (try sema.typeHasOnePossibleValue(field_ty)) |field_opv| { - field_val.* = try field_opv.intern(field_ty, mod); + field_val.* = field_opv.toIntern(); } else return null; } @@ -38310,7 +38302,7 @@ fn intAddInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type, overflow_idx: *usi }, else => |e| return e, }; - scalar.* = try val.intern(scalar_ty, mod); + scalar.* = val.toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = ty.toIntern(), @@ -38400,7 +38392,7 @@ fn intSubInner(sema: *Sema, lhs: Value, rhs: Value, ty: Type, overflow_idx: *usi }, else => |e| return e, }; - scalar.* = try val.intern(scalar_ty, mod); + scalar.* = val.toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = ty.toIntern(), @@ -38470,8 +38462,8 @@ fn intSubWithOverflow( const lhs_elem = try lhs.elemValue(sema.mod, i); const rhs_elem = try rhs.elemValue(sema.mod, i); const of_math_result = try sema.intSubWithOverflowScalar(lhs_elem, rhs_elem, scalar_ty); - of.* = try of_math_result.overflow_bit.intern(Type.u1, mod); - scalar.* = try of_math_result.wrapped_result.intern(scalar_ty, mod); + of.* = of_math_result.overflow_bit.toIntern(); + scalar.* = of_math_result.wrapped_result.toIntern(); } return Value.OverflowArithmeticResult{ .overflow_bit = Value.fromInterned((try mod.intern(.{ .aggregate = .{ @@ -38528,10 +38520,9 @@ fn intFromFloat( if (float_ty.zigTypeTag(mod) == .Vector) { const elem_ty = float_ty.scalarType(mod); const result_data = try sema.arena.alloc(InternPool.Index, float_ty.vectorLen(mod)); - const scalar_ty = int_ty.scalarType(mod); for (result_data, 0..) |*scalar, i| { const elem_val = try val.elemValue(sema.mod, i); - scalar.* = try (try sema.intFromFloatScalar(block, src, elem_val, elem_ty, int_ty.scalarType(mod), mode)).intern(scalar_ty, mod); + scalar.* = (try sema.intFromFloatScalar(block, src, elem_val, elem_ty, int_ty.scalarType(mod), mode)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = int_ty.toIntern(), @@ -38724,8 +38715,8 @@ fn intAddWithOverflow( const lhs_elem = try lhs.elemValue(sema.mod, i); const rhs_elem = try rhs.elemValue(sema.mod, i); const of_math_result = try sema.intAddWithOverflowScalar(lhs_elem, rhs_elem, scalar_ty); - of.* = try of_math_result.overflow_bit.intern(Type.u1, mod); - scalar.* = try of_math_result.wrapped_result.intern(scalar_ty, mod); + of.* = of_math_result.overflow_bit.toIntern(); + scalar.* = of_math_result.wrapped_result.toIntern(); } return Value.OverflowArithmeticResult{ .overflow_bit = Value.fromInterned((try mod.intern(.{ .aggregate = .{ @@ -38835,7 +38826,7 @@ fn compareVector( const lhs_elem = try lhs.elemValue(sema.mod, i); const rhs_elem = try rhs.elemValue(sema.mod, i); const res_bool = try sema.compareScalar(lhs_elem, op, rhs_elem, ty.scalarType(mod)); - scalar.* = try Value.makeBool(res_bool).intern(Type.bool, mod); + scalar.* = Value.makeBool(res_bool).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = (try mod.vectorType(.{ .len = ty.vectorLen(mod), .child = .bool_type })).toIntern(), @@ -39014,29 +39005,6 @@ fn validateRuntimeValue(sema: *Sema, block: *Block, val_src: LazySrcLoc, val: Ai /// Returns true if any value contained in `val` is undefined. fn anyUndef(sema: *Sema, val: Value) !bool { const mod = sema.mod; - if (val.ip_index == .none) return switch (val.tag()) { - .eu_payload => try sema.anyUndef(val.castTag(.eu_payload).?.data), - .opt_payload => try sema.anyUndef(val.castTag(.opt_payload).?.data), - .repeated => try sema.anyUndef(val.castTag(.repeated).?.data), - .slice => { - const slice = val.castTag(.slice).?.data; - for (0..@intCast(slice.len.toUnsignedInt(mod))) |idx| { - if (try sema.anyUndef((try slice.ptr.maybeElemValueFull(sema, mod, idx)).?)) return true; - } - return false; - }, - .bytes => false, - .aggregate => for (val.castTag(.aggregate).?.data) |elem| { - if (try sema.anyUndef(elem)) break true; - } else false, - .@"union" => { - const un = val.castTag(.@"union").?.data; - if (un.tag) |t| { - if (try sema.anyUndef(t)) return true; - } - return sema.anyUndef(un.val); - }, - }; return switch (val.toIntern()) { .undef => true, else => switch (mod.intern_pool.indexToKey(val.toIntern())) { diff --git a/src/TypedValue.zig b/src/TypedValue.zig index 5d9c062417..4679ce20ee 100644 --- a/src/TypedValue.zig +++ b/src/TypedValue.zig @@ -77,386 +77,275 @@ pub fn print( var val = tv.val; var ty = tv.ty; const ip = &mod.intern_pool; - while (true) switch (val.ip_index) { - .none => switch (val.tag()) { - .aggregate => return printAggregate(ty, val, writer, level, mod), - .@"union" => { - if (level == 0) { - return writer.writeAll(".{ ... }"); - } - const payload = val.castTag(.@"union").?.data; - try writer.writeAll(".{ "); - - if (payload.tag) |tag| { - try print(.{ - .ty = Type.fromInterned(ip.loadUnionType(ty.toIntern()).enum_tag_ty), - .val = tag, - }, writer, level - 1, mod); - try writer.writeAll(" = "); - const field_ty = ty.unionFieldType(tag, mod).?; - try print(.{ - .ty = field_ty, - .val = payload.val, - }, writer, level - 1, mod); - } else { - try writer.writeAll("(unknown tag) = "); - const backing_ty = try ty.unionBackingType(mod); - try print(.{ - .ty = backing_ty, - .val = payload.val, - }, writer, level - 1, mod); - } - - return writer.writeAll(" }"); - }, - .bytes => return writer.print("\"{}\"", .{std.zig.fmtEscapes(val.castTag(.bytes).?.data)}), - .repeated => { - if (level == 0) { - return writer.writeAll(".{ ... }"); - } - var i: u32 = 0; - try writer.writeAll(".{ "); - const elem_tv = TypedValue{ - .ty = ty.elemType2(mod), - .val = val.castTag(.repeated).?.data, - }; - const len = ty.arrayLen(mod); - const max_len = @min(len, max_aggregate_items); - while (i < max_len) : (i += 1) { - if (i != 0) try writer.writeAll(", "); - try print(elem_tv, writer, level - 1, mod); - } - if (len > max_aggregate_items) { - try writer.writeAll(", ..."); - } - return writer.writeAll(" }"); - }, - .slice => { - if (level == 0) { - return writer.writeAll(".{ ... }"); - } - const payload = val.castTag(.slice).?.data; - const elem_ty = ty.elemType2(mod); - const len = payload.len.toUnsignedInt(mod); - - if (elem_ty.eql(Type.u8, mod)) str: { - const max_len: usize = @min(len, max_string_len); - var buf: [max_string_len]u8 = undefined; - - var i: u32 = 0; - while (i < max_len) : (i += 1) { - const maybe_elem_val = payload.ptr.maybeElemValue(mod, i) catch |err| switch (err) { - error.OutOfMemory => @panic("OOM"), // TODO: eliminate this panic - }; - const elem_val = maybe_elem_val orelse return writer.writeAll(".{ (reinterpreted data) }"); - if (elem_val.isUndef(mod)) break :str; - buf[i] = std.math.cast(u8, elem_val.toUnsignedInt(mod)) orelse break :str; - } - - // TODO would be nice if this had a bit of unicode awareness. - const truncated = if (len > max_string_len) " (truncated)" else ""; - return writer.print("\"{}{s}\"", .{ std.zig.fmtEscapes(buf[0..max_len]), truncated }); - } - - try writer.writeAll(".{ "); - - const max_len = @min(len, max_aggregate_items); - var i: u32 = 0; - while (i < max_len) : (i += 1) { - if (i != 0) try writer.writeAll(", "); - const maybe_elem_val = payload.ptr.maybeElemValue(mod, i) catch |err| switch (err) { - error.OutOfMemory => @panic("OOM"), // TODO: eliminate this panic - }; - const elem_val = maybe_elem_val orelse return writer.writeAll("(reinterpreted data) }"); - try print(.{ - .ty = elem_ty, - .val = elem_val, - }, writer, level - 1, mod); - } - if (len > max_aggregate_items) { - try writer.writeAll(", ..."); - } - return writer.writeAll(" }"); - }, - .eu_payload => { - val = val.castTag(.eu_payload).?.data; - ty = ty.errorUnionPayload(mod); - }, - .opt_payload => { - val = val.castTag(.opt_payload).?.data; - ty = ty.optionalChild(mod); - }, + while (true) switch (ip.indexToKey(val.toIntern())) { + .int_type, + .ptr_type, + .array_type, + .vector_type, + .opt_type, + .anyframe_type, + .error_union_type, + .simple_type, + .struct_type, + .anon_struct_type, + .union_type, + .opaque_type, + .enum_type, + .func_type, + .error_set_type, + .inferred_error_set_type, + => return Type.print(val.toType(), writer, mod), + .undef => return writer.writeAll("undefined"), + .simple_value => |simple_value| switch (simple_value) { + .void => return writer.writeAll("{}"), + .empty_struct => return printAggregate(ty, val, writer, level, mod), + .generic_poison => return writer.writeAll("(generic poison)"), + else => return writer.writeAll(@tagName(simple_value)), }, - else => switch (ip.indexToKey(val.toIntern())) { - .int_type, - .ptr_type, - .array_type, - .vector_type, - .opt_type, - .anyframe_type, - .error_union_type, - .simple_type, - .struct_type, - .anon_struct_type, - .union_type, - .opaque_type, - .enum_type, - .func_type, - .error_set_type, - .inferred_error_set_type, - => return Type.print(val.toType(), writer, mod), - .undef => return writer.writeAll("undefined"), - .simple_value => |simple_value| switch (simple_value) { - .void => return writer.writeAll("{}"), - .empty_struct => return printAggregate(ty, val, writer, level, mod), - .generic_poison => return writer.writeAll("(generic poison)"), - else => return writer.writeAll(@tagName(simple_value)), - }, - .variable => return writer.writeAll("(variable)"), - .extern_func => |extern_func| return writer.print("(extern function '{}')", .{ - mod.declPtr(extern_func.decl).name.fmt(ip), + .variable => return writer.writeAll("(variable)"), + .extern_func => |extern_func| return writer.print("(extern function '{}')", .{ + mod.declPtr(extern_func.decl).name.fmt(ip), + }), + .func => |func| return writer.print("(function '{}')", .{ + mod.declPtr(func.owner_decl).name.fmt(ip), + }), + .int => |int| switch (int.storage) { + inline .u64, .i64, .big_int => |x| return writer.print("{}", .{x}), + .lazy_align => |lazy_ty| return writer.print("{d}", .{ + Type.fromInterned(lazy_ty).abiAlignment(mod), }), - .func => |func| return writer.print("(function '{}')", .{ - mod.declPtr(func.owner_decl).name.fmt(ip), + .lazy_size => |lazy_ty| return writer.print("{d}", .{ + Type.fromInterned(lazy_ty).abiSize(mod), }), - .int => |int| switch (int.storage) { - inline .u64, .i64, .big_int => |x| return writer.print("{}", .{x}), - .lazy_align => |lazy_ty| return writer.print("{d}", .{ - Type.fromInterned(lazy_ty).abiAlignment(mod), - }), - .lazy_size => |lazy_ty| return writer.print("{d}", .{ - Type.fromInterned(lazy_ty).abiSize(mod), - }), - }, - .err => |err| return writer.print("error.{}", .{ - err.name.fmt(ip), + }, + .err => |err| return writer.print("error.{}", .{ + err.name.fmt(ip), + }), + .error_union => |error_union| switch (error_union.val) { + .err_name => |err_name| return writer.print("error.{}", .{ + err_name.fmt(ip), }), - .error_union => |error_union| switch (error_union.val) { - .err_name => |err_name| return writer.print("error.{}", .{ - err_name.fmt(ip), - }), - .payload => |payload| { - val = Value.fromInterned(payload); - ty = ty.errorUnionPayload(mod); - }, + .payload => |payload| { + val = Value.fromInterned(payload); + ty = ty.errorUnionPayload(mod); }, - .enum_literal => |enum_literal| return writer.print(".{}", .{ - enum_literal.fmt(ip), - }), - .enum_tag => |enum_tag| { - if (level == 0) { - return writer.writeAll("(enum)"); - } - const enum_type = ip.loadEnumType(ty.toIntern()); - if (enum_type.tagValueIndex(ip, val.toIntern())) |tag_index| { - try writer.print(".{i}", .{enum_type.names.get(ip)[tag_index].fmt(ip)}); - return; + }, + .enum_literal => |enum_literal| return writer.print(".{}", .{ + enum_literal.fmt(ip), + }), + .enum_tag => |enum_tag| { + if (level == 0) { + return writer.writeAll("(enum)"); + } + const enum_type = ip.loadEnumType(ty.toIntern()); + if (enum_type.tagValueIndex(ip, val.toIntern())) |tag_index| { + try writer.print(".{i}", .{enum_type.names.get(ip)[tag_index].fmt(ip)}); + return; + } + try writer.writeAll("@enumFromInt("); + try print(.{ + .ty = Type.fromInterned(ip.typeOf(enum_tag.int)), + .val = Value.fromInterned(enum_tag.int), + }, writer, level - 1, mod); + try writer.writeAll(")"); + return; + }, + .empty_enum_value => return writer.writeAll("(empty enum value)"), + .float => |float| switch (float.storage) { + inline else => |x| return writer.print("{d}", .{@as(f64, @floatCast(x))}), + }, + .slice => |slice| { + const ptr_ty = switch (ip.indexToKey(slice.ptr)) { + .ptr => |ptr| ty: { + if (ptr.addr == .int) return print(.{ + .ty = Type.fromInterned(ptr.ty), + .val = Value.fromInterned(slice.ptr), + }, writer, level - 1, mod); + break :ty ip.indexToKey(ptr.ty).ptr_type; + }, + .undef => |ptr_ty| ip.indexToKey(ptr_ty).ptr_type, + else => unreachable, + }; + if (level == 0) { + return writer.writeAll(".{ ... }"); + } + const elem_ty = Type.fromInterned(ptr_ty.child); + const len = Value.fromInterned(slice.len).toUnsignedInt(mod); + if (elem_ty.eql(Type.u8, mod)) str: { + const max_len = @min(len, max_string_len); + var buf: [max_string_len]u8 = undefined; + for (buf[0..max_len], 0..) |*c, i| { + const maybe_elem = try val.maybeElemValue(mod, i); + const elem = maybe_elem orelse return writer.writeAll(".{ (reinterpreted data) }"); + if (elem.isUndef(mod)) break :str; + c.* = @as(u8, @intCast(elem.toUnsignedInt(mod))); } - try writer.writeAll("@enumFromInt("); + const truncated = if (len > max_string_len) " (truncated)" else ""; + return writer.print("\"{}{s}\"", .{ std.zig.fmtEscapes(buf[0..max_len]), truncated }); + } + try writer.writeAll(".{ "); + const max_len = @min(len, max_aggregate_items); + for (0..max_len) |i| { + if (i != 0) try writer.writeAll(", "); + const maybe_elem = try val.maybeElemValue(mod, i); + const elem = maybe_elem orelse return writer.writeAll("(reinterpreted data) }"); try print(.{ - .ty = Type.fromInterned(ip.typeOf(enum_tag.int)), - .val = Value.fromInterned(enum_tag.int), + .ty = elem_ty, + .val = elem, }, writer, level - 1, mod); - try writer.writeAll(")"); - return; - }, - .empty_enum_value => return writer.writeAll("(empty enum value)"), - .float => |float| switch (float.storage) { - inline else => |x| return writer.print("{d}", .{@as(f64, @floatCast(x))}), - }, - .slice => |slice| { - const ptr_ty = switch (ip.indexToKey(slice.ptr)) { - .ptr => |ptr| ty: { - if (ptr.addr == .int) return print(.{ - .ty = Type.fromInterned(ptr.ty), - .val = Value.fromInterned(slice.ptr), - }, writer, level - 1, mod); - break :ty ip.indexToKey(ptr.ty).ptr_type; - }, - .undef => |ptr_ty| ip.indexToKey(ptr_ty).ptr_type, - else => unreachable, - }; - if (level == 0) { - return writer.writeAll(".{ ... }"); - } - const elem_ty = Type.fromInterned(ptr_ty.child); - const len = Value.fromInterned(slice.len).toUnsignedInt(mod); - if (elem_ty.eql(Type.u8, mod)) str: { - const max_len = @min(len, max_string_len); - var buf: [max_string_len]u8 = undefined; - for (buf[0..max_len], 0..) |*c, i| { - const maybe_elem = try val.maybeElemValue(mod, i); - const elem = maybe_elem orelse return writer.writeAll(".{ (reinterpreted data) }"); - if (elem.isUndef(mod)) break :str; - c.* = @as(u8, @intCast(elem.toUnsignedInt(mod))); - } - const truncated = if (len > max_string_len) " (truncated)" else ""; - return writer.print("\"{}{s}\"", .{ std.zig.fmtEscapes(buf[0..max_len]), truncated }); - } - try writer.writeAll(".{ "); - const max_len = @min(len, max_aggregate_items); - for (0..max_len) |i| { - if (i != 0) try writer.writeAll(", "); - const maybe_elem = try val.maybeElemValue(mod, i); - const elem = maybe_elem orelse return writer.writeAll("(reinterpreted data) }"); + } + if (len > max_aggregate_items) { + try writer.writeAll(", ..."); + } + return writer.writeAll(" }"); + }, + .ptr => |ptr| { + switch (ptr.addr) { + .decl => |decl_index| { + const decl = mod.declPtr(decl_index); + if (level == 0) return writer.print("(decl '{}')", .{decl.name.fmt(ip)}); + return print(.{ + .ty = decl.typeOf(mod), + .val = decl.val, + }, writer, level - 1, mod); + }, + .anon_decl => |anon_decl| { + const decl_val = anon_decl.val; + if (level == 0) return writer.print("(anon decl '{d}')", .{ + @intFromEnum(decl_val), + }); + return print(.{ + .ty = Type.fromInterned(ip.typeOf(decl_val)), + .val = Value.fromInterned(decl_val), + }, writer, level - 1, mod); + }, + .comptime_alloc => { + // TODO: we need a Sema to print this! + return writer.writeAll("(comptime alloc)"); + }, + .comptime_field => |field_val_ip| { + return print(.{ + .ty = Type.fromInterned(ip.typeOf(field_val_ip)), + .val = Value.fromInterned(field_val_ip), + }, writer, level - 1, mod); + }, + .int => |int_ip| { + try writer.writeAll("@ptrFromInt("); try print(.{ - .ty = elem_ty, - .val = elem, + .ty = Type.usize, + .val = Value.fromInterned(int_ip), }, writer, level - 1, mod); - } - if (len > max_aggregate_items) { - try writer.writeAll(", ..."); - } - return writer.writeAll(" }"); - }, - .ptr => |ptr| { - switch (ptr.addr) { - .decl => |decl_index| { - const decl = mod.declPtr(decl_index); - if (level == 0) return writer.print("(decl '{}')", .{decl.name.fmt(ip)}); - return print(.{ - .ty = decl.typeOf(mod), - .val = decl.val, - }, writer, level - 1, mod); - }, - .anon_decl => |anon_decl| { - const decl_val = anon_decl.val; - if (level == 0) return writer.print("(anon decl '{d}')", .{ - @intFromEnum(decl_val), - }); - return print(.{ - .ty = Type.fromInterned(ip.typeOf(decl_val)), - .val = Value.fromInterned(decl_val), - }, writer, level - 1, mod); - }, - .comptime_alloc => { - // TODO: we need a Sema to print this! - return writer.writeAll("(comptime alloc)"); - }, - .comptime_field => |field_val_ip| { - return print(.{ - .ty = Type.fromInterned(ip.typeOf(field_val_ip)), - .val = Value.fromInterned(field_val_ip), - }, writer, level - 1, mod); - }, - .int => |int_ip| { - try writer.writeAll("@ptrFromInt("); - try print(.{ - .ty = Type.usize, - .val = Value.fromInterned(int_ip), - }, writer, level - 1, mod); - try writer.writeByte(')'); - }, - .eu_payload => |eu_ip| { - try writer.writeAll("(payload of "); - try print(.{ - .ty = Type.fromInterned(ip.typeOf(eu_ip)), - .val = Value.fromInterned(eu_ip), - }, writer, level - 1, mod); - try writer.writeAll(")"); - }, - .opt_payload => |opt_ip| { - try print(.{ - .ty = Type.fromInterned(ip.typeOf(opt_ip)), - .val = Value.fromInterned(opt_ip), - }, writer, level - 1, mod); - try writer.writeAll(".?"); - }, - .elem => |elem| { - if (level == 0) { - try writer.writeAll("(...)"); - } else { - try print(.{ - .ty = Type.fromInterned(ip.typeOf(elem.base)), - .val = Value.fromInterned(elem.base), - }, writer, level - 1, mod); - } - try writer.print("[{}]", .{elem.index}); - }, - .field => |field| { - const ptr_container_ty = Type.fromInterned(ip.typeOf(field.base)); - if (level == 0) { - try writer.writeAll("(...)"); - } else { - try print(.{ - .ty = ptr_container_ty, - .val = Value.fromInterned(field.base), - }, writer, level - 1, mod); - } - - const container_ty = ptr_container_ty.childType(mod); - switch (container_ty.zigTypeTag(mod)) { - .Struct => { - if (container_ty.structFieldName(@intCast(field.index), mod).unwrap()) |field_name| { - try writer.print(".{i}", .{field_name.fmt(ip)}); - } else { - try writer.print("[{d}]", .{field.index}); - } - }, - .Union => { - const field_name = mod.typeToUnion(container_ty).?.loadTagType(ip).names.get(ip)[@intCast(field.index)]; - try writer.print(".{i}", .{field_name.fmt(ip)}); - }, - .Pointer => { - std.debug.assert(container_ty.isSlice(mod)); - try writer.writeAll(switch (field.index) { - Value.slice_ptr_index => ".ptr", - Value.slice_len_index => ".len", - else => unreachable, - }); - }, - else => unreachable, - } - }, - } - return; - }, - .opt => |opt| switch (opt.val) { - .none => return writer.writeAll("null"), - else => |payload| { - val = Value.fromInterned(payload); - ty = ty.optionalChild(mod); + try writer.writeByte(')'); }, - }, - .aggregate => |aggregate| switch (aggregate.storage) { - .bytes => |bytes| { - // Strip the 0 sentinel off of strings before printing - const zero_sent = blk: { - const sent = ty.sentinel(mod) orelse break :blk false; - break :blk sent.eql(Value.zero_u8, Type.u8, mod); - }; - const str = if (zero_sent) bytes[0 .. bytes.len - 1] else bytes; - return writer.print("\"{}\"", .{std.zig.fmtEscapes(str)}); + .eu_payload => |eu_ip| { + try writer.writeAll("(payload of "); + try print(.{ + .ty = Type.fromInterned(ip.typeOf(eu_ip)), + .val = Value.fromInterned(eu_ip), + }, writer, level - 1, mod); + try writer.writeAll(")"); }, - .elems, .repeated_elem => return printAggregate(ty, val, writer, level, mod), - }, - .un => |un| { - try writer.writeAll(".{ "); - if (level > 0) { - if (un.tag != .none) { - try print(.{ - .ty = ty.unionTagTypeHypothetical(mod), - .val = Value.fromInterned(un.tag), - }, writer, level - 1, mod); - try writer.writeAll(" = "); - const field_ty = ty.unionFieldType(Value.fromInterned(un.tag), mod).?; + .opt_payload => |opt_ip| { + try print(.{ + .ty = Type.fromInterned(ip.typeOf(opt_ip)), + .val = Value.fromInterned(opt_ip), + }, writer, level - 1, mod); + try writer.writeAll(".?"); + }, + .elem => |elem| { + if (level == 0) { + try writer.writeAll("(...)"); + } else { try print(.{ - .ty = field_ty, - .val = Value.fromInterned(un.val), + .ty = Type.fromInterned(ip.typeOf(elem.base)), + .val = Value.fromInterned(elem.base), }, writer, level - 1, mod); + } + try writer.print("[{}]", .{elem.index}); + }, + .field => |field| { + const ptr_container_ty = Type.fromInterned(ip.typeOf(field.base)); + if (level == 0) { + try writer.writeAll("(...)"); } else { - try writer.writeAll("(unknown tag) = "); - const backing_ty = try ty.unionBackingType(mod); try print(.{ - .ty = backing_ty, - .val = Value.fromInterned(un.val), + .ty = ptr_container_ty, + .val = Value.fromInterned(field.base), }, writer, level - 1, mod); } - } else try writer.writeAll("..."); - return writer.writeAll(" }"); + + const container_ty = ptr_container_ty.childType(mod); + switch (container_ty.zigTypeTag(mod)) { + .Struct => { + if (container_ty.structFieldName(@intCast(field.index), mod).unwrap()) |field_name| { + try writer.print(".{i}", .{field_name.fmt(ip)}); + } else { + try writer.print("[{d}]", .{field.index}); + } + }, + .Union => { + const field_name = mod.typeToUnion(container_ty).?.loadTagType(ip).names.get(ip)[@intCast(field.index)]; + try writer.print(".{i}", .{field_name.fmt(ip)}); + }, + .Pointer => { + std.debug.assert(container_ty.isSlice(mod)); + try writer.writeAll(switch (field.index) { + Value.slice_ptr_index => ".ptr", + Value.slice_len_index => ".len", + else => unreachable, + }); + }, + else => unreachable, + } + }, + } + return; + }, + .opt => |opt| switch (opt.val) { + .none => return writer.writeAll("null"), + else => |payload| { + val = Value.fromInterned(payload); + ty = ty.optionalChild(mod); + }, + }, + .aggregate => |aggregate| switch (aggregate.storage) { + .bytes => |bytes| { + // Strip the 0 sentinel off of strings before printing + const zero_sent = blk: { + const sent = ty.sentinel(mod) orelse break :blk false; + break :blk sent.eql(Value.zero_u8, Type.u8, mod); + }; + const str = if (zero_sent) bytes[0 .. bytes.len - 1] else bytes; + return writer.print("\"{}\"", .{std.zig.fmtEscapes(str)}); }, - .memoized_call => unreachable, + .elems, .repeated_elem => return printAggregate(ty, val, writer, level, mod), + }, + .un => |un| { + try writer.writeAll(".{ "); + if (level > 0) { + if (un.tag != .none) { + try print(.{ + .ty = ty.unionTagTypeHypothetical(mod), + .val = Value.fromInterned(un.tag), + }, writer, level - 1, mod); + try writer.writeAll(" = "); + const field_ty = ty.unionFieldType(Value.fromInterned(un.tag), mod).?; + try print(.{ + .ty = field_ty, + .val = Value.fromInterned(un.val), + }, writer, level - 1, mod); + } else { + try writer.writeAll("(unknown tag) = "); + const backing_ty = try ty.unionBackingType(mod); + try print(.{ + .ty = backing_ty, + .val = Value.fromInterned(un.val), + }, writer, level - 1, mod); + } + } else try writer.writeAll("..."); + return writer.writeAll(" }"); }, + .memoized_call => unreachable, }; } diff --git a/src/Value.zig b/src/Value.zig index af24d68d7c..040961fa38 100644 --- a/src/Value.zig +++ b/src/Value.zig @@ -13,124 +13,8 @@ const Sema = @import("Sema.zig"); const InternPool = @import("InternPool.zig"); const Value = @This(); -/// We are migrating towards using this for every Value object. However, many -/// values are still represented the legacy way. This is indicated by using -/// InternPool.Index.none. ip_index: InternPool.Index, -/// This is the raw data, with no bookkeeping, no memory awareness, -/// no de-duplication, and no type system awareness. -/// This union takes advantage of the fact that the first page of memory -/// is unmapped, giving us 4096 possible enum tags that have no payload. -legacy: extern union { - ptr_otherwise: *Payload, -}, - -// 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. - // After this, the tag requires a payload. - - /// When the type is error union: - /// * If the tag is `.@"error"`, the error union is an error. - /// * If the tag is `.eu_payload`, the error union is a payload. - /// * A nested error such as `anyerror!(anyerror!T)` in which the the outer error union - /// is non-error, but the inner error union is an error, is represented as - /// a tag of `.eu_payload`, with a sub-tag of `.@"error"`. - eu_payload, - /// When the type is optional: - /// * If the tag is `.null_value`, the optional is null. - /// * If the tag is `.opt_payload`, the optional is a payload. - /// * A nested optional such as `??T` in which the the outer optional - /// is non-null, but the inner optional is null, is represented as - /// a tag of `.opt_payload`, with a sub-tag of `.null_value`. - opt_payload, - /// Pointer and length as sub `Value` objects. - slice, - /// A slice of u8 whose memory is managed externally. - bytes, - /// This value is repeated some number of times. The amount of times to repeat - /// is stored externally. - repeated, - /// An instance of a struct, array, or vector. - /// Each element/field stored as a `Value`. - /// In the case of sentinel-terminated arrays, the sentinel value *is* stored, - /// so the slice length will be one more than the type's array length. - aggregate, - /// An instance of a union. - @"union", - - pub fn Type(comptime t: Tag) type { - return switch (t) { - .eu_payload, - .opt_payload, - .repeated, - => Payload.SubValue, - .slice => Payload.Slice, - .bytes => Payload.Bytes, - .aggregate => Payload.Aggregate, - .@"union" => Payload.Union, - }; - } - - pub fn create(comptime t: Tag, ally: Allocator, data: Data(t)) error{OutOfMemory}!Value { - const ptr = try ally.create(t.Type()); - ptr.* = .{ - .base = .{ .tag = t }, - .data = data, - }; - return Value{ - .ip_index = .none, - .legacy = .{ .ptr_otherwise = &ptr.base }, - }; - } - - pub fn Data(comptime t: Tag) type { - return std.meta.fieldInfo(t.Type(), .data).type; - } -}; - -pub fn initPayload(payload: *Payload) Value { - return Value{ - .ip_index = .none, - .legacy = .{ .ptr_otherwise = payload }, - }; -} - -pub fn tag(self: Value) Tag { - assert(self.ip_index == .none); - return self.legacy.ptr_otherwise.tag; -} - -/// Prefer `castTag` to this. -pub fn cast(self: Value, comptime T: type) ?*T { - if (self.ip_index != .none) { - return null; - } - if (@hasField(T, "base_tag")) { - return self.castTag(T.base_tag); - } - inline for (@typeInfo(Tag).Enum.fields) |field| { - const t = @as(Tag, @enumFromInt(field.value)); - if (self.legacy.ptr_otherwise.tag == t) { - if (T == t.Type()) { - return @fieldParentPtr(T, "base", self.legacy.ptr_otherwise); - } - return null; - } - } - unreachable; -} - -pub fn castTag(self: Value, comptime t: Tag) ?*t.Type() { - if (self.ip_index != .none) return null; - - if (self.legacy.ptr_otherwise.tag == t) - return @fieldParentPtr(t.Type(), "base", self.legacy.ptr_otherwise); - - return null; -} - pub fn format(val: Value, comptime fmt: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void { _ = val; _ = fmt; @@ -148,33 +32,7 @@ pub fn dump( out_stream: anytype, ) !void { comptime assert(fmt.len == 0); - if (start_val.ip_index != .none) { - try out_stream.print("(interned: {})", .{start_val.toIntern()}); - return; - } - var val = start_val; - while (true) switch (val.tag()) { - .aggregate => { - return out_stream.writeAll("(aggregate)"); - }, - .@"union" => { - return out_stream.writeAll("(union value)"); - }, - .bytes => return out_stream.print("\"{}\"", .{std.zig.fmtEscapes(val.castTag(.bytes).?.data)}), - .repeated => { - try out_stream.writeAll("(repeated) "); - val = val.castTag(.repeated).?.data; - }, - .eu_payload => { - try out_stream.writeAll("(eu_payload) "); - val = val.castTag(.repeated).?.data; - }, - .opt_payload => { - try out_stream.writeAll("(opt_payload) "); - val = val.castTag(.repeated).?.data; - }, - .slice => return out_stream.writeAll("(slice)"), - }; + try out_stream.print("(interned: {})", .{start_val.toIntern()}); } pub fn fmtDebug(val: Value) std.fmt.Formatter(dump) { @@ -252,162 +110,9 @@ fn arrayToIpString(val: Value, len_u64: u64, mod: *Module) !InternPool.NullTermi return ip.getOrPutTrailingString(gpa, len); } -pub fn intern2(val: Value, ty: Type, mod: *Module) Allocator.Error!InternPool.Index { - if (val.ip_index != .none) return val.ip_index; - return intern(val, ty, mod); -} - -pub fn intern(val: Value, ty: Type, mod: *Module) Allocator.Error!InternPool.Index { - if (val.ip_index != .none) return (try mod.getCoerced(val, ty)).toIntern(); - const ip = &mod.intern_pool; - switch (val.tag()) { - .eu_payload => { - const pl = val.castTag(.eu_payload).?.data; - return mod.intern(.{ .error_union = .{ - .ty = ty.toIntern(), - .val = .{ .payload = try pl.intern(ty.errorUnionPayload(mod), mod) }, - } }); - }, - .opt_payload => { - const pl = val.castTag(.opt_payload).?.data; - return mod.intern(.{ .opt = .{ - .ty = ty.toIntern(), - .val = try pl.intern(ty.optionalChild(mod), mod), - } }); - }, - .slice => { - const pl = val.castTag(.slice).?.data; - return mod.intern(.{ .slice = .{ - .ty = ty.toIntern(), - .len = try pl.len.intern(Type.usize, mod), - .ptr = try pl.ptr.intern(ty.slicePtrFieldType(mod), mod), - } }); - }, - .bytes => { - const pl = val.castTag(.bytes).?.data; - return mod.intern(.{ .aggregate = .{ - .ty = ty.toIntern(), - .storage = .{ .bytes = pl }, - } }); - }, - .repeated => { - const pl = val.castTag(.repeated).?.data; - return mod.intern(.{ .aggregate = .{ - .ty = ty.toIntern(), - .storage = .{ .repeated_elem = try pl.intern(ty.childType(mod), mod) }, - } }); - }, - .aggregate => { - const len = @as(usize, @intCast(ty.arrayLen(mod))); - const old_elems = val.castTag(.aggregate).?.data[0..len]; - const new_elems = try mod.gpa.alloc(InternPool.Index, old_elems.len); - defer mod.gpa.free(new_elems); - const ty_key = ip.indexToKey(ty.toIntern()); - for (new_elems, old_elems, 0..) |*new_elem, old_elem, field_i| - new_elem.* = try old_elem.intern(switch (ty_key) { - .struct_type => ty.structFieldType(field_i, mod), - .anon_struct_type => |info| Type.fromInterned(info.types.get(ip)[field_i]), - inline .array_type, .vector_type => |info| Type.fromInterned(info.child), - else => unreachable, - }, mod); - return mod.intern(.{ .aggregate = .{ - .ty = ty.toIntern(), - .storage = .{ .elems = new_elems }, - } }); - }, - .@"union" => { - const pl = val.castTag(.@"union").?.data; - if (pl.tag) |pl_tag| { - return mod.intern(.{ .un = .{ - .ty = ty.toIntern(), - .tag = try pl_tag.intern(ty.unionTagTypeHypothetical(mod), mod), - .val = try pl.val.intern(ty.unionFieldType(pl_tag, mod).?, mod), - } }); - } else { - return mod.intern(.{ .un = .{ - .ty = ty.toIntern(), - .tag = .none, - .val = try pl.val.intern(try ty.unionBackingType(mod), mod), - } }); - } - }, - } -} - -pub fn unintern(val: Value, arena: Allocator, mod: *Module) Allocator.Error!Value { - return if (val.ip_index == .none) val else switch (mod.intern_pool.indexToKey(val.toIntern())) { - .int_type, - .ptr_type, - .array_type, - .vector_type, - .opt_type, - .anyframe_type, - .error_union_type, - .simple_type, - .struct_type, - .anon_struct_type, - .union_type, - .opaque_type, - .enum_type, - .func_type, - .error_set_type, - .inferred_error_set_type, - - .undef, - .simple_value, - .variable, - .extern_func, - .func, - .int, - .err, - .enum_literal, - .enum_tag, - .empty_enum_value, - .float, - .ptr, - => val, - - .error_union => |error_union| switch (error_union.val) { - .err_name => val, - .payload => |payload| Tag.eu_payload.create(arena, Value.fromInterned(payload)), - }, - - .slice => |slice| Tag.slice.create(arena, .{ - .ptr = Value.fromInterned(slice.ptr), - .len = Value.fromInterned(slice.len), - }), - - .opt => |opt| switch (opt.val) { - .none => val, - else => |payload| Tag.opt_payload.create(arena, Value.fromInterned(payload)), - }, - - .aggregate => |aggregate| switch (aggregate.storage) { - .bytes => |bytes| Tag.bytes.create(arena, try arena.dupe(u8, bytes)), - .elems => |old_elems| { - const new_elems = try arena.alloc(Value, old_elems.len); - for (new_elems, old_elems) |*new_elem, old_elem| new_elem.* = Value.fromInterned(old_elem); - return Tag.aggregate.create(arena, new_elems); - }, - .repeated_elem => |elem| Tag.repeated.create(arena, Value.fromInterned(elem)), - }, - - .un => |un| Tag.@"union".create(arena, .{ - // toValue asserts that the value cannot be .none which is valid on unions. - .tag = if (un.tag == .none) null else Value.fromInterned(un.tag), - .val = Value.fromInterned(un.val), - }), - - .memoized_call => unreachable, - }; -} - pub fn fromInterned(i: InternPool.Index) Value { assert(i != .none); - return .{ - .ip_index = i, - .legacy = undefined, - }; + return .{ .ip_index = i }; } pub fn toIntern(val: Value) InternPool.Index { @@ -492,24 +197,24 @@ pub fn isFuncBody(val: Value, mod: *Module) bool { } pub fn getFunction(val: Value, mod: *Module) ?InternPool.Key.Func { - return if (val.ip_index != .none) switch (mod.intern_pool.indexToKey(val.toIntern())) { + return switch (mod.intern_pool.indexToKey(val.toIntern())) { .func => |x| x, else => null, - } else null; + }; } pub fn getExternFunc(val: Value, mod: *Module) ?InternPool.Key.ExternFunc { - return if (val.ip_index != .none) switch (mod.intern_pool.indexToKey(val.toIntern())) { + return switch (mod.intern_pool.indexToKey(val.toIntern())) { .extern_func => |extern_func| extern_func, else => null, - } else null; + }; } pub fn getVariable(val: Value, mod: *Module) ?InternPool.Key.Variable { - return if (val.ip_index != .none) switch (mod.intern_pool.indexToKey(val.toIntern())) { + return switch (mod.intern_pool.indexToKey(val.toIntern())) { .variable => |variable| variable, else => null, - } else null; + }; } /// If the value fits in a u64, return it, otherwise null. @@ -677,25 +382,14 @@ pub fn writeToMemory(val: Value, ty: Type, mod: *Module, buffer: []u8) error{ .auto => return error.IllDefinedMemoryLayout, .@"extern" => for (0..struct_type.field_types.len) |i| { const off: usize = @intCast(ty.structFieldOffset(i, mod)); - const field_val = switch (val.ip_index) { - .none => switch (val.tag()) { - .bytes => { - buffer[off] = val.castTag(.bytes).?.data[i]; - continue; - }, - .aggregate => val.castTag(.aggregate).?.data[i], - .repeated => val.castTag(.repeated).?.data, - else => unreachable, + const field_val = Value.fromInterned(switch (ip.indexToKey(val.toIntern()).aggregate.storage) { + .bytes => |bytes| { + buffer[off] = bytes[i]; + continue; }, - else => Value.fromInterned(switch (ip.indexToKey(val.toIntern()).aggregate.storage) { - .bytes => |bytes| { - buffer[off] = bytes[i]; - continue; - }, - .elems => |elems| elems[i], - .repeated_elem => |elem| elem, - }), - }; + .elems => |elems| elems[i], + .repeated_elem => |elem| elem, + }); const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]); try writeToMemory(field_val, field_ty, mod, buffer[off..]); }, @@ -842,19 +536,11 @@ pub fn writeToPackedMemory( assert(struct_type.layout == .@"packed"); var bits: u16 = 0; for (0..struct_type.field_types.len) |i| { - const field_val = switch (val.ip_index) { - .none => switch (val.tag()) { - .bytes => unreachable, - .aggregate => val.castTag(.aggregate).?.data[i], - .repeated => val.castTag(.repeated).?.data, - else => unreachable, - }, - else => Value.fromInterned(switch (ip.indexToKey(val.toIntern()).aggregate.storage) { - .bytes => unreachable, - .elems => |elems| elems[i], - .repeated_elem => |elem| elem, - }), - }; + const field_val = Value.fromInterned(switch (ip.indexToKey(val.toIntern()).aggregate.storage) { + .bytes => unreachable, + .elems => |elems| elems[i], + .repeated_elem => |elem| elem, + }); const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]); const field_bits: u16 = @intCast(field_ty.bitSize(mod)); try field_val.writeToPackedMemory(field_ty, mod, buffer, bit_offset + bits); @@ -972,7 +658,7 @@ pub fn readFromMemory( const elems = try arena.alloc(InternPool.Index, @as(usize, @intCast(ty.arrayLen(mod)))); var offset: usize = 0; for (elems) |*elem| { - elem.* = try (try readFromMemory(elem_ty, mod, buffer[offset..], arena)).intern(elem_ty, mod); + elem.* = (try readFromMemory(elem_ty, mod, buffer[offset..], arena)).toIntern(); offset += @as(usize, @intCast(elem_size)); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ @@ -997,7 +683,7 @@ pub fn readFromMemory( const field_ty = Type.fromInterned(field_types.get(ip)[i]); const off: usize = @intCast(ty.structFieldOffset(i, mod)); const sz: usize = @intCast(field_ty.abiSize(mod)); - field_val.* = try (try readFromMemory(field_ty, mod, buffer[off..(off + sz)], arena)).intern(field_ty, mod); + field_val.* = (try readFromMemory(field_ty, mod, buffer[off..(off + sz)], arena)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = ty.toIntern(), @@ -1027,7 +713,7 @@ pub fn readFromMemory( .@"extern" => { const union_size = ty.abiSize(mod); const array_ty = try mod.arrayType(.{ .len = union_size, .child = .u8_type }); - const val = try (try readFromMemory(array_ty, mod, buffer, arena)).intern(array_ty, mod); + const val = (try readFromMemory(array_ty, mod, buffer, arena)).toIntern(); return Value.fromInterned((try mod.intern(.{ .un = .{ .ty = ty.toIntern(), .tag = .none, @@ -1094,7 +780,7 @@ pub fn readFromPackedMemory( return Value.true; } }, - .Int, .Enum => |ty_tag| { + .Int => { if (buffer.len == 0) return mod.intValue(ty, 0); const int_info = ty.intInfo(mod); const bits = int_info.bits; @@ -1102,21 +788,10 @@ pub fn readFromPackedMemory( // Fast path for integers <= u64 if (bits <= 64) { - const int_ty = switch (ty_tag) { - .Int => ty, - .Enum => ty.intTagType(mod), - else => unreachable, - }; - return mod.getCoerced(switch (int_info.signedness) { - .signed => return mod.intValue( - int_ty, - std.mem.readVarPackedInt(i64, buffer, bit_offset, bits, endian, .signed), - ), - .unsigned => return mod.intValue( - int_ty, - std.mem.readVarPackedInt(u64, buffer, bit_offset, bits, endian, .unsigned), - ), - }, ty); + return mod.intValue( + ty, + std.mem.readVarPackedInt(i64, buffer, bit_offset, bits, endian, int_info.signedness), + ); } // Slow path, we have to construct a big-int @@ -1129,6 +804,11 @@ pub fn readFromPackedMemory( bigint.readPackedTwosComplement(buffer, bit_offset, bits, endian, int_info.signedness); return mod.intValue_big(ty, bigint.toConst()); }, + .Enum => { + const int_ty = ty.intTagType(mod); + const int_val = try Value.readFromPackedMemory(int_ty, mod, buffer, bit_offset, arena); + return mod.getCoerced(int_val, ty); + }, .Float => return Value.fromInterned((try mod.intern(.{ .float = .{ .ty = ty.toIntern(), .storage = switch (ty.floatBits(target)) { @@ -1149,7 +829,7 @@ pub fn readFromPackedMemory( for (elems, 0..) |_, i| { // On big-endian systems, LLVM reverses the element order of vectors by default const tgt_elem_i = if (endian == .big) elems.len - i - 1 else i; - elems[tgt_elem_i] = try (try readFromPackedMemory(elem_ty, mod, buffer, bit_offset + bits, arena)).intern(elem_ty, mod); + elems[tgt_elem_i] = (try readFromPackedMemory(elem_ty, mod, buffer, bit_offset + bits, arena)).toIntern(); bits += elem_bit_size; } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ @@ -1166,7 +846,7 @@ pub fn readFromPackedMemory( for (field_vals, 0..) |*field_val, i| { const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]); const field_bits: u16 = @intCast(field_ty.bitSize(mod)); - field_val.* = try (try readFromPackedMemory(field_ty, mod, buffer, bit_offset + bits, arena)).intern(field_ty, mod); + field_val.* = (try readFromPackedMemory(field_ty, mod, buffer, bit_offset + bits, arena)).toIntern(); bits += field_bits; } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ @@ -1611,51 +1291,42 @@ pub fn maybeElemValue(val: Value, mod: *Module, index: usize) Allocator.Error!?V } pub fn maybeElemValueFull(val: Value, sema: ?*Sema, mod: *Module, index: usize) Allocator.Error!?Value { - return switch (val.ip_index) { - .none => switch (val.tag()) { - .bytes => try mod.intValue(Type.u8, val.castTag(.bytes).?.data[index]), - .repeated => val.castTag(.repeated).?.data, - .aggregate => val.castTag(.aggregate).?.data[index], - .slice => val.castTag(.slice).?.data.ptr.maybeElemValueFull(sema, mod, index), - else => null, - }, - else => switch (mod.intern_pool.indexToKey(val.toIntern())) { - .undef => |ty| Value.fromInterned((try mod.intern(.{ - .undef = Type.fromInterned(ty).elemType2(mod).toIntern(), - }))), - .slice => |slice| return Value.fromInterned(slice.ptr).maybeElemValueFull(sema, mod, index), - .ptr => |ptr| switch (ptr.addr) { - .decl => |decl| mod.declPtr(decl).val.maybeElemValueFull(sema, mod, index), - .anon_decl => |anon_decl| Value.fromInterned(anon_decl.val).maybeElemValueFull(sema, mod, index), - .comptime_alloc => |idx| if (sema) |s| Value.fromInterned( - try s.getComptimeAlloc(idx).val.intern(mod, s.arena), - ).maybeElemValueFull(sema, mod, index) else null, - .int, .eu_payload => null, - .opt_payload => |base| Value.fromInterned(base).maybeElemValueFull(sema, mod, index), - .comptime_field => |field_val| Value.fromInterned(field_val).maybeElemValueFull(sema, mod, index), - .elem => |elem| Value.fromInterned(elem.base).maybeElemValueFull(sema, mod, index + @as(usize, @intCast(elem.index))), - .field => |field| if (Value.fromInterned(field.base).pointerDecl(mod)) |decl_index| { - const base_decl = mod.declPtr(decl_index); - const field_val = try base_decl.val.fieldValue(mod, @as(usize, @intCast(field.index))); - return field_val.maybeElemValueFull(sema, mod, index); - } else null, - }, - .opt => |opt| Value.fromInterned(opt.val).maybeElemValueFull(sema, mod, index), - .aggregate => |aggregate| { - const len = mod.intern_pool.aggregateTypeLen(aggregate.ty); - if (index < len) return Value.fromInterned(switch (aggregate.storage) { - .bytes => |bytes| try mod.intern(.{ .int = .{ - .ty = .u8_type, - .storage = .{ .u64 = bytes[index] }, - } }), - .elems => |elems| elems[index], - .repeated_elem => |elem| elem, - }); - assert(index == len); - return Value.fromInterned(mod.intern_pool.indexToKey(aggregate.ty).array_type.sentinel); - }, - else => null, + return switch (mod.intern_pool.indexToKey(val.toIntern())) { + .undef => |ty| Value.fromInterned((try mod.intern(.{ + .undef = Type.fromInterned(ty).elemType2(mod).toIntern(), + }))), + .slice => |slice| return Value.fromInterned(slice.ptr).maybeElemValueFull(sema, mod, index), + .ptr => |ptr| switch (ptr.addr) { + .decl => |decl| mod.declPtr(decl).val.maybeElemValueFull(sema, mod, index), + .anon_decl => |anon_decl| Value.fromInterned(anon_decl.val).maybeElemValueFull(sema, mod, index), + .comptime_alloc => |idx| if (sema) |s| Value.fromInterned( + try s.getComptimeAlloc(idx).val.intern(mod, s.arena), + ).maybeElemValueFull(sema, mod, index) else null, + .int, .eu_payload => null, + .opt_payload => |base| Value.fromInterned(base).maybeElemValueFull(sema, mod, index), + .comptime_field => |field_val| Value.fromInterned(field_val).maybeElemValueFull(sema, mod, index), + .elem => |elem| Value.fromInterned(elem.base).maybeElemValueFull(sema, mod, index + @as(usize, @intCast(elem.index))), + .field => |field| if (Value.fromInterned(field.base).pointerDecl(mod)) |decl_index| { + const base_decl = mod.declPtr(decl_index); + const field_val = try base_decl.val.fieldValue(mod, @as(usize, @intCast(field.index))); + return field_val.maybeElemValueFull(sema, mod, index); + } else null, + }, + .opt => |opt| Value.fromInterned(opt.val).maybeElemValueFull(sema, mod, index), + .aggregate => |aggregate| { + const len = mod.intern_pool.aggregateTypeLen(aggregate.ty); + if (index < len) return Value.fromInterned(switch (aggregate.storage) { + .bytes => |bytes| try mod.intern(.{ .int = .{ + .ty = .u8_type, + .storage = .{ .u64 = bytes[index] }, + } }), + .elems => |elems| elems[index], + .repeated_elem => |elem| elem, + }); + assert(index == len); + return Value.fromInterned(mod.intern_pool.indexToKey(aggregate.ty).array_type.sentinel); }, + else => null, }; } @@ -1688,85 +1359,61 @@ pub fn sliceArray( ) error{OutOfMemory}!Value { // TODO: write something like getCoercedInts to avoid needing to dupe const mod = sema.mod; - return switch (val.ip_index) { - .none => switch (val.tag()) { - .slice => val.castTag(.slice).?.data.ptr.sliceArray(sema, start, end), - .bytes => Tag.bytes.create(sema.arena, val.castTag(.bytes).?.data[start..end]), - .repeated => val, - .aggregate => Tag.aggregate.create(sema.arena, val.castTag(.aggregate).?.data[start..end]), + return switch (mod.intern_pool.indexToKey(val.toIntern())) { + .ptr => |ptr| switch (ptr.addr) { + .decl => |decl| try mod.declPtr(decl).val.sliceArray(sema, start, end), + .comptime_alloc => |idx| try Value.fromInterned( + try sema.getComptimeAlloc(idx).val.intern(mod, sema.arena), + ).sliceArray(sema, start, end), + .comptime_field => |comptime_field| Value.fromInterned(comptime_field) + .sliceArray(sema, start, end), + .elem => |elem| Value.fromInterned(elem.base) + .sliceArray(sema, start + @as(usize, @intCast(elem.index)), end + @as(usize, @intCast(elem.index))), else => unreachable, }, - else => switch (mod.intern_pool.indexToKey(val.toIntern())) { - .ptr => |ptr| switch (ptr.addr) { - .decl => |decl| try mod.declPtr(decl).val.sliceArray(sema, start, end), - .comptime_alloc => |idx| try Value.fromInterned( - try sema.getComptimeAlloc(idx).val.intern(mod, sema.arena), - ).sliceArray(sema, start, end), - .comptime_field => |comptime_field| Value.fromInterned(comptime_field) - .sliceArray(sema, start, end), - .elem => |elem| Value.fromInterned(elem.base) - .sliceArray(sema, start + @as(usize, @intCast(elem.index)), end + @as(usize, @intCast(elem.index))), + .aggregate => |aggregate| Value.fromInterned((try mod.intern(.{ .aggregate = .{ + .ty = switch (mod.intern_pool.indexToKey(mod.intern_pool.typeOf(val.toIntern()))) { + .array_type => |array_type| try mod.arrayType(.{ + .len = @as(u32, @intCast(end - start)), + .child = array_type.child, + .sentinel = if (end == array_type.len) array_type.sentinel else .none, + }), + .vector_type => |vector_type| try mod.vectorType(.{ + .len = @as(u32, @intCast(end - start)), + .child = vector_type.child, + }), else => unreachable, + }.toIntern(), + .storage = switch (aggregate.storage) { + .bytes => .{ .bytes = try sema.arena.dupe(u8, mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage.bytes[start..end]) }, + .elems => .{ .elems = try sema.arena.dupe(InternPool.Index, mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage.elems[start..end]) }, + .repeated_elem => |elem| .{ .repeated_elem = elem }, }, - .aggregate => |aggregate| Value.fromInterned((try mod.intern(.{ .aggregate = .{ - .ty = switch (mod.intern_pool.indexToKey(mod.intern_pool.typeOf(val.toIntern()))) { - .array_type => |array_type| try mod.arrayType(.{ - .len = @as(u32, @intCast(end - start)), - .child = array_type.child, - .sentinel = if (end == array_type.len) array_type.sentinel else .none, - }), - .vector_type => |vector_type| try mod.vectorType(.{ - .len = @as(u32, @intCast(end - start)), - .child = vector_type.child, - }), - else => unreachable, - }.toIntern(), - .storage = switch (aggregate.storage) { - .bytes => .{ .bytes = try sema.arena.dupe(u8, mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage.bytes[start..end]) }, - .elems => .{ .elems = try sema.arena.dupe(InternPool.Index, mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage.elems[start..end]) }, - .repeated_elem => |elem| .{ .repeated_elem = elem }, - }, - } }))), - else => unreachable, - }, + } }))), + else => unreachable, }; } pub fn fieldValue(val: Value, mod: *Module, index: usize) !Value { - return switch (val.ip_index) { - .none => switch (val.tag()) { - .aggregate => { - const field_values = val.castTag(.aggregate).?.data; - return field_values[index]; - }, - .@"union" => { - const payload = val.castTag(.@"union").?.data; - // TODO assert the tag is correct - return payload.val; - }, - else => unreachable, - }, - else => switch (mod.intern_pool.indexToKey(val.toIntern())) { - .undef => |ty| Value.fromInterned((try mod.intern(.{ - .undef = Type.fromInterned(ty).structFieldType(index, mod).toIntern(), - }))), - .aggregate => |aggregate| Value.fromInterned(switch (aggregate.storage) { - .bytes => |bytes| try mod.intern(.{ .int = .{ - .ty = .u8_type, - .storage = .{ .u64 = bytes[index] }, - } }), - .elems => |elems| elems[index], - .repeated_elem => |elem| elem, - }), - // TODO assert the tag is correct - .un => |un| Value.fromInterned(un.val), - else => unreachable, - }, + return switch (mod.intern_pool.indexToKey(val.toIntern())) { + .undef => |ty| Value.fromInterned((try mod.intern(.{ + .undef = Type.fromInterned(ty).structFieldType(index, mod).toIntern(), + }))), + .aggregate => |aggregate| Value.fromInterned(switch (aggregate.storage) { + .bytes => |bytes| try mod.intern(.{ .int = .{ + .ty = .u8_type, + .storage = .{ .u64 = bytes[index] }, + } }), + .elems => |elems| elems[index], + .repeated_elem => |elem| elem, + }), + // TODO assert the tag is correct + .un => |un| Value.fromInterned(un.val), + else => unreachable, }; } pub fn unionTag(val: Value, mod: *Module) ?Value { - if (val.ip_index == .none) return val.castTag(.@"union").?.data.tag; return switch (mod.intern_pool.indexToKey(val.toIntern())) { .undef, .enum_tag => val, .un => |un| if (un.tag != .none) Value.fromInterned(un.tag) else return null, @@ -1775,7 +1422,6 @@ pub fn unionTag(val: Value, mod: *Module) ?Value { } pub fn unionValue(val: Value, mod: *Module) Value { - if (val.ip_index == .none) return val.castTag(.@"union").?.data.val; return switch (mod.intern_pool.indexToKey(val.toIntern())) { .un => |un| Value.fromInterned(un.val), else => unreachable, @@ -1821,7 +1467,7 @@ pub fn elemPtr( } pub fn isUndef(val: Value, mod: *Module) bool { - return val.ip_index != .none and mod.intern_pool.isUndef(val.toIntern()); + return mod.intern_pool.isUndef(val.toIntern()); } /// TODO: check for cases such as array that is not marked undef but all the element @@ -1915,7 +1561,7 @@ pub fn floatFromIntAdvanced(val: Value, arena: Allocator, int_ty: Type, float_ty const scalar_ty = float_ty.scalarType(mod); for (result_data, 0..) |*scalar, i| { const elem_val = try val.elemValue(mod, i); - scalar.* = try (try floatFromIntScalar(elem_val, scalar_ty, mod, opt_sema)).intern(scalar_ty, mod); + scalar.* = (try floatFromIntScalar(elem_val, scalar_ty, mod, opt_sema)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = float_ty.toIntern(), @@ -1993,7 +1639,7 @@ pub fn intAddSat( for (result_data, 0..) |*scalar, i| { const lhs_elem = try lhs.elemValue(mod, i); const rhs_elem = try rhs.elemValue(mod, i); - scalar.* = try (try intAddSatScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).intern(scalar_ty, mod); + scalar.* = (try intAddSatScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = ty.toIntern(), @@ -2043,7 +1689,7 @@ pub fn intSubSat( for (result_data, 0..) |*scalar, i| { const lhs_elem = try lhs.elemValue(mod, i); const rhs_elem = try rhs.elemValue(mod, i); - scalar.* = try (try intSubSatScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).intern(scalar_ty, mod); + scalar.* = (try intSubSatScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = ty.toIntern(), @@ -2095,8 +1741,8 @@ pub fn intMulWithOverflow( const lhs_elem = try lhs.elemValue(mod, i); const rhs_elem = try rhs.elemValue(mod, i); const of_math_result = try intMulWithOverflowScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod); - of.* = try of_math_result.overflow_bit.intern(Type.u1, mod); - scalar.* = try of_math_result.wrapped_result.intern(scalar_ty, mod); + of.* = of_math_result.overflow_bit.toIntern(); + scalar.* = of_math_result.wrapped_result.toIntern(); } return OverflowArithmeticResult{ .overflow_bit = Value.fromInterned((try mod.intern(.{ .aggregate = .{ @@ -2161,7 +1807,7 @@ pub fn numberMulWrap( for (result_data, 0..) |*scalar, i| { const lhs_elem = try lhs.elemValue(mod, i); const rhs_elem = try rhs.elemValue(mod, i); - scalar.* = try (try numberMulWrapScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).intern(scalar_ty, mod); + scalar.* = (try numberMulWrapScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = ty.toIntern(), @@ -2207,7 +1853,7 @@ pub fn intMulSat( for (result_data, 0..) |*scalar, i| { const lhs_elem = try lhs.elemValue(mod, i); const rhs_elem = try rhs.elemValue(mod, i); - scalar.* = try (try intMulSatScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).intern(scalar_ty, mod); + scalar.* = (try intMulSatScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = ty.toIntern(), @@ -2283,7 +1929,7 @@ pub fn bitwiseNot(val: Value, ty: Type, arena: Allocator, mod: *Module) !Value { const scalar_ty = ty.scalarType(mod); for (result_data, 0..) |*scalar, i| { const elem_val = try val.elemValue(mod, i); - scalar.* = try (try bitwiseNotScalar(elem_val, scalar_ty, arena, mod)).intern(scalar_ty, mod); + scalar.* = (try bitwiseNotScalar(elem_val, scalar_ty, arena, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = ty.toIntern(), @@ -2326,7 +1972,7 @@ pub fn bitwiseAnd(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: * for (result_data, 0..) |*scalar, i| { const lhs_elem = try lhs.elemValue(mod, i); const rhs_elem = try rhs.elemValue(mod, i); - scalar.* = try (try bitwiseAndScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).intern(scalar_ty, mod); + scalar.* = (try bitwiseAndScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = ty.toIntern(), @@ -2365,7 +2011,7 @@ pub fn bitwiseNand(lhs: Value, rhs: Value, ty: Type, arena: Allocator, mod: *Mod for (result_data, 0..) |*scalar, i| { const lhs_elem = try lhs.elemValue(mod, i); const rhs_elem = try rhs.elemValue(mod, i); - scalar.* = try (try bitwiseNandScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).intern(scalar_ty, mod); + scalar.* = (try bitwiseNandScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = ty.toIntern(), @@ -2393,7 +2039,7 @@ pub fn bitwiseOr(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *M for (result_data, 0..) |*scalar, i| { const lhs_elem = try lhs.elemValue(mod, i); const rhs_elem = try rhs.elemValue(mod, i); - scalar.* = try (try bitwiseOrScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).intern(scalar_ty, mod); + scalar.* = (try bitwiseOrScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = ty.toIntern(), @@ -2431,7 +2077,7 @@ pub fn bitwiseXor(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: * for (result_data, 0..) |*scalar, i| { const lhs_elem = try lhs.elemValue(mod, i); const rhs_elem = try rhs.elemValue(mod, i); - scalar.* = try (try bitwiseXorScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).intern(scalar_ty, mod); + scalar.* = (try bitwiseXorScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = ty.toIntern(), @@ -2497,7 +2143,7 @@ fn intDivInner(lhs: Value, rhs: Value, ty: Type, overflow_idx: *usize, allocator }, else => |e| return e, }; - scalar.* = try val.intern(scalar_ty, mod); + scalar.* = val.toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = ty.toIntern(), @@ -2545,7 +2191,7 @@ pub fn intDivFloor(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: for (result_data, 0..) |*scalar, i| { const lhs_elem = try lhs.elemValue(mod, i); const rhs_elem = try rhs.elemValue(mod, i); - scalar.* = try (try intDivFloorScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).intern(scalar_ty, mod); + scalar.* = (try intDivFloorScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = ty.toIntern(), @@ -2587,7 +2233,7 @@ pub fn intMod(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Modu for (result_data, 0..) |*scalar, i| { const lhs_elem = try lhs.elemValue(mod, i); const rhs_elem = try rhs.elemValue(mod, i); - scalar.* = try (try intModScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).intern(scalar_ty, mod); + scalar.* = (try intModScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = ty.toIntern(), @@ -2624,7 +2270,6 @@ pub fn intModScalar(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: /// Returns true if the value is a floating point type and is NaN. Returns false otherwise. pub fn isNan(val: Value, mod: *const Module) bool { - if (val.ip_index == .none) return false; return switch (mod.intern_pool.indexToKey(val.toIntern())) { .float => |float| switch (float.storage) { inline else => |x| std.math.isNan(x), @@ -2635,7 +2280,6 @@ pub fn isNan(val: Value, mod: *const Module) bool { /// Returns true if the value is a floating point type and is infinite. Returns false otherwise. pub fn isInf(val: Value, mod: *const Module) bool { - if (val.ip_index == .none) return false; return switch (mod.intern_pool.indexToKey(val.toIntern())) { .float => |float| switch (float.storage) { inline else => |x| std.math.isInf(x), @@ -2645,7 +2289,6 @@ pub fn isInf(val: Value, mod: *const Module) bool { } pub fn isNegativeInf(val: Value, mod: *const Module) bool { - if (val.ip_index == .none) return false; return switch (mod.intern_pool.indexToKey(val.toIntern())) { .float => |float| switch (float.storage) { inline else => |x| std.math.isNegativeInf(x), @@ -2661,7 +2304,7 @@ pub fn floatRem(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, mod: for (result_data, 0..) |*scalar, i| { const lhs_elem = try lhs.elemValue(mod, i); const rhs_elem = try rhs.elemValue(mod, i); - scalar.* = try (try floatRemScalar(lhs_elem, rhs_elem, scalar_ty, mod)).intern(scalar_ty, mod); + scalar.* = (try floatRemScalar(lhs_elem, rhs_elem, scalar_ty, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = float_type.toIntern(), @@ -2694,7 +2337,7 @@ pub fn floatMod(lhs: Value, rhs: Value, float_type: Type, arena: Allocator, mod: for (result_data, 0..) |*scalar, i| { const lhs_elem = try lhs.elemValue(mod, i); const rhs_elem = try rhs.elemValue(mod, i); - scalar.* = try (try floatModScalar(lhs_elem, rhs_elem, scalar_ty, mod)).intern(scalar_ty, mod); + scalar.* = (try floatModScalar(lhs_elem, rhs_elem, scalar_ty, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = float_type.toIntern(), @@ -2755,7 +2398,7 @@ fn intMulInner(lhs: Value, rhs: Value, ty: Type, overflow_idx: *usize, allocator }, else => |e| return e, }; - scalar.* = try val.intern(scalar_ty, mod); + scalar.* = val.toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = ty.toIntern(), @@ -2797,7 +2440,7 @@ pub fn intTrunc(val: Value, ty: Type, allocator: Allocator, signedness: std.buil const scalar_ty = ty.scalarType(mod); for (result_data, 0..) |*scalar, i| { const elem_val = try val.elemValue(mod, i); - scalar.* = try (try intTruncScalar(elem_val, scalar_ty, allocator, signedness, bits, mod)).intern(scalar_ty, mod); + scalar.* = (try intTruncScalar(elem_val, scalar_ty, allocator, signedness, bits, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = ty.toIntern(), @@ -2822,7 +2465,7 @@ pub fn intTruncBitsAsValue( for (result_data, 0..) |*scalar, i| { const elem_val = try val.elemValue(mod, i); const bits_elem = try bits.elemValue(mod, i); - scalar.* = try (try intTruncScalar(elem_val, scalar_ty, allocator, signedness, @as(u16, @intCast(bits_elem.toUnsignedInt(mod))), mod)).intern(scalar_ty, mod); + scalar.* = (try intTruncScalar(elem_val, scalar_ty, allocator, signedness, @as(u16, @intCast(bits_elem.toUnsignedInt(mod))), mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = ty.toIntern(), @@ -2862,7 +2505,7 @@ pub fn shl(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) for (result_data, 0..) |*scalar, i| { const lhs_elem = try lhs.elemValue(mod, i); const rhs_elem = try rhs.elemValue(mod, i); - scalar.* = try (try shlScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).intern(scalar_ty, mod); + scalar.* = (try shlScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = ty.toIntern(), @@ -2912,8 +2555,8 @@ pub fn shlWithOverflow( const lhs_elem = try lhs.elemValue(mod, i); const rhs_elem = try rhs.elemValue(mod, i); const of_math_result = try shlWithOverflowScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod); - of.* = try of_math_result.overflow_bit.intern(Type.u1, mod); - scalar.* = try of_math_result.wrapped_result.intern(scalar_ty, mod); + of.* = of_math_result.overflow_bit.toIntern(); + scalar.* = of_math_result.wrapped_result.toIntern(); } return OverflowArithmeticResult{ .overflow_bit = Value.fromInterned((try mod.intern(.{ .aggregate = .{ @@ -2973,7 +2616,7 @@ pub fn shlSat( for (result_data, 0..) |*scalar, i| { const lhs_elem = try lhs.elemValue(mod, i); const rhs_elem = try rhs.elemValue(mod, i); - scalar.* = try (try shlSatScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).intern(scalar_ty, mod); + scalar.* = (try shlSatScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = ty.toIntern(), @@ -3023,7 +2666,7 @@ pub fn shlTrunc( for (result_data, 0..) |*scalar, i| { const lhs_elem = try lhs.elemValue(mod, i); const rhs_elem = try rhs.elemValue(mod, i); - scalar.* = try (try shlTruncScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).intern(scalar_ty, mod); + scalar.* = (try shlTruncScalar(lhs_elem, rhs_elem, scalar_ty, arena, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = ty.toIntern(), @@ -3053,7 +2696,7 @@ pub fn shr(lhs: Value, rhs: Value, ty: Type, allocator: Allocator, mod: *Module) for (result_data, 0..) |*scalar, i| { const lhs_elem = try lhs.elemValue(mod, i); const rhs_elem = try rhs.elemValue(mod, i); - scalar.* = try (try shrScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).intern(scalar_ty, mod); + scalar.* = (try shrScalar(lhs_elem, rhs_elem, scalar_ty, allocator, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = ty.toIntern(), @@ -3105,7 +2748,7 @@ pub fn floatNeg( const scalar_ty = float_type.scalarType(mod); for (result_data, 0..) |*scalar, i| { const elem_val = try val.elemValue(mod, i); - scalar.* = try (try floatNegScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod); + scalar.* = (try floatNegScalar(elem_val, scalar_ty, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = float_type.toIntern(), @@ -3148,7 +2791,7 @@ pub fn floatAdd( for (result_data, 0..) |*scalar, i| { const lhs_elem = try lhs.elemValue(mod, i); const rhs_elem = try rhs.elemValue(mod, i); - scalar.* = try (try floatAddScalar(lhs_elem, rhs_elem, scalar_ty, mod)).intern(scalar_ty, mod); + scalar.* = (try floatAddScalar(lhs_elem, rhs_elem, scalar_ty, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = float_type.toIntern(), @@ -3192,7 +2835,7 @@ pub fn floatSub( for (result_data, 0..) |*scalar, i| { const lhs_elem = try lhs.elemValue(mod, i); const rhs_elem = try rhs.elemValue(mod, i); - scalar.* = try (try floatSubScalar(lhs_elem, rhs_elem, scalar_ty, mod)).intern(scalar_ty, mod); + scalar.* = (try floatSubScalar(lhs_elem, rhs_elem, scalar_ty, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = float_type.toIntern(), @@ -3236,7 +2879,7 @@ pub fn floatDiv( for (result_data, 0..) |*scalar, i| { const lhs_elem = try lhs.elemValue(mod, i); const rhs_elem = try rhs.elemValue(mod, i); - scalar.* = try (try floatDivScalar(lhs_elem, rhs_elem, scalar_ty, mod)).intern(scalar_ty, mod); + scalar.* = (try floatDivScalar(lhs_elem, rhs_elem, scalar_ty, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = float_type.toIntern(), @@ -3280,7 +2923,7 @@ pub fn floatDivFloor( for (result_data, 0..) |*scalar, i| { const lhs_elem = try lhs.elemValue(mod, i); const rhs_elem = try rhs.elemValue(mod, i); - scalar.* = try (try floatDivFloorScalar(lhs_elem, rhs_elem, scalar_ty, mod)).intern(scalar_ty, mod); + scalar.* = (try floatDivFloorScalar(lhs_elem, rhs_elem, scalar_ty, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = float_type.toIntern(), @@ -3324,7 +2967,7 @@ pub fn floatDivTrunc( for (result_data, 0..) |*scalar, i| { const lhs_elem = try lhs.elemValue(mod, i); const rhs_elem = try rhs.elemValue(mod, i); - scalar.* = try (try floatDivTruncScalar(lhs_elem, rhs_elem, scalar_ty, mod)).intern(scalar_ty, mod); + scalar.* = (try floatDivTruncScalar(lhs_elem, rhs_elem, scalar_ty, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = float_type.toIntern(), @@ -3368,7 +3011,7 @@ pub fn floatMul( for (result_data, 0..) |*scalar, i| { const lhs_elem = try lhs.elemValue(mod, i); const rhs_elem = try rhs.elemValue(mod, i); - scalar.* = try (try floatMulScalar(lhs_elem, rhs_elem, scalar_ty, mod)).intern(scalar_ty, mod); + scalar.* = (try floatMulScalar(lhs_elem, rhs_elem, scalar_ty, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = float_type.toIntern(), @@ -3405,7 +3048,7 @@ pub fn sqrt(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value const scalar_ty = float_type.scalarType(mod); for (result_data, 0..) |*scalar, i| { const elem_val = try val.elemValue(mod, i); - scalar.* = try (try sqrtScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod); + scalar.* = (try sqrtScalar(elem_val, scalar_ty, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = float_type.toIntern(), @@ -3437,7 +3080,7 @@ pub fn sin(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value const scalar_ty = float_type.scalarType(mod); for (result_data, 0..) |*scalar, i| { const elem_val = try val.elemValue(mod, i); - scalar.* = try (try sinScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod); + scalar.* = (try sinScalar(elem_val, scalar_ty, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = float_type.toIntern(), @@ -3469,7 +3112,7 @@ pub fn cos(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value const scalar_ty = float_type.scalarType(mod); for (result_data, 0..) |*scalar, i| { const elem_val = try val.elemValue(mod, i); - scalar.* = try (try cosScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod); + scalar.* = (try cosScalar(elem_val, scalar_ty, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = float_type.toIntern(), @@ -3501,7 +3144,7 @@ pub fn tan(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value const scalar_ty = float_type.scalarType(mod); for (result_data, 0..) |*scalar, i| { const elem_val = try val.elemValue(mod, i); - scalar.* = try (try tanScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod); + scalar.* = (try tanScalar(elem_val, scalar_ty, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = float_type.toIntern(), @@ -3533,7 +3176,7 @@ pub fn exp(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value const scalar_ty = float_type.scalarType(mod); for (result_data, 0..) |*scalar, i| { const elem_val = try val.elemValue(mod, i); - scalar.* = try (try expScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod); + scalar.* = (try expScalar(elem_val, scalar_ty, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = float_type.toIntern(), @@ -3565,7 +3208,7 @@ pub fn exp2(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value const scalar_ty = float_type.scalarType(mod); for (result_data, 0..) |*scalar, i| { const elem_val = try val.elemValue(mod, i); - scalar.* = try (try exp2Scalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod); + scalar.* = (try exp2Scalar(elem_val, scalar_ty, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = float_type.toIntern(), @@ -3597,7 +3240,7 @@ pub fn log(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value const scalar_ty = float_type.scalarType(mod); for (result_data, 0..) |*scalar, i| { const elem_val = try val.elemValue(mod, i); - scalar.* = try (try logScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod); + scalar.* = (try logScalar(elem_val, scalar_ty, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = float_type.toIntern(), @@ -3629,7 +3272,7 @@ pub fn log2(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value const scalar_ty = float_type.scalarType(mod); for (result_data, 0..) |*scalar, i| { const elem_val = try val.elemValue(mod, i); - scalar.* = try (try log2Scalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod); + scalar.* = (try log2Scalar(elem_val, scalar_ty, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = float_type.toIntern(), @@ -3661,7 +3304,7 @@ pub fn log10(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Valu const scalar_ty = float_type.scalarType(mod); for (result_data, 0..) |*scalar, i| { const elem_val = try val.elemValue(mod, i); - scalar.* = try (try log10Scalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod); + scalar.* = (try log10Scalar(elem_val, scalar_ty, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = float_type.toIntern(), @@ -3693,7 +3336,7 @@ pub fn abs(val: Value, ty: Type, arena: Allocator, mod: *Module) !Value { const scalar_ty = ty.scalarType(mod); for (result_data, 0..) |*scalar, i| { const elem_val = try val.elemValue(mod, i); - scalar.* = try (try absScalar(elem_val, scalar_ty, mod, arena)).intern(scalar_ty, mod); + scalar.* = (try absScalar(elem_val, scalar_ty, mod, arena)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = ty.toIntern(), @@ -3744,7 +3387,7 @@ pub fn floor(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Valu const scalar_ty = float_type.scalarType(mod); for (result_data, 0..) |*scalar, i| { const elem_val = try val.elemValue(mod, i); - scalar.* = try (try floorScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod); + scalar.* = (try floorScalar(elem_val, scalar_ty, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = float_type.toIntern(), @@ -3776,7 +3419,7 @@ pub fn ceil(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Value const scalar_ty = float_type.scalarType(mod); for (result_data, 0..) |*scalar, i| { const elem_val = try val.elemValue(mod, i); - scalar.* = try (try ceilScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod); + scalar.* = (try ceilScalar(elem_val, scalar_ty, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = float_type.toIntern(), @@ -3808,7 +3451,7 @@ pub fn round(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Valu const scalar_ty = float_type.scalarType(mod); for (result_data, 0..) |*scalar, i| { const elem_val = try val.elemValue(mod, i); - scalar.* = try (try roundScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod); + scalar.* = (try roundScalar(elem_val, scalar_ty, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = float_type.toIntern(), @@ -3840,7 +3483,7 @@ pub fn trunc(val: Value, float_type: Type, arena: Allocator, mod: *Module) !Valu const scalar_ty = float_type.scalarType(mod); for (result_data, 0..) |*scalar, i| { const elem_val = try val.elemValue(mod, i); - scalar.* = try (try truncScalar(elem_val, scalar_ty, mod)).intern(scalar_ty, mod); + scalar.* = (try truncScalar(elem_val, scalar_ty, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = float_type.toIntern(), @@ -3881,7 +3524,7 @@ pub fn mulAdd( const mulend1_elem = try mulend1.elemValue(mod, i); const mulend2_elem = try mulend2.elemValue(mod, i); const addend_elem = try addend.elemValue(mod, i); - scalar.* = try (try mulAddScalar(scalar_ty, mulend1_elem, mulend2_elem, addend_elem, mod)).intern(scalar_ty, mod); + scalar.* = (try mulAddScalar(scalar_ty, mulend1_elem, mulend2_elem, addend_elem, mod)).toIntern(); } return Value.fromInterned((try mod.intern(.{ .aggregate = .{ .ty = float_type.toIntern(), @@ -3957,98 +3600,26 @@ pub fn intValueBounds(val: Value, mod: *Module) !?[2]Value { }; } -/// This type is not copyable since it may contain pointers to its inner data. -pub const Payload = struct { - tag: Tag, - - pub const Slice = struct { - base: Payload, - data: struct { - ptr: Value, - len: Value, - }, - }; - - pub const Bytes = struct { - base: Payload, - /// Includes the sentinel, if any. - data: []const u8, - }; - - pub const SubValue = struct { - base: Payload, - data: Value, - }; - - pub const Aggregate = struct { - base: Payload, - /// Field values. The types are according to the struct or array type. - /// The length is provided here so that copying a Value does not depend on the Type. - data: []Value, - }; - - pub const Union = struct { - pub const base_tag = Tag.@"union"; - - base: Payload = .{ .tag = base_tag }, - data: Data, - - pub const Data = struct { - tag: ?Value, - val: Value, - }; - }; -}; - pub const BigIntSpace = InternPool.Key.Int.Storage.BigIntSpace; -pub const zero_usize: Value = .{ .ip_index = .zero_usize, .legacy = undefined }; -pub const zero_u8: Value = .{ .ip_index = .zero_u8, .legacy = undefined }; -pub const zero_comptime_int: Value = .{ .ip_index = .zero, .legacy = undefined }; -pub const one_comptime_int: Value = .{ .ip_index = .one, .legacy = undefined }; -pub const negative_one_comptime_int: Value = .{ .ip_index = .negative_one, .legacy = undefined }; -pub const undef: Value = .{ .ip_index = .undef, .legacy = undefined }; -pub const @"void": Value = .{ .ip_index = .void_value, .legacy = undefined }; -pub const @"null": Value = .{ .ip_index = .null_value, .legacy = undefined }; -pub const @"false": Value = .{ .ip_index = .bool_false, .legacy = undefined }; -pub const @"true": Value = .{ .ip_index = .bool_true, .legacy = undefined }; -pub const @"unreachable": Value = .{ .ip_index = .unreachable_value, .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 const empty_struct: Value = .{ .ip_index = .empty_struct, .legacy = undefined }; +pub const zero_usize: Value = .{ .ip_index = .zero_usize }; +pub const zero_u8: Value = .{ .ip_index = .zero_u8 }; +pub const zero_comptime_int: Value = .{ .ip_index = .zero }; +pub const one_comptime_int: Value = .{ .ip_index = .one }; +pub const negative_one_comptime_int: Value = .{ .ip_index = .negative_one }; +pub const undef: Value = .{ .ip_index = .undef }; +pub const @"void": Value = .{ .ip_index = .void_value }; +pub const @"null": Value = .{ .ip_index = .null_value }; +pub const @"false": Value = .{ .ip_index = .bool_false }; +pub const @"true": Value = .{ .ip_index = .bool_true }; +pub const @"unreachable": Value = .{ .ip_index = .unreachable_value }; + +pub const generic_poison: Value = .{ .ip_index = .generic_poison }; +pub const generic_poison_type: Value = .{ .ip_index = .generic_poison_type }; +pub const empty_struct: Value = .{ .ip_index = .empty_struct }; pub fn makeBool(x: bool) Value { return if (x) Value.true else Value.false; } pub const RuntimeIndex = InternPool.RuntimeIndex; - -/// This function is used in the debugger pretty formatters in tools/ to fetch the -/// Tag to Payload mapping to facilitate fancy debug printing for this type. -fn dbHelper(self: *Value, tag_to_payload_map: *map: { - const tags = @typeInfo(Tag).Enum.fields; - var fields: [tags.len]std.builtin.Type.StructField = undefined; - for (&fields, tags) |*field, t| field.* = .{ - .name = t.name ++ "", - .type = *@field(Tag, t.name).Type(), - .default_value = null, - .is_comptime = false, - .alignment = 0, - }; - break :map @Type(.{ .Struct = .{ - .layout = .@"extern", - .fields = &fields, - .decls = &.{}, - .is_tuple = false, - } }); -}) void { - _ = self; - _ = tag_to_payload_map; -} - -comptime { - if (!builtin.strip_debug_info) { - _ = &dbHelper; - } -} diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index e90a68bea5..11c95e318a 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -2216,7 +2216,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif }, else => {}, } - return func.fail("Expected a function, but instead found type '{}'", .{func_val.tag()}); + return func.fail("Expected a function, but instead found '{s}'", .{@tagName(ip.indexToKey(func_val.toIntern()))}); }; const sret = if (first_param_sret) blk: { diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 273358a6d2..8fe19d4e21 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -12258,7 +12258,7 @@ fn genCall(self: *Self, info: union(enum) { switch (switch (func_key) { else => func_key, .ptr => |ptr| switch (ptr.addr) { - .decl => |decl| mod.intern_pool.indexToKey(try mod.declPtr(decl).internValue(mod)), + .decl => |decl| mod.intern_pool.indexToKey(mod.declPtr(decl).val.toIntern()), else => func_key, }, }) { diff --git a/src/codegen.zig b/src/codegen.zig index 5bc0d1a81f..818284a8f0 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -925,7 +925,7 @@ fn genDeclRef( const ptr_bits = target.ptrBitWidth(); const ptr_bytes: u64 = @divExact(ptr_bits, 8); - const decl_index = switch (zcu.intern_pool.indexToKey(try ptr_decl.internValue(zcu))) { + const decl_index = switch (zcu.intern_pool.indexToKey(ptr_decl.val.toIntern())) { .func => |func| func.owner_decl, .extern_func => |extern_func| extern_func.decl, else => ptr_decl_index, diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 32ad38cd4d..d1575feaba 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -2657,7 +2657,7 @@ fn genExports(o: *Object) !void { .anon, .flush => return, }; const decl = mod.declPtr(decl_index); - const tv: TypedValue = .{ .ty = decl.typeOf(mod), .val = Value.fromInterned((try decl.internValue(mod))) }; + const tv: TypedValue = .{ .ty = decl.typeOf(mod), .val = decl.val }; const fwd = o.dg.fwdDeclWriter(); const exports = mod.decl_exports.get(decl_index) orelse return; @@ -2894,7 +2894,7 @@ pub fn genDecl(o: *Object) !void { const mod = o.dg.module; const decl_index = o.dg.pass.decl; const decl = mod.declPtr(decl_index); - const tv: TypedValue = .{ .ty = decl.typeOf(mod), .val = Value.fromInterned((try decl.internValue(mod))) }; + const tv: TypedValue = .{ .ty = decl.typeOf(mod), .val = decl.val }; if (!tv.ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return; if (tv.val.getExternFunc(mod)) |_| { diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index cef6a9f7f3..7bbe4e715a 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -5532,7 +5532,7 @@ pub const FuncGen = struct { const msg_decl_index = mod.panic_messages[@intFromEnum(panic_id)].unwrap().?; const msg_decl = mod.declPtr(msg_decl_index); const msg_len = msg_decl.typeOf(mod).childType(mod).arrayLen(mod); - const msg_ptr = try o.lowerValue(try msg_decl.internValue(mod)); + const msg_ptr = try o.lowerValue(msg_decl.val.toIntern()); const null_opt_addr_global = try fg.resolveNullOptUsize(); const target = mod.getTarget(); const llvm_usize = try o.lowerType(Type.usize); diff --git a/src/type.zig b/src/type.zig index 8a79cb445c..a382a5ad97 100644 --- a/src/type.zig +++ b/src/type.zig @@ -2481,7 +2481,7 @@ pub const Type = struct { } const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[i]); if (try field_ty.onePossibleValue(mod)) |field_opv| { - field_val.* = try field_opv.intern(field_ty, mod); + field_val.* = field_opv.toIntern(); } else return null; } -- cgit v1.2.3 From 26a94e8481385619ae049143dd67e551f333fa3f Mon Sep 17 00:00:00 2001 From: mlugg Date: Tue, 26 Mar 2024 04:06:39 +0000 Subject: Zcu: eliminate `Decl.alive` field Legacy anon decls now have three uses: * Type owner decls * Function owner decls * `@export` and `@extern` Therefore, there are no longer any cases where we wish to explicitly omit legacy anon decls from the binary. This means we can remove the concept of an "alive" vs "dead" `Decl`, which also allows us to remove the separate `anon_work_queue` in `Compilation`. --- src/Compilation.zig | 19 +------------- src/InternPool.zig | 1 - src/Module.zig | 64 +-------------------------------------------- src/Sema.zig | 2 -- src/arch/wasm/CodeGen.zig | 2 -- src/arch/x86_64/CodeGen.zig | 2 -- src/codegen.zig | 4 --- src/codegen/c.zig | 1 - src/codegen/llvm.zig | 7 ----- src/codegen/spirv.zig | 1 - 10 files changed, 2 insertions(+), 101 deletions(-) (limited to 'src/Module.zig') diff --git a/src/Compilation.zig b/src/Compilation.zig index b95a50cc59..5bbca51ede 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -102,7 +102,6 @@ link_errors: std.ArrayListUnmanaged(link.File.ErrorMsg) = .{}, lld_errors: std.ArrayListUnmanaged(LldError) = .{}, work_queue: std.fifo.LinearFifo(Job, .Dynamic), -anon_work_queue: std.fifo.LinearFifo(Job, .Dynamic), /// These jobs are to invoke the Clang compiler to create an object file, which /// gets linked with the Compilation. @@ -1417,7 +1416,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil .emit_llvm_ir = options.emit_llvm_ir, .emit_llvm_bc = options.emit_llvm_bc, .work_queue = std.fifo.LinearFifo(Job, .Dynamic).init(gpa), - .anon_work_queue = std.fifo.LinearFifo(Job, .Dynamic).init(gpa), .c_object_work_queue = std.fifo.LinearFifo(*CObject, .Dynamic).init(gpa), .win32_resource_work_queue = if (build_options.only_core_functionality) {} else std.fifo.LinearFifo(*Win32Resource, .Dynamic).init(gpa), .astgen_work_queue = std.fifo.LinearFifo(*Module.File, .Dynamic).init(gpa), @@ -1840,7 +1838,6 @@ pub fn destroy(comp: *Compilation) void { if (comp.module) |zcu| zcu.deinit(); comp.cache_use.deinit(); comp.work_queue.deinit(); - comp.anon_work_queue.deinit(); comp.c_object_work_queue.deinit(); if (!build_options.only_core_functionality) { comp.win32_resource_work_queue.deinit(); @@ -3354,18 +3351,11 @@ pub fn performAllTheWork( mod.sema_prog_node = undefined; }; - // In this main loop we give priority to non-anonymous Decls in the work queue, so - // that they can establish references to anonymous Decls, setting alive=true in the - // backend, preventing anonymous Decls from being prematurely destroyed. while (true) { if (comp.work_queue.readItem()) |work_item| { try processOneJob(comp, work_item, main_progress_node); continue; } - if (comp.anon_work_queue.readItem()) |work_item| { - try processOneJob(comp, work_item, main_progress_node); - continue; - } if (comp.module) |zcu| { // If there's no work queued, check if there's anything outdated // which we need to work on, and queue it if so. @@ -3413,14 +3403,7 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v assert(decl.has_tv); - if (decl.alive) { - try module.linkerUpdateDecl(decl_index); - return; - } - - // Instead of sending this decl to the linker, we actually will delete it - // because we found out that it in fact was never referenced. - module.deleteUnusedDecl(decl_index); + try module.linkerUpdateDecl(decl_index); return; }, } diff --git a/src/InternPool.zig b/src/InternPool.zig index e4132e577e..63d29d3760 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -6740,7 +6740,6 @@ fn finishFuncInstance( .zir_decl_index = fn_owner_decl.zir_decl_index, .is_pub = fn_owner_decl.is_pub, .is_exported = fn_owner_decl.is_exported, - .alive = true, .kind = .anon, }); errdefer ip.destroyDecl(gpa, decl_index); diff --git a/src/Module.zig b/src/Module.zig index 4391472fa5..b3abefb576 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -394,15 +394,6 @@ pub const Decl = struct { is_pub: bool, /// Whether the corresponding AST decl has a `export` keyword. is_exported: bool, - /// Flag used by garbage collection to mark and sweep. - /// Decls which correspond to an AST node always have this field set to `true`. - /// Anonymous Decls are initialized with this field set to `false` and then it - /// is the responsibility of machine code backends to mark it `true` whenever - /// a `decl_ref` Value is encountered that points to this Decl. - /// When the `codegen_decl` job is encountered in the main work queue, if the - /// Decl is marked alive, then it sends the Decl to the linker. Otherwise it - /// deletes the Decl on the spot. - alive: bool, /// If true `name` is already fully qualified. name_fully_qualified: bool = false, /// What kind of a declaration is this. @@ -3525,7 +3516,6 @@ fn semaFile(mod: *Module, file: *File) SemaError!void { new_decl.is_exported = false; new_decl.alignment = .none; new_decl.@"linksection" = .none; - new_decl.alive = true; // This Decl corresponds to a File and is therefore always alive. new_decl.analysis = .in_progress; if (file.status != .success_zir) { @@ -4375,7 +4365,6 @@ fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void const decl = zcu.declPtr(decl_index); const was_exported = decl.is_exported; assert(decl.kind == kind); // ZIR tracking should preserve this - assert(decl.alive); decl.name = decl_name; decl.src_node = decl_node; decl.src_line = line; @@ -4392,7 +4381,6 @@ fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void new_decl.is_pub = declaration.flags.is_pub; new_decl.is_exported = declaration.flags.is_export; new_decl.zir_decl_index = tracked_inst.toOptional(); - new_decl.alive = true; // This Decl corresponds to an AST node and is therefore always alive. break :decl_index .{ false, new_decl_index }; }; @@ -4470,12 +4458,8 @@ pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void { /// Finalize the creation of an anon decl. pub fn finalizeAnonDecl(mod: *Module, decl_index: Decl.Index) Allocator.Error!void { - // The Decl starts off with alive=false and the codegen backend will set alive=true - // if the Decl is referenced by an instruction or another constant. Otherwise, - // the Decl will be garbage collected by the `codegen_decl` task instead of sent - // to the linker. if (mod.declPtr(decl_index).typeOf(mod).isFnOrHasRuntimeBits(mod)) { - try mod.comp.anon_work_queue.writeItem(.{ .codegen_decl = decl_index }); + try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl_index }); } } @@ -4815,7 +4799,6 @@ pub fn allocateNewDecl( .zir_decl_index = .none, .is_pub = false, .is_exported = false, - .alive = false, .kind = .anon, }); @@ -5582,51 +5565,6 @@ fn reportRetryableFileError( gop.value_ptr.* = err_msg; } -pub fn markReferencedDeclsAlive(mod: *Module, val: Value) Allocator.Error!void { - switch (mod.intern_pool.indexToKey(val.toIntern())) { - .variable => |variable| try mod.markDeclIndexAlive(variable.decl), - .extern_func => |extern_func| try mod.markDeclIndexAlive(extern_func.decl), - .func => |func| try mod.markDeclIndexAlive(func.owner_decl), - .error_union => |error_union| switch (error_union.val) { - .err_name => {}, - .payload => |payload| try mod.markReferencedDeclsAlive(Value.fromInterned(payload)), - }, - .slice => |slice| { - try mod.markReferencedDeclsAlive(Value.fromInterned(slice.ptr)); - try mod.markReferencedDeclsAlive(Value.fromInterned(slice.len)); - }, - .ptr => |ptr| switch (ptr.addr) { - .decl => |decl| try mod.markDeclIndexAlive(decl), - .anon_decl => {}, - .int, .comptime_field, .comptime_alloc => {}, - .eu_payload, .opt_payload => |parent| try mod.markReferencedDeclsAlive(Value.fromInterned(parent)), - .elem, .field => |base_index| try mod.markReferencedDeclsAlive(Value.fromInterned(base_index.base)), - }, - .opt => |opt| if (opt.val != .none) try mod.markReferencedDeclsAlive(Value.fromInterned(opt.val)), - .aggregate => |aggregate| for (aggregate.storage.values()) |elem| - try mod.markReferencedDeclsAlive(Value.fromInterned(elem)), - .un => |un| { - if (un.tag != .none) try mod.markReferencedDeclsAlive(Value.fromInterned(un.tag)); - try mod.markReferencedDeclsAlive(Value.fromInterned(un.val)); - }, - else => {}, - } -} - -pub fn markDeclAlive(mod: *Module, decl: *Decl) Allocator.Error!void { - if (decl.alive) return; - decl.alive = true; - - // This is the first time we are marking this Decl alive. We must - // therefore recurse into its value and mark any Decl it references - // as also alive, so that any Decl referenced does not get garbage collected. - try mod.markReferencedDeclsAlive(decl.val); -} - -fn markDeclIndexAlive(mod: *Module, decl_index: Decl.Index) Allocator.Error!void { - return mod.markDeclAlive(mod.declPtr(decl_index)); -} - pub fn addGlobalAssembly(mod: *Module, decl_index: Decl.Index, source: []const u8) !void { const gop = try mod.global_assembly.getOrPut(mod.gpa, decl_index); if (gop.found_existing) { diff --git a/src/Sema.zig b/src/Sema.zig index c0b78c3e1d..8dfd0248f5 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -6445,8 +6445,6 @@ pub fn analyzeExport( return sema.fail(block, src, "export target cannot be extern", .{}); } - // This decl is alive no matter what, since it's being exported - try mod.markDeclAlive(exported_decl); try sema.maybeQueueFuncBodyAnalysis(exported_decl_index); try addExport(mod, .{ diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index 11c95e318a..be7f4ab66a 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -3121,7 +3121,6 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue fn lowerParentPtrDecl(func: *CodeGen, ptr_val: Value, decl_index: InternPool.DeclIndex, offset: u32) InnerError!WValue { const mod = func.bin_file.base.comp.module.?; const decl = mod.declPtr(decl_index); - try mod.markDeclAlive(decl); const ptr_ty = try mod.singleMutPtrType(decl.typeOf(mod)); return func.lowerDeclRefValue(.{ .ty = ptr_ty, .val = ptr_val }, decl_index, offset); } @@ -3178,7 +3177,6 @@ fn lowerDeclRefValue(func: *CodeGen, tv: TypedValue, decl_index: InternPool.Decl return WValue{ .imm32 = 0xaaaaaaaa }; } - try mod.markDeclAlive(decl); const atom_index = try func.bin_file.getOrCreateAtomForDecl(decl_index); const atom = func.bin_file.getAtom(atom_index); diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 8fe19d4e21..c5b815b429 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -12263,7 +12263,6 @@ fn genCall(self: *Self, info: union(enum) { }, }) { .func => |func| { - try mod.markDeclAlive(mod.declPtr(func.owner_decl)); if (self.bin_file.cast(link.File.Elf)) |elf_file| { const sym_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, func.owner_decl); const sym = elf_file.symbol(sym_index); @@ -12323,7 +12322,6 @@ fn genCall(self: *Self, info: union(enum) { }, .extern_func => |extern_func| { const owner_decl = mod.declPtr(extern_func.decl); - try mod.markDeclAlive(owner_decl); const lib_name = mod.intern_pool.stringToSliceUnwrap(extern_func.lib_name); const decl_name = mod.intern_pool.stringToSlice(owner_decl.name); try self.genExternSymbolRef(.call, lib_name, decl_name); diff --git a/src/codegen.zig b/src/codegen.zig index 818284a8f0..48a7f840b2 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -835,8 +835,6 @@ fn lowerDeclRef( return Result.ok; } - try zcu.markDeclAlive(decl); - const vaddr = try lf.getDeclVAddr(decl_index, .{ .parent_atom_index = reloc_info.parent_atom_index, .offset = code.items.len, @@ -958,8 +956,6 @@ fn genDeclRef( } } - try zcu.markDeclAlive(decl); - const decl_namespace = zcu.namespacePtr(decl.src_namespace); const single_threaded = decl_namespace.file_scope.mod.single_threaded; const is_threadlocal = tv.val.isPtrToThreadLocal(zcu) and !single_threaded; diff --git a/src/codegen/c.zig b/src/codegen/c.zig index d1575feaba..ed506cfdfe 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -2010,7 +2010,6 @@ pub const DeclGen = struct { fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: InternPool.DeclIndex, export_index: u32) !void { const mod = dg.module; const decl = mod.declPtr(decl_index); - try mod.markDeclAlive(decl); if (mod.decl_exports.get(decl_index)) |exports| { try writer.print("{ }", .{ diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 7bbe4e715a..421c767bd8 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -3722,15 +3722,11 @@ pub const Object = struct { => unreachable, // non-runtime values .extern_func => |extern_func| { const fn_decl_index = extern_func.decl; - const fn_decl = mod.declPtr(fn_decl_index); - try mod.markDeclAlive(fn_decl); const function_index = try o.resolveLlvmFunction(fn_decl_index); return function_index.ptrConst(&o.builder).global.toConst(); }, .func => |func| { const fn_decl_index = func.owner_decl; - const fn_decl = mod.declPtr(fn_decl_index); - try mod.markDeclAlive(fn_decl); const function_index = try o.resolveLlvmFunction(fn_decl_index); return function_index.ptrConst(&o.builder).global.toConst(); }, @@ -4262,7 +4258,6 @@ pub const Object = struct { fn lowerParentPtrDecl(o: *Object, decl_index: InternPool.DeclIndex) Allocator.Error!Builder.Constant { const mod = o.module; const decl = mod.declPtr(decl_index); - try mod.markDeclAlive(decl); const ptr_ty = try mod.singleMutPtrType(decl.typeOf(mod)); return o.lowerDeclRefValue(ptr_ty, decl_index); } @@ -4455,8 +4450,6 @@ pub const Object = struct { if ((!is_fn_body and !decl_ty.hasRuntimeBits(mod)) or (is_fn_body and mod.typeToFunc(decl_ty).?.is_generic)) return o.lowerPtrToVoid(ty); - try mod.markDeclAlive(decl); - const llvm_global = if (is_fn_body) (try o.resolveLlvmFunction(decl_index)).ptrConst(&o.builder).global else diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 17b44806e2..3e560b0918 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -255,7 +255,6 @@ pub const Object = struct { pub fn resolveDecl(self: *Object, mod: *Module, decl_index: InternPool.DeclIndex) !SpvModule.Decl.Index { const decl = mod.declPtr(decl_index); assert(decl.has_tv); // TODO: Do we need to handle a situation where this is false? - try mod.markDeclAlive(decl); const entry = try self.decl_link.getOrPut(self.gpa, decl_index); if (!entry.found_existing) { -- cgit v1.2.3 From 920f2c7794ba9b3eb3f3b78c60a0caf544f68927 Mon Sep 17 00:00:00 2001 From: mlugg Date: Tue, 26 Mar 2024 04:11:05 +0000 Subject: compiler: minor cleanups --- src/Module.zig | 2 +- src/Sema.zig | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/Module.zig') diff --git a/src/Module.zig b/src/Module.zig index b3abefb576..419205c30f 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -477,7 +477,7 @@ pub const Decl = struct { pub fn typeOf(decl: Decl, zcu: *const Zcu) Type { assert(decl.has_tv); - return Type.fromInterned(zcu.intern_pool.typeOf(decl.val.toIntern())); + return decl.val.typeOf(zcu); } pub fn typedValue(decl: Decl, zcu: *const Zcu) error{AnalysisFail}!TypedValue { diff --git a/src/Sema.zig b/src/Sema.zig index 8dfd0248f5..436715d54d 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -32431,7 +32431,7 @@ fn optRefValue(sema: *Sema, opt_val: ?Value) !Value { return Value.fromInterned((try mod.intern(.{ .opt = .{ .ty = (try mod.optionalType(ptr_anyopaque_ty.toIntern())).toIntern(), .val = if (opt_val) |val| (try mod.getCoerced( - Value.fromInterned((try sema.refValue(val.toIntern()))), + Value.fromInterned(try sema.refValue(val.toIntern())), ptr_anyopaque_ty, )).toIntern() else .none, } }))); @@ -36952,7 +36952,7 @@ fn semaStructFieldInits( }); }; - if (Value.fromInterned(default_val.toIntern()).canMutateComptimeVarState(mod)) { + if (default_val.canMutateComptimeVarState(mod)) { const init_src = mod.fieldSrcLoc(decl_index, .{ .index = field_i, .range = .value, @@ -39050,11 +39050,11 @@ fn sliceToIpString( ) CompileError!InternPool.NullTerminatedString { const zcu = sema.mod; const ip = &zcu.intern_pool; - const slice_ty = Type.fromInterned(ip.typeOf(slice_val.toIntern())); + const slice_ty = slice_val.typeOf(zcu); assert(slice_ty.isSlice(zcu)); assert(slice_ty.childType(zcu).toIntern() == .u8_type); const array_val = try sema.derefSliceAsArray(block, src, slice_val, reason); - const array_ty = Type.fromInterned(ip.typeOf(array_val.toIntern())); + const array_ty = array_val.typeOf(zcu); return array_val.toIpString(array_ty, zcu); } @@ -39084,7 +39084,7 @@ fn maybeDerefSliceAsArray( ) CompileError!?Value { const zcu = sema.mod; const ip = &zcu.intern_pool; - assert(Type.fromInterned(ip.typeOf(slice_val.toIntern())).isSlice(zcu)); + assert(slice_val.typeOf(zcu).isSlice(zcu)); const slice = switch (ip.indexToKey(slice_val.toIntern())) { .undef => return sema.failWithUseOfUndef(block, src), .slice => |slice| slice, -- cgit v1.2.3 From 0d8c7ae0078e970af39a3be760f25c51829b44f9 Mon Sep 17 00:00:00 2001 From: mlugg Date: Tue, 26 Mar 2024 04:19:50 +0000 Subject: Zcu.Decl: replace `typedValue` with `valueOrFail` Now that the legacy `Value` representation is eliminated, we can begin to phase out the redundant `TypedValue` type. --- src/Module.zig | 14 ++++---------- src/Sema.zig | 30 +++++++++++++----------------- src/codegen/llvm.zig | 2 +- 3 files changed, 18 insertions(+), 28 deletions(-) (limited to 'src/Module.zig') diff --git a/src/Module.zig b/src/Module.zig index 419205c30f..6f65cf8d2e 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -480,17 +480,11 @@ pub const Decl = struct { return decl.val.typeOf(zcu); } - pub fn typedValue(decl: Decl, zcu: *const Zcu) error{AnalysisFail}!TypedValue { + /// Small wrapper for Sema to use over direct access to the `val` field. + /// If the value is not populated, instead returns `error.AnalysisFail`. + pub fn valueOrFail(decl: Decl) error{AnalysisFail}!Value { if (!decl.has_tv) return error.AnalysisFail; - return .{ - .ty = decl.typeOf(zcu), - .val = decl.val, - }; - } - - pub fn isFunction(decl: Decl, zcu: *const Zcu) !bool { - const tv = try decl.typedValue(zcu); - return tv.ty.zigTypeTag(zcu) == .Fn; + return decl.val; } /// If the Decl owns its value and it is a struct, return it, diff --git a/src/Sema.zig b/src/Sema.zig index 436715d54d..0ff162ed2a 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -26660,13 +26660,12 @@ fn prepareSimplePanic(sema: *Sema, block: *Block) !void { // decl_index may be an alias; we must find the decl that actually // owns the function. try sema.ensureDeclAnalyzed(decl_index); - const tv = try mod.declPtr(decl_index).typedValue(mod); + const fn_val = try mod.declPtr(decl_index).valueOrFail(); try sema.declareDependency(.{ .decl_val = decl_index }); - assert(tv.ty.zigTypeTag(mod) == .Fn); - assert(try sema.fnHasRuntimeBits(tv.ty)); - const func_index = tv.val.toIntern(); - try mod.ensureFuncBodyAnalysisQueued(func_index); - mod.panic_func_index = func_index; + assert(fn_val.typeOf(mod).zigTypeTag(mod) == .Fn); + assert(try sema.fnHasRuntimeBits(fn_val.typeOf(mod))); + try mod.ensureFuncBodyAnalysisQueued(fn_val.toIntern()); + mod.panic_func_index = fn_val.toIntern(); } if (mod.null_stack_trace == .none) { @@ -32449,8 +32448,8 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: InternPool.DeclIndex, analyze_fn const mod = sema.mod; try sema.ensureDeclAnalyzed(decl_index); - const decl_tv = try mod.declPtr(decl_index).typedValue(mod); - const owner_decl = mod.declPtr(switch (mod.intern_pool.indexToKey(decl_tv.val.toIntern())) { + const decl_val = try mod.declPtr(decl_index).valueOrFail(); + const owner_decl = mod.declPtr(switch (mod.intern_pool.indexToKey(decl_val.toIntern())) { .variable => |variable| variable.decl, .extern_func => |extern_func| extern_func.decl, .func => |func| func.owner_decl, @@ -32459,10 +32458,10 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: InternPool.DeclIndex, analyze_fn // TODO: if this is a `decl_ref` of a non-variable decl, only depend on decl type try sema.declareDependency(.{ .decl_val = decl_index }); const ptr_ty = try sema.ptrType(.{ - .child = decl_tv.ty.toIntern(), + .child = decl_val.typeOf(mod).toIntern(), .flags = .{ .alignment = owner_decl.alignment, - .is_const = if (decl_tv.val.getVariable(mod)) |variable| variable.is_const else true, + .is_const = if (decl_val.getVariable(mod)) |variable| variable.is_const else true, .address_space = owner_decl.@"addrspace", }, }); @@ -32478,12 +32477,10 @@ fn analyzeDeclRefInner(sema: *Sema, decl_index: InternPool.DeclIndex, analyze_fn fn maybeQueueFuncBodyAnalysis(sema: *Sema, decl_index: InternPool.DeclIndex) !void { const mod = sema.mod; const decl = mod.declPtr(decl_index); - const tv = try decl.typedValue(mod); - if (tv.ty.zigTypeTag(mod) != .Fn) return; - if (!try sema.fnHasRuntimeBits(tv.ty)) return; - const func_index = tv.val.toIntern(); - if (!mod.intern_pool.isFuncBody(func_index)) return; // undef or extern function - try mod.ensureFuncBodyAnalysisQueued(func_index); + const decl_val = try decl.valueOrFail(); + if (!mod.intern_pool.isFuncBody(decl_val.toIntern())) return; + if (!try sema.fnHasRuntimeBits(decl_val.typeOf(mod))) return; + try mod.ensureFuncBodyAnalysisQueued(decl_val.toIntern()); } fn analyzeRef( @@ -39049,7 +39046,6 @@ fn sliceToIpString( reason: NeededComptimeReason, ) CompileError!InternPool.NullTerminatedString { const zcu = sema.mod; - const ip = &zcu.intern_pool; const slice_ty = slice_val.typeOf(zcu); assert(slice_ty.isSlice(zcu)); assert(slice_ty.childType(zcu).toIntern() == .u8_type); diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 421c767bd8..f4d91c2ebb 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1762,7 +1762,7 @@ pub const Object = struct { const decl_name = decl_name: { const decl_name = mod.intern_pool.stringToSlice(decl.name); - if (mod.getTarget().isWasm() and try decl.isFunction(mod)) { + if (mod.getTarget().isWasm() and decl.val.typeOf(mod).zigTypeTag(mod) == .Fn) { if (mod.intern_pool.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| { if (!std.mem.eql(u8, lib_name, "c")) { break :decl_name try self.builder.strtabStringFmt("{s}|{s}", .{ decl_name, lib_name }); -- cgit v1.2.3 From b8d114a29e341a0cbd4c22cf02cb1588b0154446 Mon Sep 17 00:00:00 2001 From: mlugg Date: Tue, 26 Mar 2024 04:39:01 +0000 Subject: Zcu: use `Value` instead of `TypedValue` when initializing legacy anon decls Also removes some unnecessary uses of legacy anon decls for constructing the array of test functions for the test runner. --- src/Module.zig | 74 +++++++++------------------- src/Sema.zig | 152 ++++++++++++++++++++++++++++++++++++--------------------- 2 files changed, 121 insertions(+), 105 deletions(-) (limited to 'src/Module.zig') diff --git a/src/Module.zig b/src/Module.zig index 6f65cf8d2e..044c4fb45b 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -22,7 +22,6 @@ const Compilation = @import("Compilation.zig"); const Cache = std.Build.Cache; const Value = @import("Value.zig"); const Type = @import("type.zig").Type; -const TypedValue = @import("TypedValue.zig"); const Package = @import("Package.zig"); const link = @import("link.zig"); const Air = @import("Air.zig"); @@ -4827,40 +4826,18 @@ pub fn errorSetBits(mod: *Module) u16 { return std.math.log2_int_ceil(ErrorInt, mod.error_limit + 1); // +1 for no error } -pub fn createAnonymousDecl(mod: *Module, block: *Sema.Block, typed_value: TypedValue) !Decl.Index { - const src_decl = mod.declPtr(block.src_decl); - return mod.createAnonymousDeclFromDecl(src_decl, block.namespace, typed_value); -} - -pub fn createAnonymousDeclFromDecl( - mod: *Module, - src_decl: *Decl, - namespace: Namespace.Index, - tv: TypedValue, -) !Decl.Index { - const new_decl_index = try mod.allocateNewDecl(namespace, src_decl.src_node); - errdefer mod.destroyDecl(new_decl_index); - const name = try mod.intern_pool.getOrPutStringFmt(mod.gpa, "{}__anon_{d}", .{ - src_decl.name.fmt(&mod.intern_pool), @intFromEnum(new_decl_index), - }); - try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, tv, name); - return new_decl_index; -} - pub fn initNewAnonDecl( mod: *Module, new_decl_index: Decl.Index, src_line: u32, - typed_value: TypedValue, + val: Value, name: InternPool.NullTerminatedString, ) Allocator.Error!void { - assert(typed_value.ty.toIntern() == mod.intern_pool.typeOf(typed_value.val.toIntern())); - const new_decl = mod.declPtr(new_decl_index); new_decl.name = name; new_decl.src_line = src_line; - new_decl.val = typed_value.val; + new_decl.val = val; new_decl.alignment = .none; new_decl.@"linksection" = .none; new_decl.has_tv = true; @@ -5391,7 +5368,7 @@ pub fn populateTestFunctions( const decl = mod.declPtr(decl_index); const test_fn_ty = decl.typeOf(mod).slicePtrFieldType(mod).childType(mod); - const array_decl_index = d: { + const array_anon_decl: InternPool.Key.Ptr.Addr.AnonDecl = array: { // Add mod.test_functions to an array decl then make the test_functions // decl reference it as a slice. const test_fn_vals = try gpa.alloc(InternPool.Index, mod.test_functions.count()); @@ -5401,21 +5378,20 @@ pub fn populateTestFunctions( const test_decl = mod.declPtr(test_decl_index); const test_decl_name = try gpa.dupe(u8, ip.stringToSlice(try test_decl.fullyQualifiedName(mod))); defer gpa.free(test_decl_name); - const test_name_decl_index = n: { - const test_name_decl_ty = try mod.arrayType(.{ + const test_name_anon_decl: InternPool.Key.Ptr.Addr.AnonDecl = n: { + const test_name_ty = try mod.arrayType(.{ .len = test_decl_name.len, .child = .u8_type, }); - const test_name_decl_index = try mod.createAnonymousDeclFromDecl(decl, decl.src_namespace, .{ - .ty = test_name_decl_ty, - .val = Value.fromInterned((try mod.intern(.{ .aggregate = .{ - .ty = test_name_decl_ty.toIntern(), - .storage = .{ .bytes = test_decl_name }, - } }))), - }); - break :n test_name_decl_index; + const test_name_val = try mod.intern(.{ .aggregate = .{ + .ty = test_name_ty.toIntern(), + .storage = .{ .bytes = test_decl_name }, + } }); + break :n .{ + .orig_ty = (try mod.singleConstPtrType(test_name_ty)).toIntern(), + .val = test_name_val, + }; }; - try mod.linkerUpdateDecl(test_name_decl_index); const test_fn_fields = .{ // name @@ -5423,7 +5399,7 @@ pub fn populateTestFunctions( .ty = .slice_const_u8_type, .ptr = try mod.intern(.{ .ptr = .{ .ty = .manyptr_const_u8_type, - .addr = .{ .decl = test_name_decl_index }, + .addr = .{ .anon_decl = test_name_anon_decl }, } }), .len = try mod.intern(.{ .int = .{ .ty = .usize_type, @@ -5447,22 +5423,20 @@ pub fn populateTestFunctions( } }); } - const array_decl_ty = try mod.arrayType(.{ + const array_ty = try mod.arrayType(.{ .len = test_fn_vals.len, .child = test_fn_ty.toIntern(), .sentinel = .none, }); - const array_decl_index = try mod.createAnonymousDeclFromDecl(decl, decl.src_namespace, .{ - .ty = array_decl_ty, - .val = Value.fromInterned((try mod.intern(.{ .aggregate = .{ - .ty = array_decl_ty.toIntern(), - .storage = .{ .elems = test_fn_vals }, - } }))), - }); - - break :d array_decl_index; + const array_val = try mod.intern(.{ .aggregate = .{ + .ty = array_ty.toIntern(), + .storage = .{ .elems = test_fn_vals }, + } }); + break :array .{ + .orig_ty = (try mod.singleConstPtrType(array_ty)).toIntern(), + .val = array_val, + }; }; - try mod.linkerUpdateDecl(array_decl_index); { const new_ty = try mod.ptrType(.{ @@ -5477,7 +5451,7 @@ pub fn populateTestFunctions( .ty = new_ty.toIntern(), .ptr = try mod.intern(.{ .ptr = .{ .ty = new_ty.slicePtrFieldType(mod).toIntern(), - .addr = .{ .decl = array_decl_index }, + .addr = .{ .anon_decl = array_anon_decl }, } }), .len = (try mod.intValue(Type.usize, mod.test_functions.count())).toIntern(), } }); diff --git a/src/Sema.zig b/src/Sema.zig index 0ff162ed2a..8c47a39f78 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -2825,10 +2825,14 @@ fn zirStructDecl( }); errdefer wip_ty.cancel(ip); - const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ - .ty = Type.type, - .val = Value.fromInterned(wip_ty.index), - }, small.name_strategy, "struct", inst); + const new_decl_index = try sema.createAnonymousDeclTypeNamed( + block, + src, + Value.fromInterned(wip_ty.index), + small.name_strategy, + "struct", + inst, + ); mod.declPtr(new_decl_index).owns_tv = true; errdefer mod.abortAnonDecl(new_decl_index); @@ -2861,7 +2865,7 @@ fn createAnonymousDeclTypeNamed( sema: *Sema, block: *Block, src: LazySrcLoc, - typed_value: TypedValue, + val: Value, name_strategy: Zir.Inst.NameStrategy, anon_prefix: []const u8, inst: ?Zir.Inst.Index, @@ -2887,12 +2891,12 @@ fn createAnonymousDeclTypeNamed( const name = mod.intern_pool.getOrPutStringFmt(gpa, "{}__{s}_{d}", .{ src_decl.name.fmt(&mod.intern_pool), anon_prefix, @intFromEnum(new_decl_index), }) catch unreachable; - try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, typed_value, name); + try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, val, name); return new_decl_index; }, .parent => { const name = mod.declPtr(block.src_decl).name; - try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, typed_value, name); + try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, val, name); return new_decl_index; }, .func => { @@ -2915,7 +2919,7 @@ fn createAnonymousDeclTypeNamed( // function and the name doesn't matter since it will later // result in a compile error. const arg_val = sema.resolveConstValue(block, .unneeded, arg, undefined) catch - return sema.createAnonymousDeclTypeNamed(block, src, typed_value, .anon, anon_prefix, null); + return sema.createAnonymousDeclTypeNamed(block, src, val, .anon, anon_prefix, null); if (arg_i != 0) try writer.writeByte(','); try writer.print("{}", .{arg_val.fmtValue(sema.typeOf(arg), sema.mod)}); @@ -2928,7 +2932,7 @@ fn createAnonymousDeclTypeNamed( try writer.writeByte(')'); const name = try mod.intern_pool.getOrPutString(gpa, buf.items); - try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, typed_value, name); + try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, val, name); return new_decl_index; }, .dbg_var => { @@ -2943,12 +2947,12 @@ fn createAnonymousDeclTypeNamed( src_decl.name.fmt(&mod.intern_pool), zir_data[i].str_op.getStr(sema.code), }); - try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, typed_value, name); + try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, val, name); return new_decl_index; }, else => {}, }; - return sema.createAnonymousDeclTypeNamed(block, src, typed_value, .anon, anon_prefix, null); + return sema.createAnonymousDeclTypeNamed(block, src, val, .anon, anon_prefix, null); }, } } @@ -3048,10 +3052,14 @@ fn zirEnumDecl( errdefer if (!done) wip_ty.cancel(ip); - const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ - .ty = Type.type, - .val = Value.fromInterned(wip_ty.index), - }, small.name_strategy, "enum", inst); + const new_decl_index = try sema.createAnonymousDeclTypeNamed( + block, + src, + Value.fromInterned(wip_ty.index), + small.name_strategy, + "enum", + inst, + ); const new_decl = mod.declPtr(new_decl_index); new_decl.owns_tv = true; errdefer if (!done) mod.abortAnonDecl(new_decl_index); @@ -3315,10 +3323,14 @@ fn zirUnionDecl( }); errdefer wip_ty.cancel(ip); - const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ - .ty = Type.type, - .val = Value.fromInterned(wip_ty.index), - }, small.name_strategy, "union", inst); + const new_decl_index = try sema.createAnonymousDeclTypeNamed( + block, + src, + Value.fromInterned(wip_ty.index), + small.name_strategy, + "union", + inst, + ); mod.declPtr(new_decl_index).owns_tv = true; errdefer mod.abortAnonDecl(new_decl_index); @@ -3399,10 +3411,14 @@ fn zirOpaqueDecl( }; errdefer wip_ty.cancel(ip); - const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ - .ty = Type.type, - .val = Value.fromInterned(wip_ty.index), - }, small.name_strategy, "opaque", inst); + const new_decl_index = try sema.createAnonymousDeclTypeNamed( + block, + src, + Value.fromInterned(wip_ty.index), + small.name_strategy, + "opaque", + inst, + ); mod.declPtr(new_decl_index).owns_tv = true; errdefer mod.abortAnonDecl(new_decl_index); @@ -3462,10 +3478,14 @@ fn zirErrorSetDecl( const error_set_ty = try mod.errorSetFromUnsortedNames(names.keys()); - const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ - .ty = Type.type, - .val = error_set_ty.toValue(), - }, name_strategy, "error", inst); + const new_decl_index = try sema.createAnonymousDeclTypeNamed( + block, + src, + error_set_ty.toValue(), + name_strategy, + "error", + inst, + ); const new_decl = mod.declPtr(new_decl_index); new_decl.owns_tv = true; errdefer mod.abortAnonDecl(new_decl_index); @@ -21490,10 +21510,14 @@ fn zirReify( }; errdefer wip_ty.cancel(ip); - const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ - .ty = Type.type, - .val = Value.fromInterned(wip_ty.index), - }, name_strategy, "opaque", inst); + const new_decl_index = try sema.createAnonymousDeclTypeNamed( + block, + src, + Value.fromInterned(wip_ty.index), + name_strategy, + "opaque", + inst, + ); mod.declPtr(new_decl_index).owns_tv = true; errdefer mod.abortAnonDecl(new_decl_index); @@ -21686,10 +21710,14 @@ fn reifyEnum( return sema.fail(block, src, "Type.Enum.tag_type must be an integer type", .{}); } - const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ - .ty = Type.type, - .val = Value.fromInterned(wip_ty.index), - }, name_strategy, "enum", inst); + const new_decl_index = try sema.createAnonymousDeclTypeNamed( + block, + src, + Value.fromInterned(wip_ty.index), + name_strategy, + "enum", + inst, + ); mod.declPtr(new_decl_index).owns_tv = true; errdefer mod.abortAnonDecl(new_decl_index); @@ -21829,10 +21857,14 @@ fn reifyUnion( }; errdefer wip_ty.cancel(ip); - const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ - .ty = Type.type, - .val = Value.fromInterned(wip_ty.index), - }, name_strategy, "union", inst); + const new_decl_index = try sema.createAnonymousDeclTypeNamed( + block, + src, + Value.fromInterned(wip_ty.index), + name_strategy, + "union", + inst, + ); mod.declPtr(new_decl_index).owns_tv = true; errdefer mod.abortAnonDecl(new_decl_index); @@ -22084,10 +22116,14 @@ fn reifyStruct( .auto => {}, }; - const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, src, .{ - .ty = Type.type, - .val = Value.fromInterned(wip_ty.index), - }, name_strategy, "struct", inst); + const new_decl_index = try sema.createAnonymousDeclTypeNamed( + block, + src, + Value.fromInterned(wip_ty.index), + name_strategy, + "struct", + inst, + ); mod.declPtr(new_decl_index).owns_tv = true; errdefer mod.abortAnonDecl(new_decl_index); @@ -26139,9 +26175,10 @@ fn zirBuiltinExtern( const new_decl_index = try mod.allocateNewDecl(sema.owner_decl.src_namespace, sema.owner_decl.src_node); errdefer mod.destroyDecl(new_decl_index); const new_decl = mod.declPtr(new_decl_index); - try mod.initNewAnonDecl(new_decl_index, sema.owner_decl.src_line, .{ - .ty = Type.fromInterned(ptr_info.child), - .val = Value.fromInterned( + try mod.initNewAnonDecl( + new_decl_index, + sema.owner_decl.src_line, + Value.fromInterned( if (Type.fromInterned(ptr_info.child).zigTypeTag(mod) == .Fn) try ip.getExternFunc(sema.gpa, .{ .ty = ptr_info.child, @@ -26160,7 +26197,8 @@ fn zirBuiltinExtern( .is_weak_linkage = options.linkage == .weak, } }), ), - }, options.name); + options.name, + ); new_decl.owns_tv = true; // Note that this will queue the anon decl for codegen, so that the backend can // correctly handle the extern, including duplicate detection. @@ -37381,10 +37419,12 @@ fn generateUnionTagTypeNumbered( errdefer mod.destroyDecl(new_decl_index); const fqn = try union_owner_decl.fullyQualifiedName(mod); const name = try ip.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(ip)}); - try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, .{ - .ty = Type.noreturn, - .val = Value.@"unreachable", - }, name); + try mod.initNewAnonDecl( + new_decl_index, + src_decl.src_line, + Value.@"unreachable", + name, + ); errdefer mod.abortAnonDecl(new_decl_index); const new_decl = mod.declPtr(new_decl_index); @@ -37425,10 +37465,12 @@ fn generateUnionTagTypeSimple( const new_decl_index = try mod.allocateNewDecl(block.namespace, src_decl.src_node); errdefer mod.destroyDecl(new_decl_index); const name = try ip.getOrPutStringFmt(gpa, "@typeInfo({}).Union.tag_type.?", .{fqn.fmt(ip)}); - try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, .{ - .ty = Type.noreturn, - .val = Value.@"unreachable", - }, name); + try mod.initNewAnonDecl( + new_decl_index, + src_decl.src_line, + Value.@"unreachable", + name, + ); mod.declPtr(new_decl_index).name_fully_qualified = true; break :new_decl_index new_decl_index; }; -- cgit v1.2.3 From a61def10c66abc871f92c84d9cef85b6b7752cbf Mon Sep 17 00:00:00 2001 From: mlugg Date: Tue, 26 Mar 2024 05:38:32 +0000 Subject: compiler: eliminate most usages of TypedValue --- src/Module.zig | 31 ++--- src/Sema.zig | 29 ++--- src/TypedValue.zig | 40 +----- src/Value.zig | 6 +- src/arch/aarch64/CodeGen.zig | 10 +- src/arch/arm/CodeGen.zig | 10 +- src/arch/riscv64/CodeGen.zig | 10 +- src/arch/sparc64/CodeGen.zig | 11 +- src/arch/wasm/CodeGen.zig | 32 +++-- src/arch/x86_64/CodeGen.zig | 101 ++++++--------- src/codegen.zig | 288 ++++++++++++++++++------------------------- src/codegen/c.zig | 63 +++++----- src/codegen/llvm.zig | 29 ++--- src/link.zig | 6 +- src/link/C.zig | 6 +- src/link/Coff.zig | 18 ++- src/link/Elf.zig | 6 +- src/link/Elf/ZigObject.zig | 25 ++-- src/link/MachO.zig | 6 +- src/link/MachO/ZigObject.zig | 21 ++-- src/link/Plan9.zig | 15 +-- src/link/Wasm.zig | 6 +- src/link/Wasm/ZigObject.zig | 24 ++-- src/type.zig | 1 - 24 files changed, 307 insertions(+), 487 deletions(-) (limited to 'src/Module.zig') diff --git a/src/Module.zig b/src/Module.zig index 044c4fb45b..df39a2a869 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -3678,20 +3678,21 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { const address_space_src: LazySrcLoc = .{ .node_offset_var_decl_addrspace = 0 }; const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = 0 }; const init_src: LazySrcLoc = .{ .node_offset_var_decl_init = 0 }; - const decl_tv = try sema.resolveFinalDeclValue(&block_scope, init_src, result_ref); + const decl_val = try sema.resolveFinalDeclValue(&block_scope, init_src, result_ref); + const decl_ty = decl_val.typeOf(mod); // Note this resolves the type of the Decl, not the value; if this Decl // is a struct, for example, this resolves `type` (which needs no resolution), // not the struct itself. - try sema.resolveTypeLayout(decl_tv.ty); + try sema.resolveTypeLayout(decl_ty); if (decl.kind == .@"usingnamespace") { - if (!decl_tv.ty.eql(Type.type, mod)) { + if (!decl_ty.eql(Type.type, mod)) { return sema.fail(&block_scope, ty_src, "expected type, found {}", .{ - decl_tv.ty.fmt(mod), + decl_ty.fmt(mod), }); } - const ty = decl_tv.val.toType(); + const ty = decl_val.toType(); if (ty.getNamespace(mod) == null) { return sema.fail(&block_scope, ty_src, "type {} has no namespace", .{ty.fmt(mod)}); } @@ -3713,10 +3714,10 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { var queue_linker_work = true; var is_func = false; var is_inline = false; - switch (decl_tv.val.toIntern()) { + switch (decl_val.toIntern()) { .generic_poison => unreachable, .unreachable_value => unreachable, - else => switch (ip.indexToKey(decl_tv.val.toIntern())) { + else => switch (ip.indexToKey(decl_val.toIntern())) { .variable => |variable| { decl.owns_tv = variable.decl == decl_index; queue_linker_work = decl.owns_tv; @@ -3731,7 +3732,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { .func => |func| { decl.owns_tv = func.owner_decl == decl_index; queue_linker_work = false; - is_inline = decl.owns_tv and decl_tv.ty.fnCallingConvention(mod) == .Inline; + is_inline = decl.owns_tv and decl_ty.fnCallingConvention(mod) == .Inline; is_func = decl.owns_tv; }, @@ -3739,7 +3740,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { }, } - decl.val = decl_tv.val; + decl.val = decl_val; // Function linksection, align, and addrspace were already set by Sema if (!is_func) { decl.alignment = blk: { @@ -3762,7 +3763,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { break :blk section.toOptional(); }; decl.@"addrspace" = blk: { - const addrspace_ctx: Sema.AddressSpaceContext = switch (ip.indexToKey(decl_tv.val.toIntern())) { + const addrspace_ctx: Sema.AddressSpaceContext = switch (ip.indexToKey(decl_val.toIntern())) { .variable => .variable, .extern_func, .func => .function, else => .constant, @@ -3784,10 +3785,10 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { decl.analysis = .complete; const result: SemaDeclResult = if (old_has_tv) .{ - .invalidate_decl_val = !decl_tv.ty.eql(old_ty, mod) or - !decl.val.eql(old_val, decl_tv.ty, mod) or + .invalidate_decl_val = !decl_ty.eql(old_ty, mod) or + !decl.val.eql(old_val, decl_ty, mod) or is_inline != old_is_inline, - .invalidate_decl_ref = !decl_tv.ty.eql(old_ty, mod) or + .invalidate_decl_ref = !decl_ty.eql(old_ty, mod) or decl.alignment != old_align or decl.@"linksection" != old_linksection or decl.@"addrspace" != old_addrspace or @@ -3797,11 +3798,11 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !SemaDeclResult { .invalidate_decl_ref = true, }; - const has_runtime_bits = queue_linker_work and (is_func or try sema.typeHasRuntimeBits(decl_tv.ty)); + const has_runtime_bits = queue_linker_work and (is_func or try sema.typeHasRuntimeBits(decl_ty)); if (has_runtime_bits) { // Needed for codegen_decl which will call updateDecl and then the // codegen backend wants full access to the Decl Type. - try sema.resolveTypeFully(decl_tv.ty); + try sema.resolveTypeFully(decl_ty); try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl_index }); diff --git a/src/Sema.zig b/src/Sema.zig index 8c47a39f78..18f4e01dd2 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -175,7 +175,6 @@ const Sema = @This(); const Value = @import("Value.zig"); const MutableValue = @import("mutable_value.zig").MutableValue; const Type = @import("type.zig").Type; -const TypedValue = @import("TypedValue.zig"); const Air = @import("Air.zig"); const Zir = std.zig.Zir; const Module = @import("Module.zig"); @@ -1708,7 +1707,7 @@ fn analyzeBodyInner( .needed_comptime_reason = "condition in comptime branch must be comptime-known", .block_comptime_reason = block.comptime_reason, }); - const inline_body = if (cond.val.toBool()) then_body else else_body; + const inline_body = if (cond.toBool()) then_body else else_body; try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src); @@ -1728,7 +1727,7 @@ fn analyzeBodyInner( .needed_comptime_reason = "condition in comptime branch must be comptime-known", .block_comptime_reason = block.comptime_reason, }); - const inline_body = if (cond.val.toBool()) then_body else else_body; + const inline_body = if (cond.toBool()) then_body else else_body; try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src); const old_runtime_index = block.runtime_index; @@ -2179,13 +2178,9 @@ fn resolveInstConst( src: LazySrcLoc, zir_ref: Zir.Inst.Ref, reason: NeededComptimeReason, -) CompileError!TypedValue { +) CompileError!Value { const air_ref = try sema.resolveInst(zir_ref); - const val = try sema.resolveConstDefinedValue(block, src, air_ref, reason); - return .{ - .ty = sema.typeOf(air_ref), - .val = val, - }; + return sema.resolveConstDefinedValue(block, src, air_ref, reason); } /// Value Tag may be `undef` or `variable`. @@ -2194,7 +2189,7 @@ pub fn resolveFinalDeclValue( block: *Block, src: LazySrcLoc, air_ref: Air.Inst.Ref, -) CompileError!TypedValue { +) CompileError!Value { const val = try sema.resolveValueAllowVariables(air_ref) orelse { return sema.failWithNeededComptime(block, src, .{ .needed_comptime_reason = "global variable initializer must be comptime-known", @@ -2204,10 +2199,7 @@ pub fn resolveFinalDeclValue( if (val.canMutateComptimeVarState(sema.mod)) { return sema.fail(block, src, "global variable contains reference to comptime var", .{}); } - return .{ - .ty = sema.typeOf(air_ref), - .val = val, - }; + return val; } fn failWithNeededComptime(sema: *Sema, block: *Block, src: LazySrcLoc, reason: NeededComptimeReason) CompileError { @@ -6414,7 +6406,7 @@ fn zirExportValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const options = try sema.resolveExportOptions(block, options_src, extra.options); if (options.linkage == .internal) return; - if (operand.val.getFunction(mod)) |function| { + if (operand.getFunction(mod)) |function| { const decl_index = function.owner_decl; return sema.analyzeExport(block, src, options, decl_index); } @@ -6424,7 +6416,7 @@ fn zirExportValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError .src = src, .owner_decl = sema.owner_decl_index, .src_decl = block.src_decl, - .exported = .{ .value = operand.val.toIntern() }, + .exported = .{ .value = operand.toIntern() }, .status = .in_progress, }); } @@ -25831,7 +25823,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A } else if (extra.data.bits.has_ret_ty_ref) blk: { const ret_ty_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]); extra_index += 1; - const ret_ty_tv = sema.resolveInstConst(block, ret_src, ret_ty_ref, .{ + const ret_ty_val = sema.resolveInstConst(block, ret_src, ret_ty_ref, .{ .needed_comptime_reason = "return type must be comptime-known", }) catch |err| switch (err) { error.GenericPoison => { @@ -25839,8 +25831,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A }, else => |e| return e, }; - const ty = ret_ty_tv.val.toType(); - break :blk ty; + break :blk ret_ty_val.toType(); } else Type.void; const noalias_bits: u32 = if (extra.data.bits.has_any_noalias) blk: { diff --git a/src/TypedValue.zig b/src/TypedValue.zig index ceef4116a2..6947e4cad2 100644 --- a/src/TypedValue.zig +++ b/src/TypedValue.zig @@ -1,3 +1,6 @@ +//! This type exists only for legacy purposes, and will be removed in the future. +//! It is a thin wrapper around a `Value` which also, redundantly, stores its `Type`. + const std = @import("std"); const Type = @import("type.zig").Type; const Value = @import("Value.zig"); @@ -12,42 +15,6 @@ const Target = std.Target; ty: Type, val: Value, -/// Memory management for TypedValue. The main purpose of this type -/// is to be small and have a deinit() function to free associated resources. -pub const Managed = struct { - /// If the tag value is less than Tag.no_payload_count, then no pointer - /// dereference is needed. - typed_value: TypedValue, - /// If this is `null` then there is no memory management needed. - arena: ?*std.heap.ArenaAllocator.State = null, - - pub fn deinit(self: *Managed, allocator: Allocator) void { - if (self.arena) |a| a.promote(allocator).deinit(); - self.* = undefined; - } -}; - -/// Assumes arena allocation. Does a recursive copy. -pub fn copy(self: TypedValue, arena: Allocator) error{OutOfMemory}!TypedValue { - return TypedValue{ - .ty = self.ty, - .val = try self.val.copy(arena), - }; -} - -pub fn eql(a: TypedValue, b: TypedValue, mod: *Module) bool { - if (a.ty.toIntern() != b.ty.toIntern()) return false; - return a.val.eql(b.val, a.ty, mod); -} - -pub fn hash(tv: TypedValue, hasher: *std.hash.Wyhash, mod: *Module) void { - return tv.val.hash(tv.ty, hasher, mod); -} - -pub fn intFromEnum(tv: TypedValue, mod: *Module) Allocator.Error!Value { - return tv.val.intFromEnum(tv.ty, mod); -} - const max_aggregate_items = 100; const max_string_len = 256; @@ -72,7 +39,6 @@ pub fn format( }; } -/// Prints the Value according to the Type, not according to the Value Tag. pub fn print( tv: TypedValue, writer: anytype, diff --git a/src/Value.zig b/src/Value.zig index 290f38d117..81b8583a84 100644 --- a/src/Value.zig +++ b/src/Value.zig @@ -249,12 +249,12 @@ pub fn getUnsignedIntAdvanced(val: Value, mod: *Module, opt_sema: ?*Sema) !?u64 .int => |int| Value.fromInterned(int).getUnsignedIntAdvanced(mod, opt_sema), .elem => |elem| { const base_addr = (try Value.fromInterned(elem.base).getUnsignedIntAdvanced(mod, opt_sema)) orelse return null; - const elem_ty = Type.fromInterned(mod.intern_pool.typeOf(elem.base)).elemType2(mod); + const elem_ty = Value.fromInterned(elem.base).typeOf(mod).elemType2(mod); return base_addr + elem.index * elem_ty.abiSize(mod); }, .field => |field| { const base_addr = (try Value.fromInterned(field.base).getUnsignedIntAdvanced(mod, opt_sema)) orelse return null; - const struct_ty = Type.fromInterned(mod.intern_pool.typeOf(field.base)).childType(mod); + const struct_ty = Value.fromInterned(field.base).typeOf(mod).childType(mod); if (opt_sema) |sema| try sema.resolveTypeLayout(struct_ty); return base_addr + struct_ty.structFieldOffset(@as(usize, @intCast(field.index)), mod); }, @@ -1390,7 +1390,7 @@ pub fn elemPtr( }; switch (mod.intern_pool.indexToKey(ptr_val.toIntern())) { .ptr => |ptr| switch (ptr.addr) { - .elem => |elem| if (Type.fromInterned(mod.intern_pool.typeOf(elem.base)).elemType2(mod).eql(elem_ty, mod)) + .elem => |elem| if (Value.fromInterned(elem.base).typeOf(mod).elemType2(mod).eql(elem_ty, mod)) return Value.fromInterned((try mod.intern(.{ .ptr = .{ .ty = elem_ptr_ty.toIntern(), .addr = .{ .elem = .{ diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index 9926f3ef7b..b9f8259c05 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -10,7 +10,6 @@ const Emit = @import("Emit.zig"); const Liveness = @import("../../Liveness.zig"); const Type = @import("../../type.zig").Type; const Value = @import("../../Value.zig"); -const TypedValue = @import("../../TypedValue.zig"); const link = @import("../../link.zig"); const Module = @import("../../Module.zig"); const InternPool = @import("../../InternPool.zig"); @@ -6143,10 +6142,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue { if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod) and !inst_ty.isError(mod)) return MCValue{ .none = {} }; - const inst_index = inst.toIndex() orelse return self.genTypedValue(.{ - .ty = inst_ty, - .val = (try self.air.value(inst, mod)).?, - }); + const inst_index = inst.toIndex() orelse return self.genTypedValue((try self.air.value(inst, mod)).?); return self.getResolvedInstValue(inst_index); } @@ -6163,11 +6159,11 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue { } } -fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue { +fn genTypedValue(self: *Self, val: Value) InnerError!MCValue { const mcv: MCValue = switch (try codegen.genTypedValue( self.bin_file, self.src_loc, - arg_tv, + val, self.owner_decl, )) { .mcv => |mcv| switch (mcv) { diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig index ab1b41a25e..86d4e8f7fd 100644 --- a/src/arch/arm/CodeGen.zig +++ b/src/arch/arm/CodeGen.zig @@ -10,7 +10,6 @@ const Emit = @import("Emit.zig"); const Liveness = @import("../../Liveness.zig"); const Type = @import("../../type.zig").Type; const Value = @import("../../Value.zig"); -const TypedValue = @import("../../TypedValue.zig"); const link = @import("../../link.zig"); const Module = @import("../../Module.zig"); const InternPool = @import("../../InternPool.zig"); @@ -6097,10 +6096,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue { if (!inst_ty.hasRuntimeBitsIgnoreComptime(mod) and !inst_ty.isError(mod)) return MCValue{ .none = {} }; - const inst_index = inst.toIndex() orelse return self.genTypedValue(.{ - .ty = inst_ty, - .val = (try self.air.value(inst, mod)).?, - }); + const inst_index = inst.toIndex() orelse return self.genTypedValue((try self.air.value(inst, mod)).?); return self.getResolvedInstValue(inst_index); } @@ -6117,12 +6113,12 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue { } } -fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue { +fn genTypedValue(self: *Self, val: Value) InnerError!MCValue { const mod = self.bin_file.comp.module.?; const mcv: MCValue = switch (try codegen.genTypedValue( self.bin_file, self.src_loc, - arg_tv, + val, mod.funcOwnerDeclIndex(self.func_index), )) { .mcv => |mcv| switch (mcv) { diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig index e7a872d616..5abe3afcfd 100644 --- a/src/arch/riscv64/CodeGen.zig +++ b/src/arch/riscv64/CodeGen.zig @@ -9,7 +9,6 @@ const Emit = @import("Emit.zig"); const Liveness = @import("../../Liveness.zig"); const Type = @import("../../type.zig").Type; const Value = @import("../../Value.zig"); -const TypedValue = @import("../../TypedValue.zig"); const link = @import("../../link.zig"); const Module = @import("../../Module.zig"); const InternPool = @import("../../InternPool.zig"); @@ -2552,10 +2551,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue { if (!inst_ty.hasRuntimeBits(mod)) return MCValue{ .none = {} }; - const inst_index = inst.toIndex() orelse return self.genTypedValue(.{ - .ty = inst_ty, - .val = (try self.air.value(inst, mod)).?, - }); + const inst_index = inst.toIndex() orelse return self.genTypedValue((try self.air.value(inst, mod)).?); return self.getResolvedInstValue(inst_index); } @@ -2572,12 +2568,12 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue { } } -fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { +fn genTypedValue(self: *Self, val: Value) InnerError!MCValue { const mod = self.bin_file.comp.module.?; const mcv: MCValue = switch (try codegen.genTypedValue( self.bin_file, self.src_loc, - typed_value, + val, mod.funcOwnerDeclIndex(self.func_index), )) { .mcv => |mcv| switch (mcv) { diff --git a/src/arch/sparc64/CodeGen.zig b/src/arch/sparc64/CodeGen.zig index d3417fd6de..19c18ec4a6 100644 --- a/src/arch/sparc64/CodeGen.zig +++ b/src/arch/sparc64/CodeGen.zig @@ -12,7 +12,7 @@ const builtin = @import("builtin"); const link = @import("../../link.zig"); const Module = @import("../../Module.zig"); const InternPool = @import("../../InternPool.zig"); -const TypedValue = @import("../../TypedValue.zig"); +const Value = @import("../../Value.zig"); const ErrorMsg = Module.ErrorMsg; const codegen = @import("../../codegen.zig"); const Air = @import("../../Air.zig"); @@ -4118,12 +4118,12 @@ fn genStoreASI(self: *Self, value_reg: Register, addr_reg: Register, off_reg: Re } } -fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { +fn genTypedValue(self: *Self, val: Value) InnerError!MCValue { const mod = self.bin_file.comp.module.?; const mcv: MCValue = switch (try codegen.genTypedValue( self.bin_file, self.src_loc, - typed_value, + val, mod.funcOwnerDeclIndex(self.func_index), )) { .mcv => |mcv| switch (mcv) { @@ -4546,10 +4546,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue { return self.getResolvedInstValue(inst); } - return self.genTypedValue(.{ - .ty = ty, - .val = (try self.air.value(ref, mod)).?, - }); + return self.genTypedValue((try self.air.value(ref, mod)).?); } fn ret(self: *Self, mcv: MCValue) !void { diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index be7f4ab66a..6dc2316724 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -18,7 +18,6 @@ const Value = @import("../../Value.zig"); const Compilation = @import("../../Compilation.zig"); const LazySrcLoc = std.zig.LazySrcLoc; const link = @import("../../link.zig"); -const TypedValue = @import("../../TypedValue.zig"); const Air = @import("../../Air.zig"); const Liveness = @import("../../Liveness.zig"); const target_util = @import("../../target.zig"); @@ -805,7 +804,7 @@ fn resolveInst(func: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue { // In the other cases, we will simply lower the constant to a value that fits // into a single local (such as a pointer, integer, bool, etc). const result = if (isByRef(ty, mod)) blk: { - const sym_index = try func.bin_file.lowerUnnamedConst(.{ .ty = ty, .val = val }, func.decl_index); + const sym_index = try func.bin_file.lowerUnnamedConst(val, func.decl_index); break :blk WValue{ .memory = sym_index }; } else try func.lowerConstant(val, ty); @@ -3119,10 +3118,7 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue } fn lowerParentPtrDecl(func: *CodeGen, ptr_val: Value, decl_index: InternPool.DeclIndex, offset: u32) InnerError!WValue { - const mod = func.bin_file.base.comp.module.?; - const decl = mod.declPtr(decl_index); - const ptr_ty = try mod.singleMutPtrType(decl.typeOf(mod)); - return func.lowerDeclRefValue(.{ .ty = ptr_ty, .val = ptr_val }, decl_index, offset); + return func.lowerDeclRefValue(ptr_val, decl_index, offset); } fn lowerAnonDeclRef( @@ -3157,7 +3153,7 @@ fn lowerAnonDeclRef( } else return WValue{ .memory_offset = .{ .pointer = target_sym_index, .offset = offset } }; } -fn lowerDeclRefValue(func: *CodeGen, tv: TypedValue, decl_index: InternPool.DeclIndex, offset: u32) InnerError!WValue { +fn lowerDeclRefValue(func: *CodeGen, val: Value, decl_index: InternPool.DeclIndex, offset: u32) InnerError!WValue { const mod = func.bin_file.base.comp.module.?; const decl = mod.declPtr(decl_index); @@ -3165,11 +3161,11 @@ fn lowerDeclRefValue(func: *CodeGen, tv: TypedValue, decl_index: InternPool.Decl // want to lower the actual decl, rather than the alias itself. if (decl.val.getFunction(mod)) |func_val| { if (func_val.owner_decl != decl_index) { - return func.lowerDeclRefValue(tv, func_val.owner_decl, offset); + return func.lowerDeclRefValue(val, func_val.owner_decl, offset); } } else if (decl.val.getExternFunc(mod)) |func_val| { if (func_val.decl != decl_index) { - return func.lowerDeclRefValue(tv, func_val.decl, offset); + return func.lowerDeclRefValue(val, func_val.decl, offset); } } const decl_ty = decl.typeOf(mod); @@ -3280,23 +3276,23 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue { }, .error_union => |error_union| { const err_int_ty = try mod.errorIntType(); - const err_tv: TypedValue = switch (error_union.val) { + const err_ty, const err_val = switch (error_union.val) { .err_name => |err_name| .{ - .ty = ty.errorUnionSet(mod), - .val = Value.fromInterned((try mod.intern(.{ .err = .{ + ty.errorUnionSet(mod), + Value.fromInterned((try mod.intern(.{ .err = .{ .ty = ty.errorUnionSet(mod).toIntern(), .name = err_name, } }))), }, .payload => .{ - .ty = err_int_ty, - .val = try mod.intValue(err_int_ty, 0), + err_int_ty, + try mod.intValue(err_int_ty, 0), }, }; const payload_type = ty.errorUnionPayload(mod); if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) { // We use the error type directly as the type. - return func.lowerConstant(err_tv.val, err_tv.ty); + return func.lowerConstant(err_val, err_ty); } return func.fail("Wasm TODO: lowerConstant error union with non-zero-bit payload type", .{}); @@ -3320,10 +3316,10 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue { .elem, .field => |base_index| ptr = ip.indexToKey(base_index.base).ptr, .comptime_field, .comptime_alloc => unreachable, }; - return .{ .memory = try func.bin_file.lowerUnnamedConst(.{ .ty = ty, .val = val }, owner_decl) }; + return .{ .memory = try func.bin_file.lowerUnnamedConst(val, owner_decl) }; }, .ptr => |ptr| switch (ptr.addr) { - .decl => |decl| return func.lowerDeclRefValue(.{ .ty = ty, .val = val }, decl, 0), + .decl => |decl| return func.lowerDeclRefValue(val, decl, 0), .int => |int| return func.lowerConstant(Value.fromInterned(int), Type.fromInterned(ip.typeOf(int))), .opt_payload, .elem, .field => return func.lowerParentPtr(val, 0), .anon_decl => |ad| return func.lowerAnonDeclRef(ad, 0), @@ -7285,7 +7281,7 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 { .storage = .{ .bytes = tag_name }, } }); const tag_sym_index = try func.bin_file.lowerUnnamedConst( - .{ .ty = name_ty, .val = Value.fromInterned(name_val) }, + Value.fromInterned(name_val), enum_decl_index, ); diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index c5b815b429..680dce0b48 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -32,7 +32,6 @@ const InternPool = @import("../../InternPool.zig"); const Alignment = InternPool.Alignment; const Target = std.Target; const Type = @import("../../type.zig").Type; -const TypedValue = @import("../../TypedValue.zig"); const Value = @import("../../Value.zig"); const Instruction = @import("encoder.zig").Instruction; @@ -2250,7 +2249,7 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void { for (exitlude_jump_relocs, 0..) |*exitlude_jump_reloc, tag_index| { const tag_name_len = ip.stringToSlice(tag_names.get(ip)[tag_index]).len; const tag_val = try mod.enumValueFieldIndex(enum_ty, @intCast(tag_index)); - const tag_mcv = try self.genTypedValue(.{ .ty = enum_ty, .val = tag_val }); + const tag_mcv = try self.genTypedValue(tag_val); try self.genBinOpMir(.{ ._, .cmp }, enum_ty, enum_mcv, tag_mcv); const skip_reloc = try self.asmJccReloc(.ne, undefined); @@ -3323,7 +3322,7 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void { .storage = .{ .repeated_elem = mask_val.ip_index }, } }); - const splat_mcv = try self.genTypedValue(.{ .ty = splat_ty, .val = Value.fromInterned(splat_val) }); + const splat_mcv = try self.genTypedValue(Value.fromInterned(splat_val)); const splat_addr_mcv: MCValue = switch (splat_mcv) { .memory, .indirect, .load_frame => splat_mcv.address(), else => .{ .register = try self.copyToTmpRegister(Type.usize, splat_mcv.address()) }, @@ -4992,17 +4991,14 @@ fn airShlShrBinOp(self: *Self, inst: Air.Inst.Index) !void { defer self.register_manager.unlockReg(shift_lock); const mask_ty = try mod.vectorType(.{ .len = 16, .child = .u8_type }); - const mask_mcv = try self.genTypedValue(.{ - .ty = mask_ty, - .val = Value.fromInterned((try mod.intern(.{ .aggregate = .{ - .ty = mask_ty.toIntern(), - .storage = .{ .elems = &([1]InternPool.Index{ - (try rhs_ty.childType(mod).maxIntScalar(mod, Type.u8)).toIntern(), - } ++ [1]InternPool.Index{ - (try mod.intValue(Type.u8, 0)).toIntern(), - } ** 15) }, - } }))), - }); + const mask_mcv = try self.genTypedValue(Value.fromInterned(try mod.intern(.{ .aggregate = .{ + .ty = mask_ty.toIntern(), + .storage = .{ .elems = &([1]InternPool.Index{ + (try rhs_ty.childType(mod).maxIntScalar(mod, Type.u8)).toIntern(), + } ++ [1]InternPool.Index{ + (try mod.intValue(Type.u8, 0)).toIntern(), + } ** 15) }, + } }))); const mask_addr_reg = try self.copyToTmpRegister(Type.usize, mask_mcv.address()); const mask_addr_lock = self.register_manager.lockRegAssumeUnused(mask_addr_reg); @@ -6860,11 +6856,11 @@ fn floatSign(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, ty: Type) .child = (try mod.intType(.signed, scalar_bits)).ip_index, }); - const sign_mcv = try self.genTypedValue(.{ .ty = vec_ty, .val = switch (tag) { + const sign_mcv = try self.genTypedValue(switch (tag) { .neg => try vec_ty.minInt(mod, vec_ty), .abs => try vec_ty.maxInt(mod, vec_ty), else => unreachable, - } }); + }); const sign_mem: Memory = if (sign_mcv.isMemory()) try sign_mcv.mem(self, Memory.Size.fromSize(abi_size)) else @@ -11130,10 +11126,7 @@ fn genBinOp( .cmp_neq, => { const unsigned_ty = try lhs_ty.toUnsigned(mod); - const not_mcv = try self.genTypedValue(.{ - .ty = lhs_ty, - .val = try unsigned_ty.maxInt(mod, unsigned_ty), - }); + const not_mcv = try self.genTypedValue(try unsigned_ty.maxInt(mod, unsigned_ty)); const not_mem: Memory = if (not_mcv.isMemory()) try not_mcv.mem(self, Memory.Size.fromSize(abi_size)) else @@ -14692,10 +14685,7 @@ fn genSetReg( ), else => unreachable, }, - .segment, .x87, .mmx, .sse => try self.genSetReg(dst_reg, ty, try self.genTypedValue(.{ - .ty = ty, - .val = try mod.undefValue(ty), - }), opts), + .segment, .x87, .mmx, .sse => try self.genSetReg(dst_reg, ty, try self.genTypedValue(try mod.undefValue(ty)), opts), }, .eflags => |cc| try self.asmSetccRegister(cc, dst_reg.to8()), .immediate => |imm| { @@ -16893,13 +16883,10 @@ fn airSelect(self: *Self, inst: Air.Inst.Index) !void { .ty = mask_elem_ty.toIntern(), .storage = .{ .u64 = bit / elem_bits }, } }); - const mask_mcv = try self.genTypedValue(.{ - .ty = mask_ty, - .val = Value.fromInterned(try mod.intern(.{ .aggregate = .{ - .ty = mask_ty.toIntern(), - .storage = .{ .elems = mask_elems[0..vec_len] }, - } })), - }); + const mask_mcv = try self.genTypedValue(Value.fromInterned(try mod.intern(.{ .aggregate = .{ + .ty = mask_ty.toIntern(), + .storage = .{ .elems = mask_elems[0..vec_len] }, + } }))); const mask_mem: Memory = .{ .base = .{ .reg = try self.copyToTmpRegister(Type.usize, mask_mcv.address()) }, .mod = .{ .rm = .{ .size = self.memSize(ty) } }, @@ -16921,13 +16908,10 @@ fn airSelect(self: *Self, inst: Air.Inst.Index) !void { .ty = mask_elem_ty.toIntern(), .storage = .{ .u64 = @as(u32, 1) << @intCast(bit & (elem_bits - 1)) }, } }); - const mask_mcv = try self.genTypedValue(.{ - .ty = mask_ty, - .val = Value.fromInterned(try mod.intern(.{ .aggregate = .{ - .ty = mask_ty.toIntern(), - .storage = .{ .elems = mask_elems[0..vec_len] }, - } })), - }); + const mask_mcv = try self.genTypedValue(Value.fromInterned(try mod.intern(.{ .aggregate = .{ + .ty = mask_ty.toIntern(), + .storage = .{ .elems = mask_elems[0..vec_len] }, + } }))); const mask_mem: Memory = .{ .base = .{ .reg = try self.copyToTmpRegister(Type.usize, mask_mcv.address()) }, .mod = .{ .rm = .{ .size = self.memSize(ty) } }, @@ -17658,13 +17642,10 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void { else try select_mask_elem_ty.minIntScalar(mod, select_mask_elem_ty)).toIntern(); } - const select_mask_mcv = try self.genTypedValue(.{ - .ty = select_mask_ty, - .val = Value.fromInterned(try mod.intern(.{ .aggregate = .{ - .ty = select_mask_ty.toIntern(), - .storage = .{ .elems = select_mask_elems[0..mask_elems.len] }, - } })), - }); + const select_mask_mcv = try self.genTypedValue(Value.fromInterned(try mod.intern(.{ .aggregate = .{ + .ty = select_mask_ty.toIntern(), + .storage = .{ .elems = select_mask_elems[0..mask_elems.len] }, + } }))); if (self.hasFeature(.sse4_1)) { const mir_tag: Mir.Inst.FixedTag = .{ @@ -17809,13 +17790,10 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void { } }); } const lhs_mask_ty = try mod.vectorType(.{ .len = max_abi_size, .child = .u8_type }); - const lhs_mask_mcv = try self.genTypedValue(.{ - .ty = lhs_mask_ty, - .val = Value.fromInterned(try mod.intern(.{ .aggregate = .{ - .ty = lhs_mask_ty.toIntern(), - .storage = .{ .elems = lhs_mask_elems[0..max_abi_size] }, - } })), - }); + const lhs_mask_mcv = try self.genTypedValue(Value.fromInterned(try mod.intern(.{ .aggregate = .{ + .ty = lhs_mask_ty.toIntern(), + .storage = .{ .elems = lhs_mask_elems[0..max_abi_size] }, + } }))); const lhs_mask_mem: Memory = .{ .base = .{ .reg = try self.copyToTmpRegister(Type.usize, lhs_mask_mcv.address()) }, .mod = .{ .rm = .{ .size = Memory.Size.fromSize(@max(max_abi_size, 16)) } }, @@ -17846,13 +17824,10 @@ fn airShuffle(self: *Self, inst: Air.Inst.Index) !void { } }); } const rhs_mask_ty = try mod.vectorType(.{ .len = max_abi_size, .child = .u8_type }); - const rhs_mask_mcv = try self.genTypedValue(.{ - .ty = rhs_mask_ty, - .val = Value.fromInterned(try mod.intern(.{ .aggregate = .{ - .ty = rhs_mask_ty.toIntern(), - .storage = .{ .elems = rhs_mask_elems[0..max_abi_size] }, - } })), - }); + const rhs_mask_mcv = try self.genTypedValue(Value.fromInterned(try mod.intern(.{ .aggregate = .{ + .ty = rhs_mask_ty.toIntern(), + .storage = .{ .elems = rhs_mask_elems[0..max_abi_size] }, + } }))); const rhs_mask_mem: Memory = .{ .base = .{ .reg = try self.copyToTmpRegister(Type.usize, rhs_mask_mcv.address()) }, .mod = .{ .rm = .{ .size = Memory.Size.fromSize(@max(max_abi_size, 16)) } }, @@ -18138,7 +18113,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { .{ .frame = frame_index }, @intCast(elem_size * elements.len), elem_ty, - try self.genTypedValue(.{ .ty = elem_ty, .val = sentinel }), + try self.genTypedValue(sentinel), .{}, ); break :result .{ .load_frame = .{ .index = frame_index } }; @@ -18662,7 +18637,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue { const ip_index = ref.toInterned().?; const gop = try self.const_tracking.getOrPut(self.gpa, ip_index); if (!gop.found_existing) gop.value_ptr.* = InstTracking.init(init: { - const const_mcv = try self.genTypedValue(.{ .ty = ty, .val = Value.fromInterned(ip_index) }); + const const_mcv = try self.genTypedValue(Value.fromInterned(ip_index)); switch (const_mcv) { .lea_tlv => |tlv_sym| switch (self.bin_file.tag) { .elf, .macho => { @@ -18727,9 +18702,9 @@ fn limitImmediateType(self: *Self, operand: Air.Inst.Ref, comptime T: type) !MCV return mcv; } -fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue { +fn genTypedValue(self: *Self, val: Value) InnerError!MCValue { const mod = self.bin_file.comp.module.?; - return switch (try codegen.genTypedValue(self.bin_file, self.src_loc, arg_tv, self.owner.getDecl(mod))) { + return switch (try codegen.genTypedValue(self.bin_file, self.src_loc, val, self.owner.getDecl(mod))) { .mcv => |mcv| switch (mcv) { .none => .none, .undef => .undef, diff --git a/src/codegen.zig b/src/codegen.zig index 48a7f840b2..049b10b308 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -19,7 +19,6 @@ const Liveness = @import("Liveness.zig"); const Module = @import("Module.zig"); const Target = std.Target; const Type = @import("type.zig").Type; -const TypedValue = @import("TypedValue.zig"); const Value = @import("Value.zig"); const Zir = std.zig.Zir; const Alignment = InternPool.Alignment; @@ -171,7 +170,7 @@ pub fn generateLazySymbol( pub fn generateSymbol( bin_file: *link.File, src_loc: Module.SrcLoc, - arg_tv: TypedValue, + val: Value, code: *std.ArrayList(u8), debug_output: DebugInfoOutput, reloc_info: RelocInfo, @@ -181,23 +180,22 @@ pub fn generateSymbol( const mod = bin_file.comp.module.?; const ip = &mod.intern_pool; - const typed_value = arg_tv; + const ty = val.typeOf(mod); const target = mod.getTarget(); const endian = target.cpu.arch.endian(); - log.debug("generateSymbol: ty = {}, val = {}", .{ - typed_value.ty.fmt(mod), - typed_value.val.fmtValue(typed_value.ty, mod), + log.debug("generateSymbol: val = {}", .{ + val.fmtValue(ty, mod), }); - if (typed_value.val.isUndefDeep(mod)) { - const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow; + if (val.isUndefDeep(mod)) { + const abi_size = math.cast(usize, ty.abiSize(mod)) orelse return error.Overflow; try code.appendNTimes(0xaa, abi_size); return .ok; } - switch (ip.indexToKey(typed_value.val.toIntern())) { + switch (ip.indexToKey(val.toIntern())) { .int_type, .ptr_type, .array_type, @@ -238,17 +236,17 @@ pub fn generateSymbol( .empty_enum_value, => unreachable, // non-runtime values .int => { - const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow; + const abi_size = math.cast(usize, ty.abiSize(mod)) orelse return error.Overflow; var space: Value.BigIntSpace = undefined; - const val = typed_value.val.toBigInt(&space, mod); - val.writeTwosComplement(try code.addManyAsSlice(abi_size), endian); + const int_val = val.toBigInt(&space, mod); + int_val.writeTwosComplement(try code.addManyAsSlice(abi_size), endian); }, .err => |err| { const int = try mod.getErrorValue(err.name); try code.writer().writeInt(u16, @as(u16, @intCast(int)), endian); }, .error_union => |error_union| { - const payload_ty = typed_value.ty.errorUnionPayload(mod); + const payload_ty = ty.errorUnionPayload(mod); const err_val = switch (error_union.val) { .err_name => |err_name| @as(u16, @intCast(try mod.getErrorValue(err_name))), .payload => @as(u16, 0), @@ -261,7 +259,7 @@ pub fn generateSymbol( const payload_align = payload_ty.abiAlignment(mod); const error_align = Type.anyerror.abiAlignment(mod); - const abi_align = typed_value.ty.abiAlignment(mod); + const abi_align = ty.abiAlignment(mod); // error value first when its type is larger than the error union's payload if (error_align.order(payload_align) == .gt) { @@ -271,13 +269,10 @@ pub fn generateSymbol( // emit payload part of the error union { const begin = code.items.len; - switch (try generateSymbol(bin_file, src_loc, .{ - .ty = payload_ty, - .val = Value.fromInterned(switch (error_union.val) { - .err_name => try mod.intern(.{ .undef = payload_ty.toIntern() }), - .payload => |payload| payload, - }), - }, code, debug_output, reloc_info)) { + switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(switch (error_union.val) { + .err_name => try mod.intern(.{ .undef = payload_ty.toIntern() }), + .payload => |payload| payload, + }), code, debug_output, reloc_info)) { .ok => {}, .fail => |em| return .{ .fail = em }, } @@ -304,11 +299,8 @@ pub fn generateSymbol( } }, .enum_tag => |enum_tag| { - const int_tag_ty = typed_value.ty.intTagType(mod); - switch (try generateSymbol(bin_file, src_loc, .{ - .ty = int_tag_ty, - .val = try mod.getCoerced(Value.fromInterned(enum_tag.int), int_tag_ty), - }, code, debug_output, reloc_info)) { + const int_tag_ty = ty.intTagType(mod); + switch (try generateSymbol(bin_file, src_loc, try mod.getCoerced(Value.fromInterned(enum_tag.int), int_tag_ty), code, debug_output, reloc_info)) { .ok => {}, .fail => |em| return .{ .fail = em }, } @@ -319,42 +311,33 @@ pub fn generateSymbol( .f64 => |f64_val| writeFloat(f64, f64_val, target, endian, try code.addManyAsArray(8)), .f80 => |f80_val| { writeFloat(f80, f80_val, target, endian, try code.addManyAsArray(10)); - const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow; + const abi_size = math.cast(usize, ty.abiSize(mod)) orelse return error.Overflow; try code.appendNTimes(0, abi_size - 10); }, .f128 => |f128_val| writeFloat(f128, f128_val, target, endian, try code.addManyAsArray(16)), }, - .ptr => switch (try lowerParentPtr(bin_file, src_loc, typed_value.val.toIntern(), code, debug_output, reloc_info)) { + .ptr => switch (try lowerParentPtr(bin_file, src_loc, val.toIntern(), code, debug_output, reloc_info)) { .ok => {}, .fail => |em| return .{ .fail = em }, }, .slice => |slice| { - switch (try generateSymbol(bin_file, src_loc, .{ - .ty = typed_value.ty.slicePtrFieldType(mod), - .val = Value.fromInterned(slice.ptr), - }, code, debug_output, reloc_info)) { + switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(slice.ptr), code, debug_output, reloc_info)) { .ok => {}, .fail => |em| return .{ .fail = em }, } - switch (try generateSymbol(bin_file, src_loc, .{ - .ty = Type.usize, - .val = Value.fromInterned(slice.len), - }, code, debug_output, reloc_info)) { + switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(slice.len), code, debug_output, reloc_info)) { .ok => {}, .fail => |em| return .{ .fail = em }, } }, .opt => { - const payload_type = typed_value.ty.optionalChild(mod); - const payload_val = typed_value.val.optionalValue(mod); - const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse return error.Overflow; + const payload_type = ty.optionalChild(mod); + const payload_val = val.optionalValue(mod); + const abi_size = math.cast(usize, ty.abiSize(mod)) orelse return error.Overflow; - if (typed_value.ty.optionalReprIsPayload(mod)) { + if (ty.optionalReprIsPayload(mod)) { if (payload_val) |value| { - switch (try generateSymbol(bin_file, src_loc, .{ - .ty = payload_type, - .val = value, - }, code, debug_output, reloc_info)) { + switch (try generateSymbol(bin_file, src_loc, value, code, debug_output, reloc_info)) { .ok => {}, .fail => |em| return Result{ .fail = em }, } @@ -365,10 +348,7 @@ pub fn generateSymbol( const padding = abi_size - (math.cast(usize, payload_type.abiSize(mod)) orelse return error.Overflow) - 1; if (payload_type.hasRuntimeBits(mod)) { const value = payload_val orelse Value.fromInterned((try mod.intern(.{ .undef = payload_type.toIntern() }))); - switch (try generateSymbol(bin_file, src_loc, .{ - .ty = payload_type, - .val = value, - }, code, debug_output, reloc_info)) { + switch (try generateSymbol(bin_file, src_loc, value, code, debug_output, reloc_info)) { .ok => {}, .fail => |em| return Result{ .fail = em }, } @@ -377,7 +357,7 @@ pub fn generateSymbol( try code.appendNTimes(0, padding); } }, - .aggregate => |aggregate| switch (ip.indexToKey(typed_value.ty.toIntern())) { + .aggregate => |aggregate| switch (ip.indexToKey(ty.toIntern())) { .array_type => |array_type| switch (aggregate.storage) { .bytes => |bytes| try code.appendSlice(bytes), .elems, .repeated_elem => { @@ -385,17 +365,14 @@ pub fn generateSymbol( const len_including_sentinel = array_type.len + @intFromBool(array_type.sentinel != .none); while (index < len_including_sentinel) : (index += 1) { - switch (try generateSymbol(bin_file, src_loc, .{ - .ty = Type.fromInterned(array_type.child), - .val = Value.fromInterned(switch (aggregate.storage) { - .bytes => unreachable, - .elems => |elems| elems[@as(usize, @intCast(index))], - .repeated_elem => |elem| if (index < array_type.len) - elem - else - array_type.sentinel, - }), - }, code, debug_output, reloc_info)) { + switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(switch (aggregate.storage) { + .bytes => unreachable, + .elems => |elems| elems[@as(usize, @intCast(index))], + .repeated_elem => |elem| if (index < array_type.len) + elem + else + array_type.sentinel, + }), code, debug_output, reloc_info)) { .ok => {}, .fail => |em| return .{ .fail = em }, } @@ -403,7 +380,7 @@ pub fn generateSymbol( }, }, .vector_type => |vector_type| { - const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse + const abi_size = math.cast(usize, ty.abiSize(mod)) orelse return error.Overflow; if (vector_type.child == .bool_type) { const bytes = try code.addManyAsSlice(abi_size); @@ -449,16 +426,13 @@ pub fn generateSymbol( .elems, .repeated_elem => { var index: u64 = 0; while (index < vector_type.len) : (index += 1) { - switch (try generateSymbol(bin_file, src_loc, .{ - .ty = Type.fromInterned(vector_type.child), - .val = Value.fromInterned(switch (aggregate.storage) { - .bytes => unreachable, - .elems => |elems| elems[ - math.cast(usize, index) orelse return error.Overflow - ], - .repeated_elem => |elem| elem, - }), - }, code, debug_output, reloc_info)) { + switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(switch (aggregate.storage) { + .bytes => unreachable, + .elems => |elems| elems[ + math.cast(usize, index) orelse return error.Overflow + ], + .repeated_elem => |elem| elem, + }), code, debug_output, reloc_info)) { .ok => {}, .fail => |em| return .{ .fail = em }, } @@ -491,17 +465,14 @@ pub fn generateSymbol( .repeated_elem => |elem| elem, }; - switch (try generateSymbol(bin_file, src_loc, .{ - .ty = Type.fromInterned(field_ty), - .val = Value.fromInterned(field_val), - }, code, debug_output, reloc_info)) { + switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(field_val), code, debug_output, reloc_info)) { .ok => {}, .fail => |em| return Result{ .fail = em }, } const unpadded_field_end = code.items.len - struct_begin; // Pad struct members if required - const padded_field_end = typed_value.ty.structFieldOffset(index + 1, mod); + const padded_field_end = ty.structFieldOffset(index + 1, mod); const padding = math.cast(usize, padded_field_end - unpadded_field_end) orelse return error.Overflow; @@ -511,10 +482,10 @@ pub fn generateSymbol( } }, .struct_type => { - const struct_type = ip.loadStructType(typed_value.ty.toIntern()); + const struct_type = ip.loadStructType(ty.toIntern()); switch (struct_type.layout) { .@"packed" => { - const abi_size = math.cast(usize, typed_value.ty.abiSize(mod)) orelse + const abi_size = math.cast(usize, ty.abiSize(mod)) orelse return error.Overflow; const current_pos = code.items.len; try code.resize(current_pos + abi_size); @@ -537,10 +508,7 @@ pub fn generateSymbol( return error.Overflow; var tmp_list = try std.ArrayList(u8).initCapacity(code.allocator, field_size); defer tmp_list.deinit(); - switch (try generateSymbol(bin_file, src_loc, .{ - .ty = Type.fromInterned(field_ty), - .val = Value.fromInterned(field_val), - }, &tmp_list, debug_output, reloc_info)) { + switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(field_val), &tmp_list, debug_output, reloc_info)) { .ok => @memcpy(code.items[current_pos..][0..tmp_list.items.len], tmp_list.items), .fail => |em| return Result{ .fail = em }, } @@ -560,7 +528,7 @@ pub fn generateSymbol( const field_ty = field_types[field_index]; if (!Type.fromInterned(field_ty).hasRuntimeBits(mod)) continue; - const field_val = switch (ip.indexToKey(typed_value.val.toIntern()).aggregate.storage) { + const field_val = switch (ip.indexToKey(val.toIntern()).aggregate.storage) { .bytes => |bytes| try ip.get(mod.gpa, .{ .int = .{ .ty = field_ty, .storage = .{ .u64 = bytes[field_index] }, @@ -575,10 +543,7 @@ pub fn generateSymbol( ) orelse return error.Overflow; if (padding > 0) try code.appendNTimes(0, padding); - switch (try generateSymbol(bin_file, src_loc, .{ - .ty = Type.fromInterned(field_ty), - .val = Value.fromInterned(field_val), - }, code, debug_output, reloc_info)) { + switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(field_val), code, debug_output, reloc_info)) { .ok => {}, .fail => |em| return Result{ .fail = em }, } @@ -599,37 +564,28 @@ pub fn generateSymbol( else => unreachable, }, .un => |un| { - const layout = typed_value.ty.unionGetLayout(mod); + const layout = ty.unionGetLayout(mod); if (layout.payload_size == 0) { - return generateSymbol(bin_file, src_loc, .{ - .ty = typed_value.ty.unionTagTypeSafety(mod).?, - .val = Value.fromInterned(un.tag), - }, code, debug_output, reloc_info); + return generateSymbol(bin_file, src_loc, Value.fromInterned(un.tag), code, debug_output, reloc_info); } // Check if we should store the tag first. if (layout.tag_size > 0 and layout.tag_align.compare(.gte, layout.payload_align)) { - switch (try generateSymbol(bin_file, src_loc, .{ - .ty = typed_value.ty.unionTagTypeSafety(mod).?, - .val = Value.fromInterned(un.tag), - }, code, debug_output, reloc_info)) { + switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(un.tag), code, debug_output, reloc_info)) { .ok => {}, .fail => |em| return Result{ .fail = em }, } } - const union_obj = mod.typeToUnion(typed_value.ty).?; + const union_obj = mod.typeToUnion(ty).?; if (un.tag != .none) { - const field_index = typed_value.ty.unionTagFieldIndex(Value.fromInterned(un.tag), mod).?; + const field_index = ty.unionTagFieldIndex(Value.fromInterned(un.tag), mod).?; const field_ty = Type.fromInterned(union_obj.field_types.get(ip)[field_index]); if (!field_ty.hasRuntimeBits(mod)) { try code.appendNTimes(0xaa, math.cast(usize, layout.payload_size) orelse return error.Overflow); } else { - switch (try generateSymbol(bin_file, src_loc, .{ - .ty = field_ty, - .val = Value.fromInterned(un.val), - }, code, debug_output, reloc_info)) { + switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(un.val), code, debug_output, reloc_info)) { .ok => {}, .fail => |em| return Result{ .fail = em }, } @@ -640,20 +596,14 @@ pub fn generateSymbol( } } } else { - switch (try generateSymbol(bin_file, src_loc, .{ - .ty = Type.fromInterned(ip.typeOf(un.val)), - .val = Value.fromInterned(un.val), - }, code, debug_output, reloc_info)) { + switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(un.val), code, debug_output, reloc_info)) { .ok => {}, .fail => |em| return Result{ .fail = em }, } } if (layout.tag_size > 0 and layout.tag_align.compare(.lt, layout.payload_align)) { - switch (try generateSymbol(bin_file, src_loc, .{ - .ty = Type.fromInterned(union_obj.enum_tag_ty), - .val = Value.fromInterned(un.tag), - }, code, debug_output, reloc_info)) { + switch (try generateSymbol(bin_file, src_loc, Value.fromInterned(un.tag), code, debug_output, reloc_info)) { .ok => {}, .fail => |em| return Result{ .fail = em }, } @@ -681,10 +631,7 @@ fn lowerParentPtr( return switch (ptr.addr) { .decl => |decl| try lowerDeclRef(bin_file, src_loc, decl, code, debug_output, reloc_info), .anon_decl => |ad| try lowerAnonDeclRef(bin_file, src_loc, ad, code, debug_output, reloc_info), - .int => |int| try generateSymbol(bin_file, src_loc, .{ - .ty = Type.usize, - .val = Value.fromInterned(int), - }, code, debug_output, reloc_info), + .int => |int| try generateSymbol(bin_file, src_loc, Value.fromInterned(int), code, debug_output, reloc_info), .eu_payload => |eu_payload| try lowerParentPtr( bin_file, src_loc, @@ -910,11 +857,12 @@ pub const GenResult = union(enum) { fn genDeclRef( lf: *link.File, src_loc: Module.SrcLoc, - tv: TypedValue, + val: Value, ptr_decl_index: InternPool.DeclIndex, ) CodeGenError!GenResult { const zcu = lf.comp.module.?; - log.debug("genDeclRef: ty = {}, val = {}", .{ tv.ty.fmt(zcu), tv.val.fmtValue(tv.ty, zcu) }); + const ty = val.typeOf(zcu); + log.debug("genDeclRef: val = {}", .{val.fmtValue(ty, zcu)}); const ptr_decl = zcu.declPtr(ptr_decl_index); const namespace = zcu.namespacePtr(ptr_decl.src_namespace); @@ -945,12 +893,12 @@ fn genDeclRef( const gpa = comp.gpa; // TODO this feels clunky. Perhaps we should check for it in `genTypedValue`? - if (tv.ty.castPtrToFn(zcu)) |fn_ty| { + if (ty.castPtrToFn(zcu)) |fn_ty| { if (zcu.typeToFunc(fn_ty).?.is_generic) { return GenResult.mcv(.{ .immediate = fn_ty.abiAlignment(zcu).toByteUnitsOptional().? }); } - } else if (tv.ty.zigTypeTag(zcu) == .Pointer) { - const elem_ty = tv.ty.elemType2(zcu); + } else if (ty.zigTypeTag(zcu) == .Pointer) { + const elem_ty = ty.elemType2(zcu); if (!elem_ty.hasRuntimeBits(zcu)) { return GenResult.mcv(.{ .immediate = elem_ty.abiAlignment(zcu).toByteUnitsOptional().? }); } @@ -958,7 +906,7 @@ fn genDeclRef( const decl_namespace = zcu.namespacePtr(decl.src_namespace); const single_threaded = decl_namespace.file_scope.mod.single_threaded; - const is_threadlocal = tv.val.isPtrToThreadLocal(zcu) and !single_threaded; + const is_threadlocal = val.isPtrToThreadLocal(zcu) and !single_threaded; const is_extern = decl.isExtern(zcu); if (lf.cast(link.File.Elf)) |elf_file| { @@ -1023,14 +971,14 @@ fn genDeclRef( fn genUnnamedConst( lf: *link.File, src_loc: Module.SrcLoc, - tv: TypedValue, + val: Value, owner_decl_index: InternPool.DeclIndex, ) CodeGenError!GenResult { const zcu = lf.comp.module.?; const gpa = lf.comp.gpa; - log.debug("genUnnamedConst: ty = {}, val = {}", .{ tv.ty.fmt(zcu), tv.val.fmtValue(tv.ty, zcu) }); + log.debug("genUnnamedConst: val = {}", .{val.fmtValue(val.typeOf(zcu), zcu)}); - const local_sym_index = lf.lowerUnnamedConst(tv, owner_decl_index) catch |err| { + const local_sym_index = lf.lowerUnnamedConst(val, owner_decl_index) catch |err| { return GenResult.fail(gpa, src_loc, "lowering unnamed constant failed: {s}", .{@errorName(err)}); }; switch (lf.tag) { @@ -1062,18 +1010,15 @@ fn genUnnamedConst( pub fn genTypedValue( lf: *link.File, src_loc: Module.SrcLoc, - arg_tv: TypedValue, + val: Value, owner_decl_index: InternPool.DeclIndex, ) CodeGenError!GenResult { const zcu = lf.comp.module.?; - const typed_value = arg_tv; + const ty = val.typeOf(zcu); - log.debug("genTypedValue: ty = {}, val = {}", .{ - typed_value.ty.fmt(zcu), - typed_value.val.fmtValue(typed_value.ty, zcu), - }); + log.debug("genTypedValue: val = {}", .{val.fmtValue(ty, zcu)}); - if (typed_value.val.isUndef(zcu)) + if (val.isUndef(zcu)) return GenResult.mcv(.undef); const owner_decl = zcu.declPtr(owner_decl_index); @@ -1081,85 +1026,92 @@ pub fn genTypedValue( const target = namespace.file_scope.mod.resolved_target.result; const ptr_bits = target.ptrBitWidth(); - if (!typed_value.ty.isSlice(zcu)) switch (zcu.intern_pool.indexToKey(typed_value.val.toIntern())) { + if (!ty.isSlice(zcu)) switch (zcu.intern_pool.indexToKey(val.toIntern())) { .ptr => |ptr| switch (ptr.addr) { - .decl => |decl| return genDeclRef(lf, src_loc, typed_value, decl), + .decl => |decl| return genDeclRef(lf, src_loc, val, decl), else => {}, }, else => {}, }; - switch (typed_value.ty.zigTypeTag(zcu)) { + switch (ty.zigTypeTag(zcu)) { .Void => return GenResult.mcv(.none), - .Pointer => switch (typed_value.ty.ptrSize(zcu)) { + .Pointer => switch (ty.ptrSize(zcu)) { .Slice => {}, - else => switch (typed_value.val.toIntern()) { + else => switch (val.toIntern()) { .null_value => { return GenResult.mcv(.{ .immediate = 0 }); }, .none => {}, - else => switch (zcu.intern_pool.indexToKey(typed_value.val.toIntern())) { + else => switch (zcu.intern_pool.indexToKey(val.toIntern())) { .int => { - return GenResult.mcv(.{ .immediate = typed_value.val.toUnsignedInt(zcu) }); + return GenResult.mcv(.{ .immediate = val.toUnsignedInt(zcu) }); }, else => {}, }, }, }, .Int => { - const info = typed_value.ty.intInfo(zcu); + const info = ty.intInfo(zcu); if (info.bits <= ptr_bits) { const unsigned = switch (info.signedness) { - .signed => @as(u64, @bitCast(typed_value.val.toSignedInt(zcu))), - .unsigned => typed_value.val.toUnsignedInt(zcu), + .signed => @as(u64, @bitCast(val.toSignedInt(zcu))), + .unsigned => val.toUnsignedInt(zcu), }; return GenResult.mcv(.{ .immediate = unsigned }); } }, .Bool => { - return GenResult.mcv(.{ .immediate = @intFromBool(typed_value.val.toBool()) }); + return GenResult.mcv(.{ .immediate = @intFromBool(val.toBool()) }); }, .Optional => { - if (typed_value.ty.isPtrLikeOptional(zcu)) { - return genTypedValue(lf, src_loc, .{ - .ty = typed_value.ty.optionalChild(zcu), - .val = typed_value.val.optionalValue(zcu) orelse return GenResult.mcv(.{ .immediate = 0 }), - }, owner_decl_index); - } else if (typed_value.ty.abiSize(zcu) == 1) { - return GenResult.mcv(.{ .immediate = @intFromBool(!typed_value.val.isNull(zcu)) }); + if (ty.isPtrLikeOptional(zcu)) { + return genTypedValue( + lf, + src_loc, + val.optionalValue(zcu) orelse return GenResult.mcv(.{ .immediate = 0 }), + owner_decl_index, + ); + } else if (ty.abiSize(zcu) == 1) { + return GenResult.mcv(.{ .immediate = @intFromBool(!val.isNull(zcu)) }); } }, .Enum => { - const enum_tag = zcu.intern_pool.indexToKey(typed_value.val.toIntern()).enum_tag; - const int_tag_ty = zcu.intern_pool.typeOf(enum_tag.int); - return genTypedValue(lf, src_loc, .{ - .ty = Type.fromInterned(int_tag_ty), - .val = Value.fromInterned(enum_tag.int), - }, owner_decl_index); + const enum_tag = zcu.intern_pool.indexToKey(val.toIntern()).enum_tag; + return genTypedValue( + lf, + src_loc, + Value.fromInterned(enum_tag.int), + owner_decl_index, + ); }, .ErrorSet => { - const err_name = zcu.intern_pool.indexToKey(typed_value.val.toIntern()).err.name; + const err_name = zcu.intern_pool.indexToKey(val.toIntern()).err.name; const error_index = zcu.global_error_set.getIndex(err_name).?; return GenResult.mcv(.{ .immediate = error_index }); }, .ErrorUnion => { - const err_type = typed_value.ty.errorUnionSet(zcu); - const payload_type = typed_value.ty.errorUnionPayload(zcu); + const err_type = ty.errorUnionSet(zcu); + const payload_type = ty.errorUnionPayload(zcu); if (!payload_type.hasRuntimeBitsIgnoreComptime(zcu)) { // We use the error type directly as the type. const err_int_ty = try zcu.errorIntType(); - switch (zcu.intern_pool.indexToKey(typed_value.val.toIntern()).error_union.val) { - .err_name => |err_name| return genTypedValue(lf, src_loc, .{ - .ty = err_type, - .val = Value.fromInterned((try zcu.intern(.{ .err = .{ + switch (zcu.intern_pool.indexToKey(val.toIntern()).error_union.val) { + .err_name => |err_name| return genTypedValue( + lf, + src_loc, + Value.fromInterned(try zcu.intern(.{ .err = .{ .ty = err_type.toIntern(), .name = err_name, - } }))), - }, owner_decl_index), - .payload => return genTypedValue(lf, src_loc, .{ - .ty = err_int_ty, - .val = try zcu.intValue(err_int_ty, 0), - }, owner_decl_index), + } })), + owner_decl_index, + ), + .payload => return genTypedValue( + lf, + src_loc, + try zcu.intValue(err_int_ty, 0), + owner_decl_index, + ), } } }, @@ -1176,7 +1128,7 @@ pub fn genTypedValue( else => {}, } - return genUnnamedConst(lf, src_loc, typed_value, owner_decl_index); + return genUnnamedConst(lf, src_loc, val, owner_decl_index); } pub fn errUnionPayloadOffset(payload_ty: Type, mod: *Module) u64 { diff --git a/src/codegen/c.zig b/src/codegen/c.zig index ed506cfdfe..7ae5c87ee5 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -9,7 +9,6 @@ const Module = @import("../Module.zig"); const Compilation = @import("../Compilation.zig"); const Value = @import("../Value.zig"); const Type = @import("../type.zig").Type; -const TypedValue = @import("../TypedValue.zig"); const C = link.File.C; const Decl = Module.Decl; const trace = @import("../tracy.zig").trace; @@ -1877,9 +1876,9 @@ pub const DeclGen = struct { try renderTypeSuffix(dg.pass, store.*, mod, w, cty_idx, .suffix, .{}); } - fn declIsGlobal(dg: *DeclGen, tv: TypedValue) bool { + fn declIsGlobal(dg: *DeclGen, val: Value) bool { const mod = dg.module; - return switch (mod.intern_pool.indexToKey(tv.val.ip_index)) { + return switch (mod.intern_pool.indexToKey(val.ip_index)) { .variable => |variable| mod.decl_exports.contains(variable.decl), .extern_func => true, .func => |func| mod.decl_exports.contains(func.owner_decl), @@ -1972,7 +1971,7 @@ pub const DeclGen = struct { ) !void { const decl = dg.module.declPtr(decl_index); const fwd = dg.fwdDeclWriter(); - const is_global = variable.is_extern or dg.declIsGlobal(.{ .ty = decl.typeOf(dg.module), .val = decl.val }); + const is_global = variable.is_extern or dg.declIsGlobal(decl.val); try fwd.writeAll(if (is_global) "zig_extern " else "static "); const maybe_exports = dg.module.decl_exports.get(decl_index); const export_weak_linkage = if (maybe_exports) |exports| @@ -2656,13 +2655,12 @@ fn genExports(o: *Object) !void { .anon, .flush => return, }; const decl = mod.declPtr(decl_index); - const tv: TypedValue = .{ .ty = decl.typeOf(mod), .val = decl.val }; const fwd = o.dg.fwdDeclWriter(); const exports = mod.decl_exports.get(decl_index) orelse return; if (exports.items.len < 2) return; - const is_variable_const = switch (ip.indexToKey(tv.val.toIntern())) { + const is_variable_const = switch (ip.indexToKey(decl.val.toIntern())) { .func => return for (exports.items[1..], 1..) |@"export", i| { try fwd.writeAll("zig_extern "); if (@"export".opts.linkage == .weak) try fwd.writeAll("zig_weak_linkage_fn "); @@ -2805,15 +2803,11 @@ pub fn genFunc(f: *Function) !void { const gpa = o.dg.gpa; const decl_index = o.dg.pass.decl; const decl = mod.declPtr(decl_index); - const tv: TypedValue = .{ - .ty = decl.typeOf(mod), - .val = decl.val, - }; o.code_header = std.ArrayList(u8).init(gpa); defer o.code_header.deinit(); - const is_global = o.dg.declIsGlobal(tv); + const is_global = o.dg.declIsGlobal(decl.val); const fwd_decl_writer = o.dg.fwdDeclWriter(); try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static "); @@ -2893,22 +2887,23 @@ pub fn genDecl(o: *Object) !void { const mod = o.dg.module; const decl_index = o.dg.pass.decl; const decl = mod.declPtr(decl_index); - const tv: TypedValue = .{ .ty = decl.typeOf(mod), .val = decl.val }; + const decl_val = decl.val; + const decl_ty = decl_val.typeOf(mod); - if (!tv.ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return; - if (tv.val.getExternFunc(mod)) |_| { + if (!decl_ty.isFnOrHasRuntimeBitsIgnoreComptime(mod)) return; + if (decl_val.getExternFunc(mod)) |_| { const fwd_decl_writer = o.dg.fwdDeclWriter(); try fwd_decl_writer.writeAll("zig_extern "); try o.dg.renderFunctionSignature(fwd_decl_writer, decl_index, .forward, .{ .export_index = 0 }); try fwd_decl_writer.writeAll(";\n"); try genExports(o); - } else if (tv.val.getVariable(mod)) |variable| { + } else if (decl_val.getVariable(mod)) |variable| { try o.dg.renderFwdDecl(decl_index, variable, .final); try genExports(o); if (variable.is_extern) return; - const is_global = variable.is_extern or o.dg.declIsGlobal(tv); + const is_global = variable.is_extern or o.dg.declIsGlobal(decl_val); const w = o.writer(); if (!is_global) try w.writeAll("static "); if (variable.is_weak_linkage) try w.writeAll("zig_weak_linkage "); @@ -2916,22 +2911,22 @@ pub fn genDecl(o: *Object) !void { if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s| try w.print("zig_linksection(\"{s}\", ", .{s}); const decl_c_value = .{ .decl = decl_index }; - try o.dg.renderTypeAndName(w, tv.ty, decl_c_value, .{}, decl.alignment, .complete); + try o.dg.renderTypeAndName(w, decl_ty, decl_c_value, .{}, decl.alignment, .complete); if (decl.@"linksection" != .none) try w.writeAll(", read, write)"); try w.writeAll(" = "); - try o.dg.renderValue(w, tv.ty, Value.fromInterned(variable.init), .StaticInitializer); + try o.dg.renderValue(w, decl_ty, Value.fromInterned(variable.init), .StaticInitializer); try w.writeByte(';'); try o.indent_writer.insertNewline(); } else { const is_global = o.dg.module.decl_exports.contains(decl_index); const decl_c_value = .{ .decl = decl_index }; - try genDeclValue(o, tv, is_global, decl_c_value, decl.alignment, decl.@"linksection"); + try genDeclValue(o, decl_val, is_global, decl_c_value, decl.alignment, decl.@"linksection"); } } pub fn genDeclValue( o: *Object, - tv: TypedValue, + val: Value, is_global: bool, decl_c_value: CValue, alignment: Alignment, @@ -2940,8 +2935,10 @@ pub fn genDeclValue( const mod = o.dg.module; const fwd_decl_writer = o.dg.fwdDeclWriter(); + const ty = val.typeOf(mod); + try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static "); - try o.dg.renderTypeAndName(fwd_decl_writer, tv.ty, decl_c_value, Const, alignment, .complete); + try o.dg.renderTypeAndName(fwd_decl_writer, ty, decl_c_value, Const, alignment, .complete); switch (o.dg.pass) { .decl => |decl_index| { if (mod.decl_exports.get(decl_index)) |exports| { @@ -2964,10 +2961,10 @@ pub fn genDeclValue( if (mod.intern_pool.stringToSliceUnwrap(link_section)) |s| try w.print("zig_linksection(\"{s}\", ", .{s}); - try o.dg.renderTypeAndName(w, tv.ty, decl_c_value, Const, alignment, .complete); + try o.dg.renderTypeAndName(w, ty, decl_c_value, Const, alignment, .complete); if (link_section != .none) try w.writeAll(", read)"); try w.writeAll(" = "); - try o.dg.renderValue(w, tv.ty, tv.val, .StaticInitializer); + try o.dg.renderValue(w, ty, val, .StaticInitializer); try w.writeAll(";\n"); } @@ -2978,14 +2975,10 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void { const mod = dg.module; const decl_index = dg.pass.decl; const decl = mod.declPtr(decl_index); - const tv: TypedValue = .{ - .ty = decl.typeOf(mod), - .val = decl.val, - }; const writer = dg.fwdDeclWriter(); - switch (tv.ty.zigTypeTag(mod)) { - .Fn => if (dg.declIsGlobal(tv)) { + switch (decl.val.typeOf(mod).zigTypeTag(mod)) { + .Fn => if (dg.declIsGlobal(decl.val)) { try writer.writeAll("zig_extern "); try dg.renderFunctionSignature(writer, dg.pass.decl, .complete, .{ .export_index = 0 }); try dg.fwd_decl.appendSlice(";\n"); @@ -5304,25 +5297,25 @@ fn airIsNull( const err_int_ty = try mod.errorIntType(); const rhs = if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) - TypedValue{ .ty = Type.bool, .val = Value.true } + Value.true else if (optional_ty.isPtrLikeOptional(mod)) // operand is a regular pointer, test `operand !=/== NULL` - TypedValue{ .ty = optional_ty, .val = try mod.getCoerced(Value.null, optional_ty) } + try mod.getCoerced(Value.null, optional_ty) else if (payload_ty.zigTypeTag(mod) == .ErrorSet) - TypedValue{ .ty = err_int_ty, .val = try mod.intValue(err_int_ty, 0) } + try mod.intValue(err_int_ty, 0) else if (payload_ty.isSlice(mod) and optional_ty.optionalReprIsPayload(mod)) rhs: { try writer.writeAll(".ptr"); const slice_ptr_ty = payload_ty.slicePtrFieldType(mod); const opt_slice_ptr_ty = try mod.optionalType(slice_ptr_ty.toIntern()); - break :rhs TypedValue{ .ty = opt_slice_ptr_ty, .val = try mod.nullValue(opt_slice_ptr_ty) }; + break :rhs try mod.nullValue(opt_slice_ptr_ty); } else rhs: { try writer.writeAll(".is_null"); - break :rhs TypedValue{ .ty = Type.bool, .val = Value.true }; + break :rhs Value.true; }; try writer.writeByte(' '); try writer.writeAll(operator); try writer.writeByte(' '); - try f.object.dg.renderValue(writer, rhs.ty, rhs.val, .Other); + try f.object.dg.renderValue(writer, rhs.typeOf(mod), rhs, .Other); try writer.writeAll(";\n"); return local; } diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index f4d91c2ebb..8ddacbe11c 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -18,7 +18,6 @@ const Module = @import("../Module.zig"); const Zcu = Module; const InternPool = @import("../InternPool.zig"); const Package = @import("../Package.zig"); -const TypedValue = @import("../TypedValue.zig"); const Air = @import("../Air.zig"); const Liveness = @import("../Liveness.zig"); const Value = @import("../Value.zig"); @@ -4823,19 +4822,17 @@ pub const FuncGen = struct { const o = self.dg.object; const mod = o.module; - const llvm_val = try self.resolveValue(.{ - .ty = self.typeOf(inst), - .val = (try self.air.value(inst, mod)).?, - }); + const llvm_val = try self.resolveValue((try self.air.value(inst, mod)).?); gop.value_ptr.* = llvm_val.toValue(); return llvm_val.toValue(); } - fn resolveValue(self: *FuncGen, tv: TypedValue) Error!Builder.Constant { + fn resolveValue(self: *FuncGen, val: Value) Error!Builder.Constant { const o = self.dg.object; const mod = o.module; - const llvm_val = try o.lowerValue(tv.val.toIntern()); - if (!isByRef(tv.ty, mod)) return llvm_val; + const ty = val.typeOf(mod); + const llvm_val = try o.lowerValue(val.toIntern()); + if (!isByRef(ty, mod)) return llvm_val; // We have an LLVM value but we need to create a global constant and // set the value as its initializer, and then return a pointer to the global. @@ -4849,7 +4846,7 @@ pub const FuncGen = struct { variable_index.setLinkage(.private, &o.builder); variable_index.setMutability(.constant, &o.builder); variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); - variable_index.setAlignment(tv.ty.abiAlignment(mod).toLlvm(), &o.builder); + variable_index.setAlignment(ty.abiAlignment(mod).toLlvm(), &o.builder); return o.builder.convConst( .unneeded, variable_index.toConst(&o.builder), @@ -4861,11 +4858,10 @@ pub const FuncGen = struct { const o = self.dg.object; const mod = o.module; if (o.null_opt_usize == .no_init) { - const ty = try mod.intern(.{ .opt_type = .usize_type }); - o.null_opt_usize = try self.resolveValue(.{ - .ty = Type.fromInterned(ty), - .val = Value.fromInterned((try mod.intern(.{ .opt = .{ .ty = ty, .val = .none } }))), - }); + o.null_opt_usize = try self.resolveValue(Value.fromInterned(try mod.intern(.{ .opt = .{ + .ty = try mod.intern(.{ .opt_type = .usize_type }), + .val = .none, + } }))); } return o.null_opt_usize; } @@ -10061,10 +10057,7 @@ pub const FuncGen = struct { const elem_ptr = try self.wip.gep(.inbounds, llvm_result_ty, alloca_inst, &.{ usize_zero, try o.builder.intValue(llvm_usize, array_info.len), }, ""); - const llvm_elem = try self.resolveValue(.{ - .ty = array_info.elem_type, - .val = sent_val, - }); + const llvm_elem = try self.resolveValue(sent_val); try self.store(elem_ptr, elem_ptr_ty, llvm_elem.toValue(), .none); } diff --git a/src/link.zig b/src/link.zig index 6034d8df49..9e1daa09af 100644 --- a/src/link.zig +++ b/src/link.zig @@ -17,7 +17,7 @@ const Liveness = @import("Liveness.zig"); const Module = @import("Module.zig"); const InternPool = @import("InternPool.zig"); const Type = @import("type.zig").Type; -const TypedValue = @import("TypedValue.zig"); +const Value = @import("Value.zig"); const LlvmObject = @import("codegen/llvm.zig").Object; /// When adding a new field, remember to update `hashAddSystemLibs`. @@ -376,14 +376,14 @@ pub const File = struct { /// Called from within the CodeGen to lower a local variable instantion as an unnamed /// constant. Returns the symbol index of the lowered constant in the read-only section /// of the final binary. - pub fn lowerUnnamedConst(base: *File, tv: TypedValue, decl_index: InternPool.DeclIndex) UpdateDeclError!u32 { + pub fn lowerUnnamedConst(base: *File, val: Value, decl_index: InternPool.DeclIndex) UpdateDeclError!u32 { if (build_options.only_c) @compileError("unreachable"); switch (base.tag) { .spirv => unreachable, .c => unreachable, .nvptx => unreachable, inline else => |t| { - return @fieldParentPtr(t.Type(), "base", base).lowerUnnamedConst(tv, decl_index); + return @fieldParentPtr(t.Type(), "base", base).lowerUnnamedConst(val, decl_index); }, } } diff --git a/src/link/C.zig b/src/link/C.zig index 1bfe55c70a..73049b40cd 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -283,13 +283,9 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void { code.* = object.code.moveToUnmanaged(); } - const tv: @import("../TypedValue.zig") = .{ - .ty = Type.fromInterned(module.intern_pool.typeOf(anon_decl)), - .val = Value.fromInterned(anon_decl), - }; const c_value: codegen.CValue = .{ .constant = anon_decl }; const alignment: Alignment = self.aligned_anon_decls.get(anon_decl) orelse .none; - codegen.genDeclValue(&object, tv, false, c_value, alignment, .none) catch |err| switch (err) { + codegen.genDeclValue(&object, Value.fromInterned(anon_decl), false, c_value, alignment, .none) catch |err| switch (err) { error.AnalysisFail => { @panic("TODO: C backend AnalysisFail on anonymous decl"); //try module.failed_decls.put(gpa, decl_index, object.dg.error_msg.?); diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 01fa6cac67..7becb3f366 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -1167,7 +1167,7 @@ pub fn updateFunc(self: *Coff, mod: *Module, func_index: InternPool.Index, air: return self.updateExports(mod, .{ .decl_index = decl_index }, mod.getDeclExports(decl_index)); } -pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: InternPool.DeclIndex) !u32 { +pub fn lowerUnnamedConst(self: *Coff, val: Value, decl_index: InternPool.DeclIndex) !u32 { const gpa = self.base.comp.gpa; const mod = self.base.comp.module.?; const decl = mod.declPtr(decl_index); @@ -1180,7 +1180,8 @@ pub fn lowerUnnamedConst(self: *Coff, tv: TypedValue, decl_index: InternPool.Dec const index = unnamed_consts.items.len; const sym_name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index }); defer gpa.free(sym_name); - const atom_index = switch (try self.lowerConst(sym_name, tv, tv.ty.abiAlignment(mod), self.rdata_section_index.?, decl.srcLoc(mod))) { + const ty = val.typeOf(mod); + const atom_index = switch (try self.lowerConst(sym_name, val, ty.abiAlignment(mod), self.rdata_section_index.?, decl.srcLoc(mod))) { .ok => |atom_index| atom_index, .fail => |em| { decl.analysis = .codegen_failure; @@ -1198,7 +1199,7 @@ const LowerConstResult = union(enum) { fail: *Module.ErrorMsg, }; -fn lowerConst(self: *Coff, name: []const u8, tv: TypedValue, required_alignment: InternPool.Alignment, sect_id: u16, src_loc: Module.SrcLoc) !LowerConstResult { +fn lowerConst(self: *Coff, name: []const u8, val: Value, required_alignment: InternPool.Alignment, sect_id: u16, src_loc: Module.SrcLoc) !LowerConstResult { const gpa = self.base.comp.gpa; var code_buffer = std.ArrayList(u8).init(gpa); @@ -1209,7 +1210,7 @@ fn lowerConst(self: *Coff, name: []const u8, tv: TypedValue, required_alignment: try self.setSymbolName(sym, name); sym.section_number = @as(coff.SectionNumber, @enumFromInt(sect_id + 1)); - const res = try codegen.generateSymbol(&self.base, src_loc, tv, &code_buffer, .none, .{ + const res = try codegen.generateSymbol(&self.base, src_loc, val, &code_buffer, .none, .{ .parent_atom_index = self.getAtom(atom_index).getSymbolIndex().?, }); const code = switch (res) { @@ -1271,10 +1272,7 @@ pub fn updateDecl( defer code_buffer.deinit(); const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val; - const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{ - .ty = decl.typeOf(mod), - .val = decl_val, - }, &code_buffer, .none, .{ + const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), decl_val, &code_buffer, .none, .{ .parent_atom_index = atom.getSymbolIndex().?, }); const code = switch (res) { @@ -1887,14 +1885,13 @@ pub fn lowerAnonDecl( } const val = Value.fromInterned(decl_val); - const tv = TypedValue{ .ty = ty, .val = val }; var name_buf: [32]u8 = undefined; const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{ @intFromEnum(decl_val), }) catch unreachable; const res = self.lowerConst( name, - tv, + val, decl_alignment, self.rdata_section_index.?, src_loc, @@ -2754,7 +2751,6 @@ const TableSection = @import("table_section.zig").TableSection; const StringTable = @import("StringTable.zig"); const Type = @import("../type.zig").Type; const Value = @import("../Value.zig"); -const TypedValue = @import("../TypedValue.zig"); pub const base_tag: link.File.Tag = .coff; diff --git a/src/link/Elf.zig b/src/link/Elf.zig index f0d3f89a7f..95ddc81e3c 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -3039,8 +3039,8 @@ pub fn updateDecl( return self.zigObjectPtr().?.updateDecl(self, mod, decl_index); } -pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl_index: InternPool.DeclIndex) !u32 { - return self.zigObjectPtr().?.lowerUnnamedConst(self, typed_value, decl_index); +pub fn lowerUnnamedConst(self: *Elf, val: Value, decl_index: InternPool.DeclIndex) !u32 { + return self.zigObjectPtr().?.lowerUnnamedConst(self, val, decl_index); } pub fn updateExports( @@ -6260,7 +6260,7 @@ const SharedObject = @import("Elf/SharedObject.zig"); const Symbol = @import("Elf/Symbol.zig"); const StringTable = @import("StringTable.zig"); const Thunk = thunks.Thunk; -const TypedValue = @import("../TypedValue.zig"); +const Value = @import("../Value.zig"); const VerneedSection = synthetic_sections.VerneedSection; const ZigGotSection = synthetic_sections.ZigGotSection; const ZigObject = @import("Elf/ZigObject.zig"); diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index 3bf6f1246c..6ed55dac10 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -702,7 +702,6 @@ pub fn lowerAnonDecl( } const val = Value.fromInterned(decl_val); - const tv = TypedValue{ .ty = ty, .val = val }; var name_buf: [32]u8 = undefined; const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{ @intFromEnum(decl_val), @@ -710,7 +709,7 @@ pub fn lowerAnonDecl( const res = self.lowerConst( elf_file, name, - tv, + val, decl_alignment, elf_file.zig_data_rel_ro_section_index.?, src_loc, @@ -1157,19 +1156,13 @@ pub fn updateDecl( // TODO implement .debug_info for global variables const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val; const res = if (decl_state) |*ds| - try codegen.generateSymbol(&elf_file.base, decl.srcLoc(mod), .{ - .ty = decl.typeOf(mod), - .val = decl_val, - }, &code_buffer, .{ + try codegen.generateSymbol(&elf_file.base, decl.srcLoc(mod), decl_val, &code_buffer, .{ .dwarf = ds, }, .{ .parent_atom_index = sym_index, }) else - try codegen.generateSymbol(&elf_file.base, decl.srcLoc(mod), .{ - .ty = decl.typeOf(mod), - .val = decl_val, - }, &code_buffer, .none, .{ + try codegen.generateSymbol(&elf_file.base, decl.srcLoc(mod), decl_val, &code_buffer, .none, .{ .parent_atom_index = sym_index, }); @@ -1289,7 +1282,7 @@ fn updateLazySymbol( pub fn lowerUnnamedConst( self: *ZigObject, elf_file: *Elf, - typed_value: TypedValue, + val: Value, decl_index: InternPool.DeclIndex, ) !u32 { const gpa = elf_file.base.comp.gpa; @@ -1304,11 +1297,12 @@ pub fn lowerUnnamedConst( const index = unnamed_consts.items.len; const name = try std.fmt.allocPrint(gpa, "__unnamed_{s}_{d}", .{ decl_name, index }); defer gpa.free(name); + const ty = val.typeOf(mod); const sym_index = switch (try self.lowerConst( elf_file, name, - typed_value, - typed_value.ty.abiAlignment(mod), + val, + ty.abiAlignment(mod), elf_file.zig_data_rel_ro_section_index.?, decl.srcLoc(mod), )) { @@ -1334,7 +1328,7 @@ fn lowerConst( self: *ZigObject, elf_file: *Elf, name: []const u8, - tv: TypedValue, + val: Value, required_alignment: InternPool.Alignment, output_section_index: u32, src_loc: Module.SrcLoc, @@ -1346,7 +1340,7 @@ fn lowerConst( const sym_index = try self.addAtom(elf_file); - const res = try codegen.generateSymbol(&elf_file.base, src_loc, tv, &code_buffer, .{ + const res = try codegen.generateSymbol(&elf_file.base, src_loc, val, &code_buffer, .{ .none = {}, }, .{ .parent_atom_index = sym_index, @@ -1657,5 +1651,4 @@ const Symbol = @import("Symbol.zig"); const StringTable = @import("../StringTable.zig"); const Type = @import("../../type.zig").Type; const Value = @import("../../Value.zig"); -const TypedValue = @import("../../TypedValue.zig"); const ZigObject = @This(); diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 29ac89d26c..c2b8d02df5 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -3127,8 +3127,8 @@ pub fn updateFunc(self: *MachO, mod: *Module, func_index: InternPool.Index, air: return self.getZigObject().?.updateFunc(self, mod, func_index, air, liveness); } -pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: InternPool.DeclIndex) !u32 { - return self.getZigObject().?.lowerUnnamedConst(self, typed_value, decl_index); +pub fn lowerUnnamedConst(self: *MachO, val: Value, decl_index: InternPool.DeclIndex) !u32 { + return self.getZigObject().?.lowerUnnamedConst(self, val, decl_index); } pub fn updateDecl(self: *MachO, mod: *Module, decl_index: InternPool.DeclIndex) !void { @@ -4689,7 +4689,7 @@ const StubsHelperSection = synthetic.StubsHelperSection; const Symbol = @import("MachO/Symbol.zig"); const Thunk = thunks.Thunk; const TlvPtrSection = synthetic.TlvPtrSection; -const TypedValue = @import("../TypedValue.zig"); +const Value = @import("../Value.zig"); const UnwindInfo = @import("MachO/UnwindInfo.zig"); const WeakBindSection = synthetic.WeakBindSection; const ZigGotSection = synthetic.ZigGotSection; diff --git a/src/link/MachO/ZigObject.zig b/src/link/MachO/ZigObject.zig index 42f186d961..fb27c96525 100644 --- a/src/link/MachO/ZigObject.zig +++ b/src/link/MachO/ZigObject.zig @@ -567,8 +567,6 @@ pub fn lowerAnonDecl( return .ok; } - const val = Value.fromInterned(decl_val); - const tv = TypedValue{ .ty = ty, .val = val }; var name_buf: [32]u8 = undefined; const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{ @intFromEnum(decl_val), @@ -576,7 +574,7 @@ pub fn lowerAnonDecl( const res = self.lowerConst( macho_file, name, - tv, + Value.fromInterned(decl_val), decl_alignment, macho_file.zig_const_sect_index.?, src_loc, @@ -738,11 +736,7 @@ pub fn updateDecl( const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val; const dio: codegen.DebugInfoOutput = if (decl_state) |*ds| .{ .dwarf = ds } else .none; - const res = - try codegen.generateSymbol(&macho_file.base, decl.srcLoc(mod), .{ - .ty = decl.typeOf(mod), - .val = decl_val, - }, &code_buffer, dio, .{ + const res = try codegen.generateSymbol(&macho_file.base, decl.srcLoc(mod), decl_val, &code_buffer, dio, .{ .parent_atom_index = sym_index, }); @@ -1068,7 +1062,7 @@ fn getDeclOutputSection( pub fn lowerUnnamedConst( self: *ZigObject, macho_file: *MachO, - typed_value: TypedValue, + val: Value, decl_index: InternPool.DeclIndex, ) !u32 { const gpa = macho_file.base.comp.gpa; @@ -1086,8 +1080,8 @@ pub fn lowerUnnamedConst( const sym_index = switch (try self.lowerConst( macho_file, name, - typed_value, - typed_value.ty.abiAlignment(mod), + val, + val.typeOf(mod).abiAlignment(mod), macho_file.zig_const_sect_index.?, decl.srcLoc(mod), )) { @@ -1113,7 +1107,7 @@ fn lowerConst( self: *ZigObject, macho_file: *MachO, name: []const u8, - tv: TypedValue, + val: Value, required_alignment: Atom.Alignment, output_section_index: u8, src_loc: Module.SrcLoc, @@ -1125,7 +1119,7 @@ fn lowerConst( const sym_index = try self.addAtom(macho_file); - const res = try codegen.generateSymbol(&macho_file.base, src_loc, tv, &code_buffer, .{ + const res = try codegen.generateSymbol(&macho_file.base, src_loc, val, &code_buffer, .{ .none = {}, }, .{ .parent_atom_index = sym_index, @@ -1580,5 +1574,4 @@ const Symbol = @import("Symbol.zig"); const StringTable = @import("../StringTable.zig"); const Type = @import("../../type.zig").Type; const Value = @import("../../Value.zig"); -const TypedValue = @import("../../TypedValue.zig"); const ZigObject = @This(); diff --git a/src/link/Plan9.zig b/src/link/Plan9.zig index d092351c47..d5900d2b16 100644 --- a/src/link/Plan9.zig +++ b/src/link/Plan9.zig @@ -15,7 +15,6 @@ const Air = @import("../Air.zig"); const Liveness = @import("../Liveness.zig"); const Type = @import("../type.zig").Type; const Value = @import("../Value.zig"); -const TypedValue = @import("../TypedValue.zig"); const std = @import("std"); const builtin = @import("builtin"); @@ -463,7 +462,7 @@ pub fn updateFunc(self: *Plan9, mod: *Module, func_index: InternPool.Index, air: return self.updateFinish(decl_index); } -pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: InternPool.DeclIndex) !u32 { +pub fn lowerUnnamedConst(self: *Plan9, val: Value, decl_index: InternPool.DeclIndex) !u32 { const gpa = self.base.comp.gpa; _ = try self.seeDecl(decl_index); var code_buffer = std.ArrayList(u8).init(gpa); @@ -500,7 +499,7 @@ pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: InternPool.De }; self.syms.items[info.sym_index.?] = sym; - const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), tv, &code_buffer, .{ + const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), val, &code_buffer, .{ .none = {}, }, .{ .parent_atom_index = new_atom_idx, @@ -539,10 +538,7 @@ pub fn updateDecl(self: *Plan9, mod: *Module, decl_index: InternPool.DeclIndex) defer code_buffer.deinit(); const decl_val = if (decl.val.getVariable(mod)) |variable| Value.fromInterned(variable.init) else decl.val; // TODO we need the symbol index for symbol in the table of locals for the containing atom - const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), .{ - .ty = decl.typeOf(mod), - .val = decl_val, - }, &code_buffer, .{ .none = {} }, .{ + const res = try codegen.generateSymbol(&self.base, decl.srcLoc(mod), decl_val, &code_buffer, .{ .none = {} }, .{ .parent_atom_index = @as(Atom.Index, @intCast(atom_idx)), }); const code = switch (res) { @@ -1545,11 +1541,8 @@ pub fn lowerAnonDecl( // ... const gpa = self.base.comp.gpa; const gop = try self.anon_decls.getOrPut(gpa, decl_val); - const mod = self.base.comp.module.?; if (!gop.found_existing) { - const ty = Type.fromInterned(mod.intern_pool.typeOf(decl_val)); const val = Value.fromInterned(decl_val); - const tv = TypedValue{ .ty = ty, .val = val }; const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(decl_val)}); const index = try self.createAtom(); @@ -1557,7 +1550,7 @@ pub fn lowerAnonDecl( gop.value_ptr.* = index; // we need to free name latex var code_buffer = std.ArrayList(u8).init(gpa); - const res = try codegen.generateSymbol(&self.base, src_loc, tv, &code_buffer, .{ .none = {} }, .{ .parent_atom_index = index }); + const res = try codegen.generateSymbol(&self.base, src_loc, val, &code_buffer, .{ .none = {} }, .{ .parent_atom_index = index }); const code = switch (res) { .ok => code_buffer.items, .fail => |em| return .{ .fail = em }, diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index c8fea56c16..ce91beedae 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -32,7 +32,7 @@ const Module = @import("../Module.zig"); const Object = @import("Wasm/Object.zig"); const Symbol = @import("Wasm/Symbol.zig"); const Type = @import("../type.zig").Type; -const TypedValue = @import("../TypedValue.zig"); +const Value = @import("../Value.zig"); const ZigObject = @import("Wasm/ZigObject.zig"); pub const Atom = @import("Wasm/Atom.zig"); @@ -1504,8 +1504,8 @@ fn getFunctionSignature(wasm: *const Wasm, loc: SymbolLoc) std.wasm.Type { /// Lowers a constant typed value to a local symbol and atom. /// Returns the symbol index of the local /// The given `decl` is the parent decl whom owns the constant. -pub fn lowerUnnamedConst(wasm: *Wasm, tv: TypedValue, decl_index: InternPool.DeclIndex) !u32 { - return wasm.zigObjectPtr().?.lowerUnnamedConst(wasm, tv, decl_index); +pub fn lowerUnnamedConst(wasm: *Wasm, val: Value, decl_index: InternPool.DeclIndex) !u32 { + return wasm.zigObjectPtr().?.lowerUnnamedConst(wasm, val, decl_index); } /// Returns the symbol index from a symbol of which its flag is set global, diff --git a/src/link/Wasm/ZigObject.zig b/src/link/Wasm/ZigObject.zig index 293c088c66..9bf7718d2b 100644 --- a/src/link/Wasm/ZigObject.zig +++ b/src/link/Wasm/ZigObject.zig @@ -270,7 +270,7 @@ pub fn updateDecl( const res = try codegen.generateSymbol( &wasm_file.base, decl.srcLoc(mod), - .{ .ty = decl.typeOf(mod), .val = val }, + val, &code_writer, .none, .{ .parent_atom_index = @intFromEnum(atom.sym_index) }, @@ -444,15 +444,12 @@ pub fn lowerAnonDecl( const gpa = wasm_file.base.comp.gpa; const gop = try zig_object.anon_decls.getOrPut(gpa, decl_val); if (!gop.found_existing) { - const mod = wasm_file.base.comp.module.?; - const ty = Type.fromInterned(mod.intern_pool.typeOf(decl_val)); - const tv: TypedValue = .{ .ty = ty, .val = Value.fromInterned(decl_val) }; var name_buf: [32]u8 = undefined; const name = std.fmt.bufPrint(&name_buf, "__anon_{d}", .{ @intFromEnum(decl_val), }) catch unreachable; - switch (try zig_object.lowerConst(wasm_file, name, tv, src_loc)) { + switch (try zig_object.lowerConst(wasm_file, name, Value.fromInterned(decl_val), src_loc)) { .ok => |atom_index| zig_object.anon_decls.values()[gop.index] = atom_index, .fail => |em| return .{ .fail = em }, } @@ -472,10 +469,10 @@ pub fn lowerAnonDecl( /// Lowers a constant typed value to a local symbol and atom. /// Returns the symbol index of the local /// The given `decl` is the parent decl whom owns the constant. -pub fn lowerUnnamedConst(zig_object: *ZigObject, wasm_file: *Wasm, tv: TypedValue, decl_index: InternPool.DeclIndex) !u32 { +pub fn lowerUnnamedConst(zig_object: *ZigObject, wasm_file: *Wasm, val: Value, decl_index: InternPool.DeclIndex) !u32 { const gpa = wasm_file.base.comp.gpa; const mod = wasm_file.base.comp.module.?; - std.debug.assert(tv.ty.zigTypeTag(mod) != .Fn); // cannot create local symbols for functions + std.debug.assert(val.typeOf(mod).zigTypeTag(mod) != .Fn); // cannot create local symbols for functions const decl = mod.declPtr(decl_index); const parent_atom_index = try zig_object.getOrCreateAtomForDecl(wasm_file, decl_index); @@ -487,7 +484,7 @@ pub fn lowerUnnamedConst(zig_object: *ZigObject, wasm_file: *Wasm, tv: TypedValu }); defer gpa.free(name); - switch (try zig_object.lowerConst(wasm_file, name, tv, decl.srcLoc(mod))) { + switch (try zig_object.lowerConst(wasm_file, name, val, decl.srcLoc(mod))) { .ok => |atom_index| { try wasm_file.getAtomPtr(parent_atom_index).locals.append(gpa, atom_index); return @intFromEnum(wasm_file.getAtom(atom_index).sym_index); @@ -505,10 +502,12 @@ const LowerConstResult = union(enum) { fail: *Module.ErrorMsg, }; -fn lowerConst(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8, tv: TypedValue, src_loc: Module.SrcLoc) !LowerConstResult { +fn lowerConst(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8, val: Value, src_loc: Module.SrcLoc) !LowerConstResult { const gpa = wasm_file.base.comp.gpa; const mod = wasm_file.base.comp.module.?; + const ty = val.typeOf(mod); + // Create and initialize a new local symbol and atom const sym_index = try zig_object.allocateSymbol(gpa); const atom_index = try wasm_file.createAtom(sym_index, zig_object.index); @@ -517,7 +516,7 @@ fn lowerConst(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8, tv: Ty const code = code: { const atom = wasm_file.getAtomPtr(atom_index); - atom.alignment = tv.ty.abiAlignment(mod); + atom.alignment = ty.abiAlignment(mod); const segment_name = try std.mem.concat(gpa, u8, &.{ ".rodata.", name }); errdefer gpa.free(segment_name); zig_object.symbol(sym_index).* = .{ @@ -527,7 +526,7 @@ fn lowerConst(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8, tv: Ty .index = try zig_object.createDataSegment( gpa, segment_name, - tv.ty.abiAlignment(mod), + ty.abiAlignment(mod), ), .virtual_address = undefined, }; @@ -535,7 +534,7 @@ fn lowerConst(zig_object: *ZigObject, wasm_file: *Wasm, name: []const u8, tv: Ty const result = try codegen.generateSymbol( &wasm_file.base, src_loc, - tv, + val, &value_bytes, .none, .{ @@ -1242,7 +1241,6 @@ const Module = @import("../../Module.zig"); const StringTable = @import("../StringTable.zig"); const Symbol = @import("Symbol.zig"); const Type = @import("../../type.zig").Type; -const TypedValue = @import("../../TypedValue.zig"); const Value = @import("../../Value.zig"); const Wasm = @import("../Wasm.zig"); const ZigObject = @This(); diff --git a/src/type.zig b/src/type.zig index a382a5ad97..5d67f13cbd 100644 --- a/src/type.zig +++ b/src/type.zig @@ -7,7 +7,6 @@ const Module = @import("Module.zig"); const Zcu = Module; const log = std.log.scoped(.Type); const target_util = @import("target.zig"); -const TypedValue = @import("TypedValue.zig"); const Sema = @import("Sema.zig"); const InternPool = @import("InternPool.zig"); const Alignment = InternPool.Alignment; -- cgit v1.2.3 From 513254956525f8f970e972f6973ab4df0b19d06a Mon Sep 17 00:00:00 2001 From: mlugg Date: Tue, 26 Mar 2024 21:35:21 +0000 Subject: Zcu: remove some unused functions --- src/Module.zig | 50 -------------------------------------------------- 1 file changed, 50 deletions(-) (limited to 'src/Module.zig') diff --git a/src/Module.zig b/src/Module.zig index df39a2a869..d4a4522441 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -425,14 +425,6 @@ pub const Decl = struct { return @as(i32, @bitCast(node_index)) - @as(i32, @bitCast(decl.src_node)); } - pub fn tokSrcLoc(decl: Decl, token_index: Ast.TokenIndex) LazySrcLoc { - return .{ .token_offset = token_index - decl.srcToken() }; - } - - pub fn nodeSrcLoc(decl: Decl, node_index: Ast.Node.Index) LazySrcLoc { - return LazySrcLoc.nodeOffset(decl.nodeIndexToRelative(node_index)); - } - pub fn srcLoc(decl: Decl, zcu: *Zcu) SrcLoc { return decl.nodeOffsetSrcLoc(0, zcu); } @@ -445,16 +437,6 @@ pub const Decl = struct { }; } - pub fn srcToken(decl: Decl, zcu: *Zcu) Ast.TokenIndex { - const tree = &decl.getFileScope(zcu).tree; - return tree.firstToken(decl.src_node); - } - - pub fn srcByteOffset(decl: Decl, zcu: *Zcu) u32 { - const tree = &decl.getFileScope(zcu).tree; - return tree.tokens.items(.start)[decl.srcToken()]; - } - pub fn renderFullyQualifiedName(decl: Decl, zcu: *Zcu, writer: anytype) !void { if (decl.name_fully_qualified) { try writer.print("{}", .{decl.name.fmt(&zcu.intern_pool)}); @@ -486,22 +468,6 @@ pub const Decl = struct { return decl.val; } - /// If the Decl owns its value and it is a struct, return it, - /// otherwise null. - pub fn getOwnedStruct(decl: Decl, zcu: *Zcu) ?InternPool.Key.StructType { - if (!decl.owns_tv) return null; - if (decl.val.ip_index == .none) return null; - return zcu.typeToStruct(decl.val.toType()); - } - - /// If the Decl owns its value and it is a union, return it, - /// otherwise null. - pub fn getOwnedUnion(decl: Decl, zcu: *Zcu) ?InternPool.LoadedUnionType { - if (!decl.owns_tv) return null; - if (decl.val.ip_index == .none) return null; - return zcu.typeToUnion(decl.val.toType()); - } - pub fn getOwnedFunction(decl: Decl, zcu: *Zcu) ?InternPool.Key.Func { const i = decl.getOwnedFunctionIndex(); if (i == .none) return null; @@ -4427,22 +4393,6 @@ fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void } } -/// This function is exclusively called for anonymous decls. -/// All resources referenced by anonymous decls are owned by InternPool -/// so there is no cleanup to do here. -pub fn deleteUnusedDecl(mod: *Module, decl_index: Decl.Index) void { - const gpa = mod.gpa; - const ip = &mod.intern_pool; - - ip.destroyDecl(gpa, decl_index); - - if (mod.emit_h) |mod_emit_h| { - const decl_emit_h = mod_emit_h.declPtr(decl_index); - decl_emit_h.fwd_decl.deinit(gpa); - decl_emit_h.* = undefined; - } -} - /// Cancel the creation of an anon decl and delete any references to it. /// If other decls depend on this decl, they must be aborted first. pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void { -- cgit v1.2.3