authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-09-24 19:22:25-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-10-03 12:12:50-07:00
logc0b55125443cab63945205b2f7c66bf12cae71e1
treec47592afbee6b860b6a611e594ab8e7ed732e621
parent4df7f7c86a0a105b5d3764121f259a39487a6c8a

compiler: start handling anonymous decls differently

Instead of explicitly creating a `Module.Decl` object for each anonymous declaration, each `InternPool.Index` value is implicitly understood to be an anonymous declaration when encountered by backend codegen. The memory management strategy for these anonymous decls then becomes to garbage collect them along with standard InternPool garbage. In the interest of a smooth transition, this commit only implements this new scheme for string literals and leaves all the previous mechanisms in place.

10 files changed, 201 insertions(+), 58 deletions(-)

src/InternPool.zig+40-4
...@@ -1074,6 +1074,7 @@ pub const Key = union(enum) {...@@ -1074,6 +1074,7 @@ pub const Key = union(enum) {
10741074
1075 decl: Module.Decl.Index,1075 decl: Module.Decl.Index,
1076 mut_decl: MutDecl,1076 mut_decl: MutDecl,
1077 anon_decl: Index,
1077 comptime_field: Index,1078 comptime_field: Index,
1078 int: Index,1079 int: Index,
1079 eu_payload: Index,1080 eu_payload: Index,
...@@ -1230,10 +1231,12 @@ pub const Key = union(enum) {...@@ -1230,10 +1231,12 @@ pub const Key = union(enum) {
1230 asBytes(&x.decl) ++ asBytes(&x.runtime_index),1231 asBytes(&x.decl) ++ asBytes(&x.runtime_index),
1231 ),1232 ),
12321233
1233 .int, .eu_payload, .opt_payload, .comptime_field => |int| Hash.hash(1234 .anon_decl,
1234 seed2,1235 .int,
1235 asBytes(&int),1236 .eu_payload,
1236 ),1237 .opt_payload,
1238 .comptime_field,
1239 => |int| Hash.hash(seed2, asBytes(&int)),
12371240
1238 .elem, .field => |x| Hash.hash(1241 .elem, .field => |x| Hash.hash(
1239 seed2,1242 seed2,
...@@ -1497,6 +1500,7 @@ pub const Key = union(enum) {...@@ -1497,6 +1500,7 @@ pub const Key = union(enum) {
1497 return switch (a_info.addr) {1500 return switch (a_info.addr) {
1498 .decl => |a_decl| a_decl == b_info.addr.decl,1501 .decl => |a_decl| a_decl == b_info.addr.decl,
1499 .mut_decl => |a_mut_decl| std.meta.eql(a_mut_decl, b_info.addr.mut_decl),1502 .mut_decl => |a_mut_decl| std.meta.eql(a_mut_decl, b_info.addr.mut_decl),
1503 .anon_decl => |a_decl| a_decl == b_info.addr.anon_decl,
1500 .int => |a_int| a_int == b_info.addr.int,1504 .int => |a_int| a_int == b_info.addr.int,
1501 .eu_payload => |a_eu_payload| a_eu_payload == b_info.addr.eu_payload,1505 .eu_payload => |a_eu_payload| a_eu_payload == b_info.addr.eu_payload,
1502 .opt_payload => |a_opt_payload| a_opt_payload == b_info.addr.opt_payload,1506 .opt_payload => |a_opt_payload| a_opt_payload == b_info.addr.opt_payload,
...@@ -2123,6 +2127,7 @@ pub const Index = enum(u32) {...@@ -2123,6 +2127,7 @@ pub const Index = enum(u32) {
2123 simple_value: struct { data: SimpleValue },2127 simple_value: struct { data: SimpleValue },
2124 ptr_decl: struct { data: *PtrDecl },2128 ptr_decl: struct { data: *PtrDecl },
2125 ptr_mut_decl: struct { data: *PtrMutDecl },2129 ptr_mut_decl: struct { data: *PtrMutDecl },
2130 ptr_anon_decl: struct { data: *PtrAnonDecl },
2126 ptr_comptime_field: struct { data: *PtrComptimeField },2131 ptr_comptime_field: struct { data: *PtrComptimeField },
2127 ptr_int: struct { data: *PtrBase },2132 ptr_int: struct { data: *PtrBase },
2128 ptr_eu_payload: struct { data: *PtrBase },2133 ptr_eu_payload: struct { data: *PtrBase },
...@@ -2572,6 +2577,9 @@ pub const Tag = enum(u8) {...@@ -2572,6 +2577,9 @@ pub const Tag = enum(u8) {
2572 /// A pointer to a decl that can be mutated at comptime.2577 /// A pointer to a decl that can be mutated at comptime.
2573 /// data is extra index of `PtrMutDecl`, which contains the type and address.2578 /// data is extra index of `PtrMutDecl`, which contains the type and address.
2574 ptr_mut_decl,2579 ptr_mut_decl,
2580 /// A pointer to an anonymous decl.
2581 /// data is extra index of `PtrAnonDecl`, which contains the type and decl value.
2582 ptr_anon_decl,
2575 /// data is extra index of `PtrComptimeField`, which contains the pointer type and field value.2583 /// data is extra index of `PtrComptimeField`, which contains the pointer type and field value.
2576 ptr_comptime_field,2584 ptr_comptime_field,
2577 /// A pointer with an integer value.2585 /// A pointer with an integer value.
...@@ -2767,6 +2775,7 @@ pub const Tag = enum(u8) {...@@ -2767,6 +2775,7 @@ pub const Tag = enum(u8) {
2767 .simple_value => unreachable,2775 .simple_value => unreachable,
2768 .ptr_decl => PtrDecl,2776 .ptr_decl => PtrDecl,
2769 .ptr_mut_decl => PtrMutDecl,2777 .ptr_mut_decl => PtrMutDecl,
2778 .ptr_anon_decl => PtrAnonDecl,
2770 .ptr_comptime_field => PtrComptimeField,2779 .ptr_comptime_field => PtrComptimeField,
2771 .ptr_int => PtrBase,2780 .ptr_int => PtrBase,
2772 .ptr_eu_payload => PtrBase,2781 .ptr_eu_payload => PtrBase,
...@@ -3364,6 +3373,11 @@ pub const PtrDecl = struct {...@@ -3364,6 +3373,11 @@ pub const PtrDecl = struct {
3364 decl: Module.Decl.Index,3373 decl: Module.Decl.Index,
3365};3374};
33663375
3376pub const PtrAnonDecl = struct {
3377 ty: Index,
3378 val: Index,
3379};
3380
3367pub const PtrMutDecl = struct {3381pub const PtrMutDecl = struct {
3368 ty: Index,3382 ty: Index,
3369 decl: Module.Decl.Index,3383 decl: Module.Decl.Index,
...@@ -3713,6 +3727,13 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -3713,6 +3727,13 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
3713 } },3727 } },
3714 } };3728 } };
3715 },3729 },
3730 .ptr_anon_decl => {
3731 const info = ip.extraData(PtrAnonDecl, data);
3732 return .{ .ptr = .{
3733 .ty = info.ty,
3734 .addr = .{ .anon_decl = info.val },
3735 } };
3736 },
3716 .ptr_comptime_field => {3737 .ptr_comptime_field => {
3717 const info = ip.extraData(PtrComptimeField, data);3738 const info = ip.extraData(PtrComptimeField, data);
3718 return .{ .ptr = .{3739 return .{ .ptr = .{
...@@ -3790,6 +3811,9 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {...@@ -3790,6 +3811,9 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
3790 .runtime_index = sub_info.runtime_index,3811 .runtime_index = sub_info.runtime_index,
3791 } };3812 } };
3792 },3813 },
3814 .ptr_anon_decl => .{
3815 .anon_decl = ip.extraData(PtrAnonDecl, ptr_item.data).val,
3816 },
3793 .ptr_comptime_field => .{3817 .ptr_comptime_field => .{
3794 .comptime_field = ip.extraData(PtrComptimeField, ptr_item.data).field_val,3818 .comptime_field = ip.extraData(PtrComptimeField, ptr_item.data).field_val,
3795 },3819 },
...@@ -4542,6 +4566,13 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -4542,6 +4566,13 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
4542 .runtime_index = mut_decl.runtime_index,4566 .runtime_index = mut_decl.runtime_index,
4543 }),4567 }),
4544 }),4568 }),
4569 .anon_decl => |anon_decl| ip.items.appendAssumeCapacity(.{
4570 .tag = .ptr_anon_decl,
4571 .data = try ip.addExtra(gpa, PtrAnonDecl{
4572 .ty = ptr.ty,
4573 .val = anon_decl,
4574 }),
4575 }),
4545 .comptime_field => |field_val| {4576 .comptime_field => |field_val| {
4546 assert(field_val != .none);4577 assert(field_val != .none);
4547 ip.items.appendAssumeCapacity(.{4578 ip.items.appendAssumeCapacity(.{
...@@ -7147,6 +7178,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {...@@ -7147,6 +7178,7 @@ fn dumpStatsFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
7147 .simple_value => 0,7178 .simple_value => 0,
7148 .ptr_decl => @sizeOf(PtrDecl),7179 .ptr_decl => @sizeOf(PtrDecl),
7149 .ptr_mut_decl => @sizeOf(PtrMutDecl),7180 .ptr_mut_decl => @sizeOf(PtrMutDecl),
7181 .ptr_anon_decl => @sizeOf(PtrAnonDecl),
7150 .ptr_comptime_field => @sizeOf(PtrComptimeField),7182 .ptr_comptime_field => @sizeOf(PtrComptimeField),
7151 .ptr_int => @sizeOf(PtrBase),7183 .ptr_int => @sizeOf(PtrBase),
7152 .ptr_eu_payload => @sizeOf(PtrBase),7184 .ptr_eu_payload => @sizeOf(PtrBase),
...@@ -7276,6 +7308,7 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {...@@ -7276,6 +7308,7 @@ fn dumpAllFallible(ip: *const InternPool) anyerror!void {
7276 .runtime_value,7308 .runtime_value,
7277 .ptr_decl,7309 .ptr_decl,
7278 .ptr_mut_decl,7310 .ptr_mut_decl,
7311 .ptr_anon_decl,
7279 .ptr_comptime_field,7312 .ptr_comptime_field,
7280 .ptr_int,7313 .ptr_int,
7281 .ptr_eu_payload,7314 .ptr_eu_payload,
...@@ -7656,6 +7689,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {...@@ -7656,6 +7689,7 @@ pub fn typeOf(ip: *const InternPool, index: Index) Index {
76567689
7657 inline .ptr_decl,7690 inline .ptr_decl,
7658 .ptr_mut_decl,7691 .ptr_mut_decl,
7692 .ptr_anon_decl,
7659 .ptr_comptime_field,7693 .ptr_comptime_field,
7660 .ptr_int,7694 .ptr_int,
7661 .ptr_eu_payload,7695 .ptr_eu_payload,
...@@ -7816,6 +7850,7 @@ pub fn getBackingAddrTag(ip: *const InternPool, val: Index) ?Key.Ptr.Addr.Tag {...@@ -7816,6 +7850,7 @@ pub fn getBackingAddrTag(ip: *const InternPool, val: Index) ?Key.Ptr.Addr.Tag {
7816 switch (ip.items.items(.tag)[base]) {7850 switch (ip.items.items(.tag)[base]) {
7817 .ptr_decl => return .decl,7851 .ptr_decl => return .decl,
7818 .ptr_mut_decl => return .mut_decl,7852 .ptr_mut_decl => return .mut_decl,
7853 .ptr_anon_decl => return .anon_decl,
7819 .ptr_comptime_field => return .comptime_field,7854 .ptr_comptime_field => return .comptime_field,
7820 .ptr_int => return .int,7855 .ptr_int => return .int,
7821 inline .ptr_eu_payload,7856 inline .ptr_eu_payload,
...@@ -7991,6 +8026,7 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois...@@ -7991,6 +8026,7 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois
7991 .simple_value,8026 .simple_value,
7992 .ptr_decl,8027 .ptr_decl,
7993 .ptr_mut_decl,8028 .ptr_mut_decl,
8029 .ptr_anon_decl,
7994 .ptr_comptime_field,8030 .ptr_comptime_field,
7995 .ptr_int,8031 .ptr_int,
7996 .ptr_eu_payload,8032 .ptr_eu_payload,
src/Module.zig+1-4
...@@ -109,9 +109,6 @@ comptime_capture_scopes: std.AutoArrayHashMapUnmanaged(CaptureScope.Key, InternP...@@ -109,9 +109,6 @@ comptime_capture_scopes: std.AutoArrayHashMapUnmanaged(CaptureScope.Key, InternP
109/// This memory lives until the Module is destroyed.109/// This memory lives until the Module is destroyed.
110tmp_hack_arena: std.heap.ArenaAllocator,110tmp_hack_arena: std.heap.ArenaAllocator,
111111
112/// This is currently only used for string literals.
113memoized_decls: std.AutoHashMapUnmanaged(InternPool.Index, Decl.Index) = .{},
114
115/// We optimize memory usage for a compilation with no compile errors by storing the112/// We optimize memory usage for a compilation with no compile errors by storing the
116/// error messages and mapping outside of `Decl`.113/// error messages and mapping outside of `Decl`.
117/// The ErrorMsg memory is owned by the decl, using Module's general purpose allocator.114/// The ErrorMsg memory is owned by the decl, using Module's general purpose allocator.
...@@ -2627,7 +2624,6 @@ pub fn deinit(mod: *Module) void {...@@ -2627,7 +2624,6 @@ pub fn deinit(mod: *Module) void {
2627 mod.global_assembly.deinit(gpa);2624 mod.global_assembly.deinit(gpa);
2628 mod.reference_table.deinit(gpa);2625 mod.reference_table.deinit(gpa);
26292626
2630 mod.memoized_decls.deinit(gpa);
2631 mod.intern_pool.deinit(gpa);2627 mod.intern_pool.deinit(gpa);
2632 mod.tmp_hack_arena.deinit();2628 mod.tmp_hack_arena.deinit();
26332629
...@@ -5814,6 +5810,7 @@ pub fn markReferencedDeclsAlive(mod: *Module, val: Value) Allocator.Error!void {...@@ -5814,6 +5810,7 @@ pub fn markReferencedDeclsAlive(mod: *Module, val: Value) Allocator.Error!void {
5814 .ptr => |ptr| {5810 .ptr => |ptr| {
5815 switch (ptr.addr) {5811 switch (ptr.addr) {
5816 .decl => |decl| try mod.markDeclIndexAlive(decl),5812 .decl => |decl| try mod.markDeclIndexAlive(decl),
5813 .anon_decl => {},
5817 .mut_decl => |mut_decl| try mod.markDeclIndexAlive(mut_decl.decl),5814 .mut_decl => |mut_decl| try mod.markDeclIndexAlive(mut_decl.decl),
5818 .int, .comptime_field => {},5815 .int, .comptime_field => {},
5819 .eu_payload, .opt_payload => |parent| try mod.markReferencedDeclsAlive(parent.toValue()),5816 .eu_payload, .opt_payload => |parent| try mod.markReferencedDeclsAlive(parent.toValue()),
src/Sema.zig+57-40
...@@ -1091,7 +1091,7 @@ fn analyzeBodyInner(...@@ -1091,7 +1091,7 @@ fn analyzeBodyInner(
1091 .slice_sentinel => try sema.zirSliceSentinel(block, inst),1091 .slice_sentinel => try sema.zirSliceSentinel(block, inst),
1092 .slice_start => try sema.zirSliceStart(block, inst),1092 .slice_start => try sema.zirSliceStart(block, inst),
1093 .slice_length => try sema.zirSliceLength(block, inst),1093 .slice_length => try sema.zirSliceLength(block, inst),
1094 .str => try sema.zirStr(block, inst),1094 .str => try sema.zirStr(inst),
1095 .switch_block => try sema.zirSwitchBlock(block, inst, false),1095 .switch_block => try sema.zirSwitchBlock(block, inst, false),
1096 .switch_block_ref => try sema.zirSwitchBlock(block, inst, true),1096 .switch_block_ref => try sema.zirSwitchBlock(block, inst, true),
1097 .type_info => try sema.zirTypeInfo(block, inst),1097 .type_info => try sema.zirTypeInfo(block, inst),
...@@ -2185,7 +2185,7 @@ fn resolveMaybeUndefValIntable(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Va...@@ -2185,7 +2185,7 @@ fn resolveMaybeUndefValIntable(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Va
2185 if (val.ip_index == .none) return val;2185 if (val.ip_index == .none) return val;
2186 if (sema.mod.intern_pool.isVariable(val.toIntern())) return null;2186 if (sema.mod.intern_pool.isVariable(val.toIntern())) return null;
2187 if (sema.mod.intern_pool.getBackingAddrTag(val.toIntern())) |addr| switch (addr) {2187 if (sema.mod.intern_pool.getBackingAddrTag(val.toIntern())) |addr| switch (addr) {
2188 .decl, .mut_decl, .comptime_field => return null,2188 .decl, .anon_decl, .mut_decl, .comptime_field => return null,
2189 .int => {},2189 .int => {},
2190 .eu_payload, .opt_payload, .elem, .field => unreachable,2190 .eu_payload, .opt_payload, .elem, .field => unreachable,
2191 };2191 };
...@@ -5501,38 +5501,40 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v...@@ -5501,38 +5501,40 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v
5501 return sema.storePtr2(block, src, ptr, ptr_src, operand, operand_src, air_tag);5501 return sema.storePtr2(block, src, ptr, ptr_src, operand, operand_src, air_tag);
5502}5502}
55035503
5504fn zirStr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {5504fn zirStr(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
5505 const tracy = trace(@src());
5506 defer tracy.end();
5507
5508 const bytes = sema.code.instructions.items(.data)[inst].str.get(sema.code);5505 const bytes = sema.code.instructions.items(.data)[inst].str.get(sema.code);
5509 return sema.addStrLit(block, bytes);5506 return sema.addStrLitNoAlias(bytes);
5510}5507}
55115508
5512fn addStrLit(sema: *Sema, block: *Block, bytes: []const u8) CompileError!Air.Inst.Ref {5509fn addStrLit(sema: *Sema, bytes: []const u8) CompileError!Air.Inst.Ref {
5513 const mod = sema.mod;
5514 const gpa = sema.gpa;
5515 // TODO: write something like getCoercedInts to avoid needing to dupe
5516 const duped_bytes = try sema.arena.dupe(u8, bytes);5510 const duped_bytes = try sema.arena.dupe(u8, bytes);
5517 const ty = try mod.arrayType(.{5511 return addStrLitNoAlias(sema, duped_bytes);
5512}
5513
5514/// Safe to call when `bytes` does not point into `InternPool`.
5515fn addStrLitNoAlias(sema: *Sema, bytes: []const u8) CompileError!Air.Inst.Ref {
5516 const mod = sema.mod;
5517 const array_ty = try mod.arrayType(.{
5518 .len = bytes.len,5518 .len = bytes.len,
5519 .sentinel = .zero_u8,5519 .sentinel = .zero_u8,
5520 .child = .u8_type,5520 .child = .u8_type,
5521 });5521 });
5522 const val = try mod.intern(.{ .aggregate = .{5522 const val = try mod.intern(.{ .aggregate = .{
5523 .ty = ty.toIntern(),5523 .ty = array_ty.toIntern(),
5524 .storage = .{ .bytes = duped_bytes },5524 .storage = .{ .bytes = bytes },
5525 } });5525 } });
5526 const gop = try mod.memoized_decls.getOrPut(gpa, val);5526 const ptr_ty = try sema.ptrType(.{
5527 if (!gop.found_existing) {5527 .child = array_ty.toIntern(),
5528 const new_decl_index = try mod.createAnonymousDecl(block, .{5528 .flags = .{
5529 .ty = ty,5529 .alignment = .none,
5530 .val = val.toValue(),5530 .is_const = true,
5531 });5531 .address_space = .generic,
5532 gop.value_ptr.* = new_decl_index;5532 },
5533 try mod.finalizeAnonDecl(new_decl_index);5533 });
5534 }5534 return Air.internedToRef((try mod.intern(.{ .ptr = .{
5535 return sema.analyzeDeclRef(gop.value_ptr.*);5535 .ty = ptr_ty.toIntern(),
5536 .addr = .{ .anon_decl = val },
5537 } })));
5536}5538}
55375539
5538fn zirInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {5540fn 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...@@ -12907,7 +12909,7 @@ fn maybeErrorUnwrap(sema: *Sema, block: *Block, body: []const Zir.Inst.Index, op
12907 try sema.zirSaveErrRetIndex(block, inst);12909 try sema.zirSaveErrRetIndex(block, inst);
12908 continue;12910 continue;
12909 },12911 },
12910 .str => try sema.zirStr(block, inst),12912 .str => try sema.zirStr(inst),
12911 .as_node => try sema.zirAsNode(block, inst),12913 .as_node => try sema.zirAsNode(block, inst),
12912 .field_val => try sema.zirFieldVal(block, inst),12914 .field_val => try sema.zirFieldVal(block, inst),
12913 .@"unreachable" => {12915 .@"unreachable" => {
...@@ -20170,7 +20172,7 @@ fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A...@@ -20170,7 +20172,7 @@ fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
2017020172
20171 if (try sema.resolveDefinedValue(block, operand_src, operand)) |val| {20173 if (try sema.resolveDefinedValue(block, operand_src, operand)) |val| {
20172 const err_name = sema.mod.intern_pool.indexToKey(val.toIntern()).err.name;20174 const err_name = sema.mod.intern_pool.indexToKey(val.toIntern()).err.name;
20173 return sema.addStrLit(block, sema.mod.intern_pool.stringToSlice(err_name));20175 return sema.addStrLit(sema.mod.intern_pool.stringToSlice(err_name));
20174 }20176 }
2017520177
20176 // Similar to zirTagName, we have special AIR instruction for the error name in case an optimimzation pass20178 // 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...@@ -20288,7 +20290,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
20288 .EnumLiteral => {20290 .EnumLiteral => {
20289 const val = try sema.resolveConstValue(block, .unneeded, operand, undefined);20291 const val = try sema.resolveConstValue(block, .unneeded, operand, undefined);
20290 const tag_name = ip.indexToKey(val.toIntern()).enum_literal;20292 const tag_name = ip.indexToKey(val.toIntern()).enum_literal;
20291 return sema.addStrLit(block, ip.stringToSlice(tag_name));20293 return sema.addStrLit(ip.stringToSlice(tag_name));
20292 },20294 },
20293 .Enum => operand_ty,20295 .Enum => operand_ty,
20294 .Union => operand_ty.unionTagType(mod) orelse {20296 .Union => operand_ty.unionTagType(mod) orelse {
...@@ -20330,7 +20332,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -20330,7 +20332,7 @@ fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
20330 };20332 };
20331 // TODO: write something like getCoercedInts to avoid needing to dupe20333 // TODO: write something like getCoercedInts to avoid needing to dupe
20332 const field_name = enum_ty.enumFieldName(field_index, mod);20334 const field_name = enum_ty.enumFieldName(field_index, mod);
20333 return sema.addStrLit(block, ip.stringToSlice(field_name));20335 return sema.addStrLit(ip.stringToSlice(field_name));
20334 }20336 }
20335 try sema.requireRuntimeBlock(block, src, operand_src);20337 try sema.requireRuntimeBlock(block, src, operand_src);
20336 if (block.wantSafety() and sema.mod.backendSupportsFeature(.is_named_enum_value)) {20338 if (block.wantSafety() and sema.mod.backendSupportsFeature(.is_named_enum_value)) {
...@@ -29859,7 +29861,7 @@ fn beginComptimePtrMutation(...@@ -29859,7 +29861,7 @@ fn beginComptimePtrMutation(
29859 const mod = sema.mod;29861 const mod = sema.mod;
29860 const ptr = mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr;29862 const ptr = mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr;
29861 switch (ptr.addr) {29863 switch (ptr.addr) {
29862 .decl, .int => unreachable, // isComptimeMutablePtr has been checked already29864 .decl, .anon_decl, .int => unreachable, // isComptimeMutablePtr has been checked already
29863 .mut_decl => |mut_decl| {29865 .mut_decl => |mut_decl| {
29864 const decl = mod.declPtr(mut_decl.decl);29866 const decl = mod.declPtr(mut_decl.decl);
29865 return sema.beginComptimePtrMutationInner(block, src, decl.ty, &decl.val, ptr_elem_ty, mut_decl);29867 return sema.beginComptimePtrMutationInner(block, src, decl.ty, &decl.val, ptr_elem_ty, mut_decl);
...@@ -30455,9 +30457,10 @@ fn beginComptimePtrLoad(...@@ -30455,9 +30457,10 @@ fn beginComptimePtrLoad(
30455 maybe_array_ty: ?Type,30457 maybe_array_ty: ?Type,
30456) ComptimePtrLoadError!ComptimePtrLoadKit {30458) ComptimePtrLoadError!ComptimePtrLoadKit {
30457 const mod = sema.mod;30459 const mod = sema.mod;
30460 const ip = &mod.intern_pool;
30458 const target = mod.getTarget();30461 const target = mod.getTarget();
3045930462
30460 var deref: ComptimePtrLoadKit = switch (mod.intern_pool.indexToKey(ptr_val.toIntern())) {30463 var deref: ComptimePtrLoadKit = switch (ip.indexToKey(ptr_val.toIntern())) {
30461 .ptr => |ptr| switch (ptr.addr) {30464 .ptr => |ptr| switch (ptr.addr) {
30462 .decl, .mut_decl => blk: {30465 .decl, .mut_decl => blk: {
30463 const decl_index = switch (ptr.addr) {30466 const decl_index = switch (ptr.addr) {
...@@ -30478,9 +30481,21 @@ fn beginComptimePtrLoad(...@@ -30478,9 +30481,21 @@ fn beginComptimePtrLoad(
30478 .ty_without_well_defined_layout = if (!layout_defined) decl.ty else null,30481 .ty_without_well_defined_layout = if (!layout_defined) decl.ty else null,
30479 };30482 };
30480 },30483 },
30484 .anon_decl => |decl_val| blk: {
30485 if (decl_val.toValue().getVariable(mod) != null) return error.RuntimeLoad;
30486 const decl_ty = ip.typeOf(decl_val).toType();
30487 const decl_tv: TypedValue = .{ .ty = decl_ty, .val = decl_val.toValue() };
30488 const layout_defined = decl_ty.hasWellDefinedLayout(mod);
30489 break :blk ComptimePtrLoadKit{
30490 .parent = if (layout_defined) .{ .tv = decl_tv, .byte_offset = 0 } else null,
30491 .pointee = decl_tv,
30492 .is_mutable = false,
30493 .ty_without_well_defined_layout = if (!layout_defined) decl_ty else null,
30494 };
30495 },
30481 .int => return error.RuntimeLoad,30496 .int => return error.RuntimeLoad,
30482 .eu_payload, .opt_payload => |container_ptr| blk: {30497 .eu_payload, .opt_payload => |container_ptr| blk: {
30483 const container_ty = mod.intern_pool.typeOf(container_ptr).toType().childType(mod);30498 const container_ty = ip.typeOf(container_ptr).toType().childType(mod);
30484 const payload_ty = switch (ptr.addr) {30499 const payload_ty = switch (ptr.addr) {
30485 .eu_payload => container_ty.errorUnionPayload(mod),30500 .eu_payload => container_ty.errorUnionPayload(mod),
30486 .opt_payload => container_ty.optionalChild(mod),30501 .opt_payload => container_ty.optionalChild(mod),
...@@ -30502,13 +30517,13 @@ fn beginComptimePtrLoad(...@@ -30502,13 +30517,13 @@ fn beginComptimePtrLoad(
30502 const payload_val = switch (tv.val.ip_index) {30517 const payload_val = switch (tv.val.ip_index) {
30503 .none => tv.val.cast(Value.Payload.SubValue).?.data,30518 .none => tv.val.cast(Value.Payload.SubValue).?.data,
30504 .null_value => return sema.fail(block, src, "attempt to use null value", .{}),30519 .null_value => return sema.fail(block, src, "attempt to use null value", .{}),
30505 else => switch (mod.intern_pool.indexToKey(tv.val.toIntern())) {30520 else => switch (ip.indexToKey(tv.val.toIntern())) {
30506 .error_union => |error_union| switch (error_union.val) {30521 .error_union => |error_union| switch (error_union.val) {
30507 .err_name => |err_name| return sema.fail(30522 .err_name => |err_name| return sema.fail(
30508 block,30523 block,
30509 src,30524 src,
30510 "attempt to unwrap error: {}",30525 "attempt to unwrap error: {}",
30511 .{err_name.fmt(&mod.intern_pool)},30526 .{err_name.fmt(ip)},
30512 ),30527 ),
30513 .payload => |payload| payload,30528 .payload => |payload| payload,
30514 },30529 },
...@@ -30527,7 +30542,7 @@ fn beginComptimePtrLoad(...@@ -30527,7 +30542,7 @@ fn beginComptimePtrLoad(
30527 break :blk deref;30542 break :blk deref;
30528 },30543 },
30529 .comptime_field => |comptime_field| blk: {30544 .comptime_field => |comptime_field| blk: {
30530 const field_ty = mod.intern_pool.typeOf(comptime_field).toType();30545 const field_ty = ip.typeOf(comptime_field).toType();
30531 break :blk ComptimePtrLoadKit{30546 break :blk ComptimePtrLoadKit{
30532 .parent = null,30547 .parent = null,
30533 .pointee = .{ .ty = field_ty, .val = comptime_field.toValue() },30548 .pointee = .{ .ty = field_ty, .val = comptime_field.toValue() },
...@@ -30536,15 +30551,15 @@ fn beginComptimePtrLoad(...@@ -30536,15 +30551,15 @@ fn beginComptimePtrLoad(
30536 };30551 };
30537 },30552 },
30538 .elem => |elem_ptr| blk: {30553 .elem => |elem_ptr| blk: {
30539 const elem_ty = mod.intern_pool.typeOf(elem_ptr.base).toType().elemType2(mod);30554 const elem_ty = ip.typeOf(elem_ptr.base).toType().elemType2(mod);
30540 var deref = try sema.beginComptimePtrLoad(block, src, elem_ptr.base.toValue(), null);30555 var deref = try sema.beginComptimePtrLoad(block, src, elem_ptr.base.toValue(), null);
3054130556
30542 // This code assumes that elem_ptrs have been "flattened" in order for direct dereference30557 // This code assumes that elem_ptrs have been "flattened" in order for direct dereference
30543 // to succeed, meaning that elem ptrs of the same elem_ty are coalesced. Here we check that30558 // to succeed, meaning that elem ptrs of the same elem_ty are coalesced. Here we check that
30544 // our parent is not an elem_ptr with the same elem_ty, since that would be "unflattened"30559 // our parent is not an elem_ptr with the same elem_ty, since that would be "unflattened"
30545 switch (mod.intern_pool.indexToKey(elem_ptr.base)) {30560 switch (ip.indexToKey(elem_ptr.base)) {
30546 .ptr => |base_ptr| switch (base_ptr.addr) {30561 .ptr => |base_ptr| switch (base_ptr.addr) {
30547 .elem => |base_elem| assert(!mod.intern_pool.typeOf(base_elem.base).toType().elemType2(mod).eql(elem_ty, mod)),30562 .elem => |base_elem| assert(!ip.typeOf(base_elem.base).toType().elemType2(mod).eql(elem_ty, mod)),
30548 else => {},30563 else => {},
30549 },30564 },
30550 else => {},30565 else => {},
...@@ -30616,7 +30631,7 @@ fn beginComptimePtrLoad(...@@ -30616,7 +30631,7 @@ fn beginComptimePtrLoad(
30616 },30631 },
30617 .field => |field_ptr| blk: {30632 .field => |field_ptr| blk: {
30618 const field_index: u32 = @intCast(field_ptr.index);30633 const field_index: u32 = @intCast(field_ptr.index);
30619 const container_ty = mod.intern_pool.typeOf(field_ptr.base).toType().childType(mod);30634 const container_ty = ip.typeOf(field_ptr.base).toType().childType(mod);
30620 var deref = try sema.beginComptimePtrLoad(block, src, field_ptr.base.toValue(), container_ty);30635 var deref = try sema.beginComptimePtrLoad(block, src, field_ptr.base.toValue(), container_ty);
3062130636
30622 if (container_ty.hasWellDefinedLayout(mod)) {30637 if (container_ty.hasWellDefinedLayout(mod)) {
...@@ -30655,7 +30670,7 @@ fn beginComptimePtrLoad(...@@ -30655,7 +30670,7 @@ fn beginComptimePtrLoad(
30655 },30670 },
30656 Value.slice_len_index => TypedValue{30671 Value.slice_len_index => TypedValue{
30657 .ty = Type.usize,30672 .ty = Type.usize,
30658 .val = mod.intern_pool.indexToKey(try tv.val.intern(tv.ty, mod)).ptr.len.toValue(),30673 .val = ip.indexToKey(try tv.val.intern(tv.ty, mod)).ptr.len.toValue(),
30659 },30674 },
30660 else => unreachable,30675 else => unreachable,
30661 };30676 };
...@@ -34529,7 +34544,7 @@ fn resolveLazyValue(sema: *Sema, val: Value) CompileError!Value {...@@ -34529,7 +34544,7 @@ fn resolveLazyValue(sema: *Sema, val: Value) CompileError!Value {
34529 else => (try sema.resolveLazyValue(ptr.len.toValue())).toIntern(),34544 else => (try sema.resolveLazyValue(ptr.len.toValue())).toIntern(),
34530 };34545 };
34531 switch (ptr.addr) {34546 switch (ptr.addr) {
34532 .decl, .mut_decl => return if (resolved_len == ptr.len)34547 .decl, .mut_decl, .anon_decl => return if (resolved_len == ptr.len)
34533 val34548 val
34534 else34549 else
34535 (try mod.intern(.{ .ptr = .{34550 (try mod.intern(.{ .ptr = .{
...@@ -34537,6 +34552,7 @@ fn resolveLazyValue(sema: *Sema, val: Value) CompileError!Value {...@@ -34537,6 +34552,7 @@ fn resolveLazyValue(sema: *Sema, val: Value) CompileError!Value {
34537 .addr = switch (ptr.addr) {34552 .addr = switch (ptr.addr) {
34538 .decl => |decl| .{ .decl = decl },34553 .decl => |decl| .{ .decl = decl },
34539 .mut_decl => |mut_decl| .{ .mut_decl = mut_decl },34554 .mut_decl => |mut_decl| .{ .mut_decl = mut_decl },
34555 .anon_decl => |anon_decl| .{ .anon_decl = anon_decl },
34540 else => unreachable,34556 else => unreachable,
34541 },34557 },
34542 .len = resolved_len,34558 .len = resolved_len,
...@@ -36568,6 +36584,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {...@@ -36568,6 +36584,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
36568 .runtime_value,36584 .runtime_value,
36569 .simple_value,36585 .simple_value,
36570 .ptr_decl,36586 .ptr_decl,
36587 .ptr_anon_decl,
36571 .ptr_mut_decl,36588 .ptr_mut_decl,
36572 .ptr_comptime_field,36589 .ptr_comptime_field,
36573 .ptr_int,36590 .ptr_int,
src/TypedValue.zig+9
...@@ -321,6 +321,15 @@ pub fn print(...@@ -321,6 +321,15 @@ pub fn print(
321 .val = decl.val,321 .val = decl.val,
322 }, writer, level - 1, mod);322 }, writer, level - 1, mod);
323 },323 },
324 .anon_decl => |decl_val| {
325 if (level == 0) return writer.print("(anon decl '{d}')", .{
326 @intFromEnum(decl_val),
327 });
328 return print(.{
329 .ty = ip.typeOf(decl_val).toType(),
330 .val = decl_val.toValue(),
331 }, writer, level - 1, mod);
332 },
324 .mut_decl => |mut_decl| {333 .mut_decl => |mut_decl| {
325 const decl = mod.declPtr(mut_decl.decl);334 const decl = mod.declPtr(mut_decl.decl);
326 if (level == 0) return writer.print("(mut decl '{}')", .{decl.name.fmt(ip)});335 if (level == 0) return writer.print("(mut decl '{}')", .{decl.name.fmt(ip)});
src/arch/wasm/CodeGen.zig+1
...@@ -3075,6 +3075,7 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue...@@ -3075,6 +3075,7 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value, offset: u32) InnerError!WValue
3075 .decl => |decl_index| {3075 .decl => |decl_index| {
3076 return func.lowerParentPtrDecl(ptr_val, decl_index, offset);3076 return func.lowerParentPtrDecl(ptr_val, decl_index, offset);
3077 },3077 },
3078 .anon_decl => @panic("TODO"),
3078 .mut_decl => |mut_decl| {3079 .mut_decl => |mut_decl| {
3079 const decl_index = mut_decl.decl;3080 const decl_index = mut_decl.decl;
3080 return func.lowerParentPtrDecl(ptr_val, decl_index, offset);3081 return func.lowerParentPtrDecl(ptr_val, decl_index, offset);
src/codegen.zig+1
...@@ -655,6 +655,7 @@ fn lowerParentPtr(...@@ -655,6 +655,7 @@ fn lowerParentPtr(
655 debug_output,655 debug_output,
656 reloc_info,656 reloc_info,
657 ),657 ),
658 .anon_decl => @panic("TODO"),
658 .int => |int| try generateSymbol(bin_file, src_loc, .{659 .int => |int| try generateSymbol(bin_file, src_loc, .{
659 .ty = Type.usize,660 .ty = Type.usize,
660 .val = int.toValue(),661 .val = int.toValue(),
src/codegen/c.zig+2
...@@ -604,6 +604,7 @@ pub const DeclGen = struct {...@@ -604,6 +604,7 @@ pub const DeclGen = struct {
604 },604 },
605 location,605 location,
606 ),606 ),
607 .anon_decl => @panic("TODO"),
607 .int => |int| {608 .int => |int| {
608 try writer.writeByte('(');609 try writer.writeByte('(');
609 try dg.renderCType(writer, ptr_cty);610 try dg.renderCType(writer, ptr_cty);
...@@ -1155,6 +1156,7 @@ pub const DeclGen = struct {...@@ -1155,6 +1156,7 @@ pub const DeclGen = struct {
1155 },1156 },
1156 ptr_location,1157 ptr_location,
1157 ),1158 ),
1159 .anon_decl => @panic("TODO"),
1158 .int => |int| {1160 .int => |int| {
1159 try writer.writeAll("((");1161 try writer.writeAll("((");
1160 try dg.renderType(writer, ptr_ty);1162 try dg.renderType(writer, ptr_ty);
src/codegen/llvm.zig+83-7
...@@ -810,6 +810,8 @@ pub const Object = struct {...@@ -810,6 +810,8 @@ pub const Object = struct {
810 /// * it works for functions not all globals.810 /// * it works for functions not all globals.
811 /// Therefore, this table keeps track of the mapping.811 /// Therefore, this table keeps track of the mapping.
812 decl_map: std.AutoHashMapUnmanaged(Module.Decl.Index, Builder.Global.Index),812 decl_map: std.AutoHashMapUnmanaged(Module.Decl.Index, Builder.Global.Index),
813 /// Same deal as `decl_map` but for anonymous declarations, which are always global constants.
814 anon_decl_map: std.AutoHashMapUnmanaged(InternPool.Index, Builder.Global.Index),
813 /// Serves the same purpose as `decl_map` but only used for the `is_named_enum_value` instruction.815 /// Serves the same purpose as `decl_map` but only used for the `is_named_enum_value` instruction.
814 named_enum_map: std.AutoHashMapUnmanaged(Module.Decl.Index, Builder.Function.Index),816 named_enum_map: std.AutoHashMapUnmanaged(Module.Decl.Index, Builder.Function.Index),
815 /// Maps Zig types to LLVM types. The table memory is backed by the GPA of817 /// Maps Zig types to LLVM types. The table memory is backed by the GPA of
...@@ -993,6 +995,7 @@ pub const Object = struct {...@@ -993,6 +995,7 @@ pub const Object = struct {
993 .target_data = target_data,995 .target_data = target_data,
994 .target = options.target,996 .target = options.target,
995 .decl_map = .{},997 .decl_map = .{},
998 .anon_decl_map = .{},
996 .named_enum_map = .{},999 .named_enum_map = .{},
997 .type_map = .{},1000 .type_map = .{},
998 .di_type_map = .{},1001 .di_type_map = .{},
...@@ -1011,6 +1014,7 @@ pub const Object = struct {...@@ -1011,6 +1014,7 @@ pub const Object = struct {
1011 self.target_machine.dispose();1014 self.target_machine.dispose();
1012 }1015 }
1013 self.decl_map.deinit(gpa);1016 self.decl_map.deinit(gpa);
1017 self.anon_decl_map.deinit(gpa);
1014 self.named_enum_map.deinit(gpa);1018 self.named_enum_map.deinit(gpa);
1015 self.type_map.deinit(gpa);1019 self.type_map.deinit(gpa);
1016 self.extern_collisions.deinit(gpa);1020 self.extern_collisions.deinit(gpa);
...@@ -3038,6 +3042,31 @@ pub const Object = struct {...@@ -3038,6 +3042,31 @@ pub const Object = struct {
3038 }3042 }
3039 }3043 }
30403044
3045 fn resolveGlobalAnonDecl(
3046 o: *Object,
3047 decl_val: InternPool.Index,
3048 llvm_addr_space: Builder.AddrSpace,
3049 ) Error!Builder.Variable.Index {
3050 const gop = try o.anon_decl_map.getOrPut(o.gpa, decl_val);
3051 if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.variable;
3052 errdefer assert(o.anon_decl_map.remove(decl_val));
3053
3054 const mod = o.module;
3055 const decl_ty = mod.intern_pool.typeOf(decl_val);
3056
3057 const variable_index = try o.builder.addVariable(
3058 try o.builder.fmt("__anon_{d}", .{@intFromEnum(decl_val)}),
3059 try o.lowerType(decl_ty.toType()),
3060 llvm_addr_space,
3061 );
3062 gop.value_ptr.* = variable_index.ptrConst(&o.builder).global;
3063
3064 try variable_index.setInitializer(try o.lowerValue(decl_val), &o.builder);
3065 variable_index.setLinkage(.internal, &o.builder);
3066 variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
3067 return variable_index;
3068 }
3069
3041 fn resolveGlobalDecl(3070 fn resolveGlobalDecl(
3042 o: *Object,3071 o: *Object,
3043 decl_index: Module.Decl.Index,3072 decl_index: Module.Decl.Index,
...@@ -3764,6 +3793,7 @@ pub const Object = struct {...@@ -3764,6 +3793,7 @@ pub const Object = struct {
3764 const ptr_val = switch (ptr.addr) {3793 const ptr_val = switch (ptr.addr) {
3765 .decl => |decl| try o.lowerDeclRefValue(ptr_ty, decl),3794 .decl => |decl| try o.lowerDeclRefValue(ptr_ty, decl),
3766 .mut_decl => |mut_decl| try o.lowerDeclRefValue(ptr_ty, mut_decl.decl),3795 .mut_decl => |mut_decl| try o.lowerDeclRefValue(ptr_ty, mut_decl.decl),
3796 .anon_decl => |anon_decl| try o.lowerAnonDeclRef(ptr_ty, anon_decl),
3767 .int => |int| try o.lowerIntAsPtr(int),3797 .int => |int| try o.lowerIntAsPtr(int),
3768 .eu_payload,3798 .eu_payload,
3769 .opt_payload,3799 .opt_payload,
...@@ -4216,10 +4246,12 @@ pub const Object = struct {...@@ -4216,10 +4246,12 @@ pub const Object = struct {
4216 return o.builder.bigIntConst(try o.builder.intType(ty.intInfo(mod).bits), bigint);4246 return o.builder.bigIntConst(try o.builder.intType(ty.intInfo(mod).bits), bigint);
4217 }4247 }
42184248
4219 const ParentPtr = struct {4249 fn lowerParentPtrAnonDecl(o: *Object, decl_val: InternPool.Index) Error!Builder.Constant {
4220 ty: Type,4250 const mod = o.module;
4221 llvm_ptr: Builder.Value,4251 const decl_ty = mod.intern_pool.typeOf(decl_val).toType();
4222 };4252 const ptr_ty = try mod.singleMutPtrType(decl_ty);
4253 return o.lowerAnonDeclRef(ptr_ty, decl_val);
4254 }
42234255
4224 fn lowerParentPtrDecl(o: *Object, decl_index: Module.Decl.Index) Allocator.Error!Builder.Constant {4256 fn lowerParentPtrDecl(o: *Object, decl_index: Module.Decl.Index) Allocator.Error!Builder.Constant {
4225 const mod = o.module;4257 const mod = o.module;
...@@ -4229,13 +4261,14 @@ pub const Object = struct {...@@ -4229,13 +4261,14 @@ pub const Object = struct {
4229 return o.lowerDeclRefValue(ptr_ty, decl_index);4261 return o.lowerDeclRefValue(ptr_ty, decl_index);
4230 }4262 }
42314263
4232 fn lowerParentPtr(o: *Object, ptr_val: Value) Allocator.Error!Builder.Constant {4264 fn lowerParentPtr(o: *Object, ptr_val: Value) Error!Builder.Constant {
4233 const mod = o.module;4265 const mod = o.module;
4234 const ip = &mod.intern_pool;4266 const ip = &mod.intern_pool;
4235 const ptr = ip.indexToKey(ptr_val.toIntern()).ptr;4267 const ptr = ip.indexToKey(ptr_val.toIntern()).ptr;
4236 return switch (ptr.addr) {4268 return switch (ptr.addr) {
4237 .decl => |decl| o.lowerParentPtrDecl(decl),4269 .decl => |decl| try o.lowerParentPtrDecl(decl),
4238 .mut_decl => |mut_decl| o.lowerParentPtrDecl(mut_decl.decl),4270 .mut_decl => |mut_decl| try o.lowerParentPtrDecl(mut_decl.decl),
4271 .anon_decl => |anon_decl| try o.lowerParentPtrAnonDecl(anon_decl),
4239 .int => |int| try o.lowerIntAsPtr(int),4272 .int => |int| try o.lowerIntAsPtr(int),
4240 .eu_payload => |eu_ptr| {4273 .eu_payload => |eu_ptr| {
4241 const parent_ptr = try o.lowerParentPtr(eu_ptr.toValue());4274 const parent_ptr = try o.lowerParentPtr(eu_ptr.toValue());
...@@ -4349,6 +4382,49 @@ pub const Object = struct {...@@ -4349,6 +4382,49 @@ pub const Object = struct {
4349 };4382 };
4350 }4383 }
43514384
4385 /// This logic is very similar to `lowerDeclRefValue` but for anonymous declarations.
4386 /// Maybe the logic could be unified.
4387 fn lowerAnonDeclRef(
4388 o: *Object,
4389 ptr_ty: Type,
4390 decl_val: InternPool.Index,
4391 ) Error!Builder.Constant {
4392 const mod = o.module;
4393 const ip = &mod.intern_pool;
4394 const decl_ty = ip.typeOf(decl_val).toType();
4395 const target = mod.getTarget();
4396
4397 if (decl_val.toValue().getFunction(mod)) |func| {
4398 _ = func;
4399 @panic("TODO");
4400 } else if (decl_val.toValue().getExternFunc(mod)) |func| {
4401 _ = func;
4402 @panic("TODO");
4403 }
4404
4405 const is_fn_body = decl_ty.zigTypeTag(mod) == .Fn;
4406 if ((!is_fn_body and !decl_ty.hasRuntimeBits(mod)) or
4407 (is_fn_body and mod.typeToFunc(decl_ty).?.is_generic)) return o.lowerPtrToVoid(ptr_ty);
4408
4409 if (is_fn_body)
4410 @panic("TODO");
4411
4412 const addr_space = target_util.defaultAddressSpace(target, .global_constant);
4413 const llvm_addr_space = toLlvmAddressSpace(addr_space, target);
4414 const llvm_global = (try o.resolveGlobalAnonDecl(decl_val, llvm_addr_space)).ptrConst(&o.builder).global;
4415
4416 const llvm_val = try o.builder.convConst(
4417 .unneeded,
4418 llvm_global.toConst(),
4419 try o.builder.ptrType(llvm_addr_space),
4420 );
4421
4422 return o.builder.convConst(if (ptr_ty.isAbiInt(mod)) switch (ptr_ty.intInfo(mod).signedness) {
4423 .signed => .signed,
4424 .unsigned => .unsigned,
4425 } else .unneeded, llvm_val, try o.lowerType(ptr_ty));
4426 }
4427
4352 fn lowerDeclRefValue(o: *Object, ty: Type, decl_index: Module.Decl.Index) Allocator.Error!Builder.Constant {4428 fn lowerDeclRefValue(o: *Object, ty: Type, decl_index: Module.Decl.Index) Allocator.Error!Builder.Constant {
4353 const mod = o.module;4429 const mod = o.module;
43544430
src/codegen/spirv.zig+1
...@@ -818,6 +818,7 @@ pub const DeclGen = struct {...@@ -818,6 +818,7 @@ pub const DeclGen = struct {
818 const mod = self.module;818 const mod = self.module;
819 switch (mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr.addr) {819 switch (mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr.addr) {
820 .decl => |decl| return try self.constructDeclRef(ptr_ty, decl),820 .decl => |decl| return try self.constructDeclRef(ptr_ty, decl),
821 .anon_decl => @panic("TODO"),
821 .mut_decl => |decl_mut| return try self.constructDeclRef(ptr_ty, decl_mut.decl),822 .mut_decl => |decl_mut| return try self.constructDeclRef(ptr_ty, decl_mut.decl),
822 .int => |int| {823 .int => |int| {
823 const ptr_id = self.spv.allocId();824 const ptr_id = self.spv.allocId();
src/value.zig+6-3
...@@ -1565,12 +1565,14 @@ pub const Value = struct {...@@ -1565,12 +1565,14 @@ pub const Value = struct {
1565 }1565 }
15661566
1567 pub fn sliceLen(val: Value, mod: *Module) u64 {1567 pub fn sliceLen(val: Value, mod: *Module) u64 {
1568 const ptr = mod.intern_pool.indexToKey(val.toIntern()).ptr;1568 const ip = &mod.intern_pool;
1569 const ptr = ip.indexToKey(val.toIntern()).ptr;
1569 return switch (ptr.len) {1570 return switch (ptr.len) {
1570 .none => switch (mod.intern_pool.indexToKey(switch (ptr.addr) {1571 .none => switch (ip.indexToKey(switch (ptr.addr) {
1571 .decl => |decl| mod.declPtr(decl).ty.toIntern(),1572 .decl => |decl| mod.declPtr(decl).ty.toIntern(),
1572 .mut_decl => |mut_decl| mod.declPtr(mut_decl.decl).ty.toIntern(),1573 .mut_decl => |mut_decl| mod.declPtr(mut_decl.decl).ty.toIntern(),
1573 .comptime_field => |comptime_field| mod.intern_pool.typeOf(comptime_field),1574 .anon_decl => |anon_decl| ip.typeOf(anon_decl),
1575 .comptime_field => |comptime_field| ip.typeOf(comptime_field),
1574 else => unreachable,1576 else => unreachable,
1575 })) {1577 })) {
1576 .array_type => |array_type| array_type.len,1578 .array_type => |array_type| array_type.len,
...@@ -1602,6 +1604,7 @@ pub const Value = struct {...@@ -1602,6 +1604,7 @@ pub const Value = struct {
1602 })).toValue(),1604 })).toValue(),
1603 .ptr => |ptr| switch (ptr.addr) {1605 .ptr => |ptr| switch (ptr.addr) {
1604 .decl => |decl| mod.declPtr(decl).val.maybeElemValue(mod, index),1606 .decl => |decl| mod.declPtr(decl).val.maybeElemValue(mod, index),
1607 .anon_decl => |anon_decl| anon_decl.toValue().maybeElemValue(mod, index),
1605 .mut_decl => |mut_decl| (try mod.declPtr(mut_decl.decl).internValue(mod))1608 .mut_decl => |mut_decl| (try mod.declPtr(mut_decl.decl).internValue(mod))
1606 .toValue().maybeElemValue(mod, index),1609 .toValue().maybeElemValue(mod, index),
1607 .int, .eu_payload => null,1610 .int, .eu_payload => null,