diff options
| author | mlugg <mlugg@mlugg.co.uk> | 2023-08-14 13:06:47 +0100 |
|---|---|---|
| committer | mlugg <mlugg@mlugg.co.uk> | 2023-08-15 11:45:23 +0100 |
| commit | 083ee8e0e28ed0d1c4e1df6b5aa12f2709731b50 (patch) | |
| tree | be33c2a904c85361b9f732d6e57284754859f8e0 /src/Module.zig | |
| parent | 6e2eb208aac8bb6065992bd19a6c0cc772648263 (diff) | |
| download | zig-083ee8e0e28ed0d1c4e1df6b5aa12f2709731b50.tar.gz zig-083ee8e0e28ed0d1c4e1df6b5aa12f2709731b50.zip | |
InternPool: preserve indices of builtin types when resolved
Some builtin types have a special InternPool index (e.g.
`.type_info_type`) so that AstGen can refer to them before semantic
analysis. Unfortunately, this previously led to a second index existing
to refer to the type once it was resolved, complicating Sema by having
the concept of an "unresolved" type index.
This change makes Sema modify these InternPool indices in-place to
contain the expanded representation when resolved. The analysis of the
corresponding decls is caught in `Module.semaDecl`, and a field is set
on Sema telling it which index to place struct/union/enum types at. This
system could break if `std.builtin` contained complex decls which
evaluate multiple struct types, but this will be caught by the
assertions in `InternPool.resolveBuiltinType`.
The AstGen result types which were disabled in 6917a8c have been
re-enabled.
Resolves: #16603
Diffstat (limited to 'src/Module.zig')
| -rw-r--r-- | src/Module.zig | 55 |
1 files changed, 51 insertions, 4 deletions
diff --git a/src/Module.zig b/src/Module.zig index 06976ae49c..c19b742b54 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -770,9 +770,8 @@ pub const Decl = struct { /// Gets the namespace that this Decl creates by being a struct, union, /// enum, or opaque. - /// Only returns it if the Decl is the owner. - pub fn getOwnedInnerNamespaceIndex(decl: Decl, mod: *Module) Namespace.OptionalIndex { - if (!decl.owns_tv) return .none; + pub fn getInnerNamespaceIndex(decl: Decl, mod: *Module) Namespace.OptionalIndex { + if (!decl.has_tv) return .none; return switch (decl.val.ip_index) { .empty_struct_type => .none, .none => .none, @@ -786,11 +785,22 @@ pub const Decl = struct { }; } - /// Same as `getInnerNamespaceIndex` but additionally obtains the pointer. + /// Like `getInnerNamespaceIndex`, but only returns it if the Decl is the owner. + pub fn getOwnedInnerNamespaceIndex(decl: Decl, mod: *Module) Namespace.OptionalIndex { + if (!decl.owns_tv) return .none; + return decl.getInnerNamespaceIndex(mod); + } + + /// Same as `getOwnedInnerNamespaceIndex` but additionally obtains the pointer. pub fn getOwnedInnerNamespace(decl: Decl, mod: *Module) ?*Namespace { return mod.namespacePtrUnwrap(decl.getOwnedInnerNamespaceIndex(mod)); } + /// Same as `getInnerNamespaceIndex` but additionally obtains the pointer. + pub fn getInnerNamespace(decl: Decl, mod: *Module) ?*Namespace { + return mod.namespacePtrUnwrap(decl.getInnerNamespaceIndex(mod)); + } + pub fn dump(decl: *Decl) void { const loc = std.zig.findLineColumn(decl.scope.source.bytes, decl.src); std.debug.print("{s}:{d}:{d} name={d} status={s}", .{ @@ -4283,6 +4293,40 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { const zir = decl.getFileScope(mod).zir; const zir_datas = zir.instructions.items(.data); + // TODO: figure out how this works under incremental changes to builtin.zig! + const builtin_type_target_index: InternPool.Index = blk: { + const std_mod = mod.main_pkg.table.get("std").?; + if (decl.getFileScope(mod).pkg != std_mod) break :blk .none; + // We're in the std module. + const std_file = (try mod.importPkg(std_mod)).file; + const std_decl = mod.declPtr(std_file.root_decl.unwrap().?); + const std_namespace = std_decl.getInnerNamespace(mod).?; + const builtin_str = try mod.intern_pool.getOrPutString(gpa, "builtin"); + const builtin_decl = mod.declPtr(std_namespace.decls.getKeyAdapted(builtin_str, DeclAdapter{ .mod = mod }) orelse break :blk .none); + const builtin_namespace = builtin_decl.getInnerNamespaceIndex(mod).unwrap() orelse break :blk .none; + if (decl.src_namespace != builtin_namespace) break :blk .none; + // We're in builtin.zig. This could be a builtin we need to add to a specific InternPool index. + const decl_name = mod.intern_pool.stringToSlice(decl.name); + for ([_]struct { []const u8, InternPool.Index }{ + .{ "AtomicOrder", .atomic_order_type }, + .{ "AtomicRmwOp", .atomic_rmw_op_type }, + .{ "CallingConvention", .calling_convention_type }, + .{ "AddressSpace", .address_space_type }, + .{ "FloatMode", .float_mode_type }, + .{ "ReduceOp", .reduce_op_type }, + .{ "CallModifier", .call_modifier_type }, + .{ "PrefetchOptions", .prefetch_options_type }, + .{ "ExportOptions", .export_options_type }, + .{ "ExternOptions", .extern_options_type }, + .{ "Type", .type_info_type }, + }) |pair| { + if (std.mem.eql(u8, decl_name, pair[0])) { + break :blk pair[1]; + } + } + break :blk .none; + }; + decl.analysis = .in_progress; var analysis_arena = std.heap.ArenaAllocator.init(gpa); @@ -4304,6 +4348,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { .fn_ret_ty_ies = null, .owner_func_index = .none, .comptime_mutable_decls = &comptime_mutable_decls, + .builtin_type_target_index = builtin_type_target_index, }; defer sema.deinit(); @@ -4340,6 +4385,8 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { const extra = zir.extraData(Zir.Inst.Block, inst_data.payload_index); const body = zir.extra[extra.end..][0..extra.data.body_len]; const result_ref = (try sema.analyzeBodyBreak(&block_scope, body)).?.operand; + // We'll do some other bits with the Sema. Clear the type target index just in case they analyze any type. + sema.builtin_type_target_index = .none; try wip_captures.finalize(); for (comptime_mutable_decls.items) |ct_decl_index| { const ct_decl = mod.declPtr(ct_decl_index); |
