Commit c0b5512544
Changed files (10)
src/arch/wasm/CodeGen.zig
@@ -3075,6 +3075,7 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue
.decl => |decl_index| {
return func.lowerParentPtrDecl(ptr_val, decl_index, offset);
},
+ .anon_decl => @panic("TODO"),
.mut_decl => |mut_decl| {
const decl_index = mut_decl.decl;
return func.lowerParentPtrDecl(ptr_val, decl_index, offset);
src/codegen/c.zig
@@ -604,6 +604,7 @@ pub const DeclGen = struct {
},
location,
),
+ .anon_decl => @panic("TODO"),
.int => |int| {
try writer.writeByte('(');
try dg.renderCType(writer, ptr_cty);
@@ -1155,6 +1156,7 @@ pub const DeclGen = struct {
},
ptr_location,
),
+ .anon_decl => @panic("TODO"),
.int => |int| {
try writer.writeAll("((");
try dg.renderType(writer, ptr_ty);
src/codegen/llvm.zig
@@ -810,6 +810,8 @@ pub const Object = struct {
/// * it works for functions not all globals.
/// Therefore, this table keeps track of the mapping.
decl_map: std.AutoHashMapUnmanaged(Module.Decl.Index, Builder.Global.Index),
+ /// Same deal as `decl_map` but for anonymous declarations, which are always global constants.
+ anon_decl_map: std.AutoHashMapUnmanaged(InternPool.Index, Builder.Global.Index),
/// Serves the same purpose as `decl_map` but only used for the `is_named_enum_value` instruction.
named_enum_map: std.AutoHashMapUnmanaged(Module.Decl.Index, Builder.Function.Index),
/// Maps Zig types to LLVM types. The table memory is backed by the GPA of
@@ -993,6 +995,7 @@ pub const Object = struct {
.target_data = target_data,
.target = options.target,
.decl_map = .{},
+ .anon_decl_map = .{},
.named_enum_map = .{},
.type_map = .{},
.di_type_map = .{},
@@ -1011,6 +1014,7 @@ pub const Object = struct {
self.target_machine.dispose();
}
self.decl_map.deinit(gpa);
+ self.anon_decl_map.deinit(gpa);
self.named_enum_map.deinit(gpa);
self.type_map.deinit(gpa);
self.extern_collisions.deinit(gpa);
@@ -3038,6 +3042,31 @@ pub const Object = struct {
}
}
+ fn resolveGlobalAnonDecl(
+ o: *Object,
+ decl_val: InternPool.Index,
+ llvm_addr_space: Builder.AddrSpace,
+ ) Error!Builder.Variable.Index {
+ const gop = try o.anon_decl_map.getOrPut(o.gpa, decl_val);
+ if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.variable;
+ errdefer assert(o.anon_decl_map.remove(decl_val));
+
+ const mod = o.module;
+ const decl_ty = mod.intern_pool.typeOf(decl_val);
+
+ const variable_index = try o.builder.addVariable(
+ try o.builder.fmt("__anon_{d}", .{@intFromEnum(decl_val)}),
+ try o.lowerType(decl_ty.toType()),
+ llvm_addr_space,
+ );
+ gop.value_ptr.* = variable_index.ptrConst(&o.builder).global;
+
+ try variable_index.setInitializer(try o.lowerValue(decl_val), &o.builder);
+ variable_index.setLinkage(.internal, &o.builder);
+ variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
+ return variable_index;
+ }
+
fn resolveGlobalDecl(
o: *Object,
decl_index: Module.Decl.Index,
@@ -3764,6 +3793,7 @@ pub const Object = struct {
const ptr_val = switch (ptr.addr) {
.decl => |decl| try o.lowerDeclRefValue(ptr_ty, decl),
.mut_decl => |mut_decl| try o.lowerDeclRefValue(ptr_ty, mut_decl.decl),
+ .anon_decl => |anon_decl| try o.lowerAnonDeclRef(ptr_ty, anon_decl),
.int => |int| try o.lowerIntAsPtr(int),
.eu_payload,
.opt_payload,
@@ -4216,10 +4246,12 @@ pub const Object = struct {
return o.builder.bigIntConst(try o.builder.intType(ty.intInfo(mod).bits), bigint);
}
- const ParentPtr = struct {
- ty: Type,
- llvm_ptr: Builder.Value,
- };
+ fn lowerParentPtrAnonDecl(o: *Object, decl_val: InternPool.Index) Error!Builder.Constant {
+ const mod = o.module;
+ const decl_ty = mod.intern_pool.typeOf(decl_val).toType();
+ const ptr_ty = try mod.singleMutPtrType(decl_ty);
+ return o.lowerAnonDeclRef(ptr_ty, decl_val);
+ }
fn lowerParentPtrDecl(o: *Object, decl_index: Module.Decl.Index) Allocator.Error!Builder.Constant {
const mod = o.module;
@@ -4229,13 +4261,14 @@ pub const Object = struct {
return o.lowerDeclRefValue(ptr_ty, decl_index);
}
- fn lowerParentPtr(o: *Object, ptr_val: Value) Allocator.Error!Builder.Constant {
+ fn lowerParentPtr(o: *Object, ptr_val: Value) Error!Builder.Constant {
const mod = o.module;
const ip = &mod.intern_pool;
const ptr = ip.indexToKey(ptr_val.toIntern()).ptr;
return switch (ptr.addr) {
- .decl => |decl| o.lowerParentPtrDecl(decl),
- .mut_decl => |mut_decl| o.lowerParentPtrDecl(mut_decl.decl),
+ .decl => |decl| try o.lowerParentPtrDecl(decl),
+ .mut_decl => |mut_decl| try o.lowerParentPtrDecl(mut_decl.decl),
+ .anon_decl => |anon_decl| try o.lowerParentPtrAnonDecl(anon_decl),
.int => |int| try o.lowerIntAsPtr(int),
.eu_payload => |eu_ptr| {
const parent_ptr = try o.lowerParentPtr(eu_ptr.toValue());
@@ -4349,6 +4382,49 @@ pub const Object = struct {
};
}
+ /// This logic is very similar to `lowerDeclRefValue` but for anonymous declarations.
+ /// Maybe the logic could be unified.
+ fn lowerAnonDeclRef(
+ o: *Object,
+ ptr_ty: Type,
+ decl_val: InternPool.Index,
+ ) Error!Builder.Constant {
+ const mod = o.module;
+ const ip = &mod.intern_pool;
+ const decl_ty = ip.typeOf(decl_val).toType();
+ const target = mod.getTarget();
+
+ if (decl_val.toValue().getFunction(mod)) |func| {
+ _ = func;
+ @panic("TODO");
+ } else if (decl_val.toValue().getExternFunc(mod)) |func| {
+ _ = func;
+ @panic("TODO");
+ }
+
+ const is_fn_body = decl_ty.zigTypeTag(mod) == .Fn;
+ if ((!is_fn_body and !decl_ty.hasRuntimeBits(mod)) or
+ (is_fn_body and mod.typeToFunc(decl_ty).?.is_generic)) return o.lowerPtrToVoid(ptr_ty);
+
+ if (is_fn_body)
+ @panic("TODO");
+
+ const addr_space = target_util.defaultAddressSpace(target, .global_constant);
+ const llvm_addr_space = toLlvmAddressSpace(addr_space, target);
+ const llvm_global = (try o.resolveGlobalAnonDecl(decl_val, llvm_addr_space)).ptrConst(&o.builder).global;
+
+ const llvm_val = try o.builder.convConst(
+ .unneeded,
+ llvm_global.toConst(),
+ try o.builder.ptrType(llvm_addr_space),
+ );
+
+ return o.builder.convConst(if (ptr_ty.isAbiInt(mod)) switch (ptr_ty.intInfo(mod).signedness) {
+ .signed => .signed,
+ .unsigned => .unsigned,
+ } else .unneeded, llvm_val, try o.lowerType(ptr_ty));
+ }
+
fn lowerDeclRefValue(o: *Object, ty: Type, decl_index: Module.Decl.Index) Allocator.Error!Builder.Constant {
const mod = o.module;
src/codegen/spirv.zig
@@ -818,6 +818,7 @@ pub const DeclGen = struct {
const mod = self.module;
switch (mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr.addr) {
.decl => |decl| return try self.constructDeclRef(ptr_ty, decl),
+ .anon_decl => @panic("TODO"),
.mut_decl => |decl_mut| return try self.constructDeclRef(ptr_ty, decl_mut.decl),
.int => |int| {
const ptr_id = self.spv.allocId();
src/codegen.zig
@@ -655,6 +655,7 @@ fn lowerParentPtr(
debug_output,
reloc_info,
),
+ .anon_decl => @panic("TODO"),
.int => |int| try generateSymbol(bin_file, src_loc, .{
.ty = Type.usize,
.val = int.toValue(),
src/InternPool.zig
@@ -1074,6 +1074,7 @@ pub const Key = union(enum) {
decl: Module.Decl.Index,
mut_decl: MutDecl,
+ anon_decl: Index,
comptime_field: Index,
int: Index,
eu_payload: Index,
@@ -1230,10 +1231,12 @@ pub const Key = union(enum) {
asBytes(&x.decl) ++ asBytes(&x.runtime_index),
),
- .int, .eu_payload, .opt_payload, .comptime_field => |int| Hash.hash(
- seed2,
- asBytes(&int),
- ),
+ .anon_decl,
+ .int,
+ .eu_payload,
+ .opt_payload,
+ .comptime_field,
+ => |int| Hash.hash(seed2, asBytes(&int)),
.elem, .field => |x| Hash.hash(
seed2,
@@ -1497,6 +1500,7 @@ pub const Key = union(enum) {
return switch (a_info.addr) {
.decl => |a_decl| a_decl == b_info.addr.decl,
.mut_decl => |a_mut_decl| std.meta.eql(a_mut_decl, b_info.addr.mut_decl),
+ .anon_decl => |a_decl| a_decl == b_info.addr.anon_decl,
.int => |a_int| a_int == b_info.addr.int,
.eu_payload => |a_eu_payload| a_eu_payload == b_info.addr.eu_payload,
.opt_payload => |a_opt_payload| a_opt_payload == b_info.addr.opt_payload,
@@ -2123,6 +2127,7 @@ pub const Index = enum(u32) {
simple_value: struct { data: SimpleValue },
ptr_decl: struct { data: *PtrDecl },
ptr_mut_decl: struct { data: *PtrMutDecl },
+ ptr_anon_decl: struct { data: *PtrAnonDecl },
ptr_comptime_field: struct { data: *PtrComptimeField },
ptr_int: struct { data: *PtrBase },
ptr_eu_payload: struct { data: *PtrBase },
@@ -2572,6 +2577,9 @@ pub const Tag = enum(u8) {
/// A pointer to a decl that can be mutated at comptime.
/// data is extra index of `PtrMutDecl`, which contains the type and address.
ptr_mut_decl,
+ /// A pointer to an anonymous decl.
+ /// data is extra index of `PtrAnonDecl`, which contains the type and decl value.
+ ptr_anon_decl,
/// data is extra index of `PtrComptimeField`, which contains the pointer type and field value.
ptr_comptime_field,
/// A pointer with an integer value.
@@ -2767,6 +2775,7 @@ pub const Tag = enum(u8) {
.simple_value => unreachable,
.ptr_decl => PtrDecl,
.ptr_mut_decl => PtrMutDecl,
+ .ptr_anon_decl => PtrAnonDecl,
.ptr_comptime_field => PtrComptimeField,
.ptr_int => PtrBase,
.ptr_eu_payload => PtrBase,
@@ -3364,6 +3373,11 @@ pub const PtrDecl = struct {
decl: Module.Decl.Index,
};
+pub const PtrAnonDecl = struct {
+ ty: Index,
+ val: Index,
+};
+
pub const PtrMutDecl = struct {
ty: Index,
decl: Module.Decl.Index,
@@ -3713,6 +3727,13 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
} },
} };
},
+ .ptr_anon_decl => {
+ const info = ip.extraData(PtrAnonDecl, data);
+ return .{ .ptr = .{
+ .ty = info.ty,
+ .addr = .{ .anon_decl = info.val },
+ } };
+ },
.ptr_comptime_field => {
const info = ip.extraData(PtrComptimeField, data);
return .{ .ptr = .{
@@ -3790,6 +3811,9 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
.runtime_index = sub_info.runtime_index,
} };
},
+ .ptr_anon_decl => .{
+ .anon_decl = ip.extraData(PtrAnonDecl, ptr_item.data).val,
+ },
.ptr_comptime_field => .{
.comptime_field = ip.extraData(PtrComptimeField, ptr_item.data).field_val,
},
@@ -4542,6 +4566,13 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
.runtime_index = mut_decl.runtime_index,
}),
}),
+ .anon_decl => |anon_decl| ip.items.appendAssumeCapacity(.{
+ .tag = .ptr_anon_decl,
+ .data = try ip.addExtra(gpa, PtrAnonDecl{
+ .ty = ptr.ty,
+ .val = anon_decl,
+ }),
+ }),
.comptime_field => |field_val| {
assert(field_val != .none);
ip.items.appendAssumeCapacity(.{
@@ -7147,6 +7178,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
.simple_value => 0,
.ptr_decl => @sizeOf(PtrDecl),
.ptr_mut_decl => @sizeOf(PtrMutDecl),
+ .ptr_anon_decl => @sizeOf(PtrAnonDecl),
.ptr_comptime_field => @sizeOf(PtrComptimeField),
.ptr_int => @sizeOf(PtrBase),
.ptr_eu_payload => @sizeOf(PtrBase),
@@ -7276,6 +7308,7 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {
.runtime_value,
.ptr_decl,
.ptr_mut_decl,
+ .ptr_anon_decl,
.ptr_comptime_field,
.ptr_int,
.ptr_eu_payload,
@@ -7656,6 +7689,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
inline .ptr_decl,
.ptr_mut_decl,
+ .ptr_anon_decl,
.ptr_comptime_field,
.ptr_int,
.ptr_eu_payload,
@@ -7816,6 +7850,7 @@ pub fn getBackingAddrTag(ip: *const InternPool, val: Index) ?Key.Ptr.Addr.Tag {
switch (ip.items.items(.tag)[base]) {
.ptr_decl => return .decl,
.ptr_mut_decl => return .mut_decl,
+ .ptr_anon_decl => return .anon_decl,
.ptr_comptime_field => return .comptime_field,
.ptr_int => return .int,
inline .ptr_eu_payload,
@@ -7991,6 +8026,7 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
.simple_value,
.ptr_decl,
.ptr_mut_decl,
+ .ptr_anon_decl,
.ptr_comptime_field,
.ptr_int,
.ptr_eu_payload,
src/Module.zig
@@ -109,9 +109,6 @@ comptime_capture_scopes: std.AutoArrayHashMapUnmanaged(CaptureScope.Key, InternP
/// This memory lives until the Module is destroyed.
tmp_hack_arena: std.heap.ArenaAllocator,
-/// This is currently only used for string literals.
-memoized_decls: std.AutoHashMapUnmanaged(InternPool.Index, Decl.Index) = .{},
-
/// We optimize memory usage for a compilation with no compile errors by storing the
/// error messages and mapping outside of `Decl`.
/// The ErrorMsg memory is owned by the decl, using Module's general purpose allocator.
@@ -2627,7 +2624,6 @@ pub fn deinit(mod: *Module) void {
mod.global_assembly.deinit(gpa);
mod.reference_table.deinit(gpa);
- mod.memoized_decls.deinit(gpa);
mod.intern_pool.deinit(gpa);
mod.tmp_hack_arena.deinit();
@@ -5814,6 +5810,7 @@ pub fn markReferencedDeclsAlive(mod: *Module, val: Value) Allocator.Error!void {
.ptr => |ptr| {
switch (ptr.addr) {
.decl => |decl| try mod.markDeclIndexAlive(decl),
+ .anon_decl => {},
.mut_decl => |mut_decl| try mod.markDeclIndexAlive(mut_decl.decl),
.int, .comptime_field => {},
.eu_payload, .opt_payload => |parent| try mod.markReferencedDeclsAlive(parent.toValue()),
src/Sema.zig
@@ -1091,7 +1091,7 @@ fn analyzeBodyInner(
.slice_sentinel => try sema.zirSliceSentinel(block, inst),
.slice_start => try sema.zirSliceStart(block, inst),
.slice_length => try sema.zirSliceLength(block, inst),
- .str => try sema.zirStr(block, inst),
+ .str => try sema.zirStr(inst),
.switch_block => try sema.zirSwitchBlock(block, inst, false),
.switch_block_ref => try sema.zirSwitchBlock(block, inst, true),
.type_info => try sema.zirTypeInfo(block, inst),
@@ -2185,7 +2185,7 @@ fn resolveMaybeUndefValIntable(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Va
if (val.ip_index == .none) return val;
if (sema.mod.intern_pool.isVariable(val.toIntern())) return null;
if (sema.mod.intern_pool.getBackingAddrTag(val.toIntern())) |addr| switch (addr) {
- .decl, .mut_decl, .comptime_field => return null,
+ .decl, .anon_decl, .mut_decl, .comptime_field => return null,
.int => {},
.eu_payload, .opt_payload, .elem, .field => unreachable,
};
@@ -5501,38 +5501,40 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v
return sema.storePtr2(block, src, ptr, ptr_src, operand, operand_src, air_tag);
}
-fn zirStr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
- const tracy = trace(@src());
- defer tracy.end();
-
+fn zirStr(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
const bytes = sema.code.instructions.items(.data)[inst].str.get(sema.code);
- return sema.addStrLit(block, bytes);
+ return sema.addStrLitNoAlias(bytes);
}
-fn addStrLit(sema: *Sema, block: *Block, bytes: []const u8) CompileError!Air.Inst.Ref {
- const mod = sema.mod;
- const gpa = sema.gpa;
- // TODO: write something like getCoercedInts to avoid needing to dupe
+fn addStrLit(sema: *Sema, bytes: []const u8) CompileError!Air.Inst.Ref {
const duped_bytes = try sema.arena.dupe(u8, bytes);
- const ty = try mod.arrayType(.{
+ return addStrLitNoAlias(sema, duped_bytes);
+}
+
+/// Safe to call when `bytes` does not point into `InternPool`.
+fn addStrLitNoAlias(sema: *Sema, bytes: []const u8) CompileError!Air.Inst.Ref {
+ const mod = sema.mod;
+ const array_ty = try mod.arrayType(.{
.len = bytes.len,
.sentinel = .zero_u8,
.child = .u8_type,
});
const val = try mod.intern(.{ .aggregate = .{
- .ty = ty.toIntern(),
- .storage = .{ .bytes = duped_bytes },
+ .ty = array_ty.toIntern(),
+ .storage = .{ .bytes = bytes },
} });
- const gop = try mod.memoized_decls.getOrPut(gpa, val);
- if (!gop.found_existing) {
- const new_decl_index = try mod.createAnonymousDecl(block, .{
- .ty = ty,
- .val = val.toValue(),
- });
- gop.value_ptr.* = new_decl_index;
- try mod.finalizeAnonDecl(new_decl_index);
- }
- return sema.analyzeDeclRef(gop.value_ptr.*);
+ const ptr_ty = try sema.ptrType(.{
+ .child = array_ty.toIntern(),
+ .flags = .{
+ .alignment = .none,
+ .is_const = true,
+ .address_space = .generic,
+ },
+ });
+ return Air.internedToRef((try mod.intern(.{ .ptr = .{
+ .ty = ptr_ty.toIntern(),
+ .addr = .{ .anon_decl = val },
+ } })));
}
fn zirInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -12907,7 +12909,7 @@ fn maybeErrorUnwrap(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, op
try sema.zirSaveErrRetIndex(block, inst);
continue;
},
- .str => try sema.zirStr(block, inst),
+ .str => try sema.zirStr(inst),
.as_node => try sema.zirAsNode(block, inst),
.field_val => try sema.zirFieldVal(block, inst),
.@"unreachable" => {
@@ -20170,7 +20172,7 @@ fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
if (try sema.resolveDefinedValue(block, operand_src, operand)) |val| {
const err_name = sema.mod.intern_pool.indexToKey(val.toIntern()).err.name;
- return sema.addStrLit(block, sema.mod.intern_pool.stringToSlice(err_name));
+ return sema.addStrLit(sema.mod.intern_pool.stringToSlice(err_name));
}
// Similar to zirTagName, we have special AIR instruction for the error name in case an optimimzation pass
@@ -20288,7 +20290,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
.EnumLiteral => {
const val = try sema.resolveConstValue(block, .unneeded, operand, undefined);
const tag_name = ip.indexToKey(val.toIntern()).enum_literal;
- return sema.addStrLit(block, ip.stringToSlice(tag_name));
+ return sema.addStrLit(ip.stringToSlice(tag_name));
},
.Enum => operand_ty,
.Union => operand_ty.unionTagType(mod) orelse {
@@ -20330,7 +20332,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
};
// TODO: write something like getCoercedInts to avoid needing to dupe
const field_name = enum_ty.enumFieldName(field_index, mod);
- return sema.addStrLit(block, ip.stringToSlice(field_name));
+ return sema.addStrLit(ip.stringToSlice(field_name));
}
try sema.requireRuntimeBlock(block, src, operand_src);
if (block.wantSafety() and sema.mod.backendSupportsFeature(.is_named_enum_value)) {
@@ -29859,7 +29861,7 @@ fn beginComptimePtrMutation(
const mod = sema.mod;
const ptr = mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr;
switch (ptr.addr) {
- .decl, .int => unreachable, // isComptimeMutablePtr has been checked already
+ .decl, .anon_decl, .int => unreachable, // isComptimeMutablePtr has been checked already
.mut_decl => |mut_decl| {
const decl = mod.declPtr(mut_decl.decl);
return sema.beginComptimePtrMutationInner(block, src, decl.ty, &decl.val, ptr_elem_ty, mut_decl);
@@ -30455,9 +30457,10 @@ fn beginComptimePtrLoad(
maybe_array_ty: ?Type,
) ComptimePtrLoadError!ComptimePtrLoadKit {
const mod = sema.mod;
+ const ip = &mod.intern_pool;
const target = mod.getTarget();
- var deref: ComptimePtrLoadKit = switch (mod.intern_pool.indexToKey(ptr_val.toIntern())) {
+ var deref: ComptimePtrLoadKit = switch (ip.indexToKey(ptr_val.toIntern())) {
.ptr => |ptr| switch (ptr.addr) {
.decl, .mut_decl => blk: {
const decl_index = switch (ptr.addr) {
@@ -30478,9 +30481,21 @@ fn beginComptimePtrLoad(
.ty_without_well_defined_layout = if (!layout_defined) decl.ty else null,
};
},
+ .anon_decl => |decl_val| blk: {
+ if (decl_val.toValue().getVariable(mod) != null) return error.RuntimeLoad;
+ const decl_ty = ip.typeOf(decl_val).toType();
+ const decl_tv: TypedValue = .{ .ty = decl_ty, .val = decl_val.toValue() };
+ 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,
+ .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 = mod.intern_pool.typeOf(container_ptr).toType().childType(mod);
+ const container_ty = ip.typeOf(container_ptr).toType().childType(mod);
const payload_ty = switch (ptr.addr) {
.eu_payload => container_ty.errorUnionPayload(mod),
.opt_payload => container_ty.optionalChild(mod),
@@ -30502,13 +30517,13 @@ fn beginComptimePtrLoad(
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 => switch (mod.intern_pool.indexToKey(tv.val.toIntern())) {
+ else => switch (ip.indexToKey(tv.val.toIntern())) {
.error_union => |error_union| switch (error_union.val) {
.err_name => |err_name| return sema.fail(
block,
src,
"attempt to unwrap error: {}",
- .{err_name.fmt(&mod.intern_pool)},
+ .{err_name.fmt(ip)},
),
.payload => |payload| payload,
},
@@ -30527,7 +30542,7 @@ fn beginComptimePtrLoad(
break :blk deref;
},
.comptime_field => |comptime_field| blk: {
- const field_ty = mod.intern_pool.typeOf(comptime_field).toType();
+ const field_ty = ip.typeOf(comptime_field).toType();
break :blk ComptimePtrLoadKit{
.parent = null,
.pointee = .{ .ty = field_ty, .val = comptime_field.toValue() },
@@ -30536,15 +30551,15 @@ fn beginComptimePtrLoad(
};
},
.elem => |elem_ptr| blk: {
- const elem_ty = mod.intern_pool.typeOf(elem_ptr.base).toType().elemType2(mod);
+ const elem_ty = ip.typeOf(elem_ptr.base).toType().elemType2(mod);
var deref = try sema.beginComptimePtrLoad(block, src, elem_ptr.base.toValue(), null);
// This code assumes that elem_ptrs have been "flattened" in order for direct dereference
// to succeed, meaning that elem ptrs of the same elem_ty are coalesced. Here we check that
// our parent is not an elem_ptr with the same elem_ty, since that would be "unflattened"
- switch (mod.intern_pool.indexToKey(elem_ptr.base)) {
+ switch (ip.indexToKey(elem_ptr.base)) {
.ptr => |base_ptr| switch (base_ptr.addr) {
- .elem => |base_elem| assert(!mod.intern_pool.typeOf(base_elem.base).toType().elemType2(mod).eql(elem_ty, mod)),
+ .elem => |base_elem| assert(!ip.typeOf(base_elem.base).toType().elemType2(mod).eql(elem_ty, mod)),
else => {},
},
else => {},
@@ -30616,7 +30631,7 @@ fn beginComptimePtrLoad(
},
.field => |field_ptr| blk: {
const field_index: u32 = @intCast(field_ptr.index);
- const container_ty = mod.intern_pool.typeOf(field_ptr.base).toType().childType(mod);
+ const container_ty = ip.typeOf(field_ptr.base).toType().childType(mod);
var deref = try sema.beginComptimePtrLoad(block, src, field_ptr.base.toValue(), container_ty);
if (container_ty.hasWellDefinedLayout(mod)) {
@@ -30655,7 +30670,7 @@ fn beginComptimePtrLoad(
},
Value.slice_len_index => TypedValue{
.ty = Type.usize,
- .val = mod.intern_pool.indexToKey(try tv.val.intern(tv.ty, mod)).ptr.len.toValue(),
+ .val = ip.indexToKey(try tv.val.intern(tv.ty, mod)).ptr.len.toValue(),
},
else => unreachable,
};
@@ -34529,7 +34544,7 @@ fn resolveLazyValue(sema: *Sema, val: Value) CompileError!Value {
else => (try sema.resolveLazyValue(ptr.len.toValue())).toIntern(),
};
switch (ptr.addr) {
- .decl, .mut_decl => return if (resolved_len == ptr.len)
+ .decl, .mut_decl, .anon_decl => return if (resolved_len == ptr.len)
val
else
(try mod.intern(.{ .ptr = .{
@@ -34537,6 +34552,7 @@ fn resolveLazyValue(sema: *Sema, val: Value) CompileError!Value {
.addr = switch (ptr.addr) {
.decl => |decl| .{ .decl = decl },
.mut_decl => |mut_decl| .{ .mut_decl = mut_decl },
+ .anon_decl => |anon_decl| .{ .anon_decl = anon_decl },
else => unreachable,
},
.len = resolved_len,
@@ -36568,6 +36584,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
.runtime_value,
.simple_value,
.ptr_decl,
+ .ptr_anon_decl,
.ptr_mut_decl,
.ptr_comptime_field,
.ptr_int,
src/TypedValue.zig
@@ -321,6 +321,15 @@ pub fn print(
.val = decl.val,
}, writer, level - 1, mod);
},
+ .anon_decl => |decl_val| {
+ if (level == 0) return writer.print("(anon decl '{d}')", .{
+ @intFromEnum(decl_val),
+ });
+ return print(.{
+ .ty = ip.typeOf(decl_val).toType(),
+ .val = decl_val.toValue(),
+ }, writer, level - 1, mod);
+ },
.mut_decl => |mut_decl| {
const decl = mod.declPtr(mut_decl.decl);
if (level == 0) return writer.print("(mut decl '{}')", .{decl.name.fmt(ip)});
src/value.zig
@@ -1565,12 +1565,14 @@ pub const Value = struct {
}
pub fn sliceLen(val: Value, mod: *Module) u64 {
- const ptr = mod.intern_pool.indexToKey(val.toIntern()).ptr;
+ const ip = &mod.intern_pool;
+ const ptr = ip.indexToKey(val.toIntern()).ptr;
return switch (ptr.len) {
- .none => switch (mod.intern_pool.indexToKey(switch (ptr.addr) {
+ .none => switch (ip.indexToKey(switch (ptr.addr) {
.decl => |decl| mod.declPtr(decl).ty.toIntern(),
.mut_decl => |mut_decl| mod.declPtr(mut_decl.decl).ty.toIntern(),
- .comptime_field => |comptime_field| mod.intern_pool.typeOf(comptime_field),
+ .anon_decl => |anon_decl| ip.typeOf(anon_decl),
+ .comptime_field => |comptime_field| ip.typeOf(comptime_field),
else => unreachable,
})) {
.array_type => |array_type| array_type.len,
@@ -1602,6 +1604,7 @@ pub const Value = struct {
})).toValue(),
.ptr => |ptr| switch (ptr.addr) {
.decl => |decl| mod.declPtr(decl).val.maybeElemValue(mod, index),
+ .anon_decl => |anon_decl| anon_decl.toValue().maybeElemValue(mod, index),
.mut_decl => |mut_decl| (try mod.declPtr(mut_decl.decl).internValue(mod))
.toValue().maybeElemValue(mod, index),
.int, .eu_payload => null,