From 083ee8e0e28ed0d1c4e1df6b5aa12f2709731b50 Mon Sep 17 00:00:00 2001 From: mlugg Date: Mon, 14 Aug 2023 13:06:47 +0100 Subject: 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 --- src/Module.zig | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 4 deletions(-) (limited to 'src/Module.zig') 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); -- cgit v1.2.3