diff options
Diffstat (limited to 'src/Module.zig')
| -rw-r--r-- | src/Module.zig | 395 |
1 files changed, 239 insertions, 156 deletions
diff --git a/src/Module.zig b/src/Module.zig index dc7e34adc3..7521d4d439 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -185,6 +185,11 @@ allocated_decls: std.SegmentedList(Decl, 0) = .{}, /// When a Decl object is freed from `allocated_decls`, it is pushed into this stack. decls_free_list: ArrayListUnmanaged(Decl.Index) = .{}, +/// Same pattern as with `allocated_decls`. +allocated_namespaces: std.SegmentedList(Namespace, 0) = .{}, +/// Same pattern as with `decls_free_list`. +namespaces_free_list: ArrayListUnmanaged(Namespace.Index) = .{}, + global_assembly: std.AutoHashMapUnmanaged(Decl.Index, []u8) = .{}, reference_table: std.AutoHashMapUnmanaged(Decl.Index, struct { @@ -363,7 +368,7 @@ pub const Export = struct { pub fn getSrcLoc(exp: Export, mod: *Module) SrcLoc { const src_decl = mod.declPtr(exp.src_decl); return .{ - .file_scope = src_decl.getFileScope(), + .file_scope = src_decl.getFileScope(mod), .parent_decl_node = src_decl.src_node, .lazy = exp.src, }; @@ -494,7 +499,7 @@ pub const Decl = struct { /// Reference to externally owned memory. /// In the case of the Decl corresponding to a file, this is /// the namespace of the struct, since there is no parent. - src_namespace: *Namespace, + src_namespace: Namespace.Index, /// The scope which lexically contains this decl. A decl must depend /// on its lexical parent, in order to ensure that this pointer is valid. @@ -691,8 +696,8 @@ pub const Decl = struct { /// This name is relative to the containing namespace of the decl. /// The memory is owned by the containing File ZIR. - pub fn getName(decl: Decl) ?[:0]const u8 { - const zir = decl.getFileScope().zir; + pub fn getName(decl: Decl, mod: *Module) ?[:0]const u8 { + const zir = decl.getFileScope(mod).zir; return decl.getNameZir(zir); } @@ -703,8 +708,8 @@ pub const Decl = struct { return zir.nullTerminatedString(name_index); } - pub fn contentsHash(decl: Decl) std.zig.SrcHash { - const zir = decl.getFileScope().zir; + pub fn contentsHash(decl: Decl, mod: *Module) std.zig.SrcHash { + const zir = decl.getFileScope(mod).zir; return decl.contentsHashZir(zir); } @@ -715,31 +720,31 @@ pub const Decl = struct { return contents_hash; } - pub fn zirBlockIndex(decl: *const Decl) Zir.Inst.Index { + pub fn zirBlockIndex(decl: *const Decl, mod: *Module) Zir.Inst.Index { assert(decl.zir_decl_index != 0); - const zir = decl.getFileScope().zir; + const zir = decl.getFileScope(mod).zir; return zir.extra[decl.zir_decl_index + 6]; } - pub fn zirAlignRef(decl: Decl) Zir.Inst.Ref { + pub fn zirAlignRef(decl: Decl, mod: *Module) Zir.Inst.Ref { if (!decl.has_align) return .none; assert(decl.zir_decl_index != 0); - const zir = decl.getFileScope().zir; + const zir = decl.getFileScope(mod).zir; return @intToEnum(Zir.Inst.Ref, zir.extra[decl.zir_decl_index + 8]); } - pub fn zirLinksectionRef(decl: Decl) Zir.Inst.Ref { + pub fn zirLinksectionRef(decl: Decl, mod: *Module) Zir.Inst.Ref { if (!decl.has_linksection_or_addrspace) return .none; assert(decl.zir_decl_index != 0); - const zir = decl.getFileScope().zir; + const zir = decl.getFileScope(mod).zir; const extra_index = decl.zir_decl_index + 8 + @boolToInt(decl.has_align); return @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]); } - pub fn zirAddrspaceRef(decl: Decl) Zir.Inst.Ref { + pub fn zirAddrspaceRef(decl: Decl, mod: *Module) Zir.Inst.Ref { if (!decl.has_linksection_or_addrspace) return .none; assert(decl.zir_decl_index != 0); - const zir = decl.getFileScope().zir; + const zir = decl.getFileScope(mod).zir; const extra_index = decl.zir_decl_index + 8 + @boolToInt(decl.has_align) + 1; return @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]); } @@ -764,25 +769,25 @@ pub const Decl = struct { return LazySrcLoc.nodeOffset(decl.nodeIndexToRelative(node_index)); } - pub fn srcLoc(decl: Decl) SrcLoc { - return decl.nodeOffsetSrcLoc(0); + pub fn srcLoc(decl: Decl, mod: *Module) SrcLoc { + return decl.nodeOffsetSrcLoc(0, mod); } - pub fn nodeOffsetSrcLoc(decl: Decl, node_offset: i32) SrcLoc { + pub fn nodeOffsetSrcLoc(decl: Decl, node_offset: i32, mod: *Module) SrcLoc { return .{ - .file_scope = decl.getFileScope(), + .file_scope = decl.getFileScope(mod), .parent_decl_node = decl.src_node, .lazy = LazySrcLoc.nodeOffset(node_offset), }; } - pub fn srcToken(decl: Decl) Ast.TokenIndex { - const tree = &decl.getFileScope().tree; + pub fn srcToken(decl: Decl, mod: *Module) Ast.TokenIndex { + const tree = &decl.getFileScope(mod).tree; return tree.firstToken(decl.src_node); } - pub fn srcByteOffset(decl: Decl) u32 { - const tree = &decl.getFileScope().tree; + pub fn srcByteOffset(decl: Decl, mod: *Module) u32 { + const tree = &decl.getFileScope(mod).tree; return tree.tokens.items(.start)[decl.srcToken()]; } @@ -791,12 +796,12 @@ pub const Decl = struct { if (decl.name_fully_qualified) { return writer.writeAll(unqualified_name); } - return decl.src_namespace.renderFullyQualifiedName(mod, unqualified_name, writer); + return mod.namespacePtr(decl.src_namespace).renderFullyQualifiedName(mod, unqualified_name, writer); } pub fn renderFullyQualifiedDebugName(decl: Decl, mod: *Module, writer: anytype) !void { const unqualified_name = mem.sliceTo(decl.name, 0); - return decl.src_namespace.renderFullyQualifiedDebugName(mod, unqualified_name, writer); + return mod.namespacePtr(decl.src_namespace).renderFullyQualifiedDebugName(mod, unqualified_name, writer); } pub fn getFullyQualifiedName(decl: Decl, mod: *Module) ![:0]u8 { @@ -877,32 +882,39 @@ 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 getInnerNamespace(decl: *Decl) ?*Namespace { - if (!decl.owns_tv) return null; - const ty = (decl.val.castTag(.ty) orelse return null).data; - switch (ty.tag()) { - .@"struct" => { - const struct_obj = ty.castTag(.@"struct").?.data; - return &struct_obj.namespace; - }, - .enum_full, .enum_nonexhaustive => { - const enum_obj = ty.cast(Type.Payload.EnumFull).?.data; - return &enum_obj.namespace; - }, - .empty_struct => { - return ty.castTag(.empty_struct).?.data; - }, - .@"opaque" => { - const opaque_obj = ty.cast(Type.Payload.Opaque).?.data; - return &opaque_obj.namespace; - }, - .@"union", .union_safety_tagged, .union_tagged => { - const union_obj = ty.cast(Type.Payload.Union).?.data; - return &union_obj.namespace; - }, + pub fn getInnerNamespaceIndex(decl: *Decl, mod: *Module) Namespace.OptionalIndex { + if (!decl.owns_tv) return .none; + if (decl.val.ip_index == .none) { + const ty = (decl.val.castTag(.ty) orelse return .none).data; + switch (ty.tag()) { + .@"struct" => { + const struct_obj = ty.castTag(.@"struct").?.data; + return struct_obj.namespace.toOptional(); + }, + .enum_full, .enum_nonexhaustive => { + const enum_obj = ty.cast(Type.Payload.EnumFull).?.data; + return enum_obj.namespace.toOptional(); + }, + .empty_struct => { + @panic("TODO"); + }, + .@"union", .union_safety_tagged, .union_tagged => { + const union_obj = ty.cast(Type.Payload.Union).?.data; + return union_obj.namespace.toOptional(); + }, - else => return null, + else => return .none, + } } + return switch (mod.intern_pool.indexToKey(decl.val.ip_index)) { + .opaque_type => |opaque_type| opaque_type.namespace.toOptional(), + else => .none, + }; + } + + /// Same as `getInnerNamespaceIndex` but additionally obtains the pointer. + pub fn getInnerNamespace(decl: *Decl, mod: *Module) ?*Namespace { + return if (getInnerNamespaceIndex(decl, mod).unwrap()) |i| mod.namespacePtr(i) else null; } pub fn dump(decl: *Decl) void { @@ -920,8 +932,8 @@ pub const Decl = struct { std.debug.print("\n", .{}); } - pub fn getFileScope(decl: Decl) *File { - return decl.src_namespace.file_scope; + pub fn getFileScope(decl: Decl, mod: *Module) *File { + return mod.namespacePtr(decl.src_namespace).file_scope; } pub fn removeDependant(decl: *Decl, other: Decl.Index) void { @@ -974,7 +986,7 @@ pub const ErrorSet = struct { pub fn srcLoc(self: ErrorSet, mod: *Module) SrcLoc { const owner_decl = mod.declPtr(self.owner_decl); return .{ - .file_scope = owner_decl.getFileScope(), + .file_scope = owner_decl.getFileScope(mod), .parent_decl_node = owner_decl.src_node, .lazy = LazySrcLoc.nodeOffset(0), }; @@ -1000,7 +1012,7 @@ pub const Struct = struct { /// Set of field names in declaration order. fields: Fields, /// Represents the declarations inside this struct. - namespace: Namespace, + namespace: Namespace.Index, /// The Decl that corresponds to the struct itself. owner_decl: Decl.Index, /// Index of the struct_decl ZIR instruction. @@ -1101,7 +1113,7 @@ pub const Struct = struct { pub fn srcLoc(s: Struct, mod: *Module) SrcLoc { const owner_decl = mod.declPtr(s.owner_decl); return .{ - .file_scope = owner_decl.getFileScope(), + .file_scope = owner_decl.getFileScope(mod), .parent_decl_node = owner_decl.src_node, .lazy = LazySrcLoc.nodeOffset(0), }; @@ -1110,7 +1122,7 @@ pub const Struct = struct { pub fn fieldSrcLoc(s: Struct, mod: *Module, query: FieldSrcQuery) SrcLoc { @setCold(true); const owner_decl = mod.declPtr(s.owner_decl); - const file = owner_decl.getFileScope(); + const file = owner_decl.getFileScope(mod); const tree = file.getTree(mod.gpa) catch |err| { // In this case we emit a warning + a less precise source location. log.warn("unable to load {s}: {s}", .{ @@ -1224,7 +1236,7 @@ pub const EnumSimple = struct { pub fn srcLoc(self: EnumSimple, mod: *Module) SrcLoc { const owner_decl = mod.declPtr(self.owner_decl); return .{ - .file_scope = owner_decl.getFileScope(), + .file_scope = owner_decl.getFileScope(mod), .parent_decl_node = owner_decl.src_node, .lazy = LazySrcLoc.nodeOffset(0), }; @@ -1253,7 +1265,7 @@ pub const EnumNumbered = struct { pub fn srcLoc(self: EnumNumbered, mod: *Module) SrcLoc { const owner_decl = mod.declPtr(self.owner_decl); return .{ - .file_scope = owner_decl.getFileScope(), + .file_scope = owner_decl.getFileScope(mod), .parent_decl_node = owner_decl.src_node, .lazy = LazySrcLoc.nodeOffset(0), }; @@ -1275,7 +1287,7 @@ pub const EnumFull = struct { /// If this hash map is empty, it means the enum tags are auto-numbered. values: ValueMap, /// Represents the declarations inside this enum. - namespace: Namespace, + namespace: Namespace.Index, /// true if zig inferred this tag type, false if user specified it tag_ty_inferred: bool, @@ -1285,7 +1297,7 @@ pub const EnumFull = struct { pub fn srcLoc(self: EnumFull, mod: *Module) SrcLoc { const owner_decl = mod.declPtr(self.owner_decl); return .{ - .file_scope = owner_decl.getFileScope(), + .file_scope = owner_decl.getFileScope(mod), .parent_decl_node = owner_decl.src_node, .lazy = LazySrcLoc.nodeOffset(0), }; @@ -1294,7 +1306,7 @@ pub const EnumFull = struct { pub fn fieldSrcLoc(e: EnumFull, mod: *Module, query: FieldSrcQuery) SrcLoc { @setCold(true); const owner_decl = mod.declPtr(e.owner_decl); - const file = owner_decl.getFileScope(); + const file = owner_decl.getFileScope(mod); const tree = file.getTree(mod.gpa) catch |err| { // In this case we emit a warning + a less precise source location. log.warn("unable to load {s}: {s}", .{ @@ -1323,7 +1335,7 @@ pub const Union = struct { /// Set of field names in declaration order. fields: Fields, /// Represents the declarations inside this union. - namespace: Namespace, + namespace: Namespace.Index, /// The Decl that corresponds to the union itself. owner_decl: Decl.Index, /// Index of the union_decl ZIR instruction. @@ -1371,7 +1383,7 @@ pub const Union = struct { pub fn srcLoc(self: Union, mod: *Module) SrcLoc { const owner_decl = mod.declPtr(self.owner_decl); return .{ - .file_scope = owner_decl.getFileScope(), + .file_scope = owner_decl.getFileScope(mod), .parent_decl_node = owner_decl.src_node, .lazy = LazySrcLoc.nodeOffset(0), }; @@ -1380,7 +1392,7 @@ pub const Union = struct { pub fn fieldSrcLoc(u: Union, mod: *Module, query: FieldSrcQuery) SrcLoc { @setCold(true); const owner_decl = mod.declPtr(u.owner_decl); - const file = owner_decl.getFileScope(); + const file = owner_decl.getFileScope(mod); const tree = file.getTree(mod.gpa) catch |err| { // In this case we emit a warning + a less precise source location. log.warn("unable to load {s}: {s}", .{ @@ -1563,26 +1575,6 @@ pub const Union = struct { } }; -pub const Opaque = struct { - /// The Decl that corresponds to the opaque itself. - owner_decl: Decl.Index, - /// Represents the declarations inside this opaque. - namespace: Namespace, - - pub fn srcLoc(self: Opaque, mod: *Module) SrcLoc { - const owner_decl = mod.declPtr(self.owner_decl); - return .{ - .file_scope = owner_decl.getFileScope(), - .parent_decl_node = owner_decl.src_node, - .lazy = LazySrcLoc.nodeOffset(0), - }; - } - - pub fn getFullyQualifiedName(s: *Opaque, mod: *Module) ![:0]u8 { - return mod.declPtr(s.owner_decl).getFullyQualifiedName(mod); - } -}; - /// Some extern function struct memory is owned by the Decl's TypedValue.Managed /// arena allocator. pub const ExternFn = struct { @@ -1759,7 +1751,7 @@ pub const Fn = struct { } pub fn isAnytypeParam(func: Fn, mod: *Module, index: u32) bool { - const file = mod.declPtr(func.owner_decl).getFileScope(); + const file = mod.declPtr(func.owner_decl).getFileScope(mod); const tags = file.zir.instructions.items(.tag); @@ -1774,7 +1766,7 @@ pub const Fn = struct { } pub fn getParamName(func: Fn, mod: *Module, index: u32) [:0]const u8 { - const file = mod.declPtr(func.owner_decl).getFileScope(); + const file = mod.declPtr(func.owner_decl).getFileScope(mod); const tags = file.zir.instructions.items(.tag); const data = file.zir.instructions.items(.data); @@ -1797,7 +1789,7 @@ pub const Fn = struct { pub fn hasInferredErrorSet(func: Fn, mod: *Module) bool { const owner_decl = mod.declPtr(func.owner_decl); - const zir = owner_decl.getFileScope().zir; + const zir = owner_decl.getFileScope(mod).zir; const zir_tags = zir.instructions.items(.tag); switch (zir_tags[func.zir_body_inst]) { .func => return false, @@ -1851,7 +1843,7 @@ pub const DeclAdapter = struct { /// The container that structs, enums, unions, and opaques have. pub const Namespace = struct { - parent: ?*Namespace, + parent: OptionalIndex, file_scope: *File, /// Will be a struct, enum, union, or opaque. ty: Type, @@ -1869,6 +1861,28 @@ pub const Namespace = struct { /// Value is whether the usingnamespace decl is marked `pub`. usingnamespace_set: std.AutoHashMapUnmanaged(Decl.Index, bool) = .{}, + pub const Index = enum(u32) { + _, + + pub fn toOptional(i: Index) OptionalIndex { + return @intToEnum(OptionalIndex, @enumToInt(i)); + } + }; + + pub const OptionalIndex = enum(u32) { + none = std.math.maxInt(u32), + _, + + pub fn init(oi: ?Index) OptionalIndex { + return @intToEnum(OptionalIndex, @enumToInt(oi orelse return .none)); + } + + pub fn unwrap(oi: OptionalIndex) ?Index { + if (oi == .none) return null; + return @intToEnum(Index, @enumToInt(oi)); + } + }; + const DeclContext = struct { module: *Module, @@ -1955,10 +1969,10 @@ pub const Namespace = struct { name: []const u8, writer: anytype, ) @TypeOf(writer).Error!void { - if (ns.parent) |parent| { - const decl_index = ns.getDeclIndex(); + if (ns.parent.unwrap()) |parent| { + const decl_index = ns.getDeclIndex(mod); const decl = mod.declPtr(decl_index); - try parent.renderFullyQualifiedName(mod, mem.sliceTo(decl.name, 0), writer); + try mod.namespacePtr(parent).renderFullyQualifiedName(mod, mem.sliceTo(decl.name, 0), writer); } else { try ns.file_scope.renderFullyQualifiedName(writer); } @@ -1976,10 +1990,10 @@ pub const Namespace = struct { writer: anytype, ) @TypeOf(writer).Error!void { var separator_char: u8 = '.'; - if (ns.parent) |parent| { - const decl_index = ns.getDeclIndex(); + if (ns.parent.unwrap()) |parent| { + const decl_index = ns.getDeclIndex(mod); const decl = mod.declPtr(decl_index); - try parent.renderFullyQualifiedDebugName(mod, mem.sliceTo(decl.name, 0), writer); + try mod.namespacePtr(parent).renderFullyQualifiedDebugName(mod, mem.sliceTo(decl.name, 0), writer); } else { try ns.file_scope.renderFullyQualifiedDebugName(writer); separator_char = ':'; @@ -1990,8 +2004,8 @@ pub const Namespace = struct { } } - pub fn getDeclIndex(ns: Namespace) Decl.Index { - return ns.ty.getOwnerDecl(); + pub fn getDeclIndex(ns: Namespace, mod: *Module) Decl.Index { + return ns.ty.getOwnerDecl(mod); } }; @@ -3320,7 +3334,7 @@ pub const LazySrcLoc = union(enum) { } /// Upgrade to a `SrcLoc` based on the `Decl` provided. - pub fn toSrcLoc(lazy: LazySrcLoc, decl: *Decl) SrcLoc { + pub fn toSrcLoc(lazy: LazySrcLoc, decl: *Decl, mod: *Module) SrcLoc { return switch (lazy) { .unneeded, .entire_file, @@ -3328,7 +3342,7 @@ pub const LazySrcLoc = union(enum) { .token_abs, .node_abs, => .{ - .file_scope = decl.getFileScope(), + .file_scope = decl.getFileScope(mod), .parent_decl_node = 0, .lazy = lazy, }, @@ -3394,7 +3408,7 @@ pub const LazySrcLoc = union(enum) { .for_input, .for_capture_from_input, => .{ - .file_scope = decl.getFileScope(), + .file_scope = decl.getFileScope(mod), .parent_decl_node = decl.src_node, .lazy = lazy, }, @@ -3555,6 +3569,9 @@ pub fn deinit(mod: *Module) void { mod.global_assembly.deinit(gpa); mod.reference_table.deinit(gpa); + mod.namespaces_free_list.deinit(gpa); + mod.allocated_namespaces.deinit(gpa); + mod.string_literal_table.deinit(gpa); mod.string_literal_bytes.deinit(gpa); @@ -3575,8 +3592,9 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void { gpa.free(kv.value); } if (decl.has_tv) { - if (decl.getInnerNamespace()) |namespace| { - namespace.destroyDecls(mod); + if (decl.getInnerNamespaceIndex(mod).unwrap()) |i| { + mod.namespacePtr(i).destroyDecls(mod); + mod.destroyNamespace(i); } } decl.clearValues(mod); @@ -3596,16 +3614,21 @@ pub fn destroyDecl(mod: *Module, decl_index: Decl.Index) void { } } -pub fn declPtr(mod: *Module, decl_index: Decl.Index) *Decl { - return mod.allocated_decls.at(@enumToInt(decl_index)); +pub fn declPtr(mod: *Module, index: Decl.Index) *Decl { + return mod.allocated_decls.at(@enumToInt(index)); +} + +pub fn namespacePtr(mod: *Module, index: Namespace.Index) *Namespace { + return mod.allocated_namespaces.at(@enumToInt(index)); } /// Returns true if and only if the Decl is the top level struct associated with a File. pub fn declIsRoot(mod: *Module, decl_index: Decl.Index) bool { const decl = mod.declPtr(decl_index); - if (decl.src_namespace.parent != null) + const namespace = mod.namespacePtr(decl.src_namespace); + if (namespace.parent != .none) return false; - return decl_index == decl.src_namespace.getDeclIndex(); + return decl_index == namespace.getDeclIndex(mod); } fn freeExportList(gpa: Allocator, export_list: *ArrayListUnmanaged(*Export)) void { @@ -4076,7 +4099,7 @@ fn updateZirRefs(mod: *Module, file: *File, old_zir: Zir) !void { }; } - if (decl.getInnerNamespace()) |namespace| { + if (decl.getInnerNamespace(mod)) |namespace| { for (namespace.decls.keys()) |sub_decl| { try decl_stack.append(gpa, sub_decl); } @@ -4306,7 +4329,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void { try mod.failed_decls.ensureUnusedCapacity(mod.gpa, 1); mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create( mod.gpa, - decl.srcLoc(), + decl.srcLoc(mod), "unable to analyze: {s}", .{@errorName(e)}, )); @@ -4437,7 +4460,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void { decl_index, try Module.ErrorMsg.create( gpa, - decl.srcLoc(), + decl.srcLoc(mod), "invalid liveness: {s}", .{@errorName(err)}, ), @@ -4460,7 +4483,7 @@ pub fn ensureFuncBodyAnalyzed(mod: *Module, func: *Fn) SemaError!void { try mod.failed_decls.ensureUnusedCapacity(gpa, 1); mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try Module.ErrorMsg.create( gpa, - decl.srcLoc(), + decl.srcLoc(mod), "unable to codegen: {s}", .{@errorName(err)}, )); @@ -4586,13 +4609,13 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void { .status = .none, .known_non_opv = undefined, .is_tuple = undefined, // set below - .namespace = .{ - .parent = null, + .namespace = try mod.createNamespace(.{ + .parent = .none, .ty = struct_ty, .file_scope = file, - }, + }), }; - const new_decl_index = try mod.allocateNewDecl(&struct_obj.namespace, 0, null); + const new_decl_index = try mod.allocateNewDecl(struct_obj.namespace, 0, null); const new_decl = mod.declPtr(new_decl_index); file.root_decl = new_decl_index.toOptional(); struct_obj.owner_decl = new_decl_index; @@ -4688,12 +4711,12 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { const decl = mod.declPtr(decl_index); - if (decl.getFileScope().status != .success_zir) { + if (decl.getFileScope(mod).status != .success_zir) { return error.AnalysisFail; } const gpa = mod.gpa; - const zir = decl.getFileScope().zir; + const zir = decl.getFileScope(mod).zir; const zir_datas = zir.instructions.items(.data); decl.analysis = .in_progress; @@ -4767,7 +4790,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { block_scope.params.deinit(gpa); } - const zir_block_index = decl.zirBlockIndex(); + const zir_block_index = decl.zirBlockIndex(mod); const inst_data = zir_datas[zir_block_index].pl_node; const extra = zir.extraData(Zir.Inst.Block, inst_data.payload_index); const body = zir.extra[extra.end..][0..extra.data.body_len]; @@ -4792,7 +4815,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { }); } const ty = try decl_tv.val.toType().copy(decl_arena_allocator); - if (ty.getNamespace() == null) { + if (ty.getNamespace(mod) == null) { return sema.fail(&block_scope, ty_src, "type {} has no namespace", .{ty.fmt(mod)}); } @@ -4895,12 +4918,12 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { decl.ty = try decl_tv.ty.copy(decl_arena_allocator); decl.val = try decl_tv.val.copy(decl_arena_allocator); decl.@"align" = blk: { - const align_ref = decl.zirAlignRef(); + const align_ref = decl.zirAlignRef(mod); if (align_ref == .none) break :blk 0; break :blk try sema.resolveAlign(&block_scope, align_src, align_ref); }; decl.@"linksection" = blk: { - const linksection_ref = decl.zirLinksectionRef(); + const linksection_ref = decl.zirLinksectionRef(mod); if (linksection_ref == .none) break :blk null; const bytes = try sema.resolveConstString(&block_scope, section_src, linksection_ref, "linksection must be comptime-known"); if (mem.indexOfScalar(u8, bytes, 0) != null) { @@ -4921,7 +4944,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { }; const target = sema.mod.getTarget(); - break :blk switch (decl.zirAddrspaceRef()) { + break :blk switch (decl.zirAddrspaceRef(mod)) { .none => switch (addrspace_ctx) { .function => target_util.defaultAddressSpace(target, .function), .variable => target_util.defaultAddressSpace(target, .global_mutable), @@ -5273,7 +5296,7 @@ pub fn detectEmbedFileUpdate(mod: *Module, embed_file: *EmbedFile) !void { pub fn scanNamespace( mod: *Module, - namespace: *Namespace, + namespace_index: Namespace.Index, extra_start: usize, decls_len: u32, parent_decl: *Decl, @@ -5282,6 +5305,7 @@ pub fn scanNamespace( defer tracy.end(); const gpa = mod.gpa; + const namespace = mod.namespacePtr(namespace_index); const zir = namespace.file_scope.zir; try mod.comp.work_queue.ensureUnusedCapacity(decls_len); @@ -5294,7 +5318,7 @@ pub fn scanNamespace( var decl_i: u32 = 0; var scan_decl_iter: ScanDeclIter = .{ .module = mod, - .namespace = namespace, + .namespace_index = namespace_index, .parent_decl = parent_decl, }; while (decl_i < decls_len) : (decl_i += 1) { @@ -5317,7 +5341,7 @@ pub fn scanNamespace( const ScanDeclIter = struct { module: *Module, - namespace: *Namespace, + namespace_index: Namespace.Index, parent_decl: *Decl, usingnamespace_index: usize = 0, comptime_index: usize = 0, @@ -5329,7 +5353,8 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err defer tracy.end(); const mod = iter.module; - const namespace = iter.namespace; + const namespace_index = iter.namespace_index; + const namespace = mod.namespacePtr(namespace_index); const gpa = mod.gpa; const zir = namespace.file_scope.zir; @@ -5404,7 +5429,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err ); const comp = mod.comp; if (!gop.found_existing) { - const new_decl_index = try mod.allocateNewDecl(namespace, decl_node, iter.parent_decl.src_scope); + const new_decl_index = try mod.allocateNewDecl(namespace_index, decl_node, iter.parent_decl.src_scope); const new_decl = mod.declPtr(new_decl_index); new_decl.kind = kind; new_decl.name = decl_name; @@ -5456,7 +5481,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err const decl = mod.declPtr(decl_index); if (kind == .@"test") { const src_loc = SrcLoc{ - .file_scope = decl.getFileScope(), + .file_scope = decl.getFileScope(mod), .parent_decl_node = decl.src_node, .lazy = .{ .token_offset = 1 }, }; @@ -5564,7 +5589,7 @@ pub fn clearDecl( if (decl.ty.isFnOrHasRuntimeBits(mod)) { mod.comp.bin_file.freeDecl(decl_index); } - if (decl.getInnerNamespace()) |namespace| { + if (decl.getInnerNamespace(mod)) |namespace| { try namespace.deleteAllDecls(mod, outdated_decls); } } @@ -5584,7 +5609,7 @@ pub fn deleteUnusedDecl(mod: *Module, decl_index: Decl.Index) void { log.debug("deleteUnusedDecl {d} ({s})", .{ decl_index, decl.name }); assert(!mod.declIsRoot(decl_index)); - assert(decl.src_namespace.anon_decls.swapRemove(decl_index)); + assert(mod.namespacePtr(decl.src_namespace).anon_decls.swapRemove(decl_index)); const dependants = decl.dependants.keys(); for (dependants) |dep| { @@ -5612,7 +5637,7 @@ pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void { log.debug("abortAnonDecl {*} ({s})", .{ decl, decl.name }); assert(!mod.declIsRoot(decl_index)); - assert(decl.src_namespace.anon_decls.swapRemove(decl_index)); + assert(mod.namespacePtr(decl.src_namespace).anon_decls.swapRemove(decl_index)); // An aborted decl must not have dependants -- they must have // been aborted first and removed from this list. @@ -5689,7 +5714,7 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air { .gpa = gpa, .arena = arena, .perm_arena = decl_arena_allocator, - .code = decl.getFileScope().zir, + .code = decl.getFileScope(mod).zir, .owner_decl = decl, .owner_decl_index = decl_index, .func = func, @@ -5920,9 +5945,34 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void { decl.analysis = .outdated; } +pub const CreateNamespaceOptions = struct { + parent: Namespace.OptionalIndex, + file_scope: *File, + ty: Type, +}; + +pub fn createNamespace(mod: *Module, options: CreateNamespaceOptions) !Namespace.Index { + if (mod.namespaces_free_list.popOrNull()) |index| return index; + const ptr = try mod.allocated_namespaces.addOne(mod.gpa); + ptr.* = .{ + .parent = options.parent, + .file_scope = options.file_scope, + .ty = options.ty, + }; + return @intToEnum(Namespace.Index, mod.allocated_namespaces.len - 1); +} + +pub fn destroyNamespace(mod: *Module, index: Namespace.Index) void { + mod.namespacePtr(index).* = undefined; + mod.namespaces_free_list.append(mod.gpa, index) catch { + // In order to keep `destroyNamespace` a non-fallible function, we ignore memory + // allocation failures here, instead leaking the Namespace until garbage collection. + }; +} + pub fn allocateNewDecl( mod: *Module, - namespace: *Namespace, + namespace: Namespace.Index, src_node: Ast.Node.Index, src_scope: ?*CaptureScope, ) !Decl.Index { @@ -6004,7 +6054,7 @@ pub fn createAnonymousDecl(mod: *Module, block: *Sema.Block, typed_value: TypedV pub fn createAnonymousDeclFromDecl( mod: *Module, src_decl: *Decl, - namespace: *Namespace, + namespace: Namespace.Index, src_scope: ?*CaptureScope, tv: TypedValue, ) !Decl.Index { @@ -6022,7 +6072,7 @@ pub fn initNewAnonDecl( mod: *Module, new_decl_index: Decl.Index, src_line: u32, - namespace: *Namespace, + namespace: Namespace.Index, typed_value: TypedValue, name: [:0]u8, ) !void { @@ -6040,7 +6090,7 @@ pub fn initNewAnonDecl( new_decl.analysis = .complete; new_decl.generation = mod.generation; - try namespace.anon_decls.putNoClobber(mod.gpa, new_decl_index, {}); + try mod.namespacePtr(namespace).anon_decls.putNoClobber(mod.gpa, new_decl_index, {}); // 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, @@ -6110,16 +6160,17 @@ pub const SwitchProngSrc = union(enum) { /// the LazySrcLoc in order to emit a compile error. pub fn resolve( prong_src: SwitchProngSrc, - gpa: Allocator, + mod: *Module, decl: *Decl, switch_node_offset: i32, range_expand: RangeExpand, ) LazySrcLoc { @setCold(true); - const tree = decl.getFileScope().getTree(gpa) catch |err| { + const gpa = mod.gpa; + const tree = decl.getFileScope(mod).getTree(gpa) catch |err| { // In this case we emit a warning + a less precise source location. log.warn("unable to load {s}: {s}", .{ - decl.getFileScope().sub_file_path, @errorName(err), + decl.getFileScope(mod).sub_file_path, @errorName(err), }); return LazySrcLoc.nodeOffset(0); }; @@ -6203,11 +6254,12 @@ pub const PeerTypeCandidateSrc = union(enum) { pub fn resolve( self: PeerTypeCandidateSrc, - gpa: Allocator, + mod: *Module, decl: *Decl, candidate_i: usize, ) ?LazySrcLoc { @setCold(true); + const gpa = mod.gpa; switch (self) { .none => { @@ -6229,10 +6281,10 @@ pub const PeerTypeCandidateSrc = union(enum) { else => {}, } - const tree = decl.getFileScope().getTree(gpa) catch |err| { + const tree = decl.getFileScope(mod).getTree(gpa) catch |err| { // In this case we emit a warning + a less precise source location. log.warn("unable to load {s}: {s}", .{ - decl.getFileScope().sub_file_path, @errorName(err), + decl.getFileScope(mod).sub_file_path, @errorName(err), }); return LazySrcLoc.nodeOffset(0); }; @@ -6291,15 +6343,16 @@ fn queryFieldSrc( pub fn paramSrc( func_node_offset: i32, - gpa: Allocator, + mod: *Module, decl: *Decl, param_i: usize, ) LazySrcLoc { @setCold(true); - const tree = decl.getFileScope().getTree(gpa) catch |err| { + const gpa = mod.gpa; + const tree = decl.getFileScope(mod).getTree(gpa) catch |err| { // In this case we emit a warning + a less precise source location. log.warn("unable to load {s}: {s}", .{ - decl.getFileScope().sub_file_path, @errorName(err), + decl.getFileScope(mod).sub_file_path, @errorName(err), }); return LazySrcLoc.nodeOffset(0); }; @@ -6321,19 +6374,20 @@ pub fn paramSrc( } pub fn argSrc( + mod: *Module, call_node_offset: i32, - gpa: Allocator, decl: *Decl, start_arg_i: usize, bound_arg_src: ?LazySrcLoc, ) LazySrcLoc { + @setCold(true); + const gpa = mod.gpa; if (start_arg_i == 0 and bound_arg_src != null) return bound_arg_src.?; const arg_i = start_arg_i - @boolToInt(bound_arg_src != null); - @setCold(true); - const tree = decl.getFileScope().getTree(gpa) catch |err| { + const tree = decl.getFileScope(mod).getTree(gpa) catch |err| { // In this case we emit a warning + a less precise source location. log.warn("unable to load {s}: {s}", .{ - decl.getFileScope().sub_file_path, @errorName(err), + decl.getFileScope(mod).sub_file_path, @errorName(err), }); return LazySrcLoc.nodeOffset(0); }; @@ -6347,7 +6401,7 @@ pub fn argSrc( const node_datas = tree.nodes.items(.data); const call_args_node = tree.extra_data[node_datas[node].rhs - 1]; const call_args_offset = decl.nodeIndexToRelative(call_args_node); - return initSrc(call_args_offset, gpa, decl, arg_i); + return mod.initSrc(call_args_offset, decl, arg_i); }, else => unreachable, }; @@ -6355,16 +6409,17 @@ pub fn argSrc( } pub fn initSrc( + mod: *Module, init_node_offset: i32, - gpa: Allocator, decl: *Decl, init_index: usize, ) LazySrcLoc { @setCold(true); - const tree = decl.getFileScope().getTree(gpa) catch |err| { + const gpa = mod.gpa; + const tree = decl.getFileScope(mod).getTree(gpa) catch |err| { // In this case we emit a warning + a less precise source location. log.warn("unable to load {s}: {s}", .{ - decl.getFileScope().sub_file_path, @errorName(err), + decl.getFileScope(mod).sub_file_path, @errorName(err), }); return LazySrcLoc.nodeOffset(0); }; @@ -6400,12 +6455,13 @@ pub fn initSrc( } } -pub fn optionsSrc(gpa: Allocator, decl: *Decl, base_src: LazySrcLoc, wanted: []const u8) LazySrcLoc { +pub fn optionsSrc(mod: *Module, decl: *Decl, base_src: LazySrcLoc, wanted: []const u8) LazySrcLoc { @setCold(true); - const tree = decl.getFileScope().getTree(gpa) catch |err| { + const gpa = mod.gpa; + const tree = decl.getFileScope(mod).getTree(gpa) catch |err| { // In this case we emit a warning + a less precise source location. log.warn("unable to load {s}: {s}", .{ - decl.getFileScope().sub_file_path, @errorName(err), + decl.getFileScope(mod).sub_file_path, @errorName(err), }); return LazySrcLoc.nodeOffset(0); }; @@ -6471,7 +6527,10 @@ pub fn processOutdatedAndDeletedDecls(mod: *Module) !void { // Remove from the namespace it resides in, preserving declaration order. assert(decl.zir_decl_index != 0); - _ = decl.src_namespace.decls.orderedRemoveAdapted(@as([]const u8, mem.sliceTo(decl.name, 0)), DeclAdapter{ .mod = mod }); + _ = mod.namespacePtr(decl.src_namespace).decls.orderedRemoveAdapted( + @as([]const u8, mem.sliceTo(decl.name, 0)), + DeclAdapter{ .mod = mod }, + ); try mod.clearDecl(decl_index, &outdated_decls); mod.destroyDecl(decl_index); @@ -6541,8 +6600,11 @@ pub fn populateTestFunctions( const builtin_pkg = mod.main_pkg.table.get("builtin").?; const builtin_file = (mod.importPkg(builtin_pkg) catch unreachable).file; const root_decl = mod.declPtr(builtin_file.root_decl.unwrap().?); - const builtin_namespace = root_decl.src_namespace; - const decl_index = builtin_namespace.decls.getKeyAdapted(@as([]const u8, "test_functions"), DeclAdapter{ .mod = mod }).?; + const builtin_namespace = mod.namespacePtr(root_decl.src_namespace); + const decl_index = builtin_namespace.decls.getKeyAdapted( + @as([]const u8, "test_functions"), + DeclAdapter{ .mod = mod }, + ).?; { // We have to call `ensureDeclAnalyzed` here in case `builtin.test_functions` // was not referenced by start code. @@ -6673,7 +6735,7 @@ pub fn linkerUpdateDecl(mod: *Module, decl_index: Decl.Index) !void { try mod.failed_decls.ensureUnusedCapacity(gpa, 1); mod.failed_decls.putAssumeCapacityNoClobber(decl_index, try ErrorMsg.create( gpa, - decl.srcLoc(), + decl.srcLoc(mod), "unable to codegen: {s}", .{@errorName(err)}, )); @@ -7138,3 +7200,24 @@ pub fn atomicPtrAlignment( return 0; } + +pub fn opaqueSrcLoc(mod: *Module, opaque_type: InternPool.Key.OpaqueType) SrcLoc { + const owner_decl = mod.declPtr(opaque_type.decl); + return .{ + .file_scope = owner_decl.getFileScope(mod), + .parent_decl_node = owner_decl.src_node, + .lazy = LazySrcLoc.nodeOffset(0), + }; +} + +pub fn opaqueFullyQualifiedName(mod: *Module, opaque_type: InternPool.Key.OpaqueType) ![:0]u8 { + return mod.declPtr(opaque_type.decl).getFullyQualifiedName(mod); +} + +pub fn declFileScope(mod: *Module, decl_index: Decl.Index) *File { + return mod.declPtr(decl_index).getFileScope(mod); +} + +pub fn namespaceDeclIndex(mod: *Module, namespace_index: Namespace.Index) Decl.Index { + return mod.namespacePtr(namespace_index).getDeclIndex(mod); +} |
