diff --git a/src/Compilation.zig b/src/Compilation.zig index 95337de1e1..8b44d6d51b 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -54,7 +54,7 @@ c_object_work_queue: std.fifo.LinearFifo(*CObject, .Dynamic), /// These jobs are to tokenize, parse, and astgen files, which may be outdated /// since the last compilation, as well as scan for `@import` and queue up /// additional jobs corresponding to those new files. -astgen_work_queue: std.fifo.LinearFifo(*Module.Scope.File, .Dynamic), +astgen_work_queue: std.fifo.LinearFifo(*Module.File, .Dynamic), /// The ErrorMsg memory is owned by the `CObject`, using Compilation's general purpose allocator. /// This data is accessed by multiple threads and is protected by `mutex`. @@ -446,7 +446,7 @@ pub const AllErrors = struct { pub fn addZir( arena: *Allocator, errors: *std.ArrayList(Message), - file: *Module.Scope.File, + file: *Module.File, ) !void { assert(file.zir_loaded); assert(file.tree_loaded); @@ -1444,7 +1444,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { .emit_docs = options.emit_docs, .work_queue = std.fifo.LinearFifo(Job, .Dynamic).init(gpa), .c_object_work_queue = std.fifo.LinearFifo(*CObject, .Dynamic).init(gpa), - .astgen_work_queue = std.fifo.LinearFifo(*Module.Scope.File, .Dynamic).init(gpa), + .astgen_work_queue = std.fifo.LinearFifo(*Module.File, .Dynamic).init(gpa), .keep_source_files_loaded = options.keep_source_files_loaded, .use_clang = use_clang, .clang_argv = options.clang_argv, @@ -1770,7 +1770,7 @@ pub fn update(self: *Compilation) !void { assert(decl.deletion_flag); assert(decl.dependants.count() == 0); const is_anon = if (decl.zir_decl_index == 0) blk: { - break :blk decl.namespace.anon_decls.swapRemove(decl); + break :blk decl.src_namespace.anon_decls.swapRemove(decl); } else false; try module.clearDecl(decl, null); @@ -1889,13 +1889,13 @@ pub fn totalErrorCount(self: *Compilation) usize { // the previous parse success, including compile errors, but we cannot // emit them until the file succeeds parsing. for (module.failed_decls.keys()) |key| { - if (key.namespace.file_scope.okToReportErrors()) { + if (key.getFileScope().okToReportErrors()) { total += 1; } } if (module.emit_h) |emit_h| { for (emit_h.failed_decls.keys()) |key| { - if (key.namespace.file_scope.okToReportErrors()) { + if (key.getFileScope().okToReportErrors()) { total += 1; } } @@ -1968,7 +1968,7 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors { while (it.next()) |entry| { // Skip errors for Decls within files that had a parse failure. // We'll try again once parsing succeeds. - if (entry.key_ptr.*.namespace.file_scope.okToReportErrors()) { + if (entry.key_ptr.*.getFileScope().okToReportErrors()) { try AllErrors.add(module, &arena, &errors, entry.value_ptr.*.*); } } @@ -1978,7 +1978,7 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors { while (it.next()) |entry| { // Skip errors for Decls within files that had a parse failure. // We'll try again once parsing succeeds. - if (entry.key_ptr.*.namespace.file_scope.okToReportErrors()) { + if (entry.key_ptr.*.getFileScope().okToReportErrors()) { try AllErrors.add(module, &arena, &errors, entry.value_ptr.*.*); } } @@ -2169,12 +2169,12 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor defer air.deinit(gpa); log.debug("analyze liveness of {s}", .{decl.name}); - var liveness = try Liveness.analyze(gpa, air, decl.namespace.file_scope.zir); + var liveness = try Liveness.analyze(gpa, air, decl.getFileScope().zir); defer liveness.deinit(gpa); if (builtin.mode == .Debug and self.verbose_air) { std.debug.print("# Begin Function AIR: {s}:\n", .{decl.name}); - @import("print_air.zig").dump(gpa, air, decl.namespace.file_scope.zir, liveness); + @import("print_air.zig").dump(gpa, air, decl.getFileScope().zir, liveness); std.debug.print("# End Function AIR: {s}\n\n", .{decl.name}); } @@ -2465,14 +2465,14 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor const AstGenSrc = union(enum) { root, import: struct { - importing_file: *Module.Scope.File, + importing_file: *Module.File, import_tok: std.zig.Ast.TokenIndex, }, }; fn workerAstGenFile( comp: *Compilation, - file: *Module.Scope.File, + file: *Module.File, prog_node: *std.Progress.Node, wg: *WaitGroup, src: AstGenSrc, @@ -2742,7 +2742,7 @@ fn reportRetryableCObjectError( fn reportRetryableAstGenError( comp: *Compilation, src: AstGenSrc, - file: *Module.Scope.File, + file: *Module.File, err: anyerror, ) error{OutOfMemory}!void { const mod = comp.bin_file.options.module.?; diff --git a/src/Module.zig b/src/Module.zig index 6c790d3804..828e9b9226 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -59,7 +59,7 @@ export_owners: std.AutoArrayHashMapUnmanaged(*Decl, []*Export) = .{}, /// over it and check which source files have been modified on the file system when /// an update is requested, as well as to cache `@import` results. /// Keys are fully resolved file paths. This table owns the keys and values. -import_table: std.StringArrayHashMapUnmanaged(*Scope.File) = .{}, +import_table: std.StringArrayHashMapUnmanaged(*File) = .{}, /// The set of all the generic function instantiations. This is used so that when a generic /// function is called twice with the same comptime parameter arguments, both calls dispatch @@ -85,8 +85,8 @@ failed_decls: std.AutoArrayHashMapUnmanaged(*Decl, *ErrorMsg) = .{}, /// The value is the AST node index offset from the Decl. compile_log_decls: std.AutoArrayHashMapUnmanaged(*Decl, i32) = .{}, /// Using a map here for consistency with the other fields here. -/// The ErrorMsg memory is owned by the `Scope.File`, using Module's general purpose allocator. -failed_files: std.AutoArrayHashMapUnmanaged(*Scope.File, ?*ErrorMsg) = .{}, +/// The ErrorMsg memory is owned by the `File`, using Module's general purpose allocator. +failed_files: std.AutoArrayHashMapUnmanaged(*File, ?*ErrorMsg) = .{}, /// Using a map here for consistency with the other fields here. /// The ErrorMsg memory is owned by the `Export`, using Module's general purpose allocator. failed_exports: std.AutoArrayHashMapUnmanaged(*Export, *ErrorMsg) = .{}, @@ -264,7 +264,7 @@ pub const Export = struct { pub fn getSrcLoc(exp: Export) SrcLoc { return .{ - .file_scope = exp.src_decl.namespace.file_scope, + .file_scope = exp.src_decl.getFileScope(), .parent_decl_node = exp.src_decl.src_node, .lazy = exp.src, }; @@ -350,7 +350,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. - namespace: *Scope.Namespace, + src_namespace: *Namespace, /// The scope which lexically contains this decl. A decl must depend /// on its lexical parent, in order to ensure that this pointer is valid. @@ -516,7 +516,7 @@ 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.namespace.file_scope.zir; + const zir = decl.getFileScope().zir; return decl.getNameZir(zir); } @@ -528,7 +528,7 @@ pub const Decl = struct { } pub fn contentsHash(decl: Decl) std.zig.SrcHash { - const zir = decl.namespace.file_scope.zir; + const zir = decl.getFileScope().zir; return decl.contentsHashZir(zir); } @@ -541,21 +541,21 @@ pub const Decl = struct { pub fn zirBlockIndex(decl: *const Decl) Zir.Inst.Index { assert(decl.zir_decl_index != 0); - const zir = decl.namespace.file_scope.zir; + const zir = decl.getFileScope().zir; return zir.extra[decl.zir_decl_index + 6]; } pub fn zirAlignRef(decl: Decl) Zir.Inst.Ref { if (!decl.has_align) return .none; assert(decl.zir_decl_index != 0); - const zir = decl.namespace.file_scope.zir; + const zir = decl.getFileScope().zir; return @intToEnum(Zir.Inst.Ref, zir.extra[decl.zir_decl_index + 7]); } pub fn zirLinksectionRef(decl: Decl) Zir.Inst.Ref { if (!decl.has_linksection_or_addrspace) return .none; assert(decl.zir_decl_index != 0); - const zir = decl.namespace.file_scope.zir; + const zir = decl.getFileScope().zir; const extra_index = decl.zir_decl_index + 7 + @boolToInt(decl.has_align); return @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]); } @@ -563,16 +563,16 @@ pub const Decl = struct { pub fn zirAddrspaceRef(decl: Decl) Zir.Inst.Ref { if (!decl.has_linksection_or_addrspace) return .none; assert(decl.zir_decl_index != 0); - const zir = decl.namespace.file_scope.zir; + const zir = decl.getFileScope().zir; const extra_index = decl.zir_decl_index + 7 + @boolToInt(decl.has_align) + 1; return @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]); } /// Returns true if and only if the Decl is the top level struct associated with a File. pub fn isRoot(decl: *const Decl) bool { - if (decl.namespace.parent != null) + if (decl.src_namespace.parent != null) return false; - return decl == decl.namespace.ty.getOwnerDecl(); + return decl == decl.src_namespace.getDecl(); } pub fn relativeToLine(decl: Decl, offset: u32) u32 { @@ -608,18 +608,23 @@ pub const Decl = struct { } pub fn srcToken(decl: Decl) Ast.TokenIndex { - const tree = &decl.namespace.file_scope.tree; + const tree = &decl.getFileScope().tree; return tree.firstToken(decl.src_node); } pub fn srcByteOffset(decl: Decl) u32 { - const tree = &decl.namespace.file_scope.tree; + const tree = &decl.getFileScope().tree; return tree.tokens.items(.start)[decl.srcToken()]; } pub fn renderFullyQualifiedName(decl: Decl, writer: anytype) !void { const unqualified_name = mem.spanZ(decl.name); - return decl.namespace.renderFullyQualifiedName(unqualified_name, writer); + return decl.src_namespace.renderFullyQualifiedName(unqualified_name, writer); + } + + pub fn renderFullyQualifiedDebugName(decl: Decl, writer: anytype) !void { + const unqualified_name = mem.spanZ(decl.name); + return decl.src_namespace.renderFullyQualifiedDebugName(unqualified_name, writer); } pub fn getFullyQualifiedName(decl: Decl, gpa: *Allocator) ![:0]u8 { @@ -685,7 +690,7 @@ 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) ?*Scope.Namespace { + 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()) { @@ -730,8 +735,8 @@ pub const Decl = struct { std.debug.print("\n", .{}); } - pub fn getFileScope(decl: Decl) *Scope.File { - return decl.namespace.file_scope; + pub fn getFileScope(decl: Decl) *File { + return decl.src_namespace.file_scope; } pub fn getEmitH(decl: *Decl, module: *Module) *EmitH { @@ -782,7 +787,7 @@ pub const Struct = struct { /// Set of field names in declaration order. fields: std.StringArrayHashMapUnmanaged(Field), /// Represents the declarations inside this struct. - namespace: Scope.Namespace, + namespace: Namespace, /// Offset from `owner_decl`, points to the struct AST node. node_offset: i32, /// Index of the struct_decl ZIR instruction. @@ -904,7 +909,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: Scope.Namespace, + namespace: Namespace, /// Offset from `owner_decl`, points to the enum decl AST node. node_offset: i32, @@ -932,7 +937,7 @@ pub const Union = struct { /// Set of field names in declaration order. fields: std.StringArrayHashMapUnmanaged(Field), /// Represents the declarations inside this union. - namespace: Scope.Namespace, + namespace: Namespace, /// Offset from `owner_decl`, points to the union decl AST node. node_offset: i32, /// Index of the union_decl ZIR instruction. @@ -1076,636 +1081,312 @@ pub const Var = struct { is_threadlocal: bool, }; -pub const Scope = struct { - tag: Tag, +/// The container that structs, enums, unions, and opaques have. +pub const Namespace = struct { + parent: ?*Namespace, + file_scope: *File, + /// Will be a struct, enum, union, or opaque. + ty: Type, + /// Direct children of the namespace. Used during an update to detect + /// which decls have been added/removed from source. + /// Declaration order is preserved via entry order. + /// Key memory is owned by `decl.name`. + /// TODO save memory with https://github.com/ziglang/zig/issues/8619. + /// Anonymous decls are not stored here; they are kept in `anon_decls` instead. + decls: std.StringArrayHashMapUnmanaged(*Decl) = .{}, - pub fn cast(base: *Scope, comptime T: type) ?*T { - if (base.tag != T.base_tag) - return null; + anon_decls: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{}, - return @fieldParentPtr(T, "base", base); + /// Key is usingnamespace Decl itself. To find the namespace being included, + /// the Decl Value has to be resolved as a Type which has a Namespace. + /// Value is whether the usingnamespace decl is marked `pub`. + usingnamespace_set: std.AutoHashMapUnmanaged(*Decl, bool) = .{}, + + pub fn deinit(ns: *Namespace, mod: *Module) void { + ns.destroyDecls(mod); + ns.* = undefined; } - /// Get the decl which contains this decl, for the purposes of source reporting - pub fn srcDecl(scope: *Scope) ?*Decl { - return switch (scope.tag) { - .block => scope.cast(Block).?.src_decl, - .file => null, - .namespace => scope.cast(Namespace).?.getDecl(), - }; + pub fn destroyDecls(ns: *Namespace, mod: *Module) void { + const gpa = mod.gpa; + + log.debug("destroyDecls {*}", .{ns}); + + var decls = ns.decls; + ns.decls = .{}; + + var anon_decls = ns.anon_decls; + ns.anon_decls = .{}; + + for (decls.values()) |value| { + value.destroy(mod); + } + decls.deinit(gpa); + + for (anon_decls.keys()) |key| { + key.destroy(mod); + } + anon_decls.deinit(gpa); } - /// Get the scope which contains this decl, for resolving closure_get instructions. - pub fn srcScope(scope: *Scope) ?*CaptureScope { - return switch (scope.tag) { - .block => scope.cast(Block).?.wip_capture_scope, - .file => null, - .namespace => scope.cast(Namespace).?.getDecl().src_scope, - }; + pub fn deleteAllDecls( + ns: *Namespace, + mod: *Module, + outdated_decls: ?*std.AutoArrayHashMap(*Decl, void), + ) !void { + const gpa = mod.gpa; + + log.debug("deleteAllDecls {*}", .{ns}); + + var decls = ns.decls; + ns.decls = .{}; + + var anon_decls = ns.anon_decls; + ns.anon_decls = .{}; + + // TODO rework this code to not panic on OOM. + // (might want to coordinate with the clearDecl function) + + for (decls.values()) |child_decl| { + mod.clearDecl(child_decl, outdated_decls) catch @panic("out of memory"); + child_decl.destroy(mod); + } + decls.deinit(gpa); + + for (anon_decls.keys()) |child_decl| { + mod.clearDecl(child_decl, outdated_decls) catch @panic("out of memory"); + child_decl.destroy(mod); + } + anon_decls.deinit(gpa); } - /// Asserts the scope has a parent which is a Namespace and returns it. - pub fn namespace(scope: *Scope) *Namespace { - switch (scope.tag) { - .block => return scope.cast(Block).?.sema.owner_decl.namespace, - .file => return scope.cast(File).?.root_decl.?.namespace, - .namespace => return scope.cast(Namespace).?, + // This renders e.g. "std.fs.Dir.OpenOptions" + pub fn renderFullyQualifiedName( + ns: Namespace, + name: []const u8, + writer: anytype, + ) @TypeOf(writer).Error!void { + if (ns.parent) |parent| { + const decl = ns.getDecl(); + try parent.renderFullyQualifiedName(mem.spanZ(decl.name), writer); + } else { + try ns.file_scope.renderFullyQualifiedName(writer); + } + if (name.len != 0) { + try writer.writeAll("."); + try writer.writeAll(name); } } - /// Asserts the scope has a parent which is a Namespace or File and - /// returns the sub_file_path field. - pub fn subFilePath(base: *Scope) []const u8 { - switch (base.tag) { - .namespace => return @fieldParentPtr(Namespace, "base", base).file_scope.sub_file_path, - .file => return @fieldParentPtr(File, "base", base).sub_file_path, - .block => unreachable, + /// This renders e.g. "std/fs.zig:Dir.OpenOptions" + pub fn renderFullyQualifiedDebugName( + ns: Namespace, + name: []const u8, + writer: anytype, + ) @TypeOf(writer).Error!void { + var separator_char: u8 = '.'; + if (ns.parent) |parent| { + const decl = ns.getDecl(); + try parent.renderFullyQualifiedDebugName(mem.spanZ(decl.name), writer); + } else { + try ns.file_scope.renderFullyQualifiedDebugName(writer); + separator_char = ':'; + } + if (name.len != 0) { + try writer.writeByte(separator_char); + try writer.writeAll(name); } } - /// When called from inside a Block Scope, chases the src_decl, not the owner_decl. - pub fn getFileScope(base: *Scope) *Scope.File { - var cur = base; - while (true) { - cur = switch (cur.tag) { - .namespace => return @fieldParentPtr(Namespace, "base", cur).file_scope, - .file => return @fieldParentPtr(File, "base", cur), - .block => return @fieldParentPtr(Block, "base", cur).src_decl.namespace.file_scope, - }; + pub fn getDecl(ns: Namespace) *Decl { + return ns.ty.getOwnerDecl(); + } +}; + +pub const File = struct { + status: enum { + never_loaded, + retryable_failure, + parse_failure, + astgen_failure, + success_zir, + }, + source_loaded: bool, + tree_loaded: bool, + zir_loaded: bool, + /// Relative to the owning package's root_src_dir. + /// Memory is stored in gpa, owned by File. + sub_file_path: []const u8, + /// Whether this is populated depends on `source_loaded`. + source: [:0]const u8, + /// Whether this is populated depends on `status`. + stat_size: u64, + /// Whether this is populated depends on `status`. + stat_inode: std.fs.File.INode, + /// Whether this is populated depends on `status`. + stat_mtime: i128, + /// Whether this is populated or not depends on `tree_loaded`. + tree: Ast, + /// Whether this is populated or not depends on `zir_loaded`. + zir: Zir, + /// Package that this file is a part of, managed externally. + pkg: *Package, + /// The Decl of the struct that represents this File. + root_decl: ?*Decl, + + /// Used by change detection algorithm, after astgen, contains the + /// set of decls that existed in the previous ZIR but not in the new one. + deleted_decls: std.ArrayListUnmanaged(*Decl) = .{}, + /// Used by change detection algorithm, after astgen, contains the + /// set of decls that existed both in the previous ZIR and in the new one, + /// but their source code has been modified. + outdated_decls: std.ArrayListUnmanaged(*Decl) = .{}, + + /// The most recent successful ZIR for this file, with no errors. + /// This is only populated when a previously successful ZIR + /// newly introduces compile errors during an update. When ZIR is + /// successful, this field is unloaded. + prev_zir: ?*Zir = null, + + pub fn unload(file: *File, gpa: *Allocator) void { + file.unloadTree(gpa); + file.unloadSource(gpa); + file.unloadZir(gpa); + } + + pub fn unloadTree(file: *File, gpa: *Allocator) void { + if (file.tree_loaded) { + file.tree_loaded = false; + file.tree.deinit(gpa); } } - pub const Tag = enum { - /// .zig source code. - file, - /// Namespace owned by structs, enums, unions, and opaques for decls. - namespace, - block, - }; - - /// The container that structs, enums, unions, and opaques have. - pub const Namespace = struct { - pub const base_tag: Tag = .namespace; - base: Scope = Scope{ .tag = base_tag }, - - parent: ?*Namespace, - file_scope: *Scope.File, - /// Will be a struct, enum, union, or opaque. - ty: Type, - /// Direct children of the namespace. Used during an update to detect - /// which decls have been added/removed from source. - /// Declaration order is preserved via entry order. - /// Key memory is owned by `decl.name`. - /// TODO save memory with https://github.com/ziglang/zig/issues/8619. - /// Anonymous decls are not stored here; they are kept in `anon_decls` instead. - decls: std.StringArrayHashMapUnmanaged(*Decl) = .{}, - - anon_decls: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{}, - - /// Key is usingnamespace Decl itself. To find the namespace being included, - /// the Decl Value has to be resolved as a Type which has a Namespace. - /// Value is whether the usingnamespace decl is marked `pub`. - usingnamespace_set: std.AutoHashMapUnmanaged(*Decl, bool) = .{}, - - pub fn deinit(ns: *Namespace, mod: *Module) void { - ns.destroyDecls(mod); - ns.* = undefined; + pub fn unloadSource(file: *File, gpa: *Allocator) void { + if (file.source_loaded) { + file.source_loaded = false; + gpa.free(file.source); } + } - pub fn destroyDecls(ns: *Namespace, mod: *Module) void { - const gpa = mod.gpa; - - log.debug("destroyDecls {*}", .{ns}); - - var decls = ns.decls; - ns.decls = .{}; - - var anon_decls = ns.anon_decls; - ns.anon_decls = .{}; - - for (decls.values()) |value| { - value.destroy(mod); - } - decls.deinit(gpa); - - for (anon_decls.keys()) |key| { - key.destroy(mod); - } - anon_decls.deinit(gpa); + pub fn unloadZir(file: *File, gpa: *Allocator) void { + if (file.zir_loaded) { + file.zir_loaded = false; + file.zir.deinit(gpa); } + } - pub fn deleteAllDecls( - ns: *Namespace, - mod: *Module, - outdated_decls: ?*std.AutoArrayHashMap(*Decl, void), - ) !void { - const gpa = mod.gpa; - - log.debug("deleteAllDecls {*}", .{ns}); - - var decls = ns.decls; - ns.decls = .{}; - - var anon_decls = ns.anon_decls; - ns.anon_decls = .{}; - - // TODO rework this code to not panic on OOM. - // (might want to coordinate with the clearDecl function) - - for (decls.values()) |child_decl| { - mod.clearDecl(child_decl, outdated_decls) catch @panic("out of memory"); - child_decl.destroy(mod); - } - decls.deinit(gpa); - - for (anon_decls.keys()) |child_decl| { - mod.clearDecl(child_decl, outdated_decls) catch @panic("out of memory"); - child_decl.destroy(mod); - } - anon_decls.deinit(gpa); + pub fn deinit(file: *File, mod: *Module) void { + const gpa = mod.gpa; + log.debug("deinit File {s}", .{file.sub_file_path}); + file.deleted_decls.deinit(gpa); + file.outdated_decls.deinit(gpa); + if (file.root_decl) |root_decl| { + root_decl.destroy(mod); } - - // This renders e.g. "std.fs.Dir.OpenOptions" - pub fn renderFullyQualifiedName( - ns: Namespace, - name: []const u8, - writer: anytype, - ) @TypeOf(writer).Error!void { - if (ns.parent) |parent| { - const decl = ns.getDecl(); - try parent.renderFullyQualifiedName(mem.spanZ(decl.name), writer); - } else { - try ns.file_scope.renderFullyQualifiedName(writer); - } - if (name.len != 0) { - try writer.writeAll("."); - try writer.writeAll(name); - } + gpa.free(file.sub_file_path); + file.unload(gpa); + if (file.prev_zir) |prev_zir| { + prev_zir.deinit(gpa); + gpa.destroy(prev_zir); } + file.* = undefined; + } - pub fn getDecl(ns: Namespace) *Decl { - return ns.ty.getOwnerDecl(); - } - }; + pub fn getSource(file: *File, gpa: *Allocator) ![:0]const u8 { + if (file.source_loaded) return file.source; - pub const File = struct { - pub const base_tag: Tag = .file; - base: Scope = Scope{ .tag = base_tag }, - status: enum { - never_loaded, - retryable_failure, - parse_failure, - astgen_failure, - success_zir, - }, - source_loaded: bool, - tree_loaded: bool, - zir_loaded: bool, - /// Relative to the owning package's root_src_dir. - /// Memory is stored in gpa, owned by File. - sub_file_path: []const u8, - /// Whether this is populated depends on `source_loaded`. - source: [:0]const u8, - /// Whether this is populated depends on `status`. - stat_size: u64, - /// Whether this is populated depends on `status`. - stat_inode: std.fs.File.INode, - /// Whether this is populated depends on `status`. - stat_mtime: i128, - /// Whether this is populated or not depends on `tree_loaded`. - tree: Ast, - /// Whether this is populated or not depends on `zir_loaded`. - zir: Zir, - /// Package that this file is a part of, managed externally. - pkg: *Package, - /// The Decl of the struct that represents this File. - root_decl: ?*Decl, + const root_dir_path = file.pkg.root_src_directory.path orelse "."; + log.debug("File.getSource, not cached. pkgdir={s} sub_file_path={s}", .{ + root_dir_path, file.sub_file_path, + }); - /// Used by change detection algorithm, after astgen, contains the - /// set of decls that existed in the previous ZIR but not in the new one. - deleted_decls: std.ArrayListUnmanaged(*Decl) = .{}, - /// Used by change detection algorithm, after astgen, contains the - /// set of decls that existed both in the previous ZIR and in the new one, - /// but their source code has been modified. - outdated_decls: std.ArrayListUnmanaged(*Decl) = .{}, + // Keep track of inode, file size, mtime, hash so we can detect which files + // have been modified when an incremental update is requested. + var f = try file.pkg.root_src_directory.handle.openFile(file.sub_file_path, .{}); + defer f.close(); - /// The most recent successful ZIR for this file, with no errors. - /// This is only populated when a previously successful ZIR - /// newly introduces compile errors during an update. When ZIR is - /// successful, this field is unloaded. - prev_zir: ?*Zir = null, + const stat = try f.stat(); - pub fn unload(file: *File, gpa: *Allocator) void { - file.unloadTree(gpa); - file.unloadSource(gpa); - file.unloadZir(gpa); - } + if (stat.size > std.math.maxInt(u32)) + return error.FileTooBig; - pub fn unloadTree(file: *File, gpa: *Allocator) void { - if (file.tree_loaded) { - file.tree_loaded = false; - file.tree.deinit(gpa); - } - } + const source = try gpa.allocSentinel(u8, @intCast(usize, stat.size), 0); + defer if (!file.source_loaded) gpa.free(source); + const amt = try f.readAll(source); + if (amt != stat.size) + return error.UnexpectedEndOfFile; - pub fn unloadSource(file: *File, gpa: *Allocator) void { - if (file.source_loaded) { - file.source_loaded = false; - gpa.free(file.source); - } - } + // Here we do not modify stat fields because this function is the one + // used for error reporting. We need to keep the stat fields stale so that + // astGenFile can know to regenerate ZIR. - pub fn unloadZir(file: *File, gpa: *Allocator) void { - if (file.zir_loaded) { - file.zir_loaded = false; - file.zir.deinit(gpa); - } - } + file.source = source; + file.source_loaded = true; + return source; + } - pub fn deinit(file: *File, mod: *Module) void { - const gpa = mod.gpa; - log.debug("deinit File {s}", .{file.sub_file_path}); - file.deleted_decls.deinit(gpa); - file.outdated_decls.deinit(gpa); - if (file.root_decl) |root_decl| { - root_decl.destroy(mod); - } - gpa.free(file.sub_file_path); - file.unload(gpa); - if (file.prev_zir) |prev_zir| { - prev_zir.deinit(gpa); - gpa.destroy(prev_zir); - } - file.* = undefined; - } + pub fn getTree(file: *File, gpa: *Allocator) !*const Ast { + if (file.tree_loaded) return &file.tree; - pub fn getSource(file: *File, gpa: *Allocator) ![:0]const u8 { - if (file.source_loaded) return file.source; + const source = try file.getSource(gpa); + file.tree = try std.zig.parse(gpa, source); + file.tree_loaded = true; + return &file.tree; + } - const root_dir_path = file.pkg.root_src_directory.path orelse "."; - log.debug("File.getSource, not cached. pkgdir={s} sub_file_path={s}", .{ - root_dir_path, file.sub_file_path, - }); + pub fn destroy(file: *File, mod: *Module) void { + const gpa = mod.gpa; + file.deinit(mod); + gpa.destroy(file); + } - // Keep track of inode, file size, mtime, hash so we can detect which files - // have been modified when an incremental update is requested. - var f = try file.pkg.root_src_directory.handle.openFile(file.sub_file_path, .{}); - defer f.close(); - - const stat = try f.stat(); - - if (stat.size > std.math.maxInt(u32)) - return error.FileTooBig; - - const source = try gpa.allocSentinel(u8, @intCast(usize, stat.size), 0); - defer if (!file.source_loaded) gpa.free(source); - const amt = try f.readAll(source); - if (amt != stat.size) - return error.UnexpectedEndOfFile; - - // Here we do not modify stat fields because this function is the one - // used for error reporting. We need to keep the stat fields stale so that - // astGenFile can know to regenerate ZIR. - - file.source = source; - file.source_loaded = true; - return source; - } - - pub fn getTree(file: *File, gpa: *Allocator) !*const Ast { - if (file.tree_loaded) return &file.tree; - - const source = try file.getSource(gpa); - file.tree = try std.zig.parse(gpa, source); - file.tree_loaded = true; - return &file.tree; - } - - pub fn destroy(file: *File, mod: *Module) void { - const gpa = mod.gpa; - file.deinit(mod); - gpa.destroy(file); - } - - pub fn renderFullyQualifiedName(file: File, writer: anytype) !void { - // Convert all the slashes into dots and truncate the extension. - const ext = std.fs.path.extension(file.sub_file_path); - const noext = file.sub_file_path[0 .. file.sub_file_path.len - ext.len]; - for (noext) |byte| switch (byte) { - '/', '\\' => try writer.writeByte('.'), - else => try writer.writeByte(byte), - }; - } - - pub fn fullyQualifiedNameZ(file: File, gpa: *Allocator) ![:0]u8 { - var buf = std.ArrayList(u8).init(gpa); - defer buf.deinit(); - try file.renderFullyQualifiedName(buf.writer()); - return buf.toOwnedSliceSentinel(0); - } - - /// Returns the full path to this file relative to its package. - pub fn fullPath(file: File, ally: *Allocator) ![]u8 { - return file.pkg.root_src_directory.join(ally, &[_][]const u8{file.sub_file_path}); - } - - pub fn dumpSrc(file: *File, src: LazySrcLoc) void { - const loc = std.zig.findLineColumn(file.source.bytes, src); - std.debug.print("{s}:{d}:{d}\n", .{ file.sub_file_path, loc.line + 1, loc.column + 1 }); - } - - pub fn okToReportErrors(file: File) bool { - return switch (file.status) { - .parse_failure, .astgen_failure => false, - else => true, - }; - } - }; - - /// This is the context needed to semantically analyze ZIR instructions and - /// produce AIR instructions. - /// This is a temporary structure stored on the stack; references to it are valid only - /// during semantic analysis of the block. - pub const Block = struct { - pub const base_tag: Tag = .block; - - base: Scope = Scope{ .tag = base_tag }, - parent: ?*Block, - /// Shared among all child blocks. - sema: *Sema, - /// This Decl is the Decl according to the Zig source code corresponding to this Block. - /// This can vary during inline or comptime function calls. See `Sema.owner_decl` - /// for the one that will be the same for all Block instances. - src_decl: *Decl, - instructions: ArrayListUnmanaged(Air.Inst.Index), - // `param` instructions are collected here to be used by the `func` instruction. - params: std.ArrayListUnmanaged(Param) = .{}, - - wip_capture_scope: *CaptureScope, - - label: ?*Label = null, - inlining: ?*Inlining, - /// If runtime_index is not 0 then one of these is guaranteed to be non null. - runtime_cond: ?LazySrcLoc = null, - runtime_loop: ?LazySrcLoc = null, - /// Non zero if a non-inline loop or a runtime conditional have been encountered. - /// Stores to to comptime variables are only allowed when var.runtime_index <= runtime_index. - runtime_index: u32 = 0, - - is_comptime: bool, - - /// when null, it is determined by build mode, changed by @setRuntimeSafety - want_safety: ?bool = null, - - c_import_buf: ?*std.ArrayList(u8) = null, - - const Param = struct { - /// `noreturn` means `anytype`. - ty: Type, - is_comptime: bool, + pub fn renderFullyQualifiedName(file: File, writer: anytype) !void { + // Convert all the slashes into dots and truncate the extension. + const ext = std.fs.path.extension(file.sub_file_path); + const noext = file.sub_file_path[0 .. file.sub_file_path.len - ext.len]; + for (noext) |byte| switch (byte) { + '/', '\\' => try writer.writeByte('.'), + else => try writer.writeByte(byte), }; + } - /// This `Block` maps a block ZIR instruction to the corresponding - /// AIR instruction for break instruction analysis. - pub const Label = struct { - zir_block: Zir.Inst.Index, - merges: Merges, + pub fn renderFullyQualifiedDebugName(file: File, writer: anytype) !void { + for (file.sub_file_path) |byte| switch (byte) { + '/', '\\' => try writer.writeByte('/'), + else => try writer.writeByte(byte), }; + } - /// This `Block` indicates that an inline function call is happening - /// and return instructions should be analyzed as a break instruction - /// to this AIR block instruction. - /// It is shared among all the blocks in an inline or comptime called - /// function. - pub const Inlining = struct { - comptime_result: Air.Inst.Ref, - merges: Merges, + pub fn fullyQualifiedNameZ(file: File, gpa: *Allocator) ![:0]u8 { + var buf = std.ArrayList(u8).init(gpa); + defer buf.deinit(); + try file.renderFullyQualifiedName(buf.writer()); + return buf.toOwnedSliceSentinel(0); + } + + /// Returns the full path to this file relative to its package. + pub fn fullPath(file: File, ally: *Allocator) ![]u8 { + return file.pkg.root_src_directory.join(ally, &[_][]const u8{file.sub_file_path}); + } + + pub fn dumpSrc(file: *File, src: LazySrcLoc) void { + const loc = std.zig.findLineColumn(file.source.bytes, src); + std.debug.print("{s}:{d}:{d}\n", .{ file.sub_file_path, loc.line + 1, loc.column + 1 }); + } + + pub fn okToReportErrors(file: File) bool { + return switch (file.status) { + .parse_failure, .astgen_failure => false, + else => true, }; - - pub const Merges = struct { - block_inst: Air.Inst.Index, - /// Separate array list from break_inst_list so that it can be passed directly - /// to resolvePeerTypes. - results: ArrayListUnmanaged(Air.Inst.Ref), - /// Keeps track of the break instructions so that the operand can be replaced - /// if we need to add type coercion at the end of block analysis. - /// Same indexes, capacity, length as `results`. - br_list: ArrayListUnmanaged(Air.Inst.Index), - }; - - /// For debugging purposes. - pub fn dump(block: *Block, mod: Module) void { - Zir.dumpBlock(mod, block); - } - - pub fn makeSubBlock(parent: *Block) Block { - return .{ - .parent = parent, - .sema = parent.sema, - .src_decl = parent.src_decl, - .instructions = .{}, - .wip_capture_scope = parent.wip_capture_scope, - .label = null, - .inlining = parent.inlining, - .is_comptime = parent.is_comptime, - .runtime_cond = parent.runtime_cond, - .runtime_loop = parent.runtime_loop, - .runtime_index = parent.runtime_index, - .want_safety = parent.want_safety, - .c_import_buf = parent.c_import_buf, - }; - } - - pub fn wantSafety(block: *const Block) bool { - return block.want_safety orelse switch (block.sema.mod.optimizeMode()) { - .Debug => true, - .ReleaseSafe => true, - .ReleaseFast => false, - .ReleaseSmall => false, - }; - } - - pub fn getFileScope(block: *Block) *Scope.File { - return block.src_decl.namespace.file_scope; - } - - pub fn addTy( - block: *Block, - tag: Air.Inst.Tag, - ty: Type, - ) error{OutOfMemory}!Air.Inst.Ref { - return block.addInst(.{ - .tag = tag, - .data = .{ .ty = ty }, - }); - } - - pub fn addTyOp( - block: *Block, - tag: Air.Inst.Tag, - ty: Type, - operand: Air.Inst.Ref, - ) error{OutOfMemory}!Air.Inst.Ref { - return block.addInst(.{ - .tag = tag, - .data = .{ .ty_op = .{ - .ty = try block.sema.addType(ty), - .operand = operand, - } }, - }); - } - - pub fn addNoOp(block: *Block, tag: Air.Inst.Tag) error{OutOfMemory}!Air.Inst.Ref { - return block.addInst(.{ - .tag = tag, - .data = .{ .no_op = {} }, - }); - } - - pub fn addUnOp( - block: *Block, - tag: Air.Inst.Tag, - operand: Air.Inst.Ref, - ) error{OutOfMemory}!Air.Inst.Ref { - return block.addInst(.{ - .tag = tag, - .data = .{ .un_op = operand }, - }); - } - - pub fn addBr( - block: *Block, - target_block: Air.Inst.Index, - operand: Air.Inst.Ref, - ) error{OutOfMemory}!Air.Inst.Ref { - return block.addInst(.{ - .tag = .br, - .data = .{ .br = .{ - .block_inst = target_block, - .operand = operand, - } }, - }); - } - - pub fn addBinOp( - block: *Block, - tag: Air.Inst.Tag, - lhs: Air.Inst.Ref, - rhs: Air.Inst.Ref, - ) error{OutOfMemory}!Air.Inst.Ref { - return block.addInst(.{ - .tag = tag, - .data = .{ .bin_op = .{ - .lhs = lhs, - .rhs = rhs, - } }, - }); - } - - pub fn addArg(block: *Block, ty: Type, name: u32) error{OutOfMemory}!Air.Inst.Ref { - return block.addInst(.{ - .tag = .arg, - .data = .{ .ty_str = .{ - .ty = try block.sema.addType(ty), - .str = name, - } }, - }); - } - - pub fn addStructFieldPtr( - block: *Block, - struct_ptr: Air.Inst.Ref, - field_index: u32, - ptr_field_ty: Type, - ) !Air.Inst.Ref { - const ty = try block.sema.addType(ptr_field_ty); - const tag: Air.Inst.Tag = switch (field_index) { - 0 => .struct_field_ptr_index_0, - 1 => .struct_field_ptr_index_1, - 2 => .struct_field_ptr_index_2, - 3 => .struct_field_ptr_index_3, - else => { - return block.addInst(.{ - .tag = .struct_field_ptr, - .data = .{ .ty_pl = .{ - .ty = ty, - .payload = try block.sema.addExtra(Air.StructField{ - .struct_operand = struct_ptr, - .field_index = @intCast(u32, field_index), - }), - } }, - }); - }, - }; - return block.addInst(.{ - .tag = tag, - .data = .{ .ty_op = .{ - .ty = ty, - .operand = struct_ptr, - } }, - }); - } - - pub fn addInst(block: *Block, inst: Air.Inst) error{OutOfMemory}!Air.Inst.Ref { - return Air.indexToRef(try block.addInstAsIndex(inst)); - } - - pub fn addInstAsIndex(block: *Block, inst: Air.Inst) error{OutOfMemory}!Air.Inst.Index { - const sema = block.sema; - const gpa = sema.gpa; - - try sema.air_instructions.ensureUnusedCapacity(gpa, 1); - try block.instructions.ensureUnusedCapacity(gpa, 1); - - const result_index = @intCast(Air.Inst.Index, sema.air_instructions.len); - sema.air_instructions.appendAssumeCapacity(inst); - block.instructions.appendAssumeCapacity(result_index); - return result_index; - } - - pub fn startAnonDecl(block: *Block) !WipAnonDecl { - return WipAnonDecl{ - .block = block, - .new_decl_arena = std.heap.ArenaAllocator.init(block.sema.gpa), - .finished = false, - }; - } - - pub const WipAnonDecl = struct { - block: *Scope.Block, - new_decl_arena: std.heap.ArenaAllocator, - finished: bool, - - pub fn arena(wad: *WipAnonDecl) *Allocator { - return &wad.new_decl_arena.allocator; - } - - pub fn deinit(wad: *WipAnonDecl) void { - if (!wad.finished) { - wad.new_decl_arena.deinit(); - } - wad.* = undefined; - } - - pub fn finish(wad: *WipAnonDecl, ty: Type, val: Value) !*Decl { - const new_decl = try wad.block.sema.mod.createAnonymousDecl(&wad.block.base, .{ - .ty = ty, - .val = val, - }); - errdefer wad.block.sema.mod.deleteAnonDecl(&wad.block.base, new_decl); - try new_decl.finalizeNewArena(&wad.new_decl_arena); - wad.finished = true; - return new_decl; - } - }; - }; + } }; /// This struct holds data necessary to construct API-facing `AllErrors.Message`. /// Its memory is managed with the general purpose allocator so that they /// can be created and destroyed in response to incremental updates. -/// In some cases, the Scope.File could have been inferred from where the ErrorMsg -/// is stored. For example, if it is stored in Module.failed_decls, then the Scope.File +/// In some cases, the File could have been inferred from where the ErrorMsg +/// is stored. For example, if it is stored in Module.failed_decls, then the File /// would be determined by the Decl Scope. However, the data structure contains the field /// anyway so that `ErrorMsg` can be reused for error notes, which may be in a different /// file than the parent error message. It also simplifies processing of error messages. @@ -1757,7 +1438,7 @@ pub const ErrorMsg = struct { /// Canonical reference to a position within a source file. pub const SrcLoc = struct { - file_scope: *Scope.File, + file_scope: *File, /// Might be 0 depending on tag of `lazy`. parent_decl_node: Ast.Node.Index, /// Relative to `parent_decl_node`. @@ -2334,60 +2015,8 @@ pub const LazySrcLoc = union(enum) { /// The Decl is determined contextually. node_offset_lib_name: i32, - /// Upgrade to a `SrcLoc` based on the `Decl` or file in the provided scope. - pub fn toSrcLoc(lazy: LazySrcLoc, scope: *Scope) SrcLoc { - return switch (lazy) { - .unneeded, - .entire_file, - .byte_abs, - .token_abs, - .node_abs, - => .{ - .file_scope = scope.getFileScope(), - .parent_decl_node = 0, - .lazy = lazy, - }, - - .byte_offset, - .token_offset, - .node_offset, - .node_offset_back2tok, - .node_offset_var_decl_ty, - .node_offset_for_cond, - .node_offset_builtin_call_arg0, - .node_offset_builtin_call_arg1, - .node_offset_builtin_call_arg2, - .node_offset_builtin_call_arg3, - .node_offset_builtin_call_arg4, - .node_offset_builtin_call_arg5, - .node_offset_array_access_index, - .node_offset_slice_sentinel, - .node_offset_call_func, - .node_offset_field_name, - .node_offset_deref_ptr, - .node_offset_asm_source, - .node_offset_asm_ret_ty, - .node_offset_if_cond, - .node_offset_bin_op, - .node_offset_bin_lhs, - .node_offset_bin_rhs, - .node_offset_switch_operand, - .node_offset_switch_special_prong, - .node_offset_switch_range, - .node_offset_fn_type_cc, - .node_offset_fn_type_ret_ty, - .node_offset_anyframe_type, - .node_offset_lib_name, - => .{ - .file_scope = scope.getFileScope(), - .parent_decl_node = scope.srcDecl().?.src_node, - .lazy = lazy, - }, - }; - } - /// Upgrade to a `SrcLoc` based on the `Decl` provided. - pub fn toSrcLocWithDecl(lazy: LazySrcLoc, decl: *Decl) SrcLoc { + pub fn toSrcLoc(lazy: LazySrcLoc, decl: *Decl) SrcLoc { return switch (lazy) { .unneeded, .entire_file, @@ -2576,7 +2205,7 @@ comptime { } } -pub fn astGenFile(mod: *Module, file: *Scope.File) !void { +pub fn astGenFile(mod: *Module, file: *File) !void { const tracy = trace(@src()); defer tracy.end(); @@ -2960,7 +2589,7 @@ pub fn astGenFile(mod: *Module, file: *Scope.File) !void { /// * Decl.zir_index /// * Fn.zir_body_inst /// * Decl.zir_decl_index -fn updateZirRefs(gpa: *Allocator, file: *Scope.File, old_zir: Zir) !void { +fn updateZirRefs(gpa: *Allocator, file: *File, old_zir: Zir) !void { const new_zir = file.zir; // Maps from old ZIR to new ZIR, struct_decl, enum_decl, etc. Any instruction which @@ -3216,7 +2845,7 @@ pub fn semaPkg(mod: *Module, pkg: *Package) !void { /// Regardless of the file status, will create a `Decl` so that we /// can track dependencies and re-analyze when the file becomes outdated. -pub fn semaFile(mod: *Module, file: *Scope.File) SemaError!void { +pub fn semaFile(mod: *Module, file: *File) SemaError!void { const tracy = trace(@src()); defer tracy.end(); @@ -3244,11 +2873,11 @@ pub fn semaFile(mod: *Module, file: *Scope.File) SemaError!void { .file_scope = file, }, }; - const new_decl = try mod.allocateNewDecl(&struct_obj.namespace, 0, null); + const decl_name = try file.fullyQualifiedNameZ(gpa); + const new_decl = try mod.allocateNewDecl(decl_name, &struct_obj.namespace, 0, null); file.root_decl = new_decl; struct_obj.owner_decl = new_decl; new_decl.src_line = 0; - new_decl.name = try file.fullyQualifiedNameZ(gpa); new_decl.is_pub = true; new_decl.is_exported = false; new_decl.has_align = false; @@ -3276,7 +2905,6 @@ pub fn semaFile(mod: *Module, file: *Scope.File) SemaError!void { .perm_arena = &new_decl_arena.allocator, .code = file.zir, .owner_decl = new_decl, - .namespace = &struct_obj.namespace, .func = null, .fn_ret_ty = Type.initTag(.void), .owner_func = null, @@ -3286,10 +2914,11 @@ pub fn semaFile(mod: *Module, file: *Scope.File) SemaError!void { var wip_captures = try WipCaptureScope.init(gpa, &new_decl_arena.allocator, null); defer wip_captures.deinit(); - var block_scope: Scope.Block = .{ + var block_scope: Sema.Block = .{ .parent = null, .sema = &sema, .src_decl = new_decl, + .namespace = &struct_obj.namespace, .wip_capture_scope = wip_captures.scope, .instructions = .{}, .inlining = null, @@ -3318,12 +2947,12 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { const tracy = trace(@src()); defer tracy.end(); - if (decl.namespace.file_scope.status != .success_zir) { + if (decl.getFileScope().status != .success_zir) { return error.AnalysisFail; } const gpa = mod.gpa; - const zir = decl.namespace.file_scope.zir; + const zir = decl.getFileScope().zir; const zir_datas = zir.instructions.items(.data); decl.analysis = .in_progress; @@ -3342,7 +2971,6 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { .perm_arena = &decl_arena.allocator, .code = zir, .owner_decl = decl, - .namespace = decl.namespace, .func = null, .fn_ret_ty = Type.initTag(.void), .owner_func = null, @@ -3366,10 +2994,11 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { var wip_captures = try WipCaptureScope.init(gpa, &decl_arena.allocator, decl.src_scope); defer wip_captures.deinit(); - var block_scope: Scope.Block = .{ + var block_scope: Sema.Block = .{ .parent = null, .sema = &sema, .src_decl = decl, + .namespace = decl.src_namespace, .wip_capture_scope = wip_captures.scope, .instructions = .{}, .inlining = null, @@ -3427,12 +3056,12 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { if (decl.is_usingnamespace) { const ty_ty = Type.initTag(.type); if (!decl_tv.ty.eql(ty_ty)) { - return mod.fail(&block_scope.base, src, "expected type, found {}", .{decl_tv.ty}); + return sema.fail(&block_scope, src, "expected type, found {}", .{decl_tv.ty}); } var buffer: Value.ToTypeBuffer = undefined; const ty = decl_tv.val.toType(&buffer); if (ty.getNamespace() == null) { - return mod.fail(&block_scope.base, src, "type {} has no namespace", .{ty}); + return sema.fail(&block_scope, src, "type {} has no namespace", .{ty}); } decl.ty = ty_ty; @@ -3495,11 +3124,11 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { if (decl.is_exported) { const export_src = src; // TODO make this point at `export` token if (is_inline) { - return mod.fail(&block_scope.base, export_src, "export of inline function", .{}); + return sema.fail(&block_scope, export_src, "export of inline function", .{}); } // The scope needs to have the decl in it. const options: std.builtin.ExportOptions = .{ .name = mem.spanZ(decl.name) }; - try mod.analyzeExport(&block_scope, export_src, options, decl); + try sema.analyzeExport(&block_scope, export_src, options, decl); } return type_changed or is_inline != prev_is_inline; } @@ -3548,18 +3177,12 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl }); } } - // In case this Decl is a struct or union, we need to resolve the fields - // while we still have the `Sema` in scope, so that the field type expressions - // can use the resolved AIR instructions that they possibly reference. - // We do this after the decl is populated and set to `complete` so that a `Decl` - // may reference itself. - try sema.resolvePendingTypes(&block_scope); if (decl.is_exported) { const export_src = src; // TODO point to the export token // The scope needs to have the decl in it. const options: std.builtin.ExportOptions = .{ .name = mem.spanZ(decl.name) }; - try mod.analyzeExport(&block_scope, export_src, options, decl); + try sema.analyzeExport(&block_scope, export_src, options, decl); } return type_changed; @@ -3586,7 +3209,7 @@ pub fn declareDeclDependency(mod: *Module, depender: *Decl, dependee: *Decl) !vo } pub const ImportFileResult = struct { - file: *Scope.File, + file: *File, is_new: bool, }; @@ -3612,7 +3235,7 @@ pub fn importPkg(mod: *Module, pkg: *Package) !ImportFileResult { const sub_file_path = try gpa.dupe(u8, pkg.root_src_path); errdefer gpa.free(sub_file_path); - const new_file = try gpa.create(Scope.File); + const new_file = try gpa.create(File); errdefer gpa.destroy(new_file); gop.value_ptr.* = new_file; @@ -3639,7 +3262,7 @@ pub fn importPkg(mod: *Module, pkg: *Package) !ImportFileResult { pub fn importFile( mod: *Module, - cur_file: *Scope.File, + cur_file: *File, import_string: []const u8, ) !ImportFileResult { if (cur_file.pkg.table.get(import_string)) |pkg| { @@ -3667,7 +3290,7 @@ pub fn importFile( }; keep_resolved_path = true; // It's now owned by import_table. - const new_file = try gpa.create(Scope.File); + const new_file = try gpa.create(File); errdefer gpa.destroy(new_file); const resolved_root_path = try std.fs.path.resolve(gpa, &[_][]const u8{cur_pkg_dir_path}); @@ -3708,7 +3331,7 @@ pub fn importFile( pub fn scanNamespace( mod: *Module, - namespace: *Scope.Namespace, + namespace: *Namespace, extra_start: usize, decls_len: u32, parent_decl: *Decl, @@ -3752,7 +3375,7 @@ pub fn scanNamespace( const ScanDeclIter = struct { module: *Module, - namespace: *Scope.Namespace, + namespace: *Namespace, parent_decl: *Decl, usingnamespace_index: usize = 0, comptime_index: usize = 0, @@ -3818,13 +3441,12 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) SemaError!voi // We create a Decl for it regardless of analysis status. const gop = try namespace.decls.getOrPut(gpa, decl_name); if (!gop.found_existing) { - const new_decl = try mod.allocateNewDecl(namespace, decl_node, iter.parent_decl.src_scope); + const new_decl = try mod.allocateNewDecl(decl_name, namespace, decl_node, iter.parent_decl.src_scope); if (is_usingnamespace) { namespace.usingnamespace_set.putAssumeCapacity(new_decl, is_pub); } log.debug("scan new {*} ({s}) into {*}", .{ new_decl, decl_name, namespace }); new_decl.src_line = line; - new_decl.name = decl_name; gop.value_ptr.* = new_decl; // Exported decls, comptime decls, usingnamespace decls, and // test decls if in test mode, get analyzed. @@ -4013,9 +3635,10 @@ pub fn deleteUnusedDecl(mod: *Module, decl: *Decl) void { }, } - const dependants = decl.dependants.keys(); - assert(dependants[0].namespace.anon_decls.swapRemove(decl)); + assert(!decl.isRoot()); + assert(decl.src_namespace.anon_decls.swapRemove(decl)); + const dependants = decl.dependants.keys(); for (dependants) |dep| { dep.removeDependency(decl); } @@ -4026,10 +3649,22 @@ pub fn deleteUnusedDecl(mod: *Module, decl: *Decl) void { decl.destroy(mod); } -pub fn deleteAnonDecl(mod: *Module, scope: *Scope, decl: *Decl) void { - log.debug("deleteAnonDecl {*} ({s})", .{ decl, decl.name }); - const scope_decl = scope.srcDecl().?; - assert(scope_decl.namespace.anon_decls.swapRemove(decl)); +/// Cancel the creation of an anon decl and delete any references to it. +/// If other decls depend on this decl, they must be aborted first. +pub fn abortAnonDecl(mod: *Module, decl: *Decl) void { + log.debug("abortAnonDecl {*} ({s})", .{ decl, decl.name }); + + assert(!decl.isRoot()); + assert(decl.src_namespace.anon_decls.swapRemove(decl)); + + // An aborted decl must not have dependants -- they must have + // been aborted first and removed from this list. + assert(decl.dependants.count() == 0); + + for (decl.dependencies.keys()) |dep| { + dep.removeDependant(decl); + } + decl.destroy(mod); } @@ -4087,9 +3722,8 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn, arena: *Allocator) Se .gpa = gpa, .arena = arena, .perm_arena = &decl_arena.allocator, - .code = decl.namespace.file_scope.zir, + .code = decl.getFileScope().zir, .owner_decl = decl, - .namespace = decl.namespace, .func = func, .fn_ret_ty = func.owner_decl.ty.fnReturnType(), .owner_func = func, @@ -4104,10 +3738,11 @@ pub fn analyzeFnBody(mod: *Module, decl: *Decl, func: *Fn, arena: *Allocator) Se var wip_captures = try WipCaptureScope.init(gpa, &decl_arena.allocator, decl.src_scope); defer wip_captures.deinit(); - var inner_block: Scope.Block = .{ + var inner_block: Sema.Block = .{ .parent = null, .sema = &sema, .src_decl = decl, + .namespace = decl.src_namespace, .wip_capture_scope = wip_captures.scope, .instructions = .{}, .inlining = null, @@ -4226,7 +3861,7 @@ fn markOutdatedDecl(mod: *Module, decl: *Decl) !void { decl.analysis = .outdated; } -pub fn allocateNewDecl(mod: *Module, namespace: *Scope.Namespace, src_node: Ast.Node.Index, src_scope: ?*CaptureScope) !*Decl { +pub fn allocateNewDecl(mod: *Module, name: [:0]const u8, namespace: *Namespace, src_node: Ast.Node.Index, src_scope: ?*CaptureScope) !*Decl { // If we have emit-h then we must allocate a bigger structure to store the emit-h state. const new_decl: *Decl = if (mod.emit_h != null) blk: { const parent_struct = try mod.gpa.create(DeclPlusEmitH); @@ -4238,8 +3873,8 @@ pub fn allocateNewDecl(mod: *Module, namespace: *Scope.Namespace, src_node: Ast. } else try mod.gpa.create(Decl); new_decl.* = .{ - .name = "", - .namespace = namespace, + .name = name, + .src_namespace = namespace, .src_node = src_node, .src_line = undefined, .has_tv = false, @@ -4304,119 +3939,49 @@ pub fn getErrorValue(mod: *Module, name: []const u8) !std.StringHashMapUnmanaged }; } -pub fn analyzeExport( - mod: *Module, - block: *Scope.Block, - src: LazySrcLoc, - borrowed_options: std.builtin.ExportOptions, - exported_decl: *Decl, -) !void { - try mod.ensureDeclAnalyzed(exported_decl); - switch (exported_decl.ty.zigTypeTag()) { - .Fn => {}, - else => return mod.fail(&block.base, src, "unable to export type '{}'", .{exported_decl.ty}), - } - - const gpa = mod.gpa; - - try mod.decl_exports.ensureUnusedCapacity(gpa, 1); - try mod.export_owners.ensureUnusedCapacity(gpa, 1); - - const new_export = try gpa.create(Export); - errdefer gpa.destroy(new_export); - - const symbol_name = try gpa.dupe(u8, borrowed_options.name); - errdefer gpa.free(symbol_name); - - const section: ?[]const u8 = if (borrowed_options.section) |s| try gpa.dupe(u8, s) else null; - errdefer if (section) |s| gpa.free(s); - - const src_decl = block.src_decl; - const owner_decl = block.sema.owner_decl; - - log.debug("exporting Decl '{s}' as symbol '{s}' from Decl '{s}'", .{ - exported_decl.name, symbol_name, owner_decl.name, - }); - - new_export.* = .{ - .options = .{ - .name = symbol_name, - .linkage = borrowed_options.linkage, - .section = section, - }, - .src = src, - .link = switch (mod.comp.bin_file.tag) { - .coff => .{ .coff = {} }, - .elf => .{ .elf = link.File.Elf.Export{} }, - .macho => .{ .macho = link.File.MachO.Export{} }, - .plan9 => .{ .plan9 = null }, - .c => .{ .c = {} }, - .wasm => .{ .wasm = {} }, - .spirv => .{ .spirv = {} }, - }, - .owner_decl = owner_decl, - .src_decl = src_decl, - .exported_decl = exported_decl, - .status = .in_progress, - }; - - // Add to export_owners table. - const eo_gop = mod.export_owners.getOrPutAssumeCapacity(owner_decl); - if (!eo_gop.found_existing) { - eo_gop.value_ptr.* = &[0]*Export{}; - } - eo_gop.value_ptr.* = try gpa.realloc(eo_gop.value_ptr.*, eo_gop.value_ptr.len + 1); - eo_gop.value_ptr.*[eo_gop.value_ptr.len - 1] = new_export; - errdefer eo_gop.value_ptr.* = gpa.shrink(eo_gop.value_ptr.*, eo_gop.value_ptr.len - 1); - - // Add to exported_decl table. - const de_gop = mod.decl_exports.getOrPutAssumeCapacity(exported_decl); - if (!de_gop.found_existing) { - de_gop.value_ptr.* = &[0]*Export{}; - } - de_gop.value_ptr.* = try gpa.realloc(de_gop.value_ptr.*, de_gop.value_ptr.len + 1); - de_gop.value_ptr.*[de_gop.value_ptr.len - 1] = new_export; - errdefer de_gop.value_ptr.* = gpa.shrink(de_gop.value_ptr.*, de_gop.value_ptr.len - 1); -} - /// Takes ownership of `name` even if it returns an error. pub fn createAnonymousDeclNamed( mod: *Module, - scope: *Scope, + block: *Sema.Block, typed_value: TypedValue, name: [:0]u8, ) !*Decl { - return mod.createAnonymousDeclFromDeclNamed(scope.srcDecl().?, scope.srcScope(), typed_value, name); + return mod.createAnonymousDeclFromDeclNamed(block.src_decl, block.namespace, block.wip_capture_scope, typed_value, name); } -pub fn createAnonymousDecl(mod: *Module, scope: *Scope, typed_value: TypedValue) !*Decl { - return mod.createAnonymousDeclFromDecl(scope.srcDecl().?, scope.srcScope(), typed_value); +pub fn createAnonymousDecl(mod: *Module, block: *Sema.Block, typed_value: TypedValue) !*Decl { + return mod.createAnonymousDeclFromDecl(block.src_decl, block.namespace, block.wip_capture_scope, typed_value); } -pub fn createAnonymousDeclFromDecl(mod: *Module, src_decl: *Decl, src_scope: ?*CaptureScope, tv: TypedValue) !*Decl { +pub fn createAnonymousDeclFromDecl( + mod: *Module, + src_decl: *Decl, + namespace: *Namespace, + src_scope: ?*CaptureScope, + tv: TypedValue, +) !*Decl { const name_index = mod.getNextAnonNameIndex(); const name = try std.fmt.allocPrintZ(mod.gpa, "{s}__anon_{d}", .{ src_decl.name, name_index, }); - return mod.createAnonymousDeclFromDeclNamed(src_decl, src_scope, tv, name); + return mod.createAnonymousDeclFromDeclNamed(src_decl, namespace, src_scope, tv, name); } /// Takes ownership of `name` even if it returns an error. pub fn createAnonymousDeclFromDeclNamed( mod: *Module, src_decl: *Decl, + namespace: *Namespace, src_scope: ?*CaptureScope, typed_value: TypedValue, name: [:0]u8, ) !*Decl { errdefer mod.gpa.free(name); - const namespace = src_decl.namespace; try namespace.anon_decls.ensureUnusedCapacity(mod.gpa, 1); - const new_decl = try mod.allocateNewDecl(namespace, src_decl.src_node, src_scope); + const new_decl = try mod.allocateNewDecl(name, namespace, src_decl.src_node, src_scope); - new_decl.name = name; new_decl.src_line = src_decl.src_line; new_decl.ty = typed_value.ty; new_decl.val = typed_value.val; @@ -4458,19 +4023,6 @@ pub fn makeIntType(arena: *Allocator, signedness: std.builtin.Signedness, bits: return Type.initPayload(&int_payload.base); } -/// We don't return a pointer to the new error note because the pointer -/// becomes invalid when you add another one. -pub fn errNote( - mod: *Module, - scope: *Scope, - src: LazySrcLoc, - parent: *ErrorMsg, - comptime format: []const u8, - args: anytype, -) error{OutOfMemory}!void { - return mod.errNoteNonLazy(src.toSrcLoc(scope), parent, format, args); -} - pub fn errNoteNonLazy( mod: *Module, src_loc: SrcLoc, @@ -4488,81 +4040,6 @@ pub fn errNoteNonLazy( }; } -pub fn errMsg( - mod: *Module, - scope: *Scope, - src: LazySrcLoc, - comptime format: []const u8, - args: anytype, -) error{OutOfMemory}!*ErrorMsg { - return ErrorMsg.create(mod.gpa, src.toSrcLoc(scope), format, args); -} - -pub fn fail( - mod: *Module, - scope: *Scope, - src: LazySrcLoc, - comptime format: []const u8, - args: anytype, -) CompileError { - const err_msg = try mod.errMsg(scope, src, format, args); - return mod.failWithOwnedErrorMsg(scope, err_msg); -} - -/// Same as `fail`, except given a token index, and the function sets up the `LazySrcLoc` -/// for pointing at it relatively by subtracting from the containing `Decl`. -pub fn failTok( - mod: *Module, - scope: *Scope, - token_index: Ast.TokenIndex, - comptime format: []const u8, - args: anytype, -) CompileError { - const src = scope.srcDecl().?.tokSrcLoc(token_index); - return mod.fail(scope, src, format, args); -} - -/// Same as `fail`, except given an AST node index, and the function sets up the `LazySrcLoc` -/// for pointing at it relatively by subtracting from the containing `Decl`. -pub fn failNode( - mod: *Module, - scope: *Scope, - node_index: Ast.Node.Index, - comptime format: []const u8, - args: anytype, -) CompileError { - const src = scope.srcDecl().?.nodeSrcLoc(node_index); - return mod.fail(scope, src, format, args); -} - -pub fn failWithOwnedErrorMsg(mod: *Module, scope: *Scope, err_msg: *ErrorMsg) CompileError { - @setCold(true); - - { - errdefer err_msg.destroy(mod.gpa); - if (err_msg.src_loc.lazy == .unneeded) { - return error.NeededSourceLocation; - } - try mod.failed_decls.ensureUnusedCapacity(mod.gpa, 1); - try mod.failed_files.ensureUnusedCapacity(mod.gpa, 1); - } - switch (scope.tag) { - .block => { - const block = scope.cast(Scope.Block).?; - if (block.sema.owner_func) |func| { - func.state = .sema_failure; - } else { - block.sema.owner_decl.analysis = .sema_failure; - block.sema.owner_decl.generation = mod.generation; - } - mod.failed_decls.putAssumeCapacityNoClobber(block.sema.owner_decl, err_msg); - }, - .file => unreachable, - .namespace => unreachable, - } - return error.AnalysisFail; -} - pub fn optionalType(arena: *Allocator, child_type: Type) Allocator.Error!Type { switch (child_type.tag()) { .single_const_pointer => return Type.Tag.optional_single_const_pointer.create( @@ -4631,7 +4108,7 @@ pub fn optimizeMode(mod: Module) std.builtin.Mode { return mod.comp.bin_file.options.optimize_mode; } -fn lockAndClearFileCompileError(mod: *Module, file: *Scope.File) void { +fn lockAndClearFileCompileError(mod: *Module, file: *File) void { switch (file.status) { .success_zir, .retryable_failure => {}, .never_loaded, .parse_failure, .astgen_failure => { @@ -4666,10 +4143,10 @@ pub const SwitchProngSrc = union(enum) { range_expand: RangeExpand, ) LazySrcLoc { @setCold(true); - const tree = decl.namespace.file_scope.getTree(gpa) catch |err| { + const tree = decl.getFileScope().getTree(gpa) catch |err| { // In this case we emit a warning + a less precise source location. log.warn("unable to load {s}: {s}", .{ - decl.namespace.file_scope.sub_file_path, @errorName(err), + decl.getFileScope().sub_file_path, @errorName(err), }); return LazySrcLoc{ .node_offset = 0 }; }; @@ -4778,10 +4255,10 @@ pub const PeerTypeCandidateSrc = union(enum) { else => {}, } - const tree = decl.namespace.file_scope.getTree(gpa) catch |err| { + const tree = decl.getFileScope().getTree(gpa) catch |err| { // In this case we emit a warning + a less precise source location. log.warn("unable to load {s}: {s}", .{ - decl.namespace.file_scope.sub_file_path, @errorName(err), + decl.getFileScope().sub_file_path, @errorName(err), }); return LazySrcLoc{ .node_offset = 0 }; }; @@ -4824,7 +4301,7 @@ pub fn processOutdatedAndDeletedDecls(mod: *Module) !void { // Remove from the namespace it resides in, preserving declaration order. assert(decl.zir_decl_index != 0); - _ = decl.namespace.decls.orderedRemove(mem.spanZ(decl.name)); + _ = decl.src_namespace.decls.orderedRemove(mem.spanZ(decl.name)); try mod.clearDecl(decl, &outdated_decls); decl.destroy(mod); @@ -4890,7 +4367,7 @@ pub fn populateTestFunctions(mod: *Module) !void { const gpa = mod.gpa; const builtin_pkg = mod.main_pkg.table.get("builtin").?; const builtin_file = (mod.importPkg(builtin_pkg) catch unreachable).file; - const builtin_namespace = builtin_file.root_decl.?.namespace; + const builtin_namespace = builtin_file.root_decl.?.src_namespace; const decl = builtin_namespace.decls.get("test_functions").?; var buf: Type.SlicePtrFieldTypeBuffer = undefined; const tmp_test_fn_ty = decl.ty.slicePtrFieldType(&buf).elemType(); @@ -4903,7 +4380,7 @@ pub fn populateTestFunctions(mod: *Module) !void { const arena = &new_decl_arena.allocator; const test_fn_vals = try arena.alloc(Value, mod.test_functions.count()); - const array_decl = try mod.createAnonymousDeclFromDecl(decl, null, .{ + const array_decl = try mod.createAnonymousDeclFromDecl(decl, decl.src_namespace, null, .{ .ty = try Type.Tag.array.create(arena, .{ .len = test_fn_vals.len, .elem_type = try tmp_test_fn_ty.copy(arena), @@ -4916,7 +4393,7 @@ pub fn populateTestFunctions(mod: *Module) !void { var name_decl_arena = std.heap.ArenaAllocator.init(gpa); errdefer name_decl_arena.deinit(); const bytes = try name_decl_arena.allocator.dupe(u8, test_name_slice); - const test_name_decl = try mod.createAnonymousDeclFromDecl(array_decl, null, .{ + const test_name_decl = try mod.createAnonymousDeclFromDecl(array_decl, array_decl.src_namespace, null, .{ .ty = try Type.Tag.array_u8.create(&name_decl_arena.allocator, bytes.len), .val = try Value.Tag.bytes.create(&name_decl_arena.allocator, bytes), }); diff --git a/src/Sema.zig b/src/Sema.zig index 8842a55dcc..731a5a8a8a 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -21,11 +21,9 @@ air_values: std.ArrayListUnmanaged(Value) = .{}, /// Maps ZIR to AIR. inst_map: InstMap = .{}, /// When analyzing an inline function call, owner_decl is the Decl of the caller -/// and `src_decl` of `Scope.Block` is the `Decl` of the callee. +/// and `src_decl` of `Block` is the `Decl` of the callee. /// This `Decl` owns the arena memory of this `Sema`. owner_decl: *Decl, -/// How to look up decl names. -namespace: *Scope.Namespace, /// For an inline or comptime function call, this will be the root parent function /// which contains the callsite. Corresponds to `owner_decl`. owner_func: ?*Module.Fn, @@ -62,9 +60,6 @@ comptime_args_fn_inst: Zir.Inst.Index = 0, /// extra hash table lookup in the `monomorphed_funcs` set. /// Sema will set this to null when it takes ownership. preallocated_new_func: ?*Module.Fn = null, -/// Collects struct, union, enum, and opaque decls which need to have their -/// fields resolved before this Sema is deinitialized. -types_pending_resolution: std.ArrayListUnmanaged(Type) = .{}, const std = @import("std"); const mem = std.mem; @@ -80,7 +75,7 @@ const Air = @import("Air.zig"); const Zir = @import("Zir.zig"); const Module = @import("Module.zig"); const trace = @import("tracy.zig").trace; -const Scope = Module.Scope; +const Namespace = Module.Namespace; const CompileError = Module.CompileError; const SemaError = Module.SemaError; const Decl = Module.Decl; @@ -94,6 +89,286 @@ const crash_report = @import("crash_report.zig"); pub const InstMap = std.AutoHashMapUnmanaged(Zir.Inst.Index, Air.Inst.Ref); +/// This is the context needed to semantically analyze ZIR instructions and +/// produce AIR instructions. +/// This is a temporary structure stored on the stack; references to it are valid only +/// during semantic analysis of the block. +pub const Block = struct { + parent: ?*Block, + /// Shared among all child blocks. + sema: *Sema, + /// This Decl is the Decl according to the Zig source code corresponding to this Block. + /// This can vary during inline or comptime function calls. See `Sema.owner_decl` + /// for the one that will be the same for all Block instances. + src_decl: *Decl, + /// The namespace to use for lookups from this source block + /// When analyzing fields, this is different from src_decl.src_namepsace. + namespace: *Namespace, + /// The AIR instructions generated for this block. + instructions: std.ArrayListUnmanaged(Air.Inst.Index), + // `param` instructions are collected here to be used by the `func` instruction. + params: std.ArrayListUnmanaged(Param) = .{}, + + wip_capture_scope: *CaptureScope, + + label: ?*Label = null, + inlining: ?*Inlining, + /// If runtime_index is not 0 then one of these is guaranteed to be non null. + runtime_cond: ?LazySrcLoc = null, + runtime_loop: ?LazySrcLoc = null, + /// Non zero if a non-inline loop or a runtime conditional have been encountered. + /// Stores to to comptime variables are only allowed when var.runtime_index <= runtime_index. + runtime_index: u32 = 0, + + is_comptime: bool, + + /// when null, it is determined by build mode, changed by @setRuntimeSafety + want_safety: ?bool = null, + + c_import_buf: ?*std.ArrayList(u8) = null, + + const Param = struct { + /// `noreturn` means `anytype`. + ty: Type, + is_comptime: bool, + }; + + /// This `Block` maps a block ZIR instruction to the corresponding + /// AIR instruction for break instruction analysis. + pub const Label = struct { + zir_block: Zir.Inst.Index, + merges: Merges, + }; + + /// This `Block` indicates that an inline function call is happening + /// and return instructions should be analyzed as a break instruction + /// to this AIR block instruction. + /// It is shared among all the blocks in an inline or comptime called + /// function. + pub const Inlining = struct { + comptime_result: Air.Inst.Ref, + merges: Merges, + }; + + pub const Merges = struct { + block_inst: Air.Inst.Index, + /// Separate array list from break_inst_list so that it can be passed directly + /// to resolvePeerTypes. + results: std.ArrayListUnmanaged(Air.Inst.Ref), + /// Keeps track of the break instructions so that the operand can be replaced + /// if we need to add type coercion at the end of block analysis. + /// Same indexes, capacity, length as `results`. + br_list: std.ArrayListUnmanaged(Air.Inst.Index), + }; + + /// For debugging purposes. + pub fn dump(block: *Block, mod: Module) void { + Zir.dumpBlock(mod, block); + } + + pub fn makeSubBlock(parent: *Block) Block { + return .{ + .parent = parent, + .sema = parent.sema, + .src_decl = parent.src_decl, + .namespace = parent.namespace, + .instructions = .{}, + .wip_capture_scope = parent.wip_capture_scope, + .label = null, + .inlining = parent.inlining, + .is_comptime = parent.is_comptime, + .runtime_cond = parent.runtime_cond, + .runtime_loop = parent.runtime_loop, + .runtime_index = parent.runtime_index, + .want_safety = parent.want_safety, + .c_import_buf = parent.c_import_buf, + }; + } + + pub fn wantSafety(block: *const Block) bool { + return block.want_safety orelse switch (block.sema.mod.optimizeMode()) { + .Debug => true, + .ReleaseSafe => true, + .ReleaseFast => false, + .ReleaseSmall => false, + }; + } + + pub fn getFileScope(block: *Block) *Module.File { + return block.namespace.file_scope; + } + + pub fn addTy( + block: *Block, + tag: Air.Inst.Tag, + ty: Type, + ) error{OutOfMemory}!Air.Inst.Ref { + return block.addInst(.{ + .tag = tag, + .data = .{ .ty = ty }, + }); + } + + pub fn addTyOp( + block: *Block, + tag: Air.Inst.Tag, + ty: Type, + operand: Air.Inst.Ref, + ) error{OutOfMemory}!Air.Inst.Ref { + return block.addInst(.{ + .tag = tag, + .data = .{ .ty_op = .{ + .ty = try block.sema.addType(ty), + .operand = operand, + } }, + }); + } + + pub fn addNoOp(block: *Block, tag: Air.Inst.Tag) error{OutOfMemory}!Air.Inst.Ref { + return block.addInst(.{ + .tag = tag, + .data = .{ .no_op = {} }, + }); + } + + pub fn addUnOp( + block: *Block, + tag: Air.Inst.Tag, + operand: Air.Inst.Ref, + ) error{OutOfMemory}!Air.Inst.Ref { + return block.addInst(.{ + .tag = tag, + .data = .{ .un_op = operand }, + }); + } + + pub fn addBr( + block: *Block, + target_block: Air.Inst.Index, + operand: Air.Inst.Ref, + ) error{OutOfMemory}!Air.Inst.Ref { + return block.addInst(.{ + .tag = .br, + .data = .{ .br = .{ + .block_inst = target_block, + .operand = operand, + } }, + }); + } + + pub fn addBinOp( + block: *Block, + tag: Air.Inst.Tag, + lhs: Air.Inst.Ref, + rhs: Air.Inst.Ref, + ) error{OutOfMemory}!Air.Inst.Ref { + return block.addInst(.{ + .tag = tag, + .data = .{ .bin_op = .{ + .lhs = lhs, + .rhs = rhs, + } }, + }); + } + + pub fn addArg(block: *Block, ty: Type, name: u32) error{OutOfMemory}!Air.Inst.Ref { + return block.addInst(.{ + .tag = .arg, + .data = .{ .ty_str = .{ + .ty = try block.sema.addType(ty), + .str = name, + } }, + }); + } + + pub fn addStructFieldPtr( + block: *Block, + struct_ptr: Air.Inst.Ref, + field_index: u32, + ptr_field_ty: Type, + ) !Air.Inst.Ref { + const ty = try block.sema.addType(ptr_field_ty); + const tag: Air.Inst.Tag = switch (field_index) { + 0 => .struct_field_ptr_index_0, + 1 => .struct_field_ptr_index_1, + 2 => .struct_field_ptr_index_2, + 3 => .struct_field_ptr_index_3, + else => { + return block.addInst(.{ + .tag = .struct_field_ptr, + .data = .{ .ty_pl = .{ + .ty = ty, + .payload = try block.sema.addExtra(Air.StructField{ + .struct_operand = struct_ptr, + .field_index = @intCast(u32, field_index), + }), + } }, + }); + }, + }; + return block.addInst(.{ + .tag = tag, + .data = .{ .ty_op = .{ + .ty = ty, + .operand = struct_ptr, + } }, + }); + } + + pub fn addInst(block: *Block, inst: Air.Inst) error{OutOfMemory}!Air.Inst.Ref { + return Air.indexToRef(try block.addInstAsIndex(inst)); + } + + pub fn addInstAsIndex(block: *Block, inst: Air.Inst) error{OutOfMemory}!Air.Inst.Index { + const sema = block.sema; + const gpa = sema.gpa; + + try sema.air_instructions.ensureUnusedCapacity(gpa, 1); + try block.instructions.ensureUnusedCapacity(gpa, 1); + + const result_index = @intCast(Air.Inst.Index, sema.air_instructions.len); + sema.air_instructions.appendAssumeCapacity(inst); + block.instructions.appendAssumeCapacity(result_index); + return result_index; + } + + pub fn startAnonDecl(block: *Block) !WipAnonDecl { + return WipAnonDecl{ + .block = block, + .new_decl_arena = std.heap.ArenaAllocator.init(block.sema.gpa), + .finished = false, + }; + } + + pub const WipAnonDecl = struct { + block: *Block, + new_decl_arena: std.heap.ArenaAllocator, + finished: bool, + + pub fn arena(wad: *WipAnonDecl) *Allocator { + return &wad.new_decl_arena.allocator; + } + + pub fn deinit(wad: *WipAnonDecl) void { + if (!wad.finished) { + wad.new_decl_arena.deinit(); + } + wad.* = undefined; + } + + pub fn finish(wad: *WipAnonDecl, ty: Type, val: Value) !*Decl { + const new_decl = try wad.block.sema.mod.createAnonymousDecl(wad.block, .{ + .ty = ty, + .val = val, + }); + errdefer wad.block.sema.mod.abortAnonDecl(new_decl); + try new_decl.finalizeNewArena(&wad.new_decl_arena); + wad.finished = true; + return new_decl; + } + }; +}; + pub fn deinit(sema: *Sema) void { const gpa = sema.gpa; sema.air_instructions.deinit(gpa); @@ -101,14 +376,13 @@ pub fn deinit(sema: *Sema) void { sema.air_values.deinit(gpa); sema.inst_map.deinit(gpa); sema.decl_val_table.deinit(gpa); - sema.types_pending_resolution.deinit(gpa); sema.* = undefined; } /// Returns only the result from the body that is specified. /// Only appropriate to call when it is determined at comptime that this body /// has no peers. -fn resolveBody(sema: *Sema, block: *Scope.Block, body: []const Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn resolveBody(sema: *Sema, block: *Block, body: []const Zir.Inst.Index) CompileError!Air.Inst.Ref { const break_inst = try sema.analyzeBody(block, body); const operand_ref = sema.code.instructions.items(.data)[break_inst].@"break".operand; return sema.resolveInst(operand_ref); @@ -131,7 +405,7 @@ const always_noreturn: CompileError!Zir.Inst.Index = @as(Zir.Inst.Index, undefin /// well as the operand. No block scope needs to be created for this strategy. pub fn analyzeBody( sema: *Sema, - block: *Scope.Block, + block: *Block, body: []const Zir.Inst.Index, ) CompileError!Zir.Inst.Index { // No tracy calls here, to avoid interfering with the tail call mechanism. @@ -148,9 +422,9 @@ pub fn analyzeBody( wip_captures.deinit(); }; - const map = &block.sema.inst_map; - const tags = block.sema.code.instructions.items(.tag); - const datas = block.sema.code.instructions.items(.data); + const map = &sema.inst_map; + const tags = sema.code.instructions.items(.tag); + const datas = sema.code.instructions.items(.data); var orig_captures: usize = parent_capture_scope.captures.count(); @@ -673,7 +947,7 @@ pub fn analyzeBody( return result; } -fn zirExtended(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirExtended(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const extended = sema.code.instructions.items(.data)[inst].extended; switch (extended.opcode) { // zig fmt: off @@ -725,7 +999,7 @@ pub fn resolveInst(sema: *Sema, zir_ref: Zir.Inst.Ref) Air.Inst.Ref { fn resolveConstBool( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref, ) !bool { @@ -738,7 +1012,7 @@ fn resolveConstBool( fn resolveConstString( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref, ) ![]u8 { @@ -749,14 +1023,14 @@ fn resolveConstString( return val.toAllocatedBytes(sema.arena); } -pub fn resolveType(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) !Type { +pub fn resolveType(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) !Type { const air_inst = sema.resolveInst(zir_ref); return sema.analyzeAsType(block, src, air_inst); } fn analyzeAsType( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, air_inst: Air.Inst.Ref, ) !Type { @@ -773,7 +1047,7 @@ fn analyzeAsType( /// Value Tag `generic_poison` causes `error.GenericPoison` to be returned. fn resolveValue( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, air_ref: Air.Inst.Ref, ) CompileError!Value { @@ -788,7 +1062,7 @@ fn resolveValue( /// Value Tag `undef` may be returned. fn resolveConstMaybeUndefVal( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, inst: Air.Inst.Ref, ) CompileError!Value { @@ -806,7 +1080,7 @@ fn resolveConstMaybeUndefVal( /// See `resolveValue` for an alternative. fn resolveConstValue( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, air_ref: Air.Inst.Ref, ) CompileError!Value { @@ -825,7 +1099,7 @@ fn resolveConstValue( /// Value Tag `undef` causes this function to return a compile error. fn resolveDefinedValue( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, air_ref: Air.Inst.Ref, ) CompileError!?Value { @@ -843,7 +1117,7 @@ fn resolveDefinedValue( /// Value Tag `generic_poison` causes `error.GenericPoison` to be returned. fn resolveMaybeUndefVal( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, inst: Air.Inst.Ref, ) CompileError!?Value { @@ -858,7 +1132,7 @@ fn resolveMaybeUndefVal( /// Returns all Value tags including `variable` and `undef`. fn resolveMaybeUndefValAllowVariables( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, inst: Air.Inst.Ref, ) CompileError!?Value { @@ -885,20 +1159,77 @@ fn resolveMaybeUndefValAllowVariables( } } -fn failWithNeededComptime(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) CompileError { - return sema.mod.fail(&block.base, src, "unable to resolve comptime value", .{}); +fn failWithNeededComptime(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError { + return sema.fail(block, src, "unable to resolve comptime value", .{}); } -fn failWithUseOfUndef(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) CompileError { - return sema.mod.fail(&block.base, src, "use of undefined value here causes undefined behavior", .{}); +fn failWithUseOfUndef(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError { + return sema.fail(block, src, "use of undefined value here causes undefined behavior", .{}); } -fn failWithDivideByZero(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) CompileError { - return sema.mod.fail(&block.base, src, "division by zero here causes undefined behavior", .{}); +fn failWithDivideByZero(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError { + return sema.fail(block, src, "division by zero here causes undefined behavior", .{}); } -fn failWithModRemNegative(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, lhs_ty: Type, rhs_ty: Type) CompileError { - return sema.mod.fail(&block.base, src, "remainder division with '{}' and '{}': signed integers and floats must use @rem or @mod", .{ lhs_ty, rhs_ty }); +fn failWithModRemNegative(sema: *Sema, block: *Block, src: LazySrcLoc, lhs_ty: Type, rhs_ty: Type) CompileError { + return sema.fail(block, src, "remainder division with '{}' and '{}': signed integers and floats must use @rem or @mod", .{ lhs_ty, rhs_ty }); +} + +/// We don't return a pointer to the new error note because the pointer +/// becomes invalid when you add another one. +fn errNote( + sema: *Sema, + block: *Block, + src: LazySrcLoc, + parent: *Module.ErrorMsg, + comptime format: []const u8, + args: anytype, +) error{OutOfMemory}!void { + return sema.mod.errNoteNonLazy(src.toSrcLoc(block.src_decl), parent, format, args); +} + +fn errMsg( + sema: *Sema, + block: *Block, + src: LazySrcLoc, + comptime format: []const u8, + args: anytype, +) error{OutOfMemory}!*Module.ErrorMsg { + return Module.ErrorMsg.create(sema.gpa, src.toSrcLoc(block.src_decl), format, args); +} + +pub fn fail( + sema: *Sema, + block: *Block, + src: LazySrcLoc, + comptime format: []const u8, + args: anytype, +) CompileError { + const err_msg = try sema.errMsg(block, src, format, args); + return sema.failWithOwnedErrorMsg(err_msg); +} + +fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError { + @setCold(true); + + const mod = sema.mod; + + { + errdefer err_msg.destroy(mod.gpa); + if (err_msg.src_loc.lazy == .unneeded) { + return error.NeededSourceLocation; + } + try mod.failed_decls.ensureUnusedCapacity(mod.gpa, 1); + try mod.failed_files.ensureUnusedCapacity(mod.gpa, 1); + } + if (sema.owner_func) |func| { + func.state = .sema_failure; + } else { + sema.owner_decl.analysis = .sema_failure; + sema.owner_decl.generation = mod.generation; + } + mod.failed_decls.putAssumeCapacityNoClobber(sema.owner_decl, err_msg); + return error.AnalysisFail; } /// Appropriate to call when the coercion has already been done by result @@ -907,7 +1238,7 @@ fn failWithModRemNegative(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, lhs /// TODO don't ever call this since we're migrating towards ResultLoc.coerced_ty. fn resolveAlreadyCoercedInt( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref, comptime Int: type, @@ -923,15 +1254,15 @@ fn resolveAlreadyCoercedInt( fn resolveAlign( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref, ) !u16 { const alignment_big = try sema.resolveInt(block, src, zir_ref, Type.initTag(.u16)); const alignment = @intCast(u16, alignment_big); // We coerce to u16 in the prev line. - if (alignment == 0) return sema.mod.fail(&block.base, src, "alignment must be >= 1", .{}); + if (alignment == 0) return sema.fail(block, src, "alignment must be >= 1", .{}); if (!std.math.isPowerOfTwo(alignment)) { - return sema.mod.fail(&block.base, src, "alignment value {d} is not a power of two", .{ + return sema.fail(block, src, "alignment value {d} is not a power of two", .{ alignment, }); } @@ -940,7 +1271,7 @@ fn resolveAlign( fn resolveInt( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref, dest_type: Type, @@ -956,7 +1287,7 @@ fn resolveInt( // a function that does not. pub fn resolveInstConst( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref, ) CompileError!TypedValue { @@ -972,7 +1303,7 @@ pub fn resolveInstConst( // See `resolveInstConst` for an alternative. pub fn resolveInstValue( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref, ) CompileError!TypedValue { @@ -984,13 +1315,13 @@ pub fn resolveInstValue( }; } -fn zirBitcastResultPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirBitcastResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO implement zir_sema.zirBitcastResultPtr", .{}); + return sema.fail(block, src, "TODO implement zir_sema.zirBitcastResultPtr", .{}); } -fn zirCoerceResultPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -1052,7 +1383,7 @@ pub fn analyzeStructDecl( fn zirStructDecl( sema: *Sema, - block: *Scope.Block, + block: *Block, extended: Zir.Inst.Extended.InstData, inst: Zir.Inst.Index, ) CompileError!Air.Inst.Ref { @@ -1069,12 +1400,12 @@ fn zirStructDecl( const struct_ty = try Type.Tag.@"struct".create(&new_decl_arena.allocator, struct_obj); const struct_val = try Value.Tag.ty.create(&new_decl_arena.allocator, struct_ty); const type_name = try sema.createTypeName(block, small.name_strategy); - const new_decl = try sema.mod.createAnonymousDeclNamed(&block.base, .{ + const new_decl = try sema.mod.createAnonymousDeclNamed(block, .{ .ty = Type.initTag(.type), .val = struct_val, }, type_name); new_decl.owns_tv = true; - errdefer sema.mod.deleteAnonDecl(&block.base, new_decl); + errdefer sema.mod.abortAnonDecl(new_decl); struct_obj.* = .{ .owner_decl = new_decl, .fields = .{}, @@ -1084,7 +1415,7 @@ fn zirStructDecl( .status = .none, .known_has_bits = undefined, .namespace = .{ - .parent = sema.owner_decl.namespace, + .parent = block.namespace, .ty = struct_ty, .file_scope = block.getFileScope(), }, @@ -1093,13 +1424,11 @@ fn zirStructDecl( &struct_obj.namespace, new_decl, new_decl.name, }); try sema.analyzeStructDecl(new_decl, inst, struct_obj); - try sema.types_pending_resolution.ensureUnusedCapacity(sema.gpa, 1); try new_decl.finalizeNewArena(&new_decl_arena); - sema.types_pending_resolution.appendAssumeCapacity(struct_ty); return sema.analyzeDeclVal(block, src, new_decl); } -fn createTypeName(sema: *Sema, block: *Scope.Block, name_strategy: Zir.Inst.NameStrategy) ![:0]u8 { +fn createTypeName(sema: *Sema, block: *Block, name_strategy: Zir.Inst.NameStrategy) ![:0]u8 { switch (name_strategy) { .anon => { // It would be neat to have "struct:line:column" but this name has @@ -1127,7 +1456,7 @@ fn createTypeName(sema: *Sema, block: *Scope.Block, name_strategy: Zir.Inst.Name fn zirEnumDecl( sema: *Sema, - block: *Scope.Block, + block: *Block, extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { const tracy = trace(@src()); @@ -1180,12 +1509,12 @@ fn zirEnumDecl( const enum_ty = Type.initPayload(&enum_ty_payload.base); const enum_val = try Value.Tag.ty.create(&new_decl_arena.allocator, enum_ty); const type_name = try sema.createTypeName(block, small.name_strategy); - const new_decl = try mod.createAnonymousDeclNamed(&block.base, .{ + const new_decl = try mod.createAnonymousDeclNamed(block, .{ .ty = Type.initTag(.type), .val = enum_val, }, type_name); new_decl.owns_tv = true; - errdefer sema.mod.deleteAnonDecl(&block.base, new_decl); + errdefer mod.abortAnonDecl(new_decl); enum_obj.* = .{ .owner_decl = new_decl, @@ -1194,7 +1523,7 @@ fn zirEnumDecl( .values = .{}, .node_offset = src.node_offset, .namespace = .{ - .parent = sema.owner_decl.namespace, + .parent = block.namespace, .ty = enum_ty, .file_scope = block.getFileScope(), }, @@ -1227,10 +1556,6 @@ fn zirEnumDecl( sema.owner_decl = new_decl; defer sema.owner_decl = prev_owner_decl; - const prev_namespace = sema.namespace; - sema.namespace = &enum_obj.namespace; - defer sema.namespace = prev_namespace; - const prev_owner_func = sema.owner_func; sema.owner_func = null; defer sema.owner_func = prev_owner_func; @@ -1242,10 +1567,11 @@ fn zirEnumDecl( var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, new_decl.src_scope); defer wip_captures.deinit(); - var enum_block: Scope.Block = .{ + var enum_block: Block = .{ .parent = null, .sema = sema, .src_decl = new_decl, + .namespace = &enum_obj.namespace, .wip_capture_scope = wip_captures.scope, .instructions = .{}, .inlining = null, @@ -1303,12 +1629,12 @@ fn zirEnumDecl( const field_src = enumFieldSrcLoc(block.src_decl, tree.*, src.node_offset, field_i); const other_tag_src = enumFieldSrcLoc(block.src_decl, tree.*, src.node_offset, gop.index); const msg = msg: { - const msg = try mod.errMsg(&block.base, field_src, "duplicate enum tag", .{}); + const msg = try sema.errMsg(block, field_src, "duplicate enum tag", .{}); errdefer msg.destroy(gpa); - try mod.errNote(&block.base, other_tag_src, msg, "other tag here", .{}); + try sema.errNote(block, other_tag_src, msg, "other tag here", .{}); break :msg msg; }; - return mod.failWithOwnedErrorMsg(&block.base, msg); + return sema.failWithOwnedErrorMsg(msg); } if (has_tag_value) { @@ -1331,7 +1657,7 @@ fn zirEnumDecl( fn zirUnionDecl( sema: *Sema, - block: *Scope.Block, + block: *Block, extended: Zir.Inst.Extended.InstData, inst: Zir.Inst.Index, ) CompileError!Air.Inst.Ref { @@ -1370,12 +1696,12 @@ fn zirUnionDecl( const union_ty = Type.initPayload(&union_payload.base); const union_val = try Value.Tag.ty.create(&new_decl_arena.allocator, union_ty); const type_name = try sema.createTypeName(block, small.name_strategy); - const new_decl = try sema.mod.createAnonymousDeclNamed(&block.base, .{ + const new_decl = try sema.mod.createAnonymousDeclNamed(block, .{ .ty = Type.initTag(.type), .val = union_val, }, type_name); new_decl.owns_tv = true; - errdefer sema.mod.deleteAnonDecl(&block.base, new_decl); + errdefer sema.mod.abortAnonDecl(new_decl); union_obj.* = .{ .owner_decl = new_decl, .tag_ty = Type.initTag(.@"null"), @@ -1385,7 +1711,7 @@ fn zirUnionDecl( .layout = small.layout, .status = .none, .namespace = .{ - .parent = sema.owner_decl.namespace, + .parent = block.namespace, .ty = union_ty, .file_scope = block.getFileScope(), }, @@ -1396,15 +1722,13 @@ fn zirUnionDecl( _ = try sema.mod.scanNamespace(&union_obj.namespace, extra_index, decls_len, new_decl); - try sema.types_pending_resolution.ensureUnusedCapacity(sema.gpa, 1); try new_decl.finalizeNewArena(&new_decl_arena); - sema.types_pending_resolution.appendAssumeCapacity(union_ty); return sema.analyzeDeclVal(block, src, new_decl); } fn zirOpaqueDecl( sema: *Sema, - block: *Scope.Block, + block: *Block, extended: Zir.Inst.Extended.InstData, inst: Zir.Inst.Index, ) CompileError!Air.Inst.Ref { @@ -1413,12 +1737,12 @@ fn zirOpaqueDecl( _ = extended; _ = inst; - return sema.mod.fail(&block.base, sema.src, "TODO implement zirOpaqueDecl", .{}); + return sema.fail(block, sema.src, "TODO implement zirOpaqueDecl", .{}); } fn zirErrorSetDecl( sema: *Sema, - block: *Scope.Block, + block: *Block, inst: Zir.Inst.Index, name_strategy: Zir.Inst.NameStrategy, ) CompileError!Air.Inst.Ref { @@ -1438,12 +1762,12 @@ fn zirErrorSetDecl( const error_set_ty = try Type.Tag.error_set.create(&new_decl_arena.allocator, error_set); const error_set_val = try Value.Tag.ty.create(&new_decl_arena.allocator, error_set_ty); const type_name = try sema.createTypeName(block, name_strategy); - const new_decl = try sema.mod.createAnonymousDeclNamed(&block.base, .{ + const new_decl = try sema.mod.createAnonymousDeclNamed(block, .{ .ty = Type.initTag(.type), .val = error_set_val, }, type_name); new_decl.owns_tv = true; - errdefer sema.mod.deleteAnonDecl(&block.base, new_decl); + errdefer sema.mod.abortAnonDecl(new_decl); const names = try new_decl_arena.allocator.alloc([]const u8, fields.len); for (fields) |str_index, i| { names[i] = try new_decl_arena.allocator.dupe(u8, sema.code.nullTerminatedString(str_index)); @@ -1460,7 +1784,7 @@ fn zirErrorSetDecl( fn zirRetPtr( sema: *Sema, - block: *Scope.Block, + block: *Block, extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { const tracy = trace(@src()); @@ -1480,7 +1804,7 @@ fn zirRetPtr( return block.addTy(.alloc, ptr_type); } -fn zirRef(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -1491,7 +1815,7 @@ fn zirRef(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!A fn zirRetType( sema: *Sema, - block: *Scope.Block, + block: *Block, extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { const tracy = trace(@src()); @@ -1502,7 +1826,7 @@ fn zirRetType( return sema.addType(sema.fn_ret_ty); } -fn zirEnsureResultUsed(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void { +fn zirEnsureResultUsed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { const tracy = trace(@src()); defer tracy.end(); @@ -1515,18 +1839,18 @@ fn zirEnsureResultUsed(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) C fn ensureResultUsed( sema: *Sema, - block: *Scope.Block, + block: *Block, operand: Air.Inst.Ref, src: LazySrcLoc, ) CompileError!void { const operand_ty = sema.typeOf(operand); switch (operand_ty.zigTypeTag()) { .Void, .NoReturn => return, - else => return sema.mod.fail(&block.base, src, "expression value is ignored", .{}), + else => return sema.fail(block, src, "expression value is ignored", .{}), } } -fn zirEnsureResultNonError(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void { +fn zirEnsureResultNonError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { const tracy = trace(@src()); defer tracy.end(); @@ -1535,12 +1859,12 @@ fn zirEnsureResultNonError(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Inde const src = inst_data.src(); const operand_ty = sema.typeOf(operand); switch (operand_ty.zigTypeTag()) { - .ErrorSet, .ErrorUnion => return sema.mod.fail(&block.base, src, "error is discarded", .{}), + .ErrorSet, .ErrorUnion => return sema.fail(block, src, "error is discarded", .{}), else => return, } } -fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirIndexablePtrLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -1561,15 +1885,15 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co } if (!elem_ty.isIndexable()) { const msg = msg: { - const msg = try sema.mod.errMsg( - &block.base, + const msg = try sema.errMsg( + block, src, "type '{}' does not support indexing", .{elem_ty}, ); errdefer msg.destroy(sema.gpa); - try sema.mod.errNote( - &block.base, + try sema.errNote( + block, src, msg, "for loop operand must be an array, slice, tuple, or vector", @@ -1577,18 +1901,18 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co ); break :msg msg; }; - return sema.mod.failWithOwnedErrorMsg(&block.base, msg); + return sema.failWithOwnedErrorMsg(msg); } const result_ptr = try sema.fieldPtr(block, src, array, "len", src); return sema.analyzeLoad(block, src, result_ptr, src); } - return sema.mod.fail(&block.base, src, "TODO implement Sema.zirIndexablePtrLen", .{}); + return sema.fail(block, src, "TODO implement Sema.zirIndexablePtrLen", .{}); } fn zirAllocExtended( sema: *Sema, - block: *Scope.Block, + block: *Block, extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { const extra = sema.code.extraData(Zir.Inst.AllocExtended, extended.operand); @@ -1604,7 +1928,7 @@ fn zirAllocExtended( extra_index += 1; break :blk try sema.resolveType(block, ty_src, type_ref); } else { - return sema.mod.fail(&block.base, src, "TODO implement Sema.zirAllocExtended inferred", .{}); + return sema.fail(block, src, "TODO implement Sema.zirAllocExtended inferred", .{}); }; const alignment: u16 = if (small.has_align) blk: { @@ -1615,11 +1939,11 @@ fn zirAllocExtended( } else 0; if (small.is_comptime) { - return sema.mod.fail(&block.base, src, "TODO implement Sema.zirAllocExtended comptime", .{}); + return sema.fail(block, src, "TODO implement Sema.zirAllocExtended comptime", .{}); } if (!small.is_const) { - return sema.mod.fail(&block.base, src, "TODO implement Sema.zirAllocExtended var", .{}); + return sema.fail(block, src, "TODO implement Sema.zirAllocExtended var", .{}); } const ptr_type = try Type.ptr(sema.arena, .{ @@ -1631,7 +1955,7 @@ fn zirAllocExtended( return block.addTy(.alloc, ptr_type); } -fn zirAllocComptime(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirAllocComptime(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -1651,7 +1975,7 @@ fn zirAllocInferredComptime(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air. ); } -fn zirAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -1667,7 +1991,7 @@ fn zirAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError return block.addTy(.alloc, ptr_type); } -fn zirAllocMut(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirAllocMut(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -1689,7 +2013,7 @@ fn zirAllocMut(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr fn zirAllocInferred( sema: *Sema, - block: *Scope.Block, + block: *Block, inst: Zir.Inst.Index, inferred_alloc_ty: Type, ) CompileError!Air.Inst.Ref { @@ -1720,7 +2044,7 @@ fn zirAllocInferred( return result; } -fn zirResolveInferredAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void { +fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { const tracy = trace(@src()); defer tracy.end(); @@ -1779,7 +2103,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Inde } } -fn zirValidateStructInitPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void { +fn zirValidateStructInitPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { const tracy = trace(@src()); defer tracy.end(); @@ -1811,18 +2135,16 @@ fn zirValidateStructInitPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Ind fn validateUnionInitPtr( sema: *Sema, - block: *Scope.Block, + block: *Block, union_obj: *Module.Union, init_src: LazySrcLoc, instrs: []const Zir.Inst.Index, union_ptr: Air.Inst.Ref, ) CompileError!void { - const mod = sema.mod; - if (instrs.len != 1) { // TODO add note for other field // TODO add note for union declared here - return mod.fail(&block.base, init_src, "only one union field can be active at once", .{}); + return sema.fail(block, init_src, "only one union field can be active at once", .{}); } const field_ptr = instrs[0]; @@ -1852,13 +2174,12 @@ fn validateUnionInitPtr( fn validateStructInitPtr( sema: *Sema, - block: *Scope.Block, + block: *Block, struct_obj: *Module.Struct, init_src: LazySrcLoc, instrs: []const Zir.Inst.Index, ) CompileError!void { const gpa = sema.gpa; - const mod = sema.mod; // Maps field index to field_ptr index of where it was already initialized. const found_fields = try gpa.alloc(Zir.Inst.Index, struct_obj.fields.count()); @@ -1877,12 +2198,12 @@ fn validateStructInitPtr( const other_field_ptr_data = sema.code.instructions.items(.data)[other_field_ptr].pl_node; const other_field_src: LazySrcLoc = .{ .node_offset_back2tok = other_field_ptr_data.src_node }; const msg = msg: { - const msg = try mod.errMsg(&block.base, field_src, "duplicate field", .{}); + const msg = try sema.errMsg(block, field_src, "duplicate field", .{}); errdefer msg.destroy(gpa); - try mod.errNote(&block.base, other_field_src, msg, "other field here", .{}); + try sema.errNote(block, other_field_src, msg, "other field here", .{}); break :msg msg; }; - return mod.failWithOwnedErrorMsg(&block.base, msg); + return sema.failWithOwnedErrorMsg(msg); } found_fields[field_index] = field_ptr; } @@ -1897,85 +2218,83 @@ fn validateStructInitPtr( const template = "missing struct field: {s}"; const args = .{field_name}; if (root_msg) |msg| { - try mod.errNote(&block.base, init_src, msg, template, args); + try sema.errNote(block, init_src, msg, template, args); } else { - root_msg = try mod.errMsg(&block.base, init_src, template, args); + root_msg = try sema.errMsg(block, init_src, template, args); } } if (root_msg) |msg| { const fqn = try struct_obj.getFullyQualifiedName(gpa); defer gpa.free(fqn); - try mod.errNoteNonLazy( + try sema.mod.errNoteNonLazy( struct_obj.srcLoc(), msg, "struct '{s}' declared here", .{fqn}, ); - return mod.failWithOwnedErrorMsg(&block.base, msg); + return sema.failWithOwnedErrorMsg(msg); } } -fn zirValidateArrayInitPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void { +fn zirValidateArrayInitPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO implement Sema.zirValidateArrayInitPtr", .{}); + return sema.fail(block, src, "TODO implement Sema.zirValidateArrayInitPtr", .{}); } fn failWithBadFieldAccess( sema: *Sema, - block: *Scope.Block, + block: *Block, struct_obj: *Module.Struct, field_src: LazySrcLoc, field_name: []const u8, ) CompileError { - const mod = sema.mod; const gpa = sema.gpa; const fqn = try struct_obj.getFullyQualifiedName(gpa); defer gpa.free(fqn); const msg = msg: { - const msg = try mod.errMsg( - &block.base, + const msg = try sema.errMsg( + block, field_src, "no field named '{s}' in struct '{s}'", .{ field_name, fqn }, ); errdefer msg.destroy(gpa); - try mod.errNoteNonLazy(struct_obj.srcLoc(), msg, "struct declared here", .{}); + try sema.mod.errNoteNonLazy(struct_obj.srcLoc(), msg, "struct declared here", .{}); break :msg msg; }; - return mod.failWithOwnedErrorMsg(&block.base, msg); + return sema.failWithOwnedErrorMsg(msg); } fn failWithBadUnionFieldAccess( sema: *Sema, - block: *Scope.Block, + block: *Block, union_obj: *Module.Union, field_src: LazySrcLoc, field_name: []const u8, ) CompileError { - const mod = sema.mod; const gpa = sema.gpa; const fqn = try union_obj.getFullyQualifiedName(gpa); defer gpa.free(fqn); const msg = msg: { - const msg = try mod.errMsg( - &block.base, + const msg = try sema.errMsg( + block, field_src, "no field named '{s}' in union '{s}'", .{ field_name, fqn }, ); errdefer msg.destroy(gpa); - try mod.errNoteNonLazy(union_obj.srcLoc(), msg, "union declared here", .{}); + try sema.mod.errNoteNonLazy(union_obj.srcLoc(), msg, "union declared here", .{}); break :msg msg; }; - return mod.failWithOwnedErrorMsg(&block.base, msg); + return sema.failWithOwnedErrorMsg(msg); } -fn zirStoreToBlockPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void { +fn zirStoreToBlockPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { const tracy = trace(@src()); defer tracy.end(); @@ -2000,7 +2319,7 @@ fn zirStoreToBlockPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co return sema.storePtr(block, src, bitcasted_ptr, value); } -fn zirStoreToInferredPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void { +fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { const tracy = trace(@src()); defer tracy.end(); @@ -2048,7 +2367,7 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) unreachable; } -fn zirSetEvalBranchQuota(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void { +fn zirSetEvalBranchQuota(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { const inst_data = sema.code.instructions.items(.data)[inst].un_node; const src = inst_data.src(); const quota = try sema.resolveAlreadyCoercedInt(block, src, inst_data.operand, u32); @@ -2056,7 +2375,7 @@ fn zirSetEvalBranchQuota(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) sema.branch_quota = quota; } -fn zirStore(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void { +fn zirStore(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { const tracy = trace(@src()); defer tracy.end(); @@ -2066,7 +2385,7 @@ fn zirStore(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError return sema.storePtr(block, sema.src, ptr, value); } -fn zirStoreNode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void { +fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { const tracy = trace(@src()); defer tracy.end(); @@ -2078,7 +2397,7 @@ fn zirStoreNode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileE return sema.storePtr(block, src, ptr, value); } -fn zirStr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirStr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -2097,16 +2416,16 @@ fn zirStr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!A const decl_ty = try Type.Tag.array_u8_sentinel_0.create(&new_decl_arena.allocator, bytes.len); const decl_val = try Value.Tag.bytes.create(&new_decl_arena.allocator, bytes); - const new_decl = try sema.mod.createAnonymousDecl(&block.base, .{ + const new_decl = try sema.mod.createAnonymousDecl(block, .{ .ty = decl_ty, .val = decl_val, }); - errdefer sema.mod.deleteAnonDecl(&block.base, new_decl); + errdefer sema.mod.abortAnonDecl(new_decl); try new_decl.finalizeNewArena(&new_decl_arena); return sema.analyzeDeclRef(new_decl); } -fn zirInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { _ = block; const tracy = trace(@src()); defer tracy.end(); @@ -2115,7 +2434,7 @@ fn zirInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!A return sema.addIntUnsigned(Type.initTag(.comptime_int), int); } -fn zirIntBig(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirIntBig(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { _ = block; const tracy = trace(@src()); defer tracy.end(); @@ -2133,7 +2452,7 @@ fn zirIntBig(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErro ); } -fn zirFloat(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { _ = block; const arena = sema.arena; const number = sema.code.instructions.items(.data)[inst].float; @@ -2143,7 +2462,7 @@ fn zirFloat(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError ); } -fn zirFloat128(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirFloat128(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { _ = block; const arena = sema.arena; const inst_data = sema.code.instructions.items(.data)[inst].pl_node; @@ -2155,7 +2474,7 @@ fn zirFloat128(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr ); } -fn zirCompileError(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index { +fn zirCompileError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index { const tracy = trace(@src()); defer tracy.end(); @@ -2163,12 +2482,12 @@ fn zirCompileError(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compi const src = inst_data.src(); const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const msg = try sema.resolveConstString(block, operand_src, inst_data.operand); - return sema.mod.fail(&block.base, src, "{s}", .{msg}); + return sema.fail(block, src, "{s}", .{msg}); } fn zirCompileLog( sema: *Sema, - block: *Scope.Block, + block: *Block, extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { var managed = sema.mod.compile_log_text.toManaged(sema.gpa); @@ -2200,7 +2519,7 @@ fn zirCompileLog( return Air.Inst.Ref.void_value; } -fn zirPanic(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index { +fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index { const inst_data = sema.code.instructions.items(.data)[inst].un_node; const src: LazySrcLoc = inst_data.src(); const msg_inst = sema.resolveInst(inst_data.operand); @@ -2208,7 +2527,7 @@ fn zirPanic(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError return sema.panicWithMsg(block, src, msg_inst); } -fn zirLoop(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -2236,7 +2555,7 @@ fn zirLoop(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) Compil .payload = undefined, } }, }); - var label: Scope.Block.Label = .{ + var label: Block.Label = .{ .zir_block = inst, .merges = .{ .results = .{}, @@ -2271,7 +2590,7 @@ fn zirLoop(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) Compil return sema.analyzeBlockBody(parent_block, src, &child_block, merges); } -fn zirCImport(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -2282,15 +2601,16 @@ fn zirCImport(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) Com // we check this here to avoid undefined symbols if (!@import("build_options").have_llvm) - return sema.mod.fail(&parent_block.base, src, "cannot do C import on Zig compiler not built with LLVM-extension", .{}); + return sema.fail(parent_block, src, "cannot do C import on Zig compiler not built with LLVM-extension", .{}); var c_import_buf = std.ArrayList(u8).init(sema.gpa); defer c_import_buf.deinit(); - var child_block: Scope.Block = .{ + var child_block: Block = .{ .parent = parent_block, .sema = sema, .src_decl = parent_block.src_decl, + .namespace = parent_block.namespace, .wip_capture_scope = parent_block.wip_capture_scope, .instructions = .{}, .inlining = parent_block.inlining, @@ -2302,15 +2622,15 @@ fn zirCImport(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) Com _ = try sema.analyzeBody(&child_block, body); const c_import_res = sema.mod.comp.cImport(c_import_buf.items) catch |err| - return sema.mod.fail(&child_block.base, src, "C import failed: {s}", .{@errorName(err)}); + return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)}); if (c_import_res.errors.len != 0) { const msg = msg: { - const msg = try sema.mod.errMsg(&child_block.base, src, "C import failed", .{}); + const msg = try sema.errMsg(&child_block, src, "C import failed", .{}); errdefer msg.destroy(sema.gpa); if (!sema.mod.comp.bin_file.options.link_libc) - try sema.mod.errNote(&child_block.base, src, msg, "libc headers not available; compilation does not link against libc", .{}); + try sema.errNote(&child_block, src, msg, "libc headers not available; compilation does not link against libc", .{}); for (c_import_res.errors) |_| { // TODO integrate with LazySrcLoc @@ -2322,7 +2642,7 @@ fn zirCImport(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) Com @import("clang.zig").Stage2ErrorMsg.delete(c_import_res.errors.ptr, c_import_res.errors.len); break :msg msg; }; - return sema.mod.failWithOwnedErrorMsg(&child_block.base, msg); + return sema.failWithOwnedErrorMsg(msg); } const c_import_pkg = Package.create( sema.gpa, @@ -2338,10 +2658,10 @@ fn zirCImport(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) Com try c_import_pkg.add(sema.gpa, "std", std_pkg); const result = sema.mod.importPkg(c_import_pkg) catch |err| - return sema.mod.fail(&child_block.base, src, "C import failed: {s}", .{@errorName(err)}); + return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)}); sema.mod.astGenFile(result.file) catch |err| - return sema.mod.fail(&child_block.base, src, "C import failed: {s}", .{@errorName(err)}); + return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)}); try sema.mod.semaFile(result.file); const file_root_decl = result.file.root_decl.?; @@ -2349,15 +2669,15 @@ fn zirCImport(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) Com return sema.addConstant(file_root_decl.ty, file_root_decl.val); } -fn zirSuspendBlock(sema: *Sema, parent_block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirSuspendBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); - return sema.mod.fail(&parent_block.base, src, "TODO: implement Sema.zirSuspendBlock", .{}); + return sema.fail(parent_block, src, "TODO: implement Sema.zirSuspendBlock", .{}); } fn zirBlock( sema: *Sema, - parent_block: *Scope.Block, + parent_block: *Block, inst: Zir.Inst.Index, ) CompileError!Air.Inst.Ref { const tracy = trace(@src()); @@ -2378,7 +2698,7 @@ fn zirBlock( .data = undefined, }); - var label: Scope.Block.Label = .{ + var label: Block.Label = .{ .zir_block = inst, .merges = .{ .results = .{}, @@ -2387,10 +2707,11 @@ fn zirBlock( }, }; - var child_block: Scope.Block = .{ + var child_block: Block = .{ .parent = parent_block, .sema = sema, .src_decl = parent_block.src_decl, + .namespace = parent_block.namespace, .wip_capture_scope = parent_block.wip_capture_scope, .instructions = .{}, .label = &label, @@ -2410,11 +2731,11 @@ fn zirBlock( fn resolveBlockBody( sema: *Sema, - parent_block: *Scope.Block, + parent_block: *Block, src: LazySrcLoc, - child_block: *Scope.Block, + child_block: *Block, body: []const Zir.Inst.Index, - merges: *Scope.Block.Merges, + merges: *Block.Merges, ) CompileError!Air.Inst.Ref { if (child_block.is_comptime) { return sema.resolveBody(child_block, body); @@ -2426,10 +2747,10 @@ fn resolveBlockBody( fn analyzeBlockBody( sema: *Sema, - parent_block: *Scope.Block, + parent_block: *Block, src: LazySrcLoc, - child_block: *Scope.Block, - merges: *Scope.Block.Merges, + child_block: *Block, + merges: *Block.Merges, ) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -2527,7 +2848,7 @@ fn analyzeBlockBody( return Air.indexToRef(merges.block_inst); } -fn zirExport(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void { +fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { const tracy = trace(@src()); defer tracy.end(); @@ -2538,14 +2859,14 @@ fn zirExport(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErro const options_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; const decl_name = sema.code.nullTerminatedString(extra.decl_name); if (extra.namespace != .none) { - return sema.mod.fail(&block.base, src, "TODO: implement exporting with field access", .{}); + return sema.fail(block, src, "TODO: implement exporting with field access", .{}); } const decl = try sema.lookupIdentifier(block, operand_src, decl_name); const options = try sema.resolveExportOptions(block, options_src, extra.options); - try sema.mod.analyzeExport(block, src, options, decl); + try sema.analyzeExport(block, src, options, decl); } -fn zirExportValue(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void { +fn zirExportValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { const tracy = trace(@src()); defer tracy.end(); @@ -2558,45 +2879,122 @@ fn zirExportValue(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compil const options = try sema.resolveExportOptions(block, options_src, extra.options); const decl = switch (operand.val.tag()) { .function => operand.val.castTag(.function).?.data.owner_decl, - else => return sema.mod.fail(&block.base, operand_src, "TODO implement exporting arbitrary Value objects", .{}), // TODO put this Value into an anonymous Decl and then export it. + else => return sema.fail(block, operand_src, "TODO implement exporting arbitrary Value objects", .{}), // TODO put this Value into an anonymous Decl and then export it. }; - try sema.mod.analyzeExport(block, src, options, decl); + try sema.analyzeExport(block, src, options, decl); } -fn zirSetAlignStack(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void { +pub fn analyzeExport( + sema: *Sema, + block: *Block, + src: LazySrcLoc, + borrowed_options: std.builtin.ExportOptions, + exported_decl: *Decl, +) !void { + const Export = Module.Export; const mod = sema.mod; + + try mod.ensureDeclAnalyzed(exported_decl); + switch (exported_decl.ty.zigTypeTag()) { + .Fn => {}, + else => return sema.fail(block, src, "unable to export type '{}'", .{exported_decl.ty}), + } + + const gpa = mod.gpa; + + try mod.decl_exports.ensureUnusedCapacity(gpa, 1); + try mod.export_owners.ensureUnusedCapacity(gpa, 1); + + const new_export = try gpa.create(Export); + errdefer gpa.destroy(new_export); + + const symbol_name = try gpa.dupe(u8, borrowed_options.name); + errdefer gpa.free(symbol_name); + + const section: ?[]const u8 = if (borrowed_options.section) |s| try gpa.dupe(u8, s) else null; + errdefer if (section) |s| gpa.free(s); + + const src_decl = block.src_decl; + const owner_decl = sema.owner_decl; + + log.debug("exporting Decl '{s}' as symbol '{s}' from Decl '{s}'", .{ + exported_decl.name, symbol_name, owner_decl.name, + }); + + new_export.* = .{ + .options = .{ + .name = symbol_name, + .linkage = borrowed_options.linkage, + .section = section, + }, + .src = src, + .link = switch (mod.comp.bin_file.tag) { + .coff => .{ .coff = {} }, + .elf => .{ .elf = .{} }, + .macho => .{ .macho = .{} }, + .plan9 => .{ .plan9 = null }, + .c => .{ .c = {} }, + .wasm => .{ .wasm = {} }, + .spirv => .{ .spirv = {} }, + }, + .owner_decl = owner_decl, + .src_decl = src_decl, + .exported_decl = exported_decl, + .status = .in_progress, + }; + + // Add to export_owners table. + const eo_gop = mod.export_owners.getOrPutAssumeCapacity(owner_decl); + if (!eo_gop.found_existing) { + eo_gop.value_ptr.* = &[0]*Export{}; + } + eo_gop.value_ptr.* = try gpa.realloc(eo_gop.value_ptr.*, eo_gop.value_ptr.len + 1); + eo_gop.value_ptr.*[eo_gop.value_ptr.len - 1] = new_export; + errdefer eo_gop.value_ptr.* = gpa.shrink(eo_gop.value_ptr.*, eo_gop.value_ptr.len - 1); + + // Add to exported_decl table. + const de_gop = mod.decl_exports.getOrPutAssumeCapacity(exported_decl); + if (!de_gop.found_existing) { + de_gop.value_ptr.* = &[0]*Export{}; + } + de_gop.value_ptr.* = try gpa.realloc(de_gop.value_ptr.*, de_gop.value_ptr.len + 1); + de_gop.value_ptr.*[de_gop.value_ptr.len - 1] = new_export; + errdefer de_gop.value_ptr.* = gpa.shrink(de_gop.value_ptr.*, de_gop.value_ptr.len - 1); +} + +fn zirSetAlignStack(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { const inst_data = sema.code.instructions.items(.data)[inst].un_node; const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const src: LazySrcLoc = inst_data.src(); const alignment = try sema.resolveAlign(block, operand_src, inst_data.operand); if (alignment > 256) { - return mod.fail(&block.base, src, "attempt to @setAlignStack({d}); maximum is 256", .{ + return sema.fail(block, src, "attempt to @setAlignStack({d}); maximum is 256", .{ alignment, }); } const func = sema.owner_func orelse - return mod.fail(&block.base, src, "@setAlignStack outside function body", .{}); + return sema.fail(block, src, "@setAlignStack outside function body", .{}); switch (func.owner_decl.ty.fnCallingConvention()) { - .Naked => return mod.fail(&block.base, src, "@setAlignStack in naked function", .{}), - .Inline => return mod.fail(&block.base, src, "@setAlignStack in inline function", .{}), + .Naked => return sema.fail(block, src, "@setAlignStack in naked function", .{}), + .Inline => return sema.fail(block, src, "@setAlignStack in inline function", .{}), else => {}, } - const gop = try mod.align_stack_fns.getOrPut(mod.gpa, func); + const gop = try sema.mod.align_stack_fns.getOrPut(sema.mod.gpa, func); if (gop.found_existing) { const msg = msg: { - const msg = try mod.errMsg(&block.base, src, "multiple @setAlignStack in the same function body", .{}); - errdefer msg.destroy(mod.gpa); - try mod.errNote(&block.base, src, msg, "other instance here", .{}); + const msg = try sema.errMsg(block, src, "multiple @setAlignStack in the same function body", .{}); + errdefer msg.destroy(sema.gpa); + try sema.errNote(block, src, msg, "other instance here", .{}); break :msg msg; }; - return mod.failWithOwnedErrorMsg(&block.base, msg); + return sema.failWithOwnedErrorMsg(msg); } gop.value_ptr.* = .{ .alignment = alignment, .src = src }; } -fn zirSetCold(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void { +fn zirSetCold(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { const inst_data = sema.code.instructions.items(.data)[inst].un_node; const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const is_cold = try sema.resolveConstBool(block, operand_src, inst_data.operand); @@ -2604,19 +3002,19 @@ fn zirSetCold(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr func.is_cold = is_cold; } -fn zirSetFloatMode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void { +fn zirSetFloatMode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { const inst_data = sema.code.instructions.items(.data)[inst].un_node; const src: LazySrcLoc = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirSetFloatMode", .{}); + return sema.fail(block, src, "TODO: implement Sema.zirSetFloatMode", .{}); } -fn zirSetRuntimeSafety(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void { +fn zirSetRuntimeSafety(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { const inst_data = sema.code.instructions.items(.data)[inst].un_node; const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; block.want_safety = try sema.resolveConstBool(block, operand_src, inst_data.operand); } -fn zirFence(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void { +fn zirFence(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { if (block.is_comptime) return; const inst_data = sema.code.instructions.items(.data)[inst].un_node; @@ -2624,7 +3022,7 @@ fn zirFence(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError const order = try sema.resolveAtomicOrder(block, order_src, inst_data.operand); if (@enumToInt(order) < @enumToInt(std.builtin.AtomicOrder.Acquire)) { - return sema.mod.fail(&block.base, order_src, "atomic ordering must be Acquire or stricter", .{}); + return sema.fail(block, order_src, "atomic ordering must be Acquire or stricter", .{}); } _ = try block.addInst(.{ @@ -2633,7 +3031,7 @@ fn zirFence(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError }); } -fn zirBreak(sema: *Sema, start_block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index { +fn zirBreak(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index { const tracy = trace(@src()); defer tracy.end(); @@ -2655,7 +3053,7 @@ fn zirBreak(sema: *Sema, start_block: *Scope.Block, inst: Zir.Inst.Index) Compil } } -fn zirDbgStmt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void { +fn zirDbgStmt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { const tracy = trace(@src()); defer tracy.end(); @@ -2675,7 +3073,7 @@ fn zirDbgStmt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr }); } -fn zirDeclRef(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].str_tok; const src = inst_data.src(); const decl_name = inst_data.get(sema.code); @@ -2683,7 +3081,7 @@ fn zirDeclRef(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr return sema.analyzeDeclRef(decl); } -fn zirDeclVal(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirDeclVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].str_tok; const src = inst_data.src(); const decl_name = inst_data.get(sema.code); @@ -2691,8 +3089,8 @@ fn zirDeclVal(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr return sema.analyzeDeclVal(block, src, decl); } -fn lookupIdentifier(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, name: []const u8) !*Decl { - var namespace = sema.namespace; +fn lookupIdentifier(sema: *Sema, block: *Block, src: LazySrcLoc, name: []const u8) !*Decl { + var namespace = block.namespace; while (true) { if (try sema.lookupInNamespace(block, src, namespace, name, false)) |decl| { return decl; @@ -2706,9 +3104,9 @@ fn lookupIdentifier(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, name: []c /// only for ones in the specified namespace. fn lookupInNamespace( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, - namespace: *Scope.Namespace, + namespace: *Namespace, ident_name: []const u8, observe_usingnamespace: bool, ) CompileError!?*Decl { @@ -2721,10 +3119,10 @@ fn lookupInNamespace( } if (observe_usingnamespace and namespace.usingnamespace_set.count() != 0) { - const src_file = block.src_decl.namespace.file_scope; + const src_file = block.namespace.file_scope; const gpa = sema.gpa; - var checked_namespaces: std.AutoArrayHashMapUnmanaged(*Scope.Namespace, void) = .{}; + var checked_namespaces: std.AutoArrayHashMapUnmanaged(*Namespace, void) = .{}; defer checked_namespaces.deinit(gpa); // Keep track of name conflicts for error notes. @@ -2739,7 +3137,7 @@ fn lookupInNamespace( if (check_ns.decls.get(ident_name)) |decl| { // Skip decls which are not marked pub, which are in a different // file than the `a.b`/`@hasDecl` syntax. - if (decl.is_pub or src_file == decl.namespace.file_scope) { + if (decl.is_pub or src_file == decl.getFileScope()) { try candidates.append(gpa, decl); } } @@ -2747,7 +3145,7 @@ fn lookupInNamespace( while (it.next()) |entry| { const sub_usingnamespace_decl = entry.key_ptr.*; const sub_is_pub = entry.value_ptr.*; - if (!sub_is_pub and src_file != sub_usingnamespace_decl.namespace.file_scope) { + if (!sub_is_pub and src_file != sub_usingnamespace_decl.getFileScope()) { // Skip usingnamespace decls which are not marked pub, which are in // a different file than the `a.b`/`@hasDecl` syntax. continue; @@ -2768,7 +3166,7 @@ fn lookupInNamespace( }, else => { const msg = msg: { - const msg = try mod.errMsg(&block.base, src, "ambiguous reference", .{}); + const msg = try sema.errMsg(block, src, "ambiguous reference", .{}); errdefer msg.destroy(gpa); for (candidates.items) |candidate| { const src_loc = candidate.srcLoc(); @@ -2776,7 +3174,7 @@ fn lookupInNamespace( } break :msg msg; }; - return mod.failWithOwnedErrorMsg(&block.base, msg); + return sema.failWithOwnedErrorMsg(msg); }, } } else if (namespace.decls.get(ident_name)) |decl| { @@ -2796,7 +3194,7 @@ fn lookupInNamespace( fn zirCall( sema: *Sema, - block: *Scope.Block, + block: *Block, inst: Zir.Inst.Index, ) CompileError!Air.Inst.Ref { const tracy = trace(@src()); @@ -2898,7 +3296,7 @@ const GenericRemoveAdapter = struct { fn analyzeCall( sema: *Sema, - block: *Scope.Block, + block: *Block, func: Air.Inst.Ref, func_src: LazySrcLoc, call_src: LazySrcLoc, @@ -2910,14 +3308,14 @@ fn analyzeCall( const func_ty = sema.typeOf(func); if (func_ty.zigTypeTag() != .Fn) - return mod.fail(&block.base, func_src, "type '{}' not a function", .{func_ty}); + return sema.fail(block, func_src, "type '{}' not a function", .{func_ty}); const func_ty_info = func_ty.fnInfo(); const cc = func_ty_info.cc; if (cc == .Naked) { // TODO add error note: declared here - return mod.fail( - &block.base, + return sema.fail( + block, func_src, "unable to call function with naked calling convention", .{}, @@ -2928,8 +3326,8 @@ fn analyzeCall( assert(cc == .C); if (uncasted_args.len < fn_params_len) { // TODO add error note: declared here - return mod.fail( - &block.base, + return sema.fail( + block, func_src, "expected at least {d} argument(s), found {d}", .{ fn_params_len, uncasted_args.len }, @@ -2937,8 +3335,8 @@ fn analyzeCall( } } else if (fn_params_len != uncasted_args.len) { // TODO add error note: declared here - return mod.fail( - &block.base, + return sema.fail( + block, func_src, "expected {d} argument(s), found {d}", .{ fn_params_len, uncasted_args.len }, @@ -2956,7 +3354,7 @@ fn analyzeCall( .never_inline, .no_async, .always_tail, - => return mod.fail(&block.base, call_src, "TODO implement call with modifier {}", .{ + => return sema.fail(block, call_src, "TODO implement call with modifier {}", .{ modifier, }), } @@ -2971,7 +3369,7 @@ fn analyzeCall( const func_val = try sema.resolveConstValue(block, func_src, func); const module_fn = switch (func_val.tag()) { .function => func_val.castTag(.function).?.data, - .extern_fn => return mod.fail(&block.base, call_src, "{s} call of extern function", .{ + .extern_fn => return sema.fail(block, call_src, "{s} call of extern function", .{ @as([]const u8, if (is_comptime_call) "comptime" else "inline"), }), else => unreachable, @@ -2979,7 +3377,7 @@ fn analyzeCall( // Analyze the ZIR. The same ZIR gets analyzed into a runtime function // or an inlined call depending on what union tag the `label` field is - // set to in the `Scope.Block`. + // set to in the `Block`. // This block instruction will be used to capture the return value from the // inlined function. const block_inst = @intCast(Air.Inst.Index, sema.air_instructions.len); @@ -2989,7 +3387,7 @@ fn analyzeCall( }); // This one is shared among sub-blocks within the same callee, but not // shared among the entire inline/comptime call stack. - var inlining: Scope.Block.Inlining = .{ + var inlining: Block.Inlining = .{ .comptime_result = undefined, .merges = .{ .results = .{}, @@ -3000,7 +3398,7 @@ fn analyzeCall( // In order to save a bit of stack space, directly modify Sema rather // than create a child one. const parent_zir = sema.code; - sema.code = module_fn.owner_decl.namespace.file_scope.zir; + sema.code = module_fn.owner_decl.getFileScope().zir; defer sema.code = parent_zir; const parent_inst_map = sema.inst_map; @@ -3010,10 +3408,6 @@ fn analyzeCall( sema.inst_map = parent_inst_map; } - const parent_namespace = sema.namespace; - sema.namespace = module_fn.owner_decl.namespace; - defer sema.namespace = parent_namespace; - const parent_func = sema.func; sema.func = module_fn; defer sema.func = parent_func; @@ -3021,10 +3415,11 @@ fn analyzeCall( var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, module_fn.owner_decl.src_scope); defer wip_captures.deinit(); - var child_block: Scope.Block = .{ + var child_block: Block = .{ .parent = null, .sema = sema, .src_decl = module_fn.owner_decl, + .namespace = module_fn.owner_decl.src_namespace, .wip_capture_scope = wip_captures.scope, .instructions = .{}, .label = null, @@ -3180,12 +3575,6 @@ fn analyzeCall( }); delete_memoized_call_key = false; } - - // Much like in `Module.semaDecl`, if the result is a struct or union type, - // we need to resolve the field type expressions right here, right now, while - // the child `Sema` is still available, with the AIR instruction map intact, - // because the field type expressions may reference into it. - try sema.resolvePendingTypes(&child_block); } break :res2 result; @@ -3200,7 +3589,7 @@ fn analyzeCall( // Check the Module's generic function map with an adapted context, so that we // can match against `uncasted_args` rather than doing the work below to create a // generic Scope only to junk it if it matches an existing instantiation. - const namespace = module_fn.owner_decl.namespace; + const namespace = module_fn.owner_decl.src_namespace; const fn_zir = namespace.file_scope.zir; const fn_info = fn_zir.getFnInfo(module_fn.zir_body_inst); const zir_tags = fn_zir.instructions.items(.tag); @@ -3276,12 +3665,12 @@ fn analyzeCall( // Create a Decl for the new function. const src_decl = namespace.getDecl(); - const new_decl = try mod.allocateNewDecl(namespace, module_fn.owner_decl.src_node, src_decl.src_scope); // TODO better names for generic function instantiations const name_index = mod.getNextAnonNameIndex(); - new_decl.name = try std.fmt.allocPrintZ(gpa, "{s}__anon_{d}", .{ + const decl_name = try std.fmt.allocPrintZ(gpa, "{s}__anon_{d}", .{ module_fn.owner_decl.name, name_index, }); + const new_decl = try mod.allocateNewDecl(decl_name, namespace, module_fn.owner_decl.src_node, src_decl.src_scope); new_decl.src_line = module_fn.owner_decl.src_line; new_decl.is_pub = module_fn.owner_decl.is_pub; new_decl.is_exported = module_fn.owner_decl.is_exported; @@ -3297,6 +3686,11 @@ fn analyzeCall( namespace.anon_decls.putAssumeCapacityNoClobber(new_decl, {}); + // The generic function Decl is guaranteed to be the first dependency + // of each of its instantiations. + assert(new_decl.dependencies.keys().len == 0); + try mod.declareDeclDependency(new_decl, module_fn.owner_decl); + var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa); errdefer new_decl_arena.deinit(); @@ -3311,7 +3705,6 @@ fn analyzeCall( .perm_arena = &new_decl_arena.allocator, .code = fn_zir, .owner_decl = new_decl, - .namespace = namespace, .func = null, .fn_ret_ty = Type.initTag(.void), .owner_func = null, @@ -3324,10 +3717,11 @@ fn analyzeCall( var wip_captures = try WipCaptureScope.init(gpa, sema.perm_arena, new_decl.src_scope); defer wip_captures.deinit(); - var child_block: Scope.Block = .{ + var child_block: Block = .{ .parent = null, .sema = &child_sema, .src_decl = new_decl, + .namespace = namespace, .wip_capture_scope = wip_captures.scope, .instructions = .{}, .inlining = null, @@ -3430,11 +3824,6 @@ fn analyzeCall( }); assert(!new_decl.ty.fnInfo().is_generic); - // The generic function Decl is guaranteed to be the first dependency - // of each of its instantiations. - assert(new_decl.dependencies.keys().len == 0); - try mod.declareDeclDependency(new_decl, module_fn.owner_decl); - // Queue up a `codegen_func` work item for the new Fn. The `comptime_args` field // will be populated, ensuring it will have `analyzeBody` called with the ZIR // parameters mapped appropriately. @@ -3489,7 +3878,7 @@ fn analyzeCall( fn finishGenericCall( sema: *Sema, - block: *Scope.Block, + block: *Block, call_src: LazySrcLoc, callee: *Module.Fn, func_src: LazySrcLoc, @@ -3556,7 +3945,7 @@ fn finishGenericCall( return func_inst; } -fn zirIntType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirIntType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { _ = block; const tracy = trace(@src()); defer tracy.end(); @@ -3567,7 +3956,7 @@ fn zirIntType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr return sema.addType(ty); } -fn zirOptionalType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -3579,7 +3968,7 @@ fn zirOptionalType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compi return sema.addType(opt_type); } -fn zirElemType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].un_node; const src = inst_data.src(); const array_type = try sema.resolveType(block, src, inst_data.operand); @@ -3587,7 +3976,7 @@ fn zirElemType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr return sema.addType(elem_type); } -fn zirVectorType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirVectorType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const elem_type_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const len_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; @@ -3601,7 +3990,7 @@ fn zirVectorType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compile return sema.addType(vector_type); } -fn zirArrayType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirArrayType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -3613,7 +4002,7 @@ fn zirArrayType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileE return sema.addType(array_ty); } -fn zirArrayTypeSentinel(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirArrayTypeSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -3629,7 +4018,7 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) return sema.addType(array_ty); } -fn zirAnyframeType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirAnyframeType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -3641,7 +4030,7 @@ fn zirAnyframeType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compi return sema.addType(anyframe_type); } -fn zirErrorUnionType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirErrorUnionType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -3653,7 +4042,7 @@ fn zirErrorUnionType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Com const payload = try sema.resolveType(block, rhs_src, extra.rhs); if (error_union.zigTypeTag() != .ErrorSet) { - return sema.mod.fail(&block.base, lhs_src, "expected error set type, found {}", .{ + return sema.fail(block, lhs_src, "expected error set type, found {}", .{ error_union.elemType(), }); } @@ -3661,7 +4050,7 @@ fn zirErrorUnionType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Com return sema.addType(err_union_ty); } -fn zirErrorValue(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirErrorValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { _ = block; const tracy = trace(@src()); defer tracy.end(); @@ -3679,7 +4068,7 @@ fn zirErrorValue(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compile ); } -fn zirErrorToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirErrorToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -3706,7 +4095,7 @@ fn zirErrorToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compile return block.addTyOp(.bitcast, result_ty, op_coerced); } -fn zirIntToError(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirIntToError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -3719,7 +4108,7 @@ fn zirIntToError(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compile if (try sema.resolveDefinedValue(block, operand_src, op)) |value| { const int = value.toUnsignedInt(); if (int > sema.mod.global_error_set.count() or int == 0) - return sema.mod.fail(&block.base, operand_src, "integer value {d} represents no error", .{int}); + return sema.fail(block, operand_src, "integer value {d} represents no error", .{int}); const payload = try sema.arena.create(Value.Payload.Error); payload.* = .{ .base = .{ .tag = .@"error" }, @@ -3729,14 +4118,14 @@ fn zirIntToError(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compile } try sema.requireRuntimeBlock(block, src); if (block.wantSafety()) { - return sema.mod.fail(&block.base, src, "TODO: get max errors in compilation", .{}); + return sema.fail(block, src, "TODO: get max errors in compilation", .{}); // const is_gt_max = @panic("TODO get max errors in compilation"); // try sema.addSafetyCheck(block, is_gt_max, .invalid_error_code); } return block.addTyOp(.bitcast, Type.initTag(.anyerror), op); } -fn zirMergeErrorSets(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -3749,19 +4138,19 @@ fn zirMergeErrorSets(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Com const rhs = sema.resolveInst(extra.rhs); if (sema.typeOf(lhs).zigTypeTag() == .Bool and sema.typeOf(rhs).zigTypeTag() == .Bool) { const msg = msg: { - const msg = try sema.mod.errMsg(&block.base, lhs_src, "expected error set type, found 'bool'", .{}); + const msg = try sema.errMsg(block, lhs_src, "expected error set type, found 'bool'", .{}); errdefer msg.destroy(sema.gpa); - try sema.mod.errNote(&block.base, src, msg, "'||' merges error sets; 'or' performs boolean OR", .{}); + try sema.errNote(block, src, msg, "'||' merges error sets; 'or' performs boolean OR", .{}); break :msg msg; }; - return sema.mod.failWithOwnedErrorMsg(&block.base, msg); + return sema.failWithOwnedErrorMsg(msg); } const lhs_ty = try sema.analyzeAsType(block, lhs_src, lhs); const rhs_ty = try sema.analyzeAsType(block, rhs_src, rhs); if (lhs_ty.zigTypeTag() != .ErrorSet) - return sema.mod.fail(&block.base, lhs_src, "expected error set type, found {}", .{lhs_ty}); + return sema.fail(block, lhs_src, "expected error set type, found {}", .{lhs_ty}); if (rhs_ty.zigTypeTag() != .ErrorSet) - return sema.mod.fail(&block.base, rhs_src, "expected error set type, found {}", .{rhs_ty}); + return sema.fail(block, rhs_src, "expected error set type, found {}", .{rhs_ty}); // Anything merged with anyerror is anyerror. if (lhs_ty.tag() == .anyerror or rhs_ty.tag() == .anyerror) { @@ -3820,7 +4209,7 @@ fn zirMergeErrorSets(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Com return sema.addConstant(Type.initTag(.type), try Value.Tag.ty.create(sema.arena, error_set_ty)); } -fn zirEnumLiteral(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { _ = block; const tracy = trace(@src()); defer tracy.end(); @@ -3833,8 +4222,7 @@ fn zirEnumLiteral(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compil ); } -fn zirEnumToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const mod = sema.mod; +fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const arena = sema.arena; const inst_data = sema.code.instructions.items(.data)[inst].un_node; const src = inst_data.src(); @@ -3846,17 +4234,17 @@ fn zirEnumToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileE .Enum => operand, .Union => { //if (!operand_ty.unionHasTag()) { - // return mod.fail( - // &block.base, + // return sema.fail( + // block, // operand_src, // "untagged union '{}' cannot be converted to integer", // .{dest_ty_src}, // ); //} - return mod.fail(&block.base, operand_src, "TODO zirEnumToInt for tagged unions", .{}); + return sema.fail(block, operand_src, "TODO zirEnumToInt for tagged unions", .{}); }, else => { - return mod.fail(&block.base, operand_src, "expected enum or tagged union, found {}", .{ + return sema.fail(block, operand_src, "expected enum or tagged union, found {}", .{ operand_ty, }); }, @@ -3880,9 +4268,8 @@ fn zirEnumToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileE return block.addTyOp(.bitcast, int_tag_ty, enum_tag); } -fn zirIntToEnum(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const mod = sema.mod; - const target = mod.getTarget(); +fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { + const target = sema.mod.getTarget(); const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const src = inst_data.src(); @@ -3892,7 +4279,7 @@ fn zirIntToEnum(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileE const operand = sema.resolveInst(extra.rhs); if (dest_ty.zigTypeTag() != .Enum) { - return mod.fail(&block.base, dest_ty_src, "expected enum, found {}", .{dest_ty}); + return sema.fail(block, dest_ty_src, "expected enum, found {}", .{dest_ty}); } if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |int_val| { @@ -3904,14 +4291,14 @@ fn zirIntToEnum(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileE } if (!dest_ty.enumHasInt(int_val, target)) { const msg = msg: { - const msg = try mod.errMsg( - &block.base, + const msg = try sema.errMsg( + block, src, "enum '{}' has no tag with value {}", .{ dest_ty, int_val }, ); errdefer msg.destroy(sema.gpa); - try mod.errNoteNonLazy( + try sema.mod.errNoteNonLazy( dest_ty.declSrcLoc(), msg, "enum declared here", @@ -3919,7 +4306,7 @@ fn zirIntToEnum(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileE ); break :msg msg; }; - return mod.failWithOwnedErrorMsg(&block.base, msg); + return sema.failWithOwnedErrorMsg(msg); } return sema.addConstant(dest_ty, int_val); } @@ -3931,7 +4318,7 @@ fn zirIntToEnum(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileE /// Pointer in, pointer out. fn zirOptionalPayloadPtr( sema: *Sema, - block: *Scope.Block, + block: *Block, inst: Zir.Inst.Index, safety_check: bool, ) CompileError!Air.Inst.Ref { @@ -3946,7 +4333,7 @@ fn zirOptionalPayloadPtr( const opt_type = optional_ptr_ty.elemType(); if (opt_type.zigTypeTag() != .Optional) { - return sema.mod.fail(&block.base, src, "expected optional type, found {}", .{opt_type}); + return sema.fail(block, src, "expected optional type, found {}", .{opt_type}); } const child_type = try opt_type.optionalChildAlloc(sema.arena); @@ -3959,7 +4346,7 @@ fn zirOptionalPayloadPtr( if (try sema.resolveDefinedValue(block, src, optional_ptr)) |pointer_val| { if (try pointer_val.pointerDeref(sema.arena)) |val| { if (val.isNull()) { - return sema.mod.fail(&block.base, src, "unable to unwrap null", .{}); + return sema.fail(block, src, "unable to unwrap null", .{}); } // The same Value represents the pointer to the optional and the payload. return sema.addConstant( @@ -3980,7 +4367,7 @@ fn zirOptionalPayloadPtr( /// Value in, value out. fn zirOptionalPayload( sema: *Sema, - block: *Scope.Block, + block: *Block, inst: Zir.Inst.Index, safety_check: bool, ) CompileError!Air.Inst.Ref { @@ -3993,14 +4380,14 @@ fn zirOptionalPayload( const operand_ty = sema.typeOf(operand); const opt_type = operand_ty; if (opt_type.zigTypeTag() != .Optional) { - return sema.mod.fail(&block.base, src, "expected optional type, found {}", .{opt_type}); + return sema.fail(block, src, "expected optional type, found {}", .{opt_type}); } const child_type = try opt_type.optionalChildAlloc(sema.arena); if (try sema.resolveDefinedValue(block, src, operand)) |val| { if (val.isNull()) { - return sema.mod.fail(&block.base, src, "unable to unwrap null", .{}); + return sema.fail(block, src, "unable to unwrap null", .{}); } const sub_val = val.castTag(.opt_payload).?.data; return sema.addConstant(child_type, sub_val); @@ -4017,7 +4404,7 @@ fn zirOptionalPayload( /// Value in, value out fn zirErrUnionPayload( sema: *Sema, - block: *Scope.Block, + block: *Block, inst: Zir.Inst.Index, safety_check: bool, ) CompileError!Air.Inst.Ref { @@ -4030,11 +4417,11 @@ fn zirErrUnionPayload( const operand_src = src; const operand_ty = sema.typeOf(operand); if (operand_ty.zigTypeTag() != .ErrorUnion) - return sema.mod.fail(&block.base, operand_src, "expected error union type, found '{}'", .{operand_ty}); + return sema.fail(block, operand_src, "expected error union type, found '{}'", .{operand_ty}); if (try sema.resolveDefinedValue(block, src, operand)) |val| { if (val.getError()) |name| { - return sema.mod.fail(&block.base, src, "caught unexpected error '{s}'", .{name}); + return sema.fail(block, src, "caught unexpected error '{s}'", .{name}); } const data = val.castTag(.eu_payload).?.data; const result_ty = operand_ty.errorUnionPayload(); @@ -4052,7 +4439,7 @@ fn zirErrUnionPayload( /// Pointer in, pointer out. fn zirErrUnionPayloadPtr( sema: *Sema, - block: *Scope.Block, + block: *Block, inst: Zir.Inst.Index, safety_check: bool, ) CompileError!Air.Inst.Ref { @@ -4066,7 +4453,7 @@ fn zirErrUnionPayloadPtr( assert(operand_ty.zigTypeTag() == .Pointer); if (operand_ty.elemType().zigTypeTag() != .ErrorUnion) - return sema.mod.fail(&block.base, src, "expected error union type, found {}", .{operand_ty.elemType()}); + return sema.fail(block, src, "expected error union type, found {}", .{operand_ty.elemType()}); const payload_ty = operand_ty.elemType().errorUnionPayload(); const operand_pointer_ty = try Type.ptr(sema.arena, .{ @@ -4078,7 +4465,7 @@ fn zirErrUnionPayloadPtr( if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| { if (try pointer_val.pointerDeref(sema.arena)) |val| { if (val.getError()) |name| { - return sema.mod.fail(&block.base, src, "caught unexpected error '{s}'", .{name}); + return sema.fail(block, src, "caught unexpected error '{s}'", .{name}); } return sema.addConstant( operand_pointer_ty, @@ -4096,7 +4483,7 @@ fn zirErrUnionPayloadPtr( } /// Value in, value out -fn zirErrUnionCode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirErrUnionCode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -4105,7 +4492,7 @@ fn zirErrUnionCode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compi const operand = sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); if (operand_ty.zigTypeTag() != .ErrorUnion) - return sema.mod.fail(&block.base, src, "expected error union type, found '{}'", .{operand_ty}); + return sema.fail(block, src, "expected error union type, found '{}'", .{operand_ty}); const result_ty = operand_ty.errorUnionSet(); @@ -4119,7 +4506,7 @@ fn zirErrUnionCode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compi } /// Pointer in, value out -fn zirErrUnionCodePtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirErrUnionCodePtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -4130,7 +4517,7 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co assert(operand_ty.zigTypeTag() == .Pointer); if (operand_ty.elemType().zigTypeTag() != .ErrorUnion) - return sema.mod.fail(&block.base, src, "expected error union type, found {}", .{operand_ty.elemType()}); + return sema.fail(block, src, "expected error union type, found {}", .{operand_ty.elemType()}); const result_ty = operand_ty.elemType().errorUnionSet(); @@ -4145,7 +4532,7 @@ fn zirErrUnionCodePtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co return block.addTyOp(.unwrap_errunion_err_ptr, result_ty, operand); } -fn zirEnsureErrPayloadVoid(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void { +fn zirEnsureErrPayloadVoid(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { const tracy = trace(@src()); defer tracy.end(); @@ -4154,15 +4541,15 @@ fn zirEnsureErrPayloadVoid(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Inde const operand = sema.resolveInst(inst_data.operand); const operand_ty = sema.typeOf(operand); if (operand_ty.zigTypeTag() != .ErrorUnion) - return sema.mod.fail(&block.base, src, "expected error union type, found '{}'", .{operand_ty}); + return sema.fail(block, src, "expected error union type, found '{}'", .{operand_ty}); if (operand_ty.errorUnionPayload().zigTypeTag() != .Void) { - return sema.mod.fail(&block.base, src, "expression value is ignored", .{}); + return sema.fail(block, src, "expression value is ignored", .{}); } } fn zirFunc( sema: *Sema, - block: *Scope.Block, + block: *Block, inst: Zir.Inst.Index, inferred_error_set: bool, ) CompileError!Air.Inst.Ref { @@ -4205,7 +4592,7 @@ fn zirFunc( fn funcCommon( sema: *Sema, - block: *Scope.Block, + block: *Block, src_node_offset: i32, body_inst: Zir.Inst.Index, ret_ty_body: []const Zir.Inst.Index, @@ -4297,7 +4684,7 @@ fn funcCommon( } if (align_val.tag() != .null_value) { - return mod.fail(&block.base, src, "TODO implement support for function prototypes to have alignment specified", .{}); + return sema.fail(block, src, "TODO implement support for function prototypes to have alignment specified", .{}); } is_generic = is_generic or bare_return_type.requiresComptime(); @@ -4329,15 +4716,15 @@ fn funcCommon( const lib_name_src: LazySrcLoc = .{ .node_offset_lib_name = src_node_offset }; log.debug("extern fn symbol expected in lib '{s}'", .{lib_name}); mod.comp.stage1AddLinkLib(lib_name) catch |err| { - return mod.fail(&block.base, lib_name_src, "unable to add link lib '{s}': {s}", .{ + return sema.fail(block, lib_name_src, "unable to add link lib '{s}': {s}", .{ lib_name, @errorName(err), }); }; const target = mod.getTarget(); if (target_util.is_libc_lib_name(target, lib_name)) { if (!mod.comp.bin_file.options.link_libc) { - return mod.fail( - &block.base, + return sema.fail( + block, lib_name_src, "dependency on libc must be explicitly specified in the build command", .{}, @@ -4347,8 +4734,8 @@ fn funcCommon( } if (target_util.is_libcpp_lib_name(target, lib_name)) { if (!mod.comp.bin_file.options.link_libcpp) { - return mod.fail( - &block.base, + return sema.fail( + block, lib_name_src, "dependency on libc++ must be explicitly specified in the build command", .{}, @@ -4357,8 +4744,8 @@ fn funcCommon( break :blk; } if (!target.isWasm() and !mod.comp.bin_file.options.pic) { - return mod.fail( - &block.base, + return sema.fail( + block, lib_name_src, "dependency on dynamic library '{s}' requires enabling Position Independent Code. Fixed by `-l{s}` or `-fPIC`.", .{ lib_name, lib_name }, @@ -4404,7 +4791,7 @@ fn funcCommon( fn zirParam( sema: *Sema, - block: *Scope.Block, + block: *Block, inst: Zir.Inst.Index, is_comptime: bool, ) CompileError!void { @@ -4474,7 +4861,7 @@ fn zirParam( fn zirParamAnytype( sema: *Sema, - block: *Scope.Block, + block: *Block, inst: Zir.Inst.Index, is_comptime: bool, ) CompileError!void { @@ -4509,7 +4896,7 @@ fn zirParamAnytype( try sema.inst_map.put(sema.gpa, inst, .generic_poison); } -fn zirAs(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirAs(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -4517,7 +4904,7 @@ fn zirAs(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Ai return sema.analyzeAs(block, .unneeded, bin_inst.lhs, bin_inst.rhs); } -fn zirAsNode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirAsNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -4529,7 +4916,7 @@ fn zirAsNode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErro fn analyzeAs( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, zir_dest_type: Zir.Inst.Ref, zir_operand: Zir.Inst.Ref, @@ -4539,7 +4926,7 @@ fn analyzeAs( return sema.coerce(block, dest_type, operand, src); } -fn zirPtrToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirPtrToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -4548,7 +4935,7 @@ fn zirPtrToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr const ptr_ty = sema.typeOf(ptr); if (ptr_ty.zigTypeTag() != .Pointer) { const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; - return sema.mod.fail(&block.base, ptr_src, "expected pointer, found '{}'", .{ptr_ty}); + return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty}); } // TODO handle known-pointer-address const src = inst_data.src(); @@ -4556,7 +4943,7 @@ fn zirPtrToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr return block.addUnOp(.ptrtoint, ptr); } -fn zirFieldVal(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirFieldVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -4575,7 +4962,7 @@ fn zirFieldVal(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr } } -fn zirFieldPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -4588,7 +4975,7 @@ fn zirFieldPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr return sema.fieldPtr(block, src, object_ptr, field_name, field_name_src); } -fn zirFieldCallBind(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirFieldCallBind(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -4601,7 +4988,7 @@ fn zirFieldCallBind(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Comp return sema.fieldCallBind(block, src, object_ptr, field_name, field_name_src); } -fn zirFieldValNamed(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirFieldValNamed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -4614,7 +5001,7 @@ fn zirFieldValNamed(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Comp return sema.fieldVal(block, src, object, field_name, field_name_src); } -fn zirFieldPtrNamed(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirFieldPtrNamed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -4627,7 +5014,7 @@ fn zirFieldPtrNamed(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Comp return sema.fieldPtr(block, src, object_ptr, field_name, field_name_src); } -fn zirFieldCallBindNamed(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirFieldCallBindNamed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -4640,7 +5027,7 @@ fn zirFieldCallBindNamed(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) return sema.fieldCallBind(block, src, object_ptr, field_name, field_name_src); } -fn zirIntCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirIntCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -4659,14 +5046,14 @@ fn zirIntCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr if (try sema.isComptimeKnown(block, operand_src, operand)) { return sema.coerce(block, dest_type, operand, operand_src); } else if (dest_is_comptime_int) { - return sema.mod.fail(&block.base, src, "unable to cast runtime value to 'comptime_int'", .{}); + return sema.fail(block, src, "unable to cast runtime value to 'comptime_int'", .{}); } try sema.requireRuntimeBlock(block, operand_src); return block.addTyOp(.intcast, dest_type, operand); } -fn zirBitcast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -4680,7 +5067,7 @@ fn zirBitcast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr return sema.bitcast(block, dest_type, operand, operand_src); } -fn zirFloatCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -4696,8 +5083,8 @@ fn zirFloatCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileE const dest_is_comptime_float = switch (dest_type.zigTypeTag()) { .ComptimeFloat => true, .Float => false, - else => return sema.mod.fail( - &block.base, + else => return sema.fail( + block, dest_ty_src, "expected float type, found '{}'", .{dest_type}, @@ -4707,8 +5094,8 @@ fn zirFloatCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileE const operand_ty = sema.typeOf(operand); switch (operand_ty.zigTypeTag()) { .ComptimeFloat, .Float, .ComptimeInt => {}, - else => return sema.mod.fail( - &block.base, + else => return sema.fail( + block, operand_src, "expected float type, found '{}'", .{operand_ty}, @@ -4719,7 +5106,7 @@ fn zirFloatCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileE return sema.coerce(block, dest_type, operand, operand_src); } if (dest_is_comptime_float) { - return sema.mod.fail(&block.base, src, "unable to cast runtime value to 'comptime_float'", .{}); + return sema.fail(block, src, "unable to cast runtime value to 'comptime_float'", .{}); } const target = sema.mod.getTarget(); const src_bits = operand_ty.floatBits(target); @@ -4731,7 +5118,7 @@ fn zirFloatCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileE return block.addTyOp(.fptrunc, dest_type, operand); } -fn zirElemVal(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirElemVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -4741,7 +5128,7 @@ fn zirElemVal(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr return sema.elemVal(block, sema.src, array, elem_index, sema.src); } -fn zirElemValNode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirElemValNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -4754,7 +5141,7 @@ fn zirElemValNode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compil return sema.elemVal(block, src, array, elem_index, elem_index_src); } -fn zirElemPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -4764,7 +5151,7 @@ fn zirElemPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr return sema.elemPtr(block, sema.src, array_ptr, elem_index, sema.src); } -fn zirElemPtrNode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirElemPtrNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -4777,7 +5164,7 @@ fn zirElemPtrNode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compil return sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src); } -fn zirSliceStart(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirSliceStart(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -4790,7 +5177,7 @@ fn zirSliceStart(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compile return sema.analyzeSlice(block, src, array_ptr, start, .none, .none, .unneeded); } -fn zirSliceEnd(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirSliceEnd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -4804,7 +5191,7 @@ fn zirSliceEnd(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr return sema.analyzeSlice(block, src, array_ptr, start, end, .none, .unneeded); } -fn zirSliceSentinel(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirSliceSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -4822,7 +5209,7 @@ fn zirSliceSentinel(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Comp fn zirSwitchCapture( sema: *Sema, - block: *Scope.Block, + block: *Block, inst: Zir.Inst.Index, is_multi: bool, is_ref: bool, @@ -4837,12 +5224,12 @@ fn zirSwitchCapture( _ = is_ref; _ = is_multi; - return sema.mod.fail(&block.base, src, "TODO implement Sema for zirSwitchCapture", .{}); + return sema.fail(block, src, "TODO implement Sema for zirSwitchCapture", .{}); } fn zirSwitchCaptureElse( sema: *Sema, - block: *Scope.Block, + block: *Block, inst: Zir.Inst.Index, is_ref: bool, ) CompileError!Air.Inst.Ref { @@ -4855,12 +5242,12 @@ fn zirSwitchCaptureElse( const src = switch_info.src(); _ = is_ref; - return sema.mod.fail(&block.base, src, "TODO implement Sema for zirSwitchCaptureElse", .{}); + return sema.fail(block, src, "TODO implement Sema for zirSwitchCaptureElse", .{}); } fn zirSwitchBlock( sema: *Sema, - block: *Scope.Block, + block: *Block, inst: Zir.Inst.Index, is_ref: bool, special_prong: Zir.SpecialProng, @@ -4893,7 +5280,7 @@ fn zirSwitchBlock( fn zirSwitchBlockMulti( sema: *Sema, - block: *Scope.Block, + block: *Block, inst: Zir.Inst.Index, is_ref: bool, special_prong: Zir.SpecialProng, @@ -4926,7 +5313,7 @@ fn zirSwitchBlockMulti( fn analyzeSwitch( sema: *Sema, - block: *Scope.Block, + block: *Block, operand: Air.Inst.Ref, extra_end: usize, special_prong: Zir.SpecialProng, @@ -4936,7 +5323,6 @@ fn analyzeSwitch( src_node_offset: i32, ) CompileError!Air.Inst.Ref { const gpa = sema.gpa; - const mod = sema.mod; const special: struct { body: []const Zir.Inst.Index, end: usize } = switch (special_prong) { .none => .{ .body = &.{}, .end = extra_end }, @@ -4958,15 +5344,15 @@ fn analyzeSwitch( // Validate usage of '_' prongs. if (special_prong == .under and !operand_ty.isNonexhaustiveEnum()) { const msg = msg: { - const msg = try mod.errMsg( - &block.base, + const msg = try sema.errMsg( + block, src, "'_' prong only allowed when switching on non-exhaustive enums", .{}, ); errdefer msg.destroy(gpa); - try mod.errNote( - &block.base, + try sema.errNote( + block, special_prong_src, msg, "'_' prong here", @@ -4974,7 +5360,7 @@ fn analyzeSwitch( ); break :msg msg; }; - return mod.failWithOwnedErrorMsg(&block.base, msg); + return sema.failWithOwnedErrorMsg(msg); } // Validate for duplicate items, missing else prong, and invalid range. @@ -5037,8 +5423,8 @@ fn analyzeSwitch( .none => { if (!all_tags_handled) { const msg = msg: { - const msg = try mod.errMsg( - &block.base, + const msg = try sema.errMsg( + block, src, "switch must handle all possibilities", .{}, @@ -5050,15 +5436,15 @@ fn analyzeSwitch( const field_name = operand_ty.enumFieldName(i); // TODO have this point to the tag decl instead of here - try mod.errNote( - &block.base, + try sema.errNote( + block, src, msg, "unhandled enumeration value: '{s}'", .{field_name}, ); } - try mod.errNoteNonLazy( + try sema.mod.errNoteNonLazy( operand_ty.declSrcLoc(), msg, "enum '{}' declared here", @@ -5066,20 +5452,20 @@ fn analyzeSwitch( ); break :msg msg; }; - return mod.failWithOwnedErrorMsg(&block.base, msg); + return sema.failWithOwnedErrorMsg(msg); } }, .under => { - if (all_tags_handled) return mod.fail( - &block.base, + if (all_tags_handled) return sema.fail( + block, special_prong_src, "unreachable '_' prong; all cases already handled", .{}, ); }, .@"else" => { - if (all_tags_handled) return mod.fail( - &block.base, + if (all_tags_handled) return sema.fail( + block, special_prong_src, "unreachable else prong; all cases already handled", .{}, @@ -5088,8 +5474,8 @@ fn analyzeSwitch( } }, - .ErrorSet => return mod.fail(&block.base, src, "TODO validate switch .ErrorSet", .{}), - .Union => return mod.fail(&block.base, src, "TODO validate switch .Union", .{}), + .ErrorSet => return sema.fail(block, src, "TODO validate switch .ErrorSet", .{}), + .Union => return sema.fail(block, src, "TODO validate switch .Union", .{}), .Int, .ComptimeInt => { var range_set = RangeSet.init(gpa); defer range_set.deinit(); @@ -5164,12 +5550,13 @@ fn analyzeSwitch( var arena = std.heap.ArenaAllocator.init(gpa); defer arena.deinit(); - const min_int = try operand_ty.minInt(&arena.allocator, mod.getTarget()); - const max_int = try operand_ty.maxInt(&arena.allocator, mod.getTarget()); + const target = sema.mod.getTarget(); + const min_int = try operand_ty.minInt(&arena.allocator, target); + const max_int = try operand_ty.maxInt(&arena.allocator, target); if (try range_set.spans(min_int, max_int, operand_ty)) { if (special_prong == .@"else") { - return mod.fail( - &block.base, + return sema.fail( + block, special_prong_src, "unreachable else prong; all cases already handled", .{}, @@ -5179,8 +5566,8 @@ fn analyzeSwitch( } } if (special_prong != .@"else") { - return mod.fail( - &block.base, + return sema.fail( + block, src, "switch must handle all possibilities", .{}, @@ -5241,8 +5628,8 @@ fn analyzeSwitch( switch (special_prong) { .@"else" => { if (true_count + false_count == 2) { - return mod.fail( - &block.base, + return sema.fail( + block, src, "unreachable else prong; all cases already handled", .{}, @@ -5251,8 +5638,8 @@ fn analyzeSwitch( }, .under, .none => { if (true_count + false_count < 2) { - return mod.fail( - &block.base, + return sema.fail( + block, src, "switch must handle all possibilities", .{}, @@ -5263,8 +5650,8 @@ fn analyzeSwitch( }, .EnumLiteral, .Void, .Fn, .Pointer, .Type => { if (special_prong != .@"else") { - return mod.fail( - &block.base, + return sema.fail( + block, src, "else prong required when switching on type '{}'", .{operand_ty}, @@ -5334,7 +5721,7 @@ fn analyzeSwitch( .AnyFrame, .ComptimeFloat, .Float, - => return mod.fail(&block.base, operand_src, "invalid switch operand type '{}'", .{ + => return sema.fail(block, operand_src, "invalid switch operand type '{}'", .{ operand_ty, }), } @@ -5344,7 +5731,7 @@ fn analyzeSwitch( .tag = .block, .data = undefined, }); - var label: Scope.Block.Label = .{ + var label: Block.Label = .{ .zir_block = switch_inst, .merges = .{ .results = .{}, @@ -5353,10 +5740,11 @@ fn analyzeSwitch( }, }; - var child_block: Scope.Block = .{ + var child_block: Block = .{ .parent = block, .sema = sema, .src_decl = block.src_decl, + .namespace = block.namespace, .wip_capture_scope = block.wip_capture_scope, .instructions = .{}, .label = &label, @@ -5663,7 +6051,7 @@ fn analyzeSwitch( fn resolveSwitchItemVal( sema: *Sema, - block: *Scope.Block, + block: *Block, item_ref: Zir.Inst.Ref, switch_node_offset: i32, switch_prong_src: Module.SwitchProngSrc, @@ -5690,7 +6078,7 @@ fn resolveSwitchItemVal( fn validateSwitchRange( sema: *Sema, - block: *Scope.Block, + block: *Block, range_set: *RangeSet, first_ref: Zir.Inst.Ref, last_ref: Zir.Inst.Ref, @@ -5706,7 +6094,7 @@ fn validateSwitchRange( fn validateSwitchItem( sema: *Sema, - block: *Scope.Block, + block: *Block, range_set: *RangeSet, item_ref: Zir.Inst.Ref, operand_ty: Type, @@ -5720,25 +6108,24 @@ fn validateSwitchItem( fn validateSwitchItemEnum( sema: *Sema, - block: *Scope.Block, + block: *Block, seen_fields: []?Module.SwitchProngSrc, item_ref: Zir.Inst.Ref, src_node_offset: i32, switch_prong_src: Module.SwitchProngSrc, ) CompileError!void { - const mod = sema.mod; const item_tv = try sema.resolveSwitchItemVal(block, item_ref, src_node_offset, switch_prong_src, .none); const field_index = item_tv.ty.enumTagFieldIndex(item_tv.val) orelse { const msg = msg: { const src = switch_prong_src.resolve(sema.gpa, block.src_decl, src_node_offset, .none); - const msg = try mod.errMsg( - &block.base, + const msg = try sema.errMsg( + block, src, "enum '{}' has no tag with value '{}'", .{ item_tv.ty, item_tv.val }, ); errdefer msg.destroy(sema.gpa); - try mod.errNoteNonLazy( + try sema.mod.errNoteNonLazy( item_tv.ty.declSrcLoc(), msg, "enum declared here", @@ -5746,7 +6133,7 @@ fn validateSwitchItemEnum( ); break :msg msg; }; - return mod.failWithOwnedErrorMsg(&block.base, msg); + return sema.failWithOwnedErrorMsg(msg); }; const maybe_prev_src = seen_fields[field_index]; seen_fields[field_index] = switch_prong_src; @@ -5755,26 +6142,25 @@ fn validateSwitchItemEnum( fn validateSwitchDupe( sema: *Sema, - block: *Scope.Block, + block: *Block, maybe_prev_src: ?Module.SwitchProngSrc, switch_prong_src: Module.SwitchProngSrc, src_node_offset: i32, ) CompileError!void { const prev_prong_src = maybe_prev_src orelse return; - const mod = sema.mod; const gpa = sema.gpa; const src = switch_prong_src.resolve(gpa, block.src_decl, src_node_offset, .none); const prev_src = prev_prong_src.resolve(gpa, block.src_decl, src_node_offset, .none); const msg = msg: { - const msg = try mod.errMsg( - &block.base, + const msg = try sema.errMsg( + block, src, "duplicate switch value", .{}, ); errdefer msg.destroy(sema.gpa); - try mod.errNote( - &block.base, + try sema.errNote( + block, prev_src, msg, "previous value here", @@ -5782,12 +6168,12 @@ fn validateSwitchDupe( ); break :msg msg; }; - return mod.failWithOwnedErrorMsg(&block.base, msg); + return sema.failWithOwnedErrorMsg(msg); } fn validateSwitchItemBool( sema: *Sema, - block: *Scope.Block, + block: *Block, true_count: *u8, false_count: *u8, item_ref: Zir.Inst.Ref, @@ -5802,7 +6188,7 @@ fn validateSwitchItemBool( } if (true_count.* + false_count.* > 2) { const src = switch_prong_src.resolve(sema.gpa, block.src_decl, src_node_offset, .none); - return sema.mod.fail(&block.base, src, "duplicate switch value", .{}); + return sema.fail(block, src, "duplicate switch value", .{}); } } @@ -5810,7 +6196,7 @@ const ValueSrcMap = std.HashMap(Value, Module.SwitchProngSrc, Value.HashContext, fn validateSwitchItemSparse( sema: *Sema, - block: *Scope.Block, + block: *Block, seen_values: *ValueSrcMap, item_ref: Zir.Inst.Ref, src_node_offset: i32, @@ -5823,7 +6209,7 @@ fn validateSwitchItemSparse( fn validateSwitchNoRange( sema: *Sema, - block: *Scope.Block, + block: *Block, ranges_len: u32, operand_ty: Type, src_node_offset: i32, @@ -5835,15 +6221,15 @@ fn validateSwitchNoRange( const range_src: LazySrcLoc = .{ .node_offset_switch_range = src_node_offset }; const msg = msg: { - const msg = try sema.mod.errMsg( - &block.base, + const msg = try sema.errMsg( + block, operand_src, "ranges not allowed when switching on type '{}'", .{operand_ty}, ); errdefer msg.destroy(sema.gpa); - try sema.mod.errNote( - &block.base, + try sema.errNote( + block, range_src, msg, "range here", @@ -5851,19 +6237,19 @@ fn validateSwitchNoRange( ); break :msg msg; }; - return sema.mod.failWithOwnedErrorMsg(&block.base, msg); + return sema.failWithOwnedErrorMsg(msg); } -fn zirHasField(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; _ = extra; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO implement zirHasField", .{}); + return sema.fail(block, src, "TODO implement zirHasField", .{}); } -fn zirHasDecl(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirHasDecl(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const src = inst_data.src(); @@ -5871,23 +6257,22 @@ fn zirHasDecl(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr const rhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; const container_type = try sema.resolveType(block, lhs_src, extra.lhs); const decl_name = try sema.resolveConstString(block, rhs_src, extra.rhs); - const mod = sema.mod; - const namespace = container_type.getNamespace() orelse return mod.fail( - &block.base, + const namespace = container_type.getNamespace() orelse return sema.fail( + block, lhs_src, "expected struct, enum, union, or opaque, found '{}'", .{container_type}, ); if (try sema.lookupInNamespace(block, src, namespace, decl_name, true)) |decl| { - if (decl.is_pub or decl.namespace.file_scope == block.base.namespace().file_scope) { + if (decl.is_pub or decl.getFileScope() == block.getFileScope()) { return Air.Inst.Ref.bool_true; } } return Air.Inst.Ref.bool_false; } -fn zirImport(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -5898,29 +6283,29 @@ fn zirImport(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErro const result = mod.importFile(block.getFileScope(), operand) catch |err| switch (err) { error.ImportOutsidePkgPath => { - return mod.fail(&block.base, src, "import of file outside package path: '{s}'", .{operand}); + return sema.fail(block, src, "import of file outside package path: '{s}'", .{operand}); }, else => { // TODO: these errors are file system errors; make sure an update() will // retry this and not cache the file system error, which may be transient. - return mod.fail(&block.base, src, "unable to open '{s}': {s}", .{ operand, @errorName(err) }); + return sema.fail(block, src, "unable to open '{s}': {s}", .{ operand, @errorName(err) }); }, }; try mod.semaFile(result.file); const file_root_decl = result.file.root_decl.?; - try sema.mod.declareDeclDependency(sema.owner_decl, file_root_decl); + try mod.declareDeclDependency(sema.owner_decl, file_root_decl); return sema.addConstant(file_root_decl.ty, file_root_decl.val); } -fn zirRetErrValueCode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirRetErrValueCode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { _ = block; _ = inst; - return sema.mod.fail(&block.base, sema.src, "TODO implement zirRetErrValueCode", .{}); + return sema.fail(block, sema.src, "TODO implement zirRetErrValueCode", .{}); } fn zirShl( sema: *Sema, - block: *Scope.Block, + block: *Block, inst: Zir.Inst.Index, air_tag: Air.Inst.Tag, ) CompileError!Air.Inst.Ref { @@ -5952,8 +6337,8 @@ fn zirShl( } const val = try lhs_val.shl(rhs_val, sema.arena); switch (air_tag) { - .shl_exact => return sema.mod.fail(&block.base, lhs_src, "TODO implement Sema for comptime shl_exact", .{}), - .shl_sat => return sema.mod.fail(&block.base, lhs_src, "TODO implement Sema for comptime shl_sat", .{}), + .shl_exact => return sema.fail(block, lhs_src, "TODO implement Sema for comptime shl_exact", .{}), + .shl_sat => return sema.fail(block, lhs_src, "TODO implement Sema for comptime shl_sat", .{}), .shl => {}, else => unreachable, } @@ -5971,7 +6356,7 @@ fn zirShl( return block.addBinOp(air_tag, lhs, rhs); } -fn zirShr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirShr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -6004,7 +6389,7 @@ fn zirShr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!A fn zirBitwise( sema: *Sema, - block: *Scope.Block, + block: *Block, inst: Zir.Inst.Index, air_tag: Air.Inst.Tag, ) CompileError!Air.Inst.Ref { @@ -6035,14 +6420,14 @@ fn zirBitwise( if (lhs_ty.zigTypeTag() == .Vector and rhs_ty.zigTypeTag() == .Vector) { if (lhs_ty.arrayLen() != rhs_ty.arrayLen()) { - return sema.mod.fail(&block.base, src, "vector length mismatch: {d} and {d}", .{ + return sema.fail(block, src, "vector length mismatch: {d} and {d}", .{ lhs_ty.arrayLen(), rhs_ty.arrayLen(), }); } - return sema.mod.fail(&block.base, src, "TODO implement support for vectors in zirBitwise", .{}); + return sema.fail(block, src, "TODO implement support for vectors in zirBitwise", .{}); } else if (lhs_ty.zigTypeTag() == .Vector or rhs_ty.zigTypeTag() == .Vector) { - return sema.mod.fail(&block.base, src, "mixed scalar and vector operands to binary expression: '{}' and '{}'", .{ + return sema.fail(block, src, "mixed scalar and vector operands to binary expression: '{}' and '{}'", .{ lhs_ty, rhs_ty, }); @@ -6051,7 +6436,7 @@ fn zirBitwise( const is_int = scalar_tag == .Int or scalar_tag == .ComptimeInt; if (!is_int) { - return sema.mod.fail(&block.base, src, "invalid operands to binary bitwise expression: '{s}' and '{s}'", .{ @tagName(lhs_ty.zigTypeTag()), @tagName(rhs_ty.zigTypeTag()) }); + return sema.fail(block, src, "invalid operands to binary bitwise expression: '{s}' and '{s}'", .{ @tagName(lhs_ty.zigTypeTag()), @tagName(rhs_ty.zigTypeTag()) }); } if (try sema.resolveMaybeUndefVal(block, lhs_src, casted_lhs)) |lhs_val| { @@ -6070,15 +6455,15 @@ fn zirBitwise( return block.addBinOp(air_tag, casted_lhs, casted_rhs); } -fn zirBitNot(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); _ = inst; - return sema.mod.fail(&block.base, sema.src, "TODO implement zirBitNot", .{}); + return sema.fail(block, sema.src, "TODO implement zirBitNot", .{}); } -fn zirArrayCat(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -6092,11 +6477,11 @@ fn zirArrayCat(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node }; const lhs_info = getArrayCatInfo(lhs_ty) orelse - return sema.mod.fail(&block.base, lhs_src, "expected array, found '{}'", .{lhs_ty}); + return sema.fail(block, lhs_src, "expected array, found '{}'", .{lhs_ty}); const rhs_info = getArrayCatInfo(rhs_ty) orelse - return sema.mod.fail(&block.base, rhs_src, "expected array, found '{}'", .{rhs_ty}); + return sema.fail(block, rhs_src, "expected array, found '{}'", .{rhs_ty}); if (!lhs_info.elem_type.eql(rhs_info.elem_type)) { - return sema.mod.fail(&block.base, rhs_src, "expected array of type '{}', found '{}'", .{ lhs_info.elem_type, rhs_ty }); + return sema.fail(block, rhs_src, "expected array of type '{}', found '{}'", .{ lhs_info.elem_type, rhs_ty }); } // When there is a sentinel mismatch, no sentinel on the result. The type system @@ -6142,10 +6527,10 @@ fn zirArrayCat(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr else sema.analyzeDeclVal(block, .unneeded, try anon_decl.finish(ty, val)); } else { - return sema.mod.fail(&block.base, lhs_src, "TODO runtime array_cat", .{}); + return sema.fail(block, lhs_src, "TODO runtime array_cat", .{}); } } else { - return sema.mod.fail(&block.base, lhs_src, "TODO runtime array_cat", .{}); + return sema.fail(block, lhs_src, "TODO runtime array_cat", .{}); } } @@ -6162,7 +6547,7 @@ fn getArrayCatInfo(t: Type) ?Type.ArrayInfo { }; } -fn zirArrayMul(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -6176,9 +6561,9 @@ fn zirArrayMul(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr // In `**` rhs has to be comptime-known, but lhs can be runtime-known const tomulby = try sema.resolveInt(block, rhs_src, extra.rhs, Type.initTag(.usize)); const mulinfo = getArrayCatInfo(lhs_ty) orelse - return sema.mod.fail(&block.base, lhs_src, "expected array, found '{}'", .{lhs_ty}); + return sema.fail(block, lhs_src, "expected array, found '{}'", .{lhs_ty}); - const final_len = std.math.mul(u64, mulinfo.len, tomulby) catch return sema.mod.fail(&block.base, rhs_src, "operation results in overflow", .{}); + const final_len = std.math.mul(u64, mulinfo.len, tomulby) catch return sema.fail(block, rhs_src, "operation results in overflow", .{}); if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| { var anon_decl = try block.startAnonDecl(); defer anon_decl.deinit(); @@ -6211,12 +6596,12 @@ fn zirArrayMul(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr return sema.analyzeDeclVal(block, .unneeded, try anon_decl.finish(final_ty, val)); } } - return sema.mod.fail(&block.base, lhs_src, "TODO runtime array_mul", .{}); + return sema.fail(block, lhs_src, "TODO runtime array_mul", .{}); } fn zirNegate( sema: *Sema, - block: *Scope.Block, + block: *Block, inst: Zir.Inst.Index, tag_override: Zir.Inst.Tag, ) CompileError!Air.Inst.Ref { @@ -6235,7 +6620,7 @@ fn zirNegate( fn zirArithmetic( sema: *Sema, - block: *Scope.Block, + block: *Block, inst: Zir.Inst.Index, zir_tag: Zir.Inst.Tag, ) CompileError!Air.Inst.Ref { @@ -6255,7 +6640,7 @@ fn zirArithmetic( fn zirOverflowArithmetic( sema: *Sema, - block: *Scope.Block, + block: *Block, extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { const tracy = trace(@src()); @@ -6264,12 +6649,12 @@ fn zirOverflowArithmetic( const extra = sema.code.extraData(Zir.Inst.OverflowArithmetic, extended.operand).data; const src: LazySrcLoc = .{ .node_offset = extra.node }; - return sema.mod.fail(&block.base, src, "TODO implement Sema.zirOverflowArithmetic", .{}); + return sema.fail(block, src, "TODO implement Sema.zirOverflowArithmetic", .{}); } fn analyzeArithmetic( sema: *Sema, - block: *Scope.Block, + block: *Block, /// TODO performance investigation: make this comptime? zir_tag: Zir.Inst.Tag, lhs: Air.Inst.Ref, @@ -6284,13 +6669,13 @@ fn analyzeArithmetic( const rhs_zig_ty_tag = try rhs_ty.zigTypeTagOrPoison(); if (lhs_zig_ty_tag == .Vector and rhs_zig_ty_tag == .Vector) { if (lhs_ty.arrayLen() != rhs_ty.arrayLen()) { - return sema.mod.fail(&block.base, src, "vector length mismatch: {d} and {d}", .{ + return sema.fail(block, src, "vector length mismatch: {d} and {d}", .{ lhs_ty.arrayLen(), rhs_ty.arrayLen(), }); } - return sema.mod.fail(&block.base, src, "TODO implement support for vectors in Sema.analyzeArithmetic", .{}); + return sema.fail(block, src, "TODO implement support for vectors in Sema.analyzeArithmetic", .{}); } else if (lhs_zig_ty_tag == .Vector or rhs_zig_ty_tag == .Vector) { - return sema.mod.fail(&block.base, src, "mixed scalar and vector operands to binary expression: '{}' and '{}'", .{ + return sema.fail(block, src, "mixed scalar and vector operands to binary expression: '{}' and '{}'", .{ lhs_ty, rhs_ty, }); } @@ -6302,8 +6687,8 @@ fn analyzeArithmetic( const air_tag: Air.Inst.Tag = switch (zir_tag) { .add => .ptr_add, .sub => .ptr_sub, - else => return sema.mod.fail( - &block.base, + else => return sema.fail( + block, op_src, "invalid pointer arithmetic operand: '{s}''", .{@tagName(zir_tag)}, @@ -6317,7 +6702,7 @@ fn analyzeArithmetic( if (try sema.resolveDefinedValue(block, rhs_src, casted_rhs)) |rhs_val| { _ = lhs_val; _ = rhs_val; - return sema.mod.fail(&block.base, src, "TODO implement Sema for comptime pointer arithmetic", .{}); + return sema.fail(block, src, "TODO implement Sema for comptime pointer arithmetic", .{}); } else { break :runtime_src rhs_src; } @@ -6348,7 +6733,7 @@ fn analyzeArithmetic( const is_float = scalar_tag == .Float or scalar_tag == .ComptimeFloat; if (!is_int and !(is_float and floatOpAllowed(zir_tag))) { - return sema.mod.fail(&block.base, src, "invalid operands to binary expression: '{s}' and '{s}'", .{ + return sema.fail(block, src, "invalid operands to binary expression: '{s}' and '{s}'", .{ @tagName(lhs_zig_ty_tag), @tagName(rhs_zig_ty_tag), }); } @@ -6930,7 +7315,7 @@ fn analyzeArithmetic( return block.addBinOp(rs.air_tag, casted_lhs, casted_rhs); } -fn zirLoad(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -6943,7 +7328,7 @@ fn zirLoad(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError! fn zirAsm( sema: *Sema, - block: *Scope.Block, + block: *Block, extended: Zir.Inst.Extended.InstData, inst: Zir.Inst.Index, ) CompileError!Air.Inst.Ref { @@ -6958,7 +7343,7 @@ fn zirAsm( const clobbers_len = @truncate(u5, extended.small >> 10); if (outputs_len > 1) { - return sema.mod.fail(&block.base, src, "TODO implement Sema for asm with more than 1 output", .{}); + return sema.fail(block, src, "TODO implement Sema for asm with more than 1 output", .{}); } var extra_i = extra.end; @@ -6973,7 +7358,7 @@ fn zirAsm( output_type_bits >>= 1; if (!is_type) { - return sema.mod.fail(&block.base, src, "TODO implement Sema for asm with non `->` output", .{}); + return sema.fail(block, src, "TODO implement Sema for asm with non `->` output", .{}); } const constraint = sema.code.nullTerminatedString(output.data.constraint); @@ -7022,7 +7407,7 @@ fn zirAsm( /// Only called for equality operators. See also `zirCmp`. fn zirCmpEq( sema: *Sema, - block: *Scope.Block, + block: *Block, inst: Zir.Inst.Index, op: std.math.CompareOperator, air_tag: Air.Inst.Tag, @@ -7030,7 +7415,6 @@ fn zirCmpEq( const tracy = trace(@src()); defer tracy.end(); - const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const src: LazySrcLoc = inst_data.src(); @@ -7059,11 +7443,11 @@ fn zirCmpEq( return sema.analyzeIsNull(block, src, opt_operand, op == .neq); } if (((lhs_ty_tag == .Null and rhs_ty.isCPtr()) or (rhs_ty_tag == .Null and lhs_ty.isCPtr()))) { - return mod.fail(&block.base, src, "TODO implement C pointer cmp", .{}); + return sema.fail(block, src, "TODO implement C pointer cmp", .{}); } if (lhs_ty_tag == .Null or rhs_ty_tag == .Null) { const non_null_type = if (lhs_ty_tag == .Null) rhs_ty else lhs_ty; - return mod.fail(&block.base, src, "comparison of '{}' with null", .{non_null_type}); + return sema.fail(block, src, "comparison of '{}' with null", .{non_null_type}); } if (lhs_ty_tag == .EnumLiteral and rhs_ty_tag == .Union) { return sema.analyzeCmpUnionTag(block, rhs, rhs_src, lhs, lhs_src, op); @@ -7112,7 +7496,7 @@ fn zirCmpEq( fn analyzeCmpUnionTag( sema: *Sema, - block: *Scope.Block, + block: *Block, un: Air.Inst.Ref, un_src: LazySrcLoc, tag: Air.Inst.Ref, @@ -7122,7 +7506,7 @@ fn analyzeCmpUnionTag( const union_ty = sema.typeOf(un); const union_tag_ty = union_ty.unionTagType() orelse { // TODO note at declaration site that says "union foo is not tagged" - return sema.mod.fail(&block.base, un_src, "comparison of union and enum literal is only valid for tagged union types", .{}); + return sema.fail(block, un_src, "comparison of union and enum literal is only valid for tagged union types", .{}); }; // Coerce both the union and the tag to the union's tag type, and then execute the // enum comparison codepath. @@ -7135,7 +7519,7 @@ fn analyzeCmpUnionTag( /// Only called for non-equality operators. See also `zirCmpEq`. fn zirCmp( sema: *Sema, - block: *Scope.Block, + block: *Block, inst: Zir.Inst.Index, op: std.math.CompareOperator, ) CompileError!Air.Inst.Ref { @@ -7154,7 +7538,7 @@ fn zirCmp( fn analyzeCmp( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref, @@ -7174,7 +7558,7 @@ fn analyzeCmp( const instructions = &[_]Air.Inst.Ref{ lhs, rhs }; const resolved_type = try sema.resolvePeerTypes(block, src, instructions, .{ .override = &[_]LazySrcLoc{ lhs_src, rhs_src } }); if (!resolved_type.isSelfComparable(is_equality_cmp)) { - return sema.mod.fail(&block.base, src, "{s} operator not allowed for type '{}'", .{ + return sema.fail(block, src, "{s} operator not allowed for type '{}'", .{ @tagName(op), resolved_type, }); } @@ -7185,7 +7569,7 @@ fn analyzeCmp( fn cmpSelf( sema: *Sema, - block: *Scope.Block, + block: *Block, casted_lhs: Air.Inst.Ref, casted_rhs: Air.Inst.Ref, op: std.math.CompareOperator, @@ -7243,7 +7627,7 @@ fn cmpSelf( /// cmp_neq(x, true ) => not(x) fn runtimeBoolCmp( sema: *Sema, - block: *Scope.Block, + block: *Block, op: std.math.CompareOperator, lhs: Air.Inst.Ref, rhs: bool, @@ -7257,7 +7641,7 @@ fn runtimeBoolCmp( } } -fn zirSizeOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].un_node; const src = inst_data.src(); const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; @@ -7271,7 +7655,7 @@ fn zirSizeOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErro .Null, .BoundFn, .Opaque, - => return sema.mod.fail(&block.base, src, "no size available for type '{}'", .{operand_ty}), + => return sema.fail(block, src, "no size available for type '{}'", .{operand_ty}), .Type, .EnumLiteral, .ComptimeFloat, @@ -7298,7 +7682,7 @@ fn zirSizeOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErro return sema.addIntUnsigned(Type.initTag(.comptime_int), abi_size); } -fn zirBitSizeOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirBitSizeOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].un_node; const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const operand_ty = try sema.resolveType(block, operand_src, inst_data.operand); @@ -7309,17 +7693,17 @@ fn zirBitSizeOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileE fn zirThis( sema: *Sema, - block: *Scope.Block, + block: *Block, extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { - const this_decl = block.base.namespace().getDecl(); + const this_decl = block.namespace.getDecl(); const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) }; return sema.analyzeDeclVal(block, src, this_decl); } fn zirClosureCapture( sema: *Sema, - block: *Scope.Block, + block: *Block, inst: Zir.Inst.Index, ) CompileError!void { // TODO: Compile error when closed over values are modified @@ -7333,7 +7717,7 @@ fn zirClosureCapture( fn zirClosureGet( sema: *Sema, - block: *Scope.Block, + block: *Block, inst: Zir.Inst.Index, ) CompileError!Air.Inst.Ref { // TODO CLOSURE: Test this with inline functions @@ -7355,23 +7739,23 @@ fn zirClosureGet( fn zirRetAddr( sema: *Sema, - block: *Scope.Block, + block: *Block, extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) }; - return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirRetAddr", .{}); + return sema.fail(block, src, "TODO: implement Sema.zirRetAddr", .{}); } fn zirBuiltinSrc( sema: *Sema, - block: *Scope.Block, + block: *Block, extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) }; - return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirBuiltinSrc", .{}); + return sema.fail(block, src, "TODO: implement Sema.zirBuiltinSrc", .{}); } -fn zirTypeInfo(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].un_node; const src = inst_data.src(); const ty = try sema.resolveType(block, src, inst_data.operand); @@ -7570,13 +7954,13 @@ fn zirTypeInfo(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr }), ); }, - else => |t| return sema.mod.fail(&block.base, src, "TODO: implement zirTypeInfo for {s}", .{ + else => |t| return sema.fail(block, src, "TODO: implement zirTypeInfo for {s}", .{ @tagName(t), }), } } -fn zirTypeof(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirTypeof(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { _ = block; const zir_datas = sema.code.instructions.items(.data); const inst_data = zir_datas[inst].un_node; @@ -7585,7 +7969,7 @@ fn zirTypeof(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErro return sema.addType(operand_ty); } -fn zirTypeofElem(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirTypeofElem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { _ = block; const inst_data = sema.code.instructions.items(.data)[inst].un_node; const operand_ptr = sema.resolveInst(inst_data.operand); @@ -7593,7 +7977,7 @@ fn zirTypeofElem(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compile return sema.addType(elem_ty); } -fn zirTypeofLog2IntType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirTypeofLog2IntType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].un_node; const src = inst_data.src(); const operand = sema.resolveInst(inst_data.operand); @@ -7601,14 +7985,14 @@ fn zirTypeofLog2IntType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) return sema.log2IntType(block, operand_ty, src); } -fn zirLog2IntType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirLog2IntType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].un_node; const src = inst_data.src(); const operand = try sema.resolveType(block, src, inst_data.operand); return sema.log2IntType(block, operand, src); } -fn log2IntType(sema: *Sema, block: *Scope.Block, operand: Type, src: LazySrcLoc) CompileError!Air.Inst.Ref { +fn log2IntType(sema: *Sema, block: *Block, operand: Type, src: LazySrcLoc) CompileError!Air.Inst.Ref { switch (operand.zigTypeTag()) { .ComptimeInt => return Air.Inst.Ref.comptime_int_type, .Int => { @@ -7620,8 +8004,8 @@ fn log2IntType(sema: *Sema, block: *Scope.Block, operand: Type, src: LazySrcLoc) const res = try Module.makeIntType(sema.arena, .unsigned, count); return sema.addType(res); }, - else => return sema.mod.fail( - &block.base, + else => return sema.fail( + block, src, "bit shifting operation expected integer type, found '{}'", .{operand}, @@ -7631,7 +8015,7 @@ fn log2IntType(sema: *Sema, block: *Scope.Block, operand: Type, src: LazySrcLoc) fn zirTypeofPeer( sema: *Sema, - block: *Scope.Block, + block: *Block, extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { const tracy = trace(@src()); @@ -7652,7 +8036,7 @@ fn zirTypeofPeer( return sema.addType(result_type); } -fn zirBoolNot(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirBoolNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -7676,7 +8060,7 @@ fn zirBoolNot(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr fn zirBoolBr( sema: *Sema, - parent_block: *Scope.Block, + parent_block: *Block, inst: Zir.Inst.Index, is_bool_or: bool, ) CompileError!Air.Inst.Ref { @@ -7762,7 +8146,7 @@ fn zirBoolBr( fn zirIsNonNull( sema: *Sema, - block: *Scope.Block, + block: *Block, inst: Zir.Inst.Index, ) CompileError!Air.Inst.Ref { const tracy = trace(@src()); @@ -7776,7 +8160,7 @@ fn zirIsNonNull( fn zirIsNonNullPtr( sema: *Sema, - block: *Scope.Block, + block: *Block, inst: Zir.Inst.Index, ) CompileError!Air.Inst.Ref { const tracy = trace(@src()); @@ -7789,7 +8173,7 @@ fn zirIsNonNullPtr( return sema.analyzeIsNull(block, src, loaded, true); } -fn zirIsNonErr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirIsNonErr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -7798,7 +8182,7 @@ fn zirIsNonErr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr return sema.analyzeIsNonErr(block, inst_data.src(), operand); } -fn zirIsNonErrPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirIsNonErrPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -7811,7 +8195,7 @@ fn zirIsNonErrPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compil fn zirCondbr( sema: *Sema, - parent_block: *Scope.Block, + parent_block: *Block, inst: Zir.Inst.Index, ) CompileError!Zir.Inst.Index { const tracy = trace(@src()); @@ -7866,7 +8250,7 @@ fn zirCondbr( return always_noreturn; } -fn zirUnreachable(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index { +fn zirUnreachable(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index { const tracy = trace(@src()); defer tracy.end(); @@ -7885,7 +8269,7 @@ fn zirUnreachable(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compil fn zirRetErrValue( sema: *Sema, - block: *Scope.Block, + block: *Block, inst: Zir.Inst.Index, ) CompileError!Zir.Inst.Index { const inst_data = sema.code.instructions.items(.data)[inst].str_tok; @@ -7909,7 +8293,7 @@ fn zirRetErrValue( fn zirRetCoerce( sema: *Sema, - block: *Scope.Block, + block: *Block, inst: Zir.Inst.Index, ) CompileError!Zir.Inst.Index { const tracy = trace(@src()); @@ -7922,7 +8306,7 @@ fn zirRetCoerce( return sema.analyzeRet(block, operand, src, true); } -fn zirRetNode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index { +fn zirRetNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index { const tracy = trace(@src()); defer tracy.end(); @@ -7937,7 +8321,7 @@ fn zirRetNode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr return sema.analyzeRet(block, operand, src, false); } -fn zirRetLoad(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index { +fn zirRetLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index { const tracy = trace(@src()); defer tracy.end(); @@ -7954,7 +8338,7 @@ fn zirRetLoad(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr fn analyzeRet( sema: *Sema, - block: *Scope.Block, + block: *Block, uncasted_operand: Air.Inst.Ref, src: LazySrcLoc, need_coercion: bool, @@ -7987,7 +8371,7 @@ fn floatOpAllowed(tag: Zir.Inst.Tag) bool { }; } -fn zirPtrTypeSimple(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirPtrTypeSimple(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -8004,7 +8388,7 @@ fn zirPtrTypeSimple(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Comp return sema.addType(ty); } -fn zirPtrType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -8045,7 +8429,7 @@ fn zirPtrType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr } else 0; if (bit_end != 0 and bit_start >= bit_end * 8) - return sema.mod.fail(&block.base, src, "bit offset starts after end of host integer", .{}); + return sema.fail(block, src, "bit offset starts after end of host integer", .{}); const elem_type = try sema.resolveType(block, .unneeded, extra.data.elem_type); @@ -8064,7 +8448,7 @@ fn zirPtrType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr return sema.addType(ty); } -fn zirStructInitEmpty(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirStructInitEmpty(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -8075,14 +8459,13 @@ fn zirStructInitEmpty(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co return sema.addConstant(struct_type, Value.initTag(.empty_struct_value)); } -fn zirUnionInitPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirUnionInitPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirUnionInitPtr", .{}); + return sema.fail(block, src, "TODO: Sema.zirUnionInitPtr", .{}); } -fn zirStructInit(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref: bool) CompileError!Air.Inst.Ref { - const mod = sema.mod; +fn zirStructInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_ref: bool) CompileError!Air.Inst.Ref { const gpa = sema.gpa; const zir_datas = sema.code.instructions.items(.data); const inst_data = zir_datas[inst].pl_node; @@ -8126,12 +8509,12 @@ fn zirStructInit(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref: const other_field_type_data = zir_datas[other_field_type].pl_node; const other_field_src: LazySrcLoc = .{ .node_offset_back2tok = other_field_type_data.src_node }; const msg = msg: { - const msg = try mod.errMsg(&block.base, field_src, "duplicate field", .{}); + const msg = try sema.errMsg(block, field_src, "duplicate field", .{}); errdefer msg.destroy(gpa); - try mod.errNote(&block.base, other_field_src, msg, "other field here", .{}); + try sema.errNote(block, other_field_src, msg, "other field here", .{}); break :msg msg; }; - return mod.failWithOwnedErrorMsg(&block.base, msg); + return sema.failWithOwnedErrorMsg(msg); } found_fields[field_index] = item.data.field_type; field_inits[field_index] = sema.resolveInst(item.data.init); @@ -8149,9 +8532,9 @@ fn zirStructInit(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref: const template = "missing struct field: {s}"; const args = .{field_name}; if (root_msg) |msg| { - try mod.errNote(&block.base, src, msg, template, args); + try sema.errNote(block, src, msg, template, args); } else { - root_msg = try mod.errMsg(&block.base, src, template, args); + root_msg = try sema.errMsg(block, src, template, args); } } else { field_inits[i] = try sema.addConstant(field.ty, field.default_val); @@ -8160,17 +8543,17 @@ fn zirStructInit(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref: if (root_msg) |msg| { const fqn = try struct_obj.getFullyQualifiedName(gpa); defer gpa.free(fqn); - try mod.errNoteNonLazy( + try sema.mod.errNoteNonLazy( struct_obj.srcLoc(), msg, "struct '{s}' declared here", .{fqn}, ); - return mod.failWithOwnedErrorMsg(&block.base, msg); + return sema.failWithOwnedErrorMsg(msg); } if (is_ref) { - return mod.fail(&block.base, src, "TODO: Sema.zirStructInit is_ref=true", .{}); + return sema.fail(block, src, "TODO: Sema.zirStructInit is_ref=true", .{}); } const is_comptime = for (field_inits) |field_init| { @@ -8187,12 +8570,12 @@ fn zirStructInit(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref: return sema.addConstant(resolved_ty, try Value.Tag.@"struct".create(sema.arena, values)); } - return mod.fail(&block.base, src, "TODO: Sema.zirStructInit for runtime-known struct values", .{}); + return sema.fail(block, src, "TODO: Sema.zirStructInit for runtime-known struct values", .{}); } else if (resolved_ty.cast(Type.Payload.Union)) |union_payload| { const union_obj = union_payload.data; if (extra.data.fields_len != 1) { - return sema.mod.fail(&block.base, src, "union initialization expects exactly one field", .{}); + return sema.fail(block, src, "union initialization expects exactly one field", .{}); } const item = sema.code.extraData(Zir.Inst.StructInit.Item, extra.end); @@ -8205,7 +8588,7 @@ fn zirStructInit(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref: return sema.failWithBadUnionFieldAccess(block, union_obj, field_src, field_name); if (is_ref) { - return mod.fail(&block.base, src, "TODO: Sema.zirStructInit is_ref=true union", .{}); + return sema.fail(block, src, "TODO: Sema.zirStructInit is_ref=true union", .{}); } const init_inst = sema.resolveInst(item.data.init); @@ -8218,20 +8601,20 @@ fn zirStructInit(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref: }), ); } - return mod.fail(&block.base, src, "TODO: Sema.zirStructInit for runtime-known union values", .{}); + return sema.fail(block, src, "TODO: Sema.zirStructInit for runtime-known union values", .{}); } unreachable; } -fn zirStructInitAnon(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref: bool) CompileError!Air.Inst.Ref { +fn zirStructInitAnon(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_ref: bool) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); _ = is_ref; - return sema.mod.fail(&block.base, src, "TODO: Sema.zirStructInitAnon", .{}); + return sema.fail(block, src, "TODO: Sema.zirStructInitAnon", .{}); } -fn zirArrayInit(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref: bool) CompileError!Air.Inst.Ref { +fn zirArrayInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_ref: bool) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); @@ -8249,10 +8632,13 @@ fn zirArrayInit(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref: var anon_decl = try block.startAnonDecl(); defer anon_decl.deinit(); assert(!(resolved_args.len == 0)); - const final_ty = try Type.Tag.array.create(anon_decl.arena(), .{ .len = resolved_args.len, .elem_type = sema.typeOf(resolved_args[0]) }); + const final_ty = try Type.Tag.array.create(anon_decl.arena(), .{ + .len = resolved_args.len, + .elem_type = try sema.typeOf(resolved_args[0]).copy(anon_decl.arena()), + }); const buf = try anon_decl.arena().alloc(Value, resolved_args.len); for (resolved_args) |arg, i| { - buf[i] = (try sema.resolveMaybeUndefVal(block, src, arg)).?; + buf[i] = try (try sema.resolveMaybeUndefVal(block, src, arg)).?.copy(anon_decl.arena()); } const val = try Value.Tag.array.create(anon_decl.arena(), buf); @@ -8280,21 +8666,21 @@ fn zirArrayInit(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref: try sema.analyzeLoad(block, .unneeded, alloc, .unneeded); } -fn zirArrayInitAnon(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index, is_ref: bool) CompileError!Air.Inst.Ref { +fn zirArrayInitAnon(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_ref: bool) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); _ = is_ref; - return sema.mod.fail(&block.base, src, "TODO: Sema.zirArrayInitAnon", .{}); + return sema.fail(block, src, "TODO: Sema.zirArrayInitAnon", .{}); } -fn zirFieldTypeRef(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirFieldTypeRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirFieldTypeRef", .{}); + return sema.fail(block, src, "TODO: Sema.zirFieldTypeRef", .{}); } -fn zirFieldType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const extra = sema.code.extraData(Zir.Inst.FieldType, inst_data.payload_index).data; const src = inst_data.src(); @@ -8314,7 +8700,7 @@ fn zirFieldType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileE return sema.failWithBadUnionFieldAccess(block, union_obj, src, field_name); return sema.addType(field.ty); }, - else => return sema.mod.fail(&block.base, src, "expected struct or union; found '{}'", .{ + else => return sema.fail(block, src, "expected struct or union; found '{}'", .{ resolved_ty, }), } @@ -8322,32 +8708,32 @@ fn zirFieldType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileE fn zirErrorReturnTrace( sema: *Sema, - block: *Scope.Block, + block: *Block, extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) }; - return sema.mod.fail(&block.base, src, "TODO: Sema.zirErrorReturnTrace", .{}); + return sema.fail(block, src, "TODO: Sema.zirErrorReturnTrace", .{}); } fn zirFrame( sema: *Sema, - block: *Scope.Block, + block: *Block, extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) }; - return sema.mod.fail(&block.base, src, "TODO: Sema.zirFrame", .{}); + return sema.fail(block, src, "TODO: Sema.zirFrame", .{}); } fn zirFrameAddress( sema: *Sema, - block: *Scope.Block, + block: *Block, extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) }; - return sema.mod.fail(&block.base, src, "TODO: Sema.zirFrameAddress", .{}); + return sema.fail(block, src, "TODO: Sema.zirFrameAddress", .{}); } -fn zirAlignOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].un_node; const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const ty = try sema.resolveType(block, operand_src, inst_data.operand); @@ -8356,7 +8742,7 @@ fn zirAlignOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr return sema.addIntUnsigned(Type.comptime_int, abi_align); } -fn zirBoolToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirBoolToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].un_node; const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const operand = sema.resolveInst(inst_data.operand); @@ -8368,31 +8754,31 @@ fn zirBoolToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileE return block.addUnOp(.bool_to_int, operand); } -fn zirEmbedFile(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirEmbedFile(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].un_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirEmbedFile", .{}); + return sema.fail(block, src, "TODO: Sema.zirEmbedFile", .{}); } -fn zirErrorName(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].un_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirErrorName", .{}); + return sema.fail(block, src, "TODO: Sema.zirErrorName", .{}); } -fn zirUnaryMath(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirUnaryMath(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].un_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirUnaryMath", .{}); + return sema.fail(block, src, "TODO: Sema.zirUnaryMath", .{}); } -fn zirTagName(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirTagName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].un_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirTagName", .{}); + return sema.fail(block, src, "TODO: Sema.zirTagName", .{}); } -fn zirReify(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].un_node; const src = inst_data.src(); const type_info_ty = try sema.getBuiltinType(block, src, "TypeInfo"); @@ -8422,55 +8808,55 @@ fn zirReify(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError }; return sema.addType(ty); }, - .Float => return sema.mod.fail(&block.base, src, "TODO: Sema.zirReify for Float", .{}), - .Pointer => return sema.mod.fail(&block.base, src, "TODO: Sema.zirReify for Pointer", .{}), - .Array => return sema.mod.fail(&block.base, src, "TODO: Sema.zirReify for Array", .{}), - .Struct => return sema.mod.fail(&block.base, src, "TODO: Sema.zirReify for Struct", .{}), + .Float => return sema.fail(block, src, "TODO: Sema.zirReify for Float", .{}), + .Pointer => return sema.fail(block, src, "TODO: Sema.zirReify for Pointer", .{}), + .Array => return sema.fail(block, src, "TODO: Sema.zirReify for Array", .{}), + .Struct => return sema.fail(block, src, "TODO: Sema.zirReify for Struct", .{}), .ComptimeFloat => return Air.Inst.Ref.comptime_float_type, .ComptimeInt => return Air.Inst.Ref.comptime_int_type, .Undefined => return Air.Inst.Ref.undefined_type, .Null => return Air.Inst.Ref.null_type, - .Optional => return sema.mod.fail(&block.base, src, "TODO: Sema.zirReify for Optional", .{}), - .ErrorUnion => return sema.mod.fail(&block.base, src, "TODO: Sema.zirReify for ErrorUnion", .{}), - .ErrorSet => return sema.mod.fail(&block.base, src, "TODO: Sema.zirReify for ErrorSet", .{}), - .Enum => return sema.mod.fail(&block.base, src, "TODO: Sema.zirReify for Enum", .{}), - .Union => return sema.mod.fail(&block.base, src, "TODO: Sema.zirReify for Union", .{}), - .Fn => return sema.mod.fail(&block.base, src, "TODO: Sema.zirReify for Fn", .{}), + .Optional => return sema.fail(block, src, "TODO: Sema.zirReify for Optional", .{}), + .ErrorUnion => return sema.fail(block, src, "TODO: Sema.zirReify for ErrorUnion", .{}), + .ErrorSet => return sema.fail(block, src, "TODO: Sema.zirReify for ErrorSet", .{}), + .Enum => return sema.fail(block, src, "TODO: Sema.zirReify for Enum", .{}), + .Union => return sema.fail(block, src, "TODO: Sema.zirReify for Union", .{}), + .Fn => return sema.fail(block, src, "TODO: Sema.zirReify for Fn", .{}), .BoundFn => @panic("TODO delete BoundFn from the language"), - .Opaque => return sema.mod.fail(&block.base, src, "TODO: Sema.zirReify for Opaque", .{}), - .Frame => return sema.mod.fail(&block.base, src, "TODO: Sema.zirReify for Frame", .{}), + .Opaque => return sema.fail(block, src, "TODO: Sema.zirReify for Opaque", .{}), + .Frame => return sema.fail(block, src, "TODO: Sema.zirReify for Frame", .{}), .AnyFrame => return Air.Inst.Ref.anyframe_type, - .Vector => return sema.mod.fail(&block.base, src, "TODO: Sema.zirReify for Vector", .{}), + .Vector => return sema.fail(block, src, "TODO: Sema.zirReify for Vector", .{}), .EnumLiteral => return Air.Inst.Ref.enum_literal_type, } } -fn zirTypeName(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].un_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirTypeName", .{}); + return sema.fail(block, src, "TODO: Sema.zirTypeName", .{}); } -fn zirFrameType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirFrameType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].un_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirFrameType", .{}); + return sema.fail(block, src, "TODO: Sema.zirFrameType", .{}); } -fn zirFrameSize(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirFrameSize(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].un_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirFrameSize", .{}); + return sema.fail(block, src, "TODO: Sema.zirFrameSize", .{}); } -fn zirFloatToInt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirFloatToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); // TODO don't forget the safety check! - return sema.mod.fail(&block.base, src, "TODO: Sema.zirFloatToInt", .{}); + return sema.fail(block, src, "TODO: Sema.zirFloatToInt", .{}); } -fn zirIntToFloat(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirIntToFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; @@ -8492,7 +8878,7 @@ fn zirIntToFloat(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compile return block.addTyOp(.int_to_float, dest_ty, operand); } -fn zirIntToPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); @@ -8505,15 +8891,15 @@ fn zirIntToPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr const type_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const type_res = try sema.resolveType(block, src, extra.lhs); if (type_res.zigTypeTag() != .Pointer) - return sema.mod.fail(&block.base, type_src, "expected pointer, found '{}'", .{type_res}); + return sema.fail(block, type_src, "expected pointer, found '{}'", .{type_res}); const ptr_align = type_res.ptrAlignment(sema.mod.getTarget()); if (try sema.resolveDefinedValue(block, operand_src, operand_coerced)) |val| { const addr = val.toUnsignedInt(); if (!type_res.isAllowzeroPtr() and addr == 0) - return sema.mod.fail(&block.base, operand_src, "pointer type '{}' does not allow address zero", .{type_res}); + return sema.fail(block, operand_src, "pointer type '{}' does not allow address zero", .{type_res}); if (addr != 0 and addr % ptr_align != 0) - return sema.mod.fail(&block.base, operand_src, "pointer type '{}' requires aligned address", .{type_res}); + return sema.fail(block, operand_src, "pointer type '{}' requires aligned address", .{type_res}); const val_payload = try sema.arena.create(Value.Payload.U64); val_payload.* = .{ @@ -8548,13 +8934,13 @@ fn zirIntToPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr return block.addTyOp(.bitcast, type_res, operand_coerced); } -fn zirErrSetCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirErrSetCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirErrSetCast", .{}); + return sema.fail(block, src, "TODO: Sema.zirErrSetCast", .{}); } -fn zirPtrCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; @@ -8563,12 +8949,12 @@ fn zirPtrCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr const operand = sema.resolveInst(extra.rhs); const operand_ty = sema.typeOf(operand); if (operand_ty.zigTypeTag() != .Pointer) { - return sema.mod.fail(&block.base, operand_src, "expected pointer, found {s} type '{}'", .{ + return sema.fail(block, operand_src, "expected pointer, found {s} type '{}'", .{ @tagName(operand_ty.zigTypeTag()), operand_ty, }); } if (dest_ty.zigTypeTag() != .Pointer) { - return sema.mod.fail(&block.base, dest_ty_src, "expected pointer, found {s} type '{}'", .{ + return sema.fail(block, dest_ty_src, "expected pointer, found {s} type '{}'", .{ @tagName(dest_ty.zigTypeTag()), dest_ty, }); } @@ -8578,7 +8964,7 @@ fn zirPtrCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr return block.addTyOp(.bitcast, dest_ty, operand); } -fn zirTruncate(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; @@ -8587,7 +8973,6 @@ fn zirTruncate(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs); const operand = sema.resolveInst(extra.rhs); const operand_ty = sema.typeOf(operand); - const mod = sema.mod; const dest_is_comptime_int = try sema.checkIntType(block, dest_ty_src, dest_ty); const src_is_comptime_int = try sema.checkIntType(block, operand_src, operand_ty); @@ -8595,7 +8980,7 @@ fn zirTruncate(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr return sema.coerce(block, dest_ty, operand, operand_src); } - const target = mod.getTarget(); + const target = sema.mod.getTarget(); const src_info = operand_ty.intInfo(target); const dest_info = dest_ty.intInfo(target); @@ -8605,28 +8990,28 @@ fn zirTruncate(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr if (!src_is_comptime_int) { if (src_info.signedness != dest_info.signedness) { - return mod.fail(&block.base, operand_src, "expected {s} integer type, found '{}'", .{ + return sema.fail(block, operand_src, "expected {s} integer type, found '{}'", .{ @tagName(dest_info.signedness), operand_ty, }); } if (src_info.bits > 0 and src_info.bits < dest_info.bits) { const msg = msg: { - const msg = try mod.errMsg( - &block.base, + const msg = try sema.errMsg( + block, src, "destination type '{}' has more bits than source type '{}'", .{ dest_ty, operand_ty }, ); - errdefer msg.destroy(mod.gpa); - try mod.errNote(&block.base, dest_ty_src, msg, "destination type has {d} bits", .{ + errdefer msg.destroy(sema.gpa); + try sema.errNote(block, dest_ty_src, msg, "destination type has {d} bits", .{ dest_info.bits, }); - try mod.errNote(&block.base, operand_src, msg, "source type has {d} bits", .{ + try sema.errNote(block, operand_src, msg, "source type has {d} bits", .{ src_info.bits, }); break :msg msg; }; - return mod.failWithOwnedErrorMsg(&block.base, msg); + return sema.failWithOwnedErrorMsg(msg); } } @@ -8639,13 +9024,13 @@ fn zirTruncate(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileEr return block.addTyOp(.trunc, dest_ty, operand); } -fn zirAlignCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirAlignCast", .{}); + return sema.fail(block, src, "TODO: Sema.zirAlignCast", .{}); } -fn zirClz(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirClz(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].un_node; const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; @@ -8653,7 +9038,7 @@ fn zirClz(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!A const operand_ty = sema.typeOf(operand); // TODO implement support for vectors if (operand_ty.zigTypeTag() != .Int) { - return sema.mod.fail(&block.base, ty_src, "expected integer type, found '{}'", .{ + return sema.fail(block, ty_src, "expected integer type, found '{}'", .{ operand_ty, }); } @@ -8672,7 +9057,7 @@ fn zirClz(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!A return block.addTyOp(.clz, result_ty, operand); } -fn zirCtz(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirCtz(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].un_node; const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; @@ -8680,7 +9065,7 @@ fn zirCtz(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!A const operand_ty = sema.typeOf(operand); // TODO implement support for vectors if (operand_ty.zigTypeTag() != .Int) { - return sema.mod.fail(&block.base, ty_src, "expected integer type, found '{}'", .{ + return sema.fail(block, ty_src, "expected integer type, found '{}'", .{ operand_ty, }); } @@ -8692,85 +9077,85 @@ fn zirCtz(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!A const runtime_src = if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| { if (val.isUndef()) return sema.addConstUndef(result_ty); - return sema.mod.fail(&block.base, operand_src, "TODO: implement comptime @ctz", .{}); + return sema.fail(block, operand_src, "TODO: implement comptime @ctz", .{}); } else operand_src; try sema.requireRuntimeBlock(block, runtime_src); return block.addTyOp(.ctz, result_ty, operand); } -fn zirPopCount(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirPopCount(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].un_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirPopCount", .{}); + return sema.fail(block, src, "TODO: Sema.zirPopCount", .{}); } -fn zirByteSwap(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].un_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirByteSwap", .{}); + return sema.fail(block, src, "TODO: Sema.zirByteSwap", .{}); } -fn zirBitReverse(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].un_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirBitReverse", .{}); + return sema.fail(block, src, "TODO: Sema.zirBitReverse", .{}); } -fn zirDivExact(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirDivExact", .{}); + return sema.fail(block, src, "TODO: Sema.zirDivExact", .{}); } -fn zirDivFloor(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirDivFloor", .{}); + return sema.fail(block, src, "TODO: Sema.zirDivFloor", .{}); } -fn zirDivTrunc(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirDivTrunc", .{}); + return sema.fail(block, src, "TODO: Sema.zirDivTrunc", .{}); } -fn zirShrExact(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirShrExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirShrExact", .{}); + return sema.fail(block, src, "TODO: Sema.zirShrExact", .{}); } -fn zirBitOffsetOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirBitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirBitOffsetOf", .{}); + return sema.fail(block, src, "TODO: Sema.zirBitOffsetOf", .{}); } -fn zirOffsetOf(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirOffsetOf", .{}); + return sema.fail(block, src, "TODO: Sema.zirOffsetOf", .{}); } /// Returns `true` if the type was a comptime_int. -fn checkIntType(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, ty: Type) CompileError!bool { +fn checkIntType(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!bool { switch (ty.zigTypeTag()) { .ComptimeInt => return true, .Int => return false, - else => return sema.mod.fail(&block.base, src, "expected integer type, found '{}'", .{ty}), + else => return sema.fail(block, src, "expected integer type, found '{}'", .{ty}), } } fn checkFloatType( sema: *Sema, - block: *Scope.Block, + block: *Block, ty_src: LazySrcLoc, ty: Type, ) CompileError!void { switch (ty.zigTypeTag()) { .ComptimeFloat, .Float => {}, - else => return sema.mod.fail(&block.base, ty_src, "expected float type, found '{}'", .{ + else => return sema.fail(block, ty_src, "expected float type, found '{}'", .{ ty, }), } @@ -8778,7 +9163,7 @@ fn checkFloatType( fn checkAtomicOperandType( sema: *Sema, - block: *Scope.Block, + block: *Block, ty_src: LazySrcLoc, ty: Type, ) CompileError!void { @@ -8791,8 +9176,8 @@ fn checkAtomicOperandType( .Float => { const bit_count = ty.floatBits(target); if (bit_count > max_atomic_bits) { - return sema.mod.fail( - &block.base, + return sema.fail( + block, ty_src, "expected {d}-bit float type or smaller; found {d}-bit float type", .{ max_atomic_bits, bit_count }, @@ -8804,8 +9189,8 @@ fn checkAtomicOperandType( else => { if (ty.isPtrAtRuntime()) return; - return sema.mod.fail( - &block.base, + return sema.fail( + block, ty_src, "expected bool, integer, float, enum, or pointer type; found {}", .{ty}, @@ -8814,8 +9199,8 @@ fn checkAtomicOperandType( }; const bit_count = int_ty.intInfo(target).bits; if (bit_count > max_atomic_bits) { - return sema.mod.fail( - &block.base, + return sema.fail( + block, ty_src, "expected {d}-bit integer type or smaller; found {d}-bit integer type", .{ max_atomic_bits, bit_count }, @@ -8825,7 +9210,7 @@ fn checkAtomicOperandType( fn resolveExportOptions( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref, ) CompileError!std.builtin.ExportOptions { @@ -8839,7 +9224,7 @@ fn resolveExportOptions( const linkage_index = struct_obj.fields.getIndex("linkage").?; const section_index = struct_obj.fields.getIndex("section").?; if (!fields[section_index].isNull()) { - return sema.mod.fail(&block.base, src, "TODO: implement exporting with linksection", .{}); + return sema.fail(block, src, "TODO: implement exporting with linksection", .{}); } return std.builtin.ExportOptions{ .name = try fields[name_index].toAllocatedBytes(sema.arena), @@ -8850,7 +9235,7 @@ fn resolveExportOptions( fn resolveAtomicOrder( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref, ) CompileError!std.builtin.AtomicOrder { @@ -8863,7 +9248,7 @@ fn resolveAtomicOrder( fn resolveAtomicRmwOp( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref, ) CompileError!std.builtin.AtomicRmwOp { @@ -8876,11 +9261,10 @@ fn resolveAtomicRmwOp( fn zirCmpxchg( sema: *Sema, - block: *Scope.Block, + block: *Block, inst: Zir.Inst.Index, air_tag: Air.Inst.Tag, ) CompileError!Air.Inst.Ref { - const mod = sema.mod; const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const extra = sema.code.extraData(Zir.Inst.Cmpxchg, inst_data.payload_index).data; const src = inst_data.src(); @@ -8896,8 +9280,8 @@ fn zirCmpxchg( const elem_ty = sema.typeOf(ptr).elemType(); try sema.checkAtomicOperandType(block, elem_ty_src, elem_ty); if (elem_ty.zigTypeTag() == .Float) { - return mod.fail( - &block.base, + return sema.fail( + block, elem_ty_src, "expected bool, integer, enum, or pointer type; found '{}'", .{elem_ty}, @@ -8909,16 +9293,16 @@ fn zirCmpxchg( const failure_order = try sema.resolveAtomicOrder(block, failure_order_src, extra.failure_order); if (@enumToInt(success_order) < @enumToInt(std.builtin.AtomicOrder.Monotonic)) { - return mod.fail(&block.base, success_order_src, "success atomic ordering must be Monotonic or stricter", .{}); + return sema.fail(block, success_order_src, "success atomic ordering must be Monotonic or stricter", .{}); } if (@enumToInt(failure_order) < @enumToInt(std.builtin.AtomicOrder.Monotonic)) { - return mod.fail(&block.base, failure_order_src, "failure atomic ordering must be Monotonic or stricter", .{}); + return sema.fail(block, failure_order_src, "failure atomic ordering must be Monotonic or stricter", .{}); } if (@enumToInt(failure_order) > @enumToInt(success_order)) { - return mod.fail(&block.base, failure_order_src, "failure atomic ordering must be no stricter than success", .{}); + return sema.fail(block, failure_order_src, "failure atomic ordering must be no stricter than success", .{}); } if (failure_order == .Release or failure_order == .AcqRel) { - return mod.fail(&block.base, failure_order_src, "failure atomic ordering must not be Release or AcqRel", .{}); + return sema.fail(block, failure_order_src, "failure atomic ordering must not be Release or AcqRel", .{}); } const result_ty = try Module.optionalType(sema.arena, elem_ty); @@ -8965,31 +9349,31 @@ fn zirCmpxchg( }); } -fn zirSplat(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirSplat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirSplat", .{}); + return sema.fail(block, src, "TODO: Sema.zirSplat", .{}); } -fn zirReduce(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirReduce(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirReduce", .{}); + return sema.fail(block, src, "TODO: Sema.zirReduce", .{}); } -fn zirShuffle(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirShuffle(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirShuffle", .{}); + return sema.fail(block, src, "TODO: Sema.zirShuffle", .{}); } -fn zirSelect(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirSelect(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirSelect", .{}); + return sema.fail(block, src, "TODO: Sema.zirSelect", .{}); } -fn zirAtomicLoad(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirAtomicLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; // zig fmt: off @@ -9004,8 +9388,8 @@ fn zirAtomicLoad(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compile switch (order) { .Release, .AcqRel => { - return sema.mod.fail( - &block.base, + return sema.fail( + block, order_src, "@atomicLoad atomic ordering must not be Release or AcqRel", .{}, @@ -9034,8 +9418,7 @@ fn zirAtomicLoad(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compile }); } -fn zirAtomicRmw(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { - const mod = sema.mod; +fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const extra = sema.code.extraData(Zir.Inst.AtomicRmw, inst_data.payload_index).data; const src = inst_data.src(); @@ -9053,14 +9436,14 @@ fn zirAtomicRmw(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileE switch (operand_ty.zigTypeTag()) { .Enum => if (op != .Xchg) { - return mod.fail(&block.base, op_src, "@atomicRmw with enum only allowed with .Xchg", .{}); + return sema.fail(block, op_src, "@atomicRmw with enum only allowed with .Xchg", .{}); }, .Bool => if (op != .Xchg) { - return mod.fail(&block.base, op_src, "@atomicRmw with bool only allowed with .Xchg", .{}); + return sema.fail(block, op_src, "@atomicRmw with bool only allowed with .Xchg", .{}); }, .Float => switch (op) { .Xchg, .Add, .Sub => {}, - else => return mod.fail(&block.base, op_src, "@atomicRmw with float only allowed with .Xchg, .Add, and .Sub", .{}), + else => return sema.fail(block, op_src, "@atomicRmw with float only allowed with .Xchg, .Add, and .Sub", .{}), }, else => {}, } @@ -9068,7 +9451,7 @@ fn zirAtomicRmw(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileE const order = try sema.resolveAtomicOrder(block, order_src, extra.ordering); if (order == .Unordered) { - return mod.fail(&block.base, order_src, "@atomicRmw atomic ordering must not be Unordered", .{}); + return sema.fail(block, order_src, "@atomicRmw atomic ordering must not be Unordered", .{}); } // special case zero bit types @@ -9113,7 +9496,7 @@ fn zirAtomicRmw(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileE }); } -fn zirAtomicStore(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void { +fn zirAtomicStore(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const extra = sema.code.extraData(Zir.Inst.AtomicStore, inst_data.payload_index).data; const src = inst_data.src(); @@ -9131,8 +9514,8 @@ fn zirAtomicStore(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compil const air_tag: Air.Inst.Tag = switch (order) { .Acquire, .AcqRel => { - return sema.mod.fail( - &block.base, + return sema.fail( + block, order_src, "@atomicStore atomic ordering must not be Acquire or AcqRel", .{}, @@ -9147,37 +9530,37 @@ fn zirAtomicStore(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compil return sema.storePtr2(block, src, ptr, ptr_src, operand, operand_src, air_tag); } -fn zirMulAdd(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirMulAdd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirMulAdd", .{}); + return sema.fail(block, src, "TODO: Sema.zirMulAdd", .{}); } -fn zirBuiltinCall(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirBuiltinCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirBuiltinCall", .{}); + return sema.fail(block, src, "TODO: Sema.zirBuiltinCall", .{}); } -fn zirFieldPtrType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirFieldPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirFieldPtrType", .{}); + return sema.fail(block, src, "TODO: Sema.zirFieldPtrType", .{}); } -fn zirFieldParentPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirFieldParentPtr", .{}); + return sema.fail(block, src, "TODO: Sema.zirFieldParentPtr", .{}); } -fn zirMaximum(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirMaximum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirMaximum", .{}); + return sema.fail(block, src, "TODO: Sema.zirMaximum", .{}); } -fn zirMemcpy(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void { +fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const extra = sema.code.extraData(Zir.Inst.Memcpy, inst_data.payload_index).data; const src = inst_data.src(); @@ -9188,16 +9571,16 @@ fn zirMemcpy(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErro const dest_ptr_ty = sema.typeOf(dest_ptr); if (dest_ptr_ty.zigTypeTag() != .Pointer) { - return sema.mod.fail(&block.base, dest_src, "expected pointer, found '{}'", .{dest_ptr_ty}); + return sema.fail(block, dest_src, "expected pointer, found '{}'", .{dest_ptr_ty}); } if (dest_ptr_ty.isConstPtr()) { - return sema.mod.fail(&block.base, dest_src, "cannot store through const pointer '{}'", .{dest_ptr_ty}); + return sema.fail(block, dest_src, "cannot store through const pointer '{}'", .{dest_ptr_ty}); } const uncasted_src_ptr = sema.resolveInst(extra.source); const uncasted_src_ptr_ty = sema.typeOf(uncasted_src_ptr); if (uncasted_src_ptr_ty.zigTypeTag() != .Pointer) { - return sema.mod.fail(&block.base, src_src, "expected pointer, found '{}'", .{ + return sema.fail(block, src_src, "expected pointer, found '{}'", .{ uncasted_src_ptr_ty, }); } @@ -9224,7 +9607,7 @@ fn zirMemcpy(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErro _ = dest_ptr_val; _ = src_ptr_val; _ = len_val; - return sema.mod.fail(&block.base, src, "TODO: Sema.zirMemcpy at comptime", .{}); + return sema.fail(block, src, "TODO: Sema.zirMemcpy at comptime", .{}); } else break :rs len_src; } else break :rs src_src; } else dest_src; @@ -9242,7 +9625,7 @@ fn zirMemcpy(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErro }); } -fn zirMemset(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!void { +fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const extra = sema.code.extraData(Zir.Inst.Memset, inst_data.payload_index).data; const src = inst_data.src(); @@ -9252,10 +9635,10 @@ fn zirMemset(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErro const dest_ptr = sema.resolveInst(extra.dest); const dest_ptr_ty = sema.typeOf(dest_ptr); if (dest_ptr_ty.zigTypeTag() != .Pointer) { - return sema.mod.fail(&block.base, dest_src, "expected pointer, found '{}'", .{dest_ptr_ty}); + return sema.fail(block, dest_src, "expected pointer, found '{}'", .{dest_ptr_ty}); } if (dest_ptr_ty.isConstPtr()) { - return sema.mod.fail(&block.base, dest_src, "cannot store through const pointer '{}'", .{dest_ptr_ty}); + return sema.fail(block, dest_src, "cannot store through const pointer '{}'", .{dest_ptr_ty}); } const elem_ty = dest_ptr_ty.elemType2(); const value = try sema.coerce(block, elem_ty, sema.resolveInst(extra.byte), value_src); @@ -9270,7 +9653,7 @@ fn zirMemset(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErro _ = ptr_val; _ = len_val; _ = val; - return sema.mod.fail(&block.base, src, "TODO: Sema.zirMemset at comptime", .{}); + return sema.fail(block, src, "TODO: Sema.zirMemset at comptime", .{}); } else break :rs value_src; } else break :rs len_src; } else dest_src; @@ -9288,27 +9671,27 @@ fn zirMemset(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErro }); } -fn zirMinimum(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirMinimum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirMinimum", .{}); + return sema.fail(block, src, "TODO: Sema.zirMinimum", .{}); } -fn zirBuiltinAsyncCall(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirBuiltinAsyncCall(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].pl_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirBuiltinAsyncCall", .{}); + return sema.fail(block, src, "TODO: Sema.zirBuiltinAsyncCall", .{}); } -fn zirResume(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirResume(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const inst_data = sema.code.instructions.items(.data)[inst].un_node; const src = inst_data.src(); - return sema.mod.fail(&block.base, src, "TODO: Sema.zirResume", .{}); + return sema.fail(block, src, "TODO: Sema.zirResume", .{}); } fn zirAwait( sema: *Sema, - block: *Scope.Block, + block: *Block, inst: Zir.Inst.Index, is_nosuspend: bool, ) CompileError!Air.Inst.Ref { @@ -9316,12 +9699,12 @@ fn zirAwait( const src = inst_data.src(); _ = is_nosuspend; - return sema.mod.fail(&block.base, src, "TODO: Sema.zirAwait", .{}); + return sema.fail(block, src, "TODO: Sema.zirAwait", .{}); } fn zirVarExtended( sema: *Sema, - block: *Scope.Block, + block: *Block, extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { const extra = sema.code.extraData(Zir.Inst.ExtendedVar, extended.operand); @@ -9376,7 +9759,7 @@ fn zirVarExtended( if (lib_name != null) { // Look at the sema code for functions which has this logic, it just needs to // be extracted and shared by both var and func - return sema.mod.fail(&block.base, src, "TODO: handle var with lib_name in Sema", .{}); + return sema.fail(block, src, "TODO: handle var with lib_name in Sema", .{}); } const new_var = try sema.gpa.create(Module.Var); @@ -9396,7 +9779,7 @@ fn zirVarExtended( fn zirFuncExtended( sema: *Sema, - block: *Scope.Block, + block: *Block, extended: Zir.Inst.Extended.InstData, inst: Zir.Inst.Index, ) CompileError!Air.Inst.Ref { @@ -9463,7 +9846,7 @@ fn zirFuncExtended( fn zirCUndef( sema: *Sema, - block: *Scope.Block, + block: *Block, extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; @@ -9476,7 +9859,7 @@ fn zirCUndef( fn zirCInclude( sema: *Sema, - block: *Scope.Block, + block: *Block, extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; @@ -9489,7 +9872,7 @@ fn zirCInclude( fn zirCDefine( sema: *Sema, - block: *Scope.Block, + block: *Block, extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; @@ -9507,41 +9890,41 @@ fn zirCDefine( fn zirWasmMemorySize( sema: *Sema, - block: *Scope.Block, + block: *Block, extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; const src: LazySrcLoc = .{ .node_offset = extra.node }; - return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirWasmMemorySize", .{}); + return sema.fail(block, src, "TODO: implement Sema.zirWasmMemorySize", .{}); } fn zirWasmMemoryGrow( sema: *Sema, - block: *Scope.Block, + block: *Block, extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; const src: LazySrcLoc = .{ .node_offset = extra.node }; - return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirWasmMemoryGrow", .{}); + return sema.fail(block, src, "TODO: implement Sema.zirWasmMemoryGrow", .{}); } fn zirBuiltinExtern( sema: *Sema, - block: *Scope.Block, + block: *Block, extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data; const src: LazySrcLoc = .{ .node_offset = extra.node }; - return sema.mod.fail(&block.base, src, "TODO: implement Sema.zirBuiltinExtern", .{}); + return sema.fail(block, src, "TODO: implement Sema.zirBuiltinExtern", .{}); } -fn requireFunctionBlock(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) !void { +fn requireFunctionBlock(sema: *Sema, block: *Block, src: LazySrcLoc) !void { if (sema.func == null) { - return sema.mod.fail(&block.base, src, "instruction illegal outside function body", .{}); + return sema.fail(block, src, "instruction illegal outside function body", .{}); } } -fn requireRuntimeBlock(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) !void { +fn requireRuntimeBlock(sema: *Sema, block: *Block, src: LazySrcLoc) !void { if (block.is_comptime) { return sema.failWithNeededComptime(block, src); } @@ -9551,7 +9934,7 @@ fn requireRuntimeBlock(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) !void /// Emit a compile error if type cannot be used for a runtime variable. fn validateVarType( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, var_ty: Type, is_extern: bool, @@ -9595,7 +9978,7 @@ fn validateVarType( }, } else unreachable; // TODO should not need else unreachable if (!ok) { - return sema.mod.fail(&block.base, src, "variable of type '{}' must be const or comptime", .{var_ty}); + return sema.fail(block, src, "variable of type '{}' must be const or comptime", .{var_ty}); } } @@ -9610,17 +9993,18 @@ pub const PanicId = enum { fn addSafetyCheck( sema: *Sema, - parent_block: *Scope.Block, + parent_block: *Block, ok: Air.Inst.Ref, panic_id: PanicId, ) !void { const gpa = sema.gpa; - var fail_block: Scope.Block = .{ + var fail_block: Block = .{ .parent = parent_block, .sema = sema, - .wip_capture_scope = parent_block.wip_capture_scope, .src_decl = parent_block.src_decl, + .namespace = parent_block.namespace, + .wip_capture_scope = parent_block.wip_capture_scope, .instructions = .{}, .inlining = parent_block.inlining, .is_comptime = parent_block.is_comptime, @@ -9679,7 +10063,7 @@ fn addSafetyCheck( fn panicWithMsg( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, msg_inst: Air.Inst.Ref, ) !Zir.Inst.Index { @@ -9699,7 +10083,7 @@ fn panicWithMsg( const stack_trace_ty = try sema.resolveTypeFields(block, src, unresolved_stack_trace_ty); const ptr_stack_trace_ty = try Type.ptr(arena, .{ .pointee_type = stack_trace_ty, - .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .global_constant), // TODO might need a place that is more dynamic + .@"addrspace" = target_util.defaultAddressSpace(mod.getTarget(), .global_constant), // TODO might need a place that is more dynamic }); const null_stack_trace = try sema.addConstant( try Module.optionalType(arena, ptr_stack_trace_ty), @@ -9713,7 +10097,7 @@ fn panicWithMsg( fn safetyPanic( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, panic_id: PanicId, ) CompileError!Zir.Inst.Index { @@ -9741,17 +10125,17 @@ fn safetyPanic( return sema.panicWithMsg(block, src, casted_msg_inst); } -fn emitBackwardBranch(sema: *Sema, block: *Scope.Block, src: LazySrcLoc) !void { +fn emitBackwardBranch(sema: *Sema, block: *Block, src: LazySrcLoc) !void { sema.branch_count += 1; if (sema.branch_count > sema.branch_quota) { // TODO show the "called from here" stack - return sema.mod.fail(&block.base, src, "evaluation exceeded {d} backwards branches", .{sema.branch_quota}); + return sema.fail(block, src, "evaluation exceeded {d} backwards branches", .{sema.branch_quota}); } } fn fieldVal( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, object: Air.Inst.Ref, field_name: []const u8, @@ -9760,7 +10144,6 @@ fn fieldVal( // When editing this function, note that there is corresponding logic to be edited // in `fieldPtr`. This function takes a value and returns a value. - const mod = sema.mod; const arena = sema.arena; const object_src = src; // TODO better source location const object_ty = sema.typeOf(object); @@ -9773,8 +10156,8 @@ fn fieldVal( try Value.Tag.int_u64.create(arena, object_ty.arrayLen()), ); } else { - return mod.fail( - &block.base, + return sema.fail( + block, field_name_src, "no member named '{s}' in '{}'", .{ field_name, object_ty }, @@ -9788,8 +10171,8 @@ fn fieldVal( const result_ty = object_ty.slicePtrFieldType(buf); if (try sema.resolveMaybeUndefVal(block, object_src, object)) |val| { if (val.isUndef()) return sema.addConstUndef(result_ty); - return mod.fail( - &block.base, + return sema.fail( + block, field_name_src, "TODO implement comptime slice ptr", .{}, @@ -9809,8 +10192,8 @@ fn fieldVal( try sema.requireRuntimeBlock(block, src); return block.addTyOp(.slice_len, result_ty, object); } else { - return mod.fail( - &block.base, + return sema.fail( + block, field_name_src, "no member named '{s}' in '{}'", .{ field_name, object_ty }, @@ -9827,8 +10210,8 @@ fn fieldVal( try Value.Tag.int_u64.create(arena, ptr_child.arrayLen()), ); } else { - return mod.fail( - &block.base, + return sema.fail( + block, field_name_src, "no member named '{s}' in '{}'", .{ field_name, object_ty }, @@ -9865,10 +10248,10 @@ fn fieldVal( break :blk name; } } - return mod.fail(&block.base, src, "no error named '{s}' in '{}'", .{ + return sema.fail(block, src, "no error named '{s}' in '{}'", .{ field_name, child_type, }); - } else (try mod.getErrorValue(field_name)).key; + } else (try sema.mod.getErrorValue(field_name)).key; return sema.addConstant( try child_type.copy(arena), @@ -9888,7 +10271,7 @@ fn fieldVal( .Union => "union", else => unreachable, }; - return mod.fail(&block.base, src, "{s} '{}' has no member named '{s}'", .{ + return sema.fail(block, src, "{s} '{}' has no member named '{s}'", .{ kw_name, child_type, field_name, }); }, @@ -9900,14 +10283,14 @@ fn fieldVal( } const field_index = child_type.enumFieldIndex(field_name) orelse { const msg = msg: { - const msg = try mod.errMsg( - &block.base, + const msg = try sema.errMsg( + block, src, "enum '{}' has no member named '{s}'", .{ child_type, field_name }, ); errdefer msg.destroy(sema.gpa); - try mod.errNoteNonLazy( + try sema.mod.errNoteNonLazy( child_type.declSrcLoc(), msg, "enum declared here", @@ -9915,25 +10298,25 @@ fn fieldVal( ); break :msg msg; }; - return mod.failWithOwnedErrorMsg(&block.base, msg); + return sema.failWithOwnedErrorMsg(msg); }; const field_index_u32 = @intCast(u32, field_index); const enum_val = try Value.Tag.enum_field_index.create(arena, field_index_u32); return sema.addConstant(try child_type.copy(arena), enum_val); }, - else => return mod.fail(&block.base, src, "type '{}' has no members", .{child_type}), + else => return sema.fail(block, src, "type '{}' has no members", .{child_type}), } }, .Struct => return sema.structFieldVal(block, src, object, field_name, field_name_src, object_ty), .Union => return sema.unionFieldVal(block, src, object, field_name, field_name_src, object_ty), else => {}, } - return mod.fail(&block.base, src, "type '{}' does not support field access", .{object_ty}); + return sema.fail(block, src, "type '{}' does not support field access", .{object_ty}); } fn fieldPtr( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, object_ptr: Air.Inst.Ref, field_name: []const u8, @@ -9942,12 +10325,11 @@ fn fieldPtr( // When editing this function, note that there is corresponding logic to be edited // in `fieldVal`. This function takes a pointer and returns a pointer. - const mod = sema.mod; const object_ptr_src = src; // TODO better source location const object_ptr_ty = sema.typeOf(object_ptr); const object_ty = switch (object_ptr_ty.zigTypeTag()) { .Pointer => object_ptr_ty.elemType(), - else => return mod.fail(&block.base, object_ptr_src, "expected pointer, found '{}'", .{object_ptr_ty}), + else => return sema.fail(block, object_ptr_src, "expected pointer, found '{}'", .{object_ptr_ty}), }; switch (object_ty.zigTypeTag()) { .Array => { @@ -9959,8 +10341,8 @@ fn fieldPtr( try Value.Tag.int_u64.create(anon_decl.arena(), object_ty.arrayLen()), )); } else { - return mod.fail( - &block.base, + return sema.fail( + block, field_name_src, "no member named '{s}' in '{}'", .{ field_name, object_ty }, @@ -9977,22 +10359,22 @@ fn fieldPtr( // the runtime value to it, and then return the `alloc`. // In both cases the pointer should be const. if (mem.eql(u8, field_name, "ptr")) { - return mod.fail( - &block.base, + return sema.fail( + block, field_name_src, "TODO: implement reference to 'ptr' field of slice '{}'", .{object_ty}, ); } else if (mem.eql(u8, field_name, "len")) { - return mod.fail( - &block.base, + return sema.fail( + block, field_name_src, "TODO: implement reference to 'len' field of slice '{}'", .{object_ty}, ); } else { - return mod.fail( - &block.base, + return sema.fail( + block, field_name_src, "no member named '{s}' in '{}'", .{ field_name, object_ty }, @@ -10011,8 +10393,8 @@ fn fieldPtr( try Value.Tag.int_u64.create(anon_decl.arena(), ptr_child.arrayLen()), )); } else { - return mod.fail( - &block.base, + return sema.fail( + block, field_name_src, "no member named '{s}' in '{}'", .{ field_name, object_ty }, @@ -10051,10 +10433,10 @@ fn fieldPtr( break :blk name; } } - return mod.fail(&block.base, src, "no error named '{s}' in '{}'", .{ + return sema.fail(block, src, "no error named '{s}' in '{}'", .{ field_name, child_type, }); - } else (try mod.getErrorValue(field_name)).key; + } else (try sema.mod.getErrorValue(field_name)).key; var anon_decl = try block.startAnonDecl(); defer anon_decl.deinit(); @@ -10076,7 +10458,7 @@ fn fieldPtr( .Union => "union", else => unreachable, }; - return mod.fail(&block.base, src, "{s} '{}' has no member named '{s}'", .{ + return sema.fail(block, src, "{s} '{}' has no member named '{s}'", .{ kw_name, child_type, field_name, }); }, @@ -10088,14 +10470,14 @@ fn fieldPtr( } const field_index = child_type.enumFieldIndex(field_name) orelse { const msg = msg: { - const msg = try mod.errMsg( - &block.base, + const msg = try sema.errMsg( + block, src, "enum '{}' has no member named '{s}'", .{ child_type, field_name }, ); errdefer msg.destroy(sema.gpa); - try mod.errNoteNonLazy( + try sema.mod.errNoteNonLazy( child_type.declSrcLoc(), msg, "enum declared here", @@ -10103,7 +10485,7 @@ fn fieldPtr( ); break :msg msg; }; - return mod.failWithOwnedErrorMsg(&block.base, msg); + return sema.failWithOwnedErrorMsg(msg); }; const field_index_u32 = @intCast(u32, field_index); var anon_decl = try block.startAnonDecl(); @@ -10113,19 +10495,19 @@ fn fieldPtr( try Value.Tag.enum_field_index.create(anon_decl.arena(), field_index_u32), )); }, - else => return mod.fail(&block.base, src, "type '{}' has no members", .{child_type}), + else => return sema.fail(block, src, "type '{}' has no members", .{child_type}), } }, .Struct => return sema.structFieldPtr(block, src, object_ptr, field_name, field_name_src, object_ty), .Union => return sema.unionFieldPtr(block, src, object_ptr, field_name, field_name_src, object_ty), else => {}, } - return mod.fail(&block.base, src, "type '{}' does not support field access", .{object_ty}); + return sema.fail(block, src, "type '{}' does not support field access", .{object_ty}); } fn fieldCallBind( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, raw_ptr: Air.Inst.Ref, field_name: []const u8, @@ -10134,13 +10516,12 @@ fn fieldCallBind( // When editing this function, note that there is corresponding logic to be edited // in `fieldVal`. This function takes a pointer and returns a pointer. - const mod = sema.mod; const raw_ptr_src = src; // TODO better source location const raw_ptr_ty = sema.typeOf(raw_ptr); const inner_ty = if (raw_ptr_ty.zigTypeTag() == .Pointer and raw_ptr_ty.ptrSize() == .One) raw_ptr_ty.childType() else - return mod.fail(&block.base, raw_ptr_src, "expected single pointer, found '{}'", .{raw_ptr_ty}); + return sema.fail(block, raw_ptr_src, "expected single pointer, found '{}'", .{raw_ptr_ty}); // Optionally dereference a second pointer to get the concrete type. const is_double_ptr = inner_ty.zigTypeTag() == .Pointer and inner_ty.ptrSize() == .One; @@ -10209,7 +10590,7 @@ fn fieldCallBind( }; return sema.analyzeLoad(block, src, ptr_inst, src); }, - .Union => return sema.mod.fail(&block.base, src, "TODO implement field calls on unions", .{}), + .Union => return sema.fail(block, src, "TODO implement field calls on unions", .{}), .Type => { const namespace = try sema.analyzeLoad(block, src, object_ptr, src); return sema.fieldVal(block, src, namespace, field_name, field_name_src); @@ -10262,29 +10643,28 @@ fn fieldCallBind( else => {}, } - return mod.fail(&block.base, src, "type '{}' has no field or member function named '{s}'", .{ concrete_ty, field_name }); + return sema.fail(block, src, "type '{}' has no field or member function named '{s}'", .{ concrete_ty, field_name }); } fn namespaceLookup( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, - namespace: *Scope.Namespace, + namespace: *Namespace, decl_name: []const u8, ) CompileError!?*Decl { - const mod = sema.mod; const gpa = sema.gpa; if (try sema.lookupInNamespace(block, src, namespace, decl_name, true)) |decl| { - if (!decl.is_pub and decl.namespace.file_scope != block.getFileScope()) { + if (!decl.is_pub and decl.getFileScope() != block.getFileScope()) { const msg = msg: { - const msg = try mod.errMsg(&block.base, src, "'{s}' is not marked 'pub'", .{ + const msg = try sema.errMsg(block, src, "'{s}' is not marked 'pub'", .{ decl_name, }); errdefer msg.destroy(gpa); - try mod.errNoteNonLazy(decl.srcLoc(), msg, "declared here", .{}); + try sema.mod.errNoteNonLazy(decl.srcLoc(), msg, "declared here", .{}); break :msg msg; }; - return mod.failWithOwnedErrorMsg(&block.base, msg); + return sema.failWithOwnedErrorMsg(msg); } return decl; } @@ -10293,9 +10673,9 @@ fn namespaceLookup( fn namespaceLookupRef( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, - namespace: *Scope.Namespace, + namespace: *Namespace, decl_name: []const u8, ) CompileError!?Air.Inst.Ref { const decl = (try sema.namespaceLookup(block, src, namespace, decl_name)) orelse return null; @@ -10304,7 +10684,7 @@ fn namespaceLookupRef( fn structFieldPtr( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, struct_ptr: Air.Inst.Ref, field_name: []const u8, @@ -10344,7 +10724,7 @@ fn structFieldPtr( fn structFieldVal( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, struct_byval: Air.Inst.Ref, field_name: []const u8, @@ -10382,7 +10762,7 @@ fn structFieldVal( fn unionFieldPtr( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, union_ptr: Air.Inst.Ref, field_name: []const u8, @@ -10424,7 +10804,7 @@ fn unionFieldPtr( fn unionFieldVal( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, union_byval: Air.Inst.Ref, field_name: []const u8, @@ -10450,12 +10830,12 @@ fn unionFieldVal( } try sema.requireRuntimeBlock(block, src); - return sema.mod.fail(&block.base, src, "TODO implement runtime union field access", .{}); + return sema.fail(block, src, "TODO implement runtime union field access", .{}); } fn elemPtr( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, array_ptr: Air.Inst.Ref, elem_index: Air.Inst.Ref, @@ -10465,10 +10845,10 @@ fn elemPtr( const array_ptr_ty = sema.typeOf(array_ptr); const array_ty = switch (array_ptr_ty.zigTypeTag()) { .Pointer => array_ptr_ty.elemType(), - else => return sema.mod.fail(&block.base, array_ptr_src, "expected pointer, found '{}'", .{array_ptr_ty}), + else => return sema.fail(block, array_ptr_src, "expected pointer, found '{}'", .{array_ptr_ty}), }; if (!array_ty.isIndexable()) { - return sema.mod.fail(&block.base, src, "array access of non-array type '{}'", .{array_ty}); + return sema.fail(block, src, "array access of non-array type '{}'", .{array_ty}); } if (array_ty.isSinglePointer() and array_ty.elemType().zigTypeTag() == .Array) { // we have to deref the ptr operand to get the actual array pointer @@ -10479,12 +10859,12 @@ fn elemPtr( return sema.elemPtrArray(block, src, array_ptr, elem_index, elem_index_src); } - return sema.mod.fail(&block.base, src, "TODO implement more analyze elemptr", .{}); + return sema.fail(block, src, "TODO implement more analyze elemptr", .{}); } fn elemVal( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, array_maybe_ptr: Air.Inst.Ref, elem_index: Air.Inst.Ref, @@ -10497,7 +10877,7 @@ fn elemVal( .Slice => { if (try sema.resolveDefinedValue(block, src, array_maybe_ptr)) |slice_val| { _ = slice_val; - return sema.mod.fail(&block.base, src, "TODO implement Sema for elemVal for comptime known slice", .{}); + return sema.fail(block, src, "TODO implement Sema for elemVal for comptime known slice", .{}); } try sema.requireRuntimeBlock(block, src); return block.addBinOp(.slice_elem_val, array_maybe_ptr, elem_index); @@ -10505,7 +10885,7 @@ fn elemVal( .Many, .C => { if (try sema.resolveDefinedValue(block, src, array_maybe_ptr)) |ptr_val| { _ = ptr_val; - return sema.mod.fail(&block.base, src, "TODO implement Sema for elemVal for comptime known pointer", .{}); + return sema.fail(block, src, "TODO implement Sema for elemVal for comptime known pointer", .{}); } try sema.requireRuntimeBlock(block, src); return block.addBinOp(.ptr_elem_val, array_maybe_ptr, elem_index); @@ -10520,7 +10900,7 @@ fn elemVal( const slice = try sema.analyzeLoad(block, src, array_maybe_ptr, array_ptr_src); if (try sema.resolveDefinedValue(block, src, slice)) |slice_val| { _ = slice_val; - return sema.mod.fail(&block.base, src, "TODO implement Sema for elemVal for comptime known slice", .{}); + return sema.fail(block, src, "TODO implement Sema for elemVal for comptime known slice", .{}); } try sema.requireRuntimeBlock(block, src); return block.addBinOp(.slice_elem_val, slice, elem_index); @@ -10534,7 +10914,7 @@ fn elemVal( const ptr = try sema.analyzeLoad(block, src, array_maybe_ptr, array_ptr_src); if (try sema.resolveDefinedValue(block, src, ptr)) |ptr_val| { _ = ptr_val; - return sema.mod.fail(&block.base, src, "TODO implement Sema for elemVal for comptime known pointer", .{}); + return sema.fail(block, src, "TODO implement Sema for elemVal for comptime known pointer", .{}); } try sema.requireRuntimeBlock(block, src); return block.addBinOp(.ptr_elem_val, ptr, elem_index); @@ -10542,8 +10922,8 @@ fn elemVal( try sema.requireRuntimeBlock(block, src); return block.addBinOp(.ptr_ptr_elem_val, array_maybe_ptr, elem_index); }, - .One => return sema.mod.fail( - &block.base, + .One => return sema.fail( + block, array_ptr_src, "expected pointer, found '{}'", .{indexable_ty.elemType()}, @@ -10553,8 +10933,8 @@ fn elemVal( const ptr = try sema.elemPtr(block, src, array_maybe_ptr, elem_index, elem_index_src); return sema.analyzeLoad(block, src, ptr, elem_index_src); }, - else => return sema.mod.fail( - &block.base, + else => return sema.fail( + block, array_ptr_src, "expected pointer, found '{}'", .{indexable_ty}, @@ -10562,8 +10942,8 @@ fn elemVal( } }, }, - else => return sema.mod.fail( - &block.base, + else => return sema.fail( + block, array_ptr_src, "expected pointer, found '{}'", .{maybe_ptr_ty}, @@ -10573,7 +10953,7 @@ fn elemVal( fn elemPtrArray( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, array_ptr: Air.Inst.Ref, elem_index: Air.Inst.Ref, @@ -10613,7 +10993,7 @@ fn elemPtrArray( fn coerce( sema: *Sema, - block: *Scope.Block, + block: *Block, dest_type_unresolved: Type, inst: Air.Inst.Ref, inst_src: LazySrcLoc, @@ -10631,10 +11011,10 @@ fn coerce( if (dest_type.eql(inst_ty)) return inst; - const mod = sema.mod; const arena = sema.arena; + const target = sema.mod.getTarget(); - const in_memory_result = coerceInMemoryAllowed(dest_type, inst_ty, false, mod.getTarget()); + const in_memory_result = coerceInMemoryAllowed(dest_type, inst_ty, false, target); if (in_memory_result == .ok) { return sema.bitcast(block, dest_type, inst, inst_src); } @@ -10651,8 +11031,6 @@ fn coerce( if (try sema.coerceNum(block, dest_type, inst, inst_src)) |some| return some; - const target = mod.getTarget(); - switch (dest_type.zigTypeTag()) { .Optional => { // null to ?T @@ -10679,7 +11057,7 @@ fn coerce( if (inst_ty.ptrAddressSpace() != dest_type.ptrAddressSpace()) break :src_array_ptr; const dst_elem_type = dest_type.elemType(); - switch (coerceInMemoryAllowed(dst_elem_type, array_elem_type, dest_is_mut, mod.getTarget())) { + switch (coerceInMemoryAllowed(dst_elem_type, array_elem_type, dest_is_mut, target)) { .ok => {}, .no_match => break :src_array_ptr, } @@ -10748,14 +11126,14 @@ fn coerce( const resolved_dest_type = try sema.resolveTypeFields(block, inst_src, dest_type); const field_index = resolved_dest_type.enumFieldIndex(bytes) orelse { const msg = msg: { - const msg = try mod.errMsg( - &block.base, + const msg = try sema.errMsg( + block, inst_src, "enum '{}' has no field named '{s}'", .{ resolved_dest_type, bytes }, ); errdefer msg.destroy(sema.gpa); - try mod.errNoteNonLazy( + try sema.mod.errNoteNonLazy( resolved_dest_type.declSrcLoc(), msg, "enum declared here", @@ -10763,7 +11141,7 @@ fn coerce( ); break :msg msg; }; - return mod.failWithOwnedErrorMsg(&block.base, msg); + return sema.failWithOwnedErrorMsg(msg); }; return sema.addConstant( resolved_dest_type, @@ -10786,7 +11164,7 @@ fn coerce( else => {}, } - return mod.fail(&block.base, inst_src, "expected {}, found {}", .{ dest_type, inst_ty }); + return sema.fail(block, inst_src, "expected {}, found {}", .{ dest_type, inst_ty }); } const InMemoryCoercionResult = enum { @@ -10887,7 +11265,7 @@ fn coerceInMemoryAllowed(dest_type: Type, src_type: Type, dest_is_mut: bool, tar fn coerceNum( sema: *Sema, - block: *Scope.Block, + block: *Block, dest_type: Type, inst: Air.Inst.Ref, inst_src: LazySrcLoc, @@ -10903,13 +11281,13 @@ fn coerceNum( .ComptimeInt, .Int => switch (src_zig_tag) { .Float, .ComptimeFloat => { if (val.floatHasFraction()) { - return sema.mod.fail(&block.base, inst_src, "fractional component prevents float value {} from coercion to type '{}'", .{ val, dest_type }); + return sema.fail(block, inst_src, "fractional component prevents float value {} from coercion to type '{}'", .{ val, dest_type }); } - return sema.mod.fail(&block.base, inst_src, "TODO float to int", .{}); + return sema.fail(block, inst_src, "TODO float to int", .{}); }, .Int, .ComptimeInt => { if (!val.intFitsInType(dest_type, target)) { - return sema.mod.fail(&block.base, inst_src, "type {} cannot represent integer value {}", .{ dest_type, val }); + return sema.fail(block, inst_src, "type {} cannot represent integer value {}", .{ dest_type, val }); } return try sema.addConstant(dest_type, val); }, @@ -10923,8 +11301,8 @@ fn coerceNum( .Float => { const result_val = try val.floatCast(sema.arena, dest_type); if (!val.eql(result_val, dest_type)) { - return sema.mod.fail( - &block.base, + return sema.fail( + block, inst_src, "type {} cannot represent float value {}", .{ dest_type, val }, @@ -10937,8 +11315,8 @@ fn coerceNum( // TODO implement this compile error //const int_again_val = try result_val.floatToInt(sema.arena, inst_ty); //if (!int_again_val.eql(val, inst_ty)) { - // return sema.mod.fail( - // &block.base, + // return sema.fail( + // block, // inst_src, // "type {} cannot represent integer value {}", // .{ dest_type, val }, @@ -10955,13 +11333,13 @@ fn coerceNum( fn coerceVarArgParam( sema: *Sema, - block: *Scope.Block, + block: *Block, inst: Air.Inst.Ref, inst_src: LazySrcLoc, ) !Air.Inst.Ref { const inst_ty = sema.typeOf(inst); switch (inst_ty.zigTypeTag()) { - .ComptimeInt, .ComptimeFloat => return sema.mod.fail(&block.base, inst_src, "integer and float literals in var args function must be casted", .{}), + .ComptimeInt, .ComptimeFloat => return sema.fail(block, inst_src, "integer and float literals in var args function must be casted", .{}), else => {}, } // TODO implement more of this function. @@ -10971,17 +11349,17 @@ fn coerceVarArgParam( // TODO migrate callsites to use storePtr2 instead. fn storePtr( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, ptr: Air.Inst.Ref, uncasted_operand: Air.Inst.Ref, -) !void { +) CompileError!void { return sema.storePtr2(block, src, ptr, src, uncasted_operand, src, .store); } fn storePtr2( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, ptr: Air.Inst.Ref, ptr_src: LazySrcLoc, @@ -10991,7 +11369,7 @@ fn storePtr2( ) !void { const ptr_ty = sema.typeOf(ptr); if (ptr_ty.isConstPtr()) - return sema.mod.fail(&block.base, src, "cannot assign to constant", .{}); + return sema.fail(block, src, "cannot assign to constant", .{}); const elem_ty = ptr_ty.elemType(); const operand = try sema.coerce(block, elem_ty, uncasted_operand, operand_src); @@ -11000,7 +11378,7 @@ fn storePtr2( const runtime_src = if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| rs: { const operand_val = (try sema.resolveMaybeUndefVal(block, operand_src, operand)) orelse - return sema.mod.fail(&block.base, src, "cannot store runtime value in compile time variable", .{}); + return sema.fail(block, src, "cannot store runtime value in compile time variable", .{}); if (ptr_val.tag() == .decl_ref_mut) { try sema.storePtrVal(block, src, ptr_val, operand_val, elem_ty); return; @@ -11018,7 +11396,7 @@ fn storePtr2( /// assert the store must be done at comptime. fn storePtrVal( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, ptr_val: Value, operand_val: Value, @@ -11028,21 +11406,21 @@ fn storePtrVal( if (decl_ref_mut.data.runtime_index < block.runtime_index) { if (block.runtime_cond) |cond_src| { const msg = msg: { - const msg = try sema.mod.errMsg(&block.base, src, "store to comptime variable depends on runtime condition", .{}); + const msg = try sema.errMsg(block, src, "store to comptime variable depends on runtime condition", .{}); errdefer msg.destroy(sema.gpa); - try sema.mod.errNote(&block.base, cond_src, msg, "runtime condition here", .{}); + try sema.errNote(block, cond_src, msg, "runtime condition here", .{}); break :msg msg; }; - return sema.mod.failWithOwnedErrorMsg(&block.base, msg); + return sema.failWithOwnedErrorMsg(msg); } if (block.runtime_loop) |loop_src| { const msg = msg: { - const msg = try sema.mod.errMsg(&block.base, src, "cannot store to comptime variable in non-inline loop", .{}); + const msg = try sema.errMsg(block, src, "cannot store to comptime variable in non-inline loop", .{}); errdefer msg.destroy(sema.gpa); - try sema.mod.errNote(&block.base, loop_src, msg, "non-inline loop here", .{}); + try sema.errNote(block, loop_src, msg, "non-inline loop here", .{}); break :msg msg; }; - return sema.mod.failWithOwnedErrorMsg(&block.base, msg); + return sema.failWithOwnedErrorMsg(msg); } unreachable; } @@ -11063,7 +11441,7 @@ fn storePtrVal( fn bitcast( sema: *Sema, - block: *Scope.Block, + block: *Block, dest_type: Type, inst: Air.Inst.Ref, inst_src: LazySrcLoc, @@ -11079,7 +11457,7 @@ fn bitcast( fn coerceArrayPtrToSlice( sema: *Sema, - block: *Scope.Block, + block: *Block, dest_type: Type, inst: Air.Inst.Ref, inst_src: LazySrcLoc, @@ -11094,7 +11472,7 @@ fn coerceArrayPtrToSlice( fn coerceArrayPtrToMany( sema: *Sema, - block: *Scope.Block, + block: *Block, dest_type: Type, inst: Air.Inst.Ref, inst_src: LazySrcLoc, @@ -11109,7 +11487,7 @@ fn coerceArrayPtrToMany( fn analyzeDeclVal( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, decl: *Decl, ) CompileError!Air.Inst.Ref { @@ -11163,7 +11541,7 @@ fn analyzeDeclRef(sema: *Sema, decl: *Decl) CompileError!Air.Inst.Ref { fn analyzeRef( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref, ) CompileError!Air.Inst.Ref { @@ -11198,7 +11576,7 @@ fn analyzeRef( fn analyzeLoad( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, ptr: Air.Inst.Ref, ptr_src: LazySrcLoc, @@ -11206,7 +11584,7 @@ fn analyzeLoad( const ptr_ty = sema.typeOf(ptr); const elem_ty = switch (ptr_ty.zigTypeTag()) { .Pointer => ptr_ty.elemType(), - else => return sema.mod.fail(&block.base, ptr_src, "expected pointer, found '{}'", .{ptr_ty}), + else => return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty}), }; if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| { if (try ptr_val.pointerDeref(sema.arena)) |elem_val| { @@ -11220,7 +11598,7 @@ fn analyzeLoad( fn analyzeSliceLen( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, slice_inst: Air.Inst.Ref, ) CompileError!Air.Inst.Ref { @@ -11228,7 +11606,7 @@ fn analyzeSliceLen( if (slice_val.isUndef()) { return sema.addConstUndef(Type.initTag(.usize)); } - return sema.mod.fail(&block.base, src, "TODO implement Sema analyzeSliceLen on comptime slice", .{}); + return sema.fail(block, src, "TODO implement Sema analyzeSliceLen on comptime slice", .{}); } try sema.requireRuntimeBlock(block, src); return block.addTyOp(.slice_len, Type.initTag(.usize), slice_inst); @@ -11236,7 +11614,7 @@ fn analyzeSliceLen( fn analyzeIsNull( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref, invert_logic: bool, @@ -11261,7 +11639,7 @@ fn analyzeIsNull( fn analyzeIsNonErr( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref, ) CompileError!Air.Inst.Ref { @@ -11287,7 +11665,7 @@ fn analyzeIsNonErr( fn analyzeSlice( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, array_ptr: Air.Inst.Ref, start: Air.Inst.Ref, @@ -11298,7 +11676,7 @@ fn analyzeSlice( const array_ptr_ty = sema.typeOf(array_ptr); const ptr_child = switch (array_ptr_ty.zigTypeTag()) { .Pointer => array_ptr_ty.elemType(), - else => return sema.mod.fail(&block.base, src, "expected pointer, found '{}'", .{array_ptr_ty}), + else => return sema.fail(block, src, "expected pointer, found '{}'", .{array_ptr_ty}), }; var array_type = ptr_child; @@ -11311,11 +11689,11 @@ fn analyzeSlice( break :blk ptr_child.elemType().elemType(); } - return sema.mod.fail(&block.base, src, "slice of single-item pointer", .{}); + return sema.fail(block, src, "slice of single-item pointer", .{}); } break :blk ptr_child.elemType(); }, - else => return sema.mod.fail(&block.base, src, "slice of non-array type '{}'", .{ptr_child}), + else => return sema.fail(block, src, "slice of non-array type '{}'", .{ptr_child}), }; const slice_sentinel = if (sentinel_opt != .none) blk: { @@ -11331,7 +11709,7 @@ fn analyzeSlice( const start_u64 = start_val.toUnsignedInt(); const end_u64 = end_val.toUnsignedInt(); if (start_u64 > end_u64) { - return sema.mod.fail(&block.base, src, "out of bounds slice", .{}); + return sema.fail(block, src, "out of bounds slice", .{}); } const len = end_u64 - start_u64; @@ -11356,13 +11734,13 @@ fn analyzeSlice( }); _ = return_type; - return sema.mod.fail(&block.base, src, "TODO implement analysis of slice", .{}); + return sema.fail(block, src, "TODO implement analysis of slice", .{}); } /// Asserts that lhs and rhs types are both numeric. fn cmpNumeric( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref, @@ -11381,13 +11759,13 @@ fn cmpNumeric( if (lhs_ty_tag == .Vector and rhs_ty_tag == .Vector) { if (lhs_ty.arrayLen() != rhs_ty.arrayLen()) { - return sema.mod.fail(&block.base, src, "vector length mismatch: {d} and {d}", .{ + return sema.fail(block, src, "vector length mismatch: {d} and {d}", .{ lhs_ty.arrayLen(), rhs_ty.arrayLen(), }); } - return sema.mod.fail(&block.base, src, "TODO implement support for vectors in cmpNumeric", .{}); + return sema.fail(block, src, "TODO implement support for vectors in cmpNumeric", .{}); } else if (lhs_ty_tag == .Vector or rhs_ty_tag == .Vector) { - return sema.mod.fail(&block.base, src, "mixed scalar and vector operands to comparison operator: '{}' and '{}'", .{ + return sema.fail(block, src, "mixed scalar and vector operands to comparison operator: '{}' and '{}'", .{ lhs_ty, rhs_ty, }); } @@ -11537,7 +11915,7 @@ fn cmpNumeric( const dest_type = if (dest_float_type) |ft| ft else blk: { const max_bits = std.math.max(lhs_bits, rhs_bits); const casted_bits = std.math.cast(u16, max_bits) catch |err| switch (err) { - error.Overflow => return sema.mod.fail(&block.base, src, "{d} exceeds maximum integer bit count", .{max_bits}), + error.Overflow => return sema.fail(block, src, "{d} exceeds maximum integer bit count", .{max_bits}), }; const signedness: std.builtin.Signedness = if (dest_int_is_signed) .signed else .unsigned; break :blk try Module.makeIntType(sema.arena, signedness, casted_bits); @@ -11550,7 +11928,7 @@ fn cmpNumeric( fn wrapOptional( sema: *Sema, - block: *Scope.Block, + block: *Block, dest_type: Type, inst: Air.Inst.Ref, inst_src: LazySrcLoc, @@ -11565,7 +11943,7 @@ fn wrapOptional( fn wrapErrorUnion( sema: *Sema, - block: *Scope.Block, + block: *Block, dest_type: Type, inst: Air.Inst.Ref, inst_src: LazySrcLoc, @@ -11584,8 +11962,8 @@ fn wrapErrorUnion( const expected_name = val.castTag(.@"error").?.data.name; const n = dest_err_set_ty.castTag(.error_set_single).?.data; if (!mem.eql(u8, expected_name, n)) { - return sema.mod.fail( - &block.base, + return sema.fail( + block, inst_src, "expected type '{}', found type '{}'", .{ dest_err_set_ty, inst_ty }, @@ -11602,8 +11980,8 @@ fn wrapErrorUnion( if (mem.eql(u8, expected_name, name)) break true; } else false; if (!found) { - return sema.mod.fail( - &block.base, + return sema.fail( + block, inst_src, "expected type '{}', found type '{}'", .{ dest_err_set_ty, inst_ty }, @@ -11614,8 +11992,8 @@ fn wrapErrorUnion( const expected_name = val.castTag(.@"error").?.data.name; const map = &dest_err_set_ty.castTag(.error_set_inferred).?.data.map; if (!map.contains(expected_name)) { - return sema.mod.fail( - &block.base, + return sema.fail( + block, inst_src, "expected type '{}', found type '{}'", .{ dest_err_set_ty, inst_ty }, @@ -11641,7 +12019,7 @@ fn wrapErrorUnion( fn unionToTag( sema: *Sema, - block: *Scope.Block, + block: *Block, dest_type: Type, un: Air.Inst.Ref, un_src: LazySrcLoc, @@ -11655,7 +12033,7 @@ fn unionToTag( fn resolvePeerTypes( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, instructions: []Air.Inst.Ref, candidate_srcs: Module.PeerTypeCandidateSrc, @@ -11750,18 +12128,18 @@ fn resolvePeerTypes( ); const msg = msg: { - const msg = try sema.mod.errMsg(&block.base, src, "incompatible types: '{}' and '{}'", .{ chosen_ty, candidate_ty }); + const msg = try sema.errMsg(block, src, "incompatible types: '{}' and '{}'", .{ chosen_ty, candidate_ty }); errdefer msg.destroy(sema.gpa); if (chosen_src) |src_loc| - try sema.mod.errNote(&block.base, src_loc, msg, "type '{}' here", .{chosen_ty}); + try sema.errNote(block, src_loc, msg, "type '{}' here", .{chosen_ty}); if (candidate_src) |src_loc| - try sema.mod.errNote(&block.base, src_loc, msg, "type '{}' here", .{candidate_ty}); + try sema.errNote(block, src_loc, msg, "type '{}' here", .{candidate_ty}); break :msg msg; }; - return sema.mod.failWithOwnedErrorMsg(&block.base, msg); + return sema.failWithOwnedErrorMsg(msg); } return sema.typeOf(chosen); @@ -11769,7 +12147,7 @@ fn resolvePeerTypes( pub fn resolveTypeLayout( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, ty: Type, ) CompileError!void { @@ -11780,7 +12158,7 @@ pub fn resolveTypeLayout( switch (struct_obj.status) { .none, .have_field_types => {}, .field_types_wip, .layout_wip => { - return sema.mod.fail(&block.base, src, "struct {} depends on itself", .{ty}); + return sema.fail(block, src, "struct {} depends on itself", .{ty}); }, .have_layout => return, } @@ -11794,78 +12172,23 @@ pub fn resolveTypeLayout( } } -pub fn resolvePendingTypes(sema: *Sema, block: *Scope.Block) !void { - for (sema.types_pending_resolution.items) |ty| { - // If an error happens resolving the fields of a struct, it will be marked - // invalid and a proper compile error set up. But we should still look at the - // other types pending resolution. - const src: LazySrcLoc = .{ .node_offset = 0 }; - sema.resolveDeclFields(block, src, ty) catch continue; - } -} - -/// `sema` and `block` are expected to be the same ones used for the `Decl`. -pub fn resolveDeclFields(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, ty: Type) !void { - switch (ty.tag()) { - .@"struct" => { - const struct_obj = ty.castTag(.@"struct").?.data; - if (struct_obj.owner_decl.namespace != sema.owner_decl.namespace) return; - switch (struct_obj.status) { - .none => {}, - .field_types_wip => { - return sema.mod.fail(&block.base, src, "struct {} depends on itself", .{ty}); - }, - .have_field_types, .have_layout, .layout_wip => return, - } - const prev_namespace = sema.namespace; - sema.namespace = &struct_obj.namespace; - defer sema.namespace = prev_namespace; - - const old_src = block.src_decl; - defer block.src_decl = old_src; - block.src_decl = struct_obj.owner_decl; - - struct_obj.status = .field_types_wip; - try sema.analyzeStructFields(block, struct_obj); - struct_obj.status = .have_field_types; - }, - .@"union", .union_tagged => { - const union_obj = ty.cast(Type.Payload.Union).?.data; - if (union_obj.owner_decl.namespace != sema.owner_decl.namespace) return; - switch (union_obj.status) { - .none => {}, - .field_types_wip => { - return sema.mod.fail(&block.base, src, "union {} depends on itself", .{ty}); - }, - .have_field_types, .have_layout, .layout_wip => return, - } - const prev_namespace = sema.namespace; - sema.namespace = &union_obj.namespace; - defer sema.namespace = prev_namespace; - - const old_src = block.src_decl; - defer block.src_decl = old_src; - block.src_decl = union_obj.owner_decl; - - union_obj.status = .field_types_wip; - try sema.analyzeUnionFields(block, union_obj); - union_obj.status = .have_field_types; - }, - else => return, - } -} - -fn resolveTypeFields(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, ty: Type) CompileError!Type { +fn resolveTypeFields(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError!Type { switch (ty.tag()) { .@"struct" => { const struct_obj = ty.castTag(.@"struct").?.data; switch (struct_obj.status) { - .none => unreachable, + .none => {}, .field_types_wip => { - return sema.mod.fail(&block.base, src, "struct {} depends on itself", .{ty}); + return sema.fail(block, src, "struct {} depends on itself", .{ty}); }, .have_field_types, .have_layout, .layout_wip => return ty, } + + struct_obj.status = .field_types_wip; + try semaStructFields(sema.mod, struct_obj); + struct_obj.status = .have_field_types; + + return ty; }, .type_info => return sema.resolveBuiltinTypeFields(block, src, "TypeInfo"), .extern_options => return sema.resolveBuiltinTypeFields(block, src, "ExternOptions"), @@ -11881,12 +12204,18 @@ fn resolveTypeFields(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, ty: Type .@"union", .union_tagged => { const union_obj = ty.cast(Type.Payload.Union).?.data; switch (union_obj.status) { - .none => unreachable, + .none => {}, .field_types_wip => { - return sema.mod.fail(&block.base, src, "union {} depends on itself", .{ty}); + return sema.fail(block, src, "union {} depends on itself", .{ty}); }, .have_field_types, .have_layout, .layout_wip => return ty, } + + union_obj.status = .field_types_wip; + try semaUnionFields(sema.mod, union_obj); + union_obj.status = .have_field_types; + + return ty; }, else => return ty, } @@ -11894,7 +12223,7 @@ fn resolveTypeFields(sema: *Sema, block: *Scope.Block, src: LazySrcLoc, ty: Type fn resolveBuiltinTypeFields( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, name: []const u8, ) CompileError!Type { @@ -11902,16 +12231,16 @@ fn resolveBuiltinTypeFields( return sema.resolveTypeFields(block, src, resolved_ty); } -fn analyzeStructFields( - sema: *Sema, - block: *Scope.Block, +fn semaStructFields( + mod: *Module, struct_obj: *Module.Struct, ) CompileError!void { const tracy = trace(@src()); defer tracy.end(); - const gpa = sema.gpa; - const zir = sema.code; + const gpa = mod.gpa; + const decl = struct_obj.owner_decl; + const zir = struct_obj.namespace.file_scope.zir; const extended = zir.instructions.items(.data)[struct_obj.zir_index].extended; assert(extended.opcode == .struct_decl); const small = @bitCast(Zir.Inst.StructDecl.Small, extended.small); @@ -11950,15 +12279,51 @@ fn analyzeStructFields( } extra_index += body.len; - var decl_arena = struct_obj.owner_decl.value_arena.?.promote(gpa); - defer struct_obj.owner_decl.value_arena.?.* = decl_arena.state; + var decl_arena = decl.value_arena.?.promote(gpa); + defer decl.value_arena.?.* = decl_arena.state; - try struct_obj.fields.ensureTotalCapacity(&decl_arena.allocator, fields_len); + var analysis_arena = std.heap.ArenaAllocator.init(gpa); + defer analysis_arena.deinit(); + + var sema: Sema = .{ + .mod = mod, + .gpa = gpa, + .arena = &analysis_arena.allocator, + .perm_arena = &decl_arena.allocator, + .code = zir, + .owner_decl = decl, + .func = null, + .fn_ret_ty = Type.initTag(.void), + .owner_func = null, + }; + defer sema.deinit(); + + var wip_captures = try WipCaptureScope.init(gpa, &decl_arena.allocator, decl.src_scope); + defer wip_captures.deinit(); + + var block_scope: Block = .{ + .parent = null, + .sema = &sema, + .src_decl = decl, + .namespace = &struct_obj.namespace, + .wip_capture_scope = wip_captures.scope, + .instructions = .{}, + .inlining = null, + .is_comptime = true, + }; + defer { + assert(block_scope.instructions.items.len == 0); + block_scope.params.deinit(gpa); + } if (body.len != 0) { - _ = try sema.analyzeBody(block, body); + _ = try sema.analyzeBody(&block_scope, body); } + try wip_captures.finalize(); + + try struct_obj.fields.ensureTotalCapacity(&decl_arena.allocator, fields_len); + const bits_per_field = 4; const fields_per_u32 = 32 / bits_per_field; const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable; @@ -11995,7 +12360,7 @@ fn analyzeStructFields( // TODO: if we need to report an error here, use a source location // that points to this type expression rather than the struct. // But only resolve the source location if we need to emit a compile error. - try sema.resolveType(block, src, field_type_ref); + try sema.resolveType(&block_scope, src, field_type_ref); const gop = struct_obj.fields.getOrPutAssumeCapacity(field_name); assert(!gop.found_existing); @@ -12013,7 +12378,7 @@ fn analyzeStructFields( // TODO: if we need to report an error here, use a source location // that points to this alignment expression rather than the struct. // But only resolve the source location if we need to emit a compile error. - const abi_align_val = (try sema.resolveInstConst(block, src, align_ref)).val; + const abi_align_val = (try sema.resolveInstConst(&block_scope, src, align_ref)).val; gop.value_ptr.abi_align = try abi_align_val.copy(&decl_arena.allocator); } if (has_default) { @@ -12023,23 +12388,23 @@ fn analyzeStructFields( // TODO: if we need to report an error here, use a source location // that points to this default value expression rather than the struct. // But only resolve the source location if we need to emit a compile error. - const default_val = (try sema.resolveMaybeUndefVal(block, src, default_inst)) orelse - return sema.failWithNeededComptime(block, src); + const default_val = (try sema.resolveMaybeUndefVal(&block_scope, src, default_inst)) orelse + return sema.failWithNeededComptime(&block_scope, src); gop.value_ptr.default_val = try default_val.copy(&decl_arena.allocator); } } } -fn analyzeUnionFields( - sema: *Sema, - block: *Scope.Block, +fn semaUnionFields( + mod: *Module, union_obj: *Module.Union, ) CompileError!void { const tracy = trace(@src()); defer tracy.end(); - const gpa = sema.gpa; - const zir = sema.code; + const gpa = mod.gpa; + const decl = union_obj.owner_decl; + const zir = union_obj.namespace.file_scope.zir; const extended = zir.instructions.items(.data)[union_obj.zir_index].extended; assert(extended.opcode == .union_decl); const small = @bitCast(Zir.Inst.UnionDecl.Small, extended.small); @@ -12087,20 +12452,57 @@ fn analyzeUnionFields( var decl_arena = union_obj.owner_decl.value_arena.?.promote(gpa); defer union_obj.owner_decl.value_arena.?.* = decl_arena.state; - try union_obj.fields.ensureTotalCapacity(&decl_arena.allocator, fields_len); + var analysis_arena = std.heap.ArenaAllocator.init(gpa); + defer analysis_arena.deinit(); + + var sema: Sema = .{ + .mod = mod, + .gpa = gpa, + .arena = &analysis_arena.allocator, + .perm_arena = &decl_arena.allocator, + .code = zir, + .owner_decl = decl, + .func = null, + .fn_ret_ty = Type.initTag(.void), + .owner_func = null, + }; + defer sema.deinit(); + + var wip_captures = try WipCaptureScope.init(gpa, &decl_arena.allocator, decl.src_scope); + defer wip_captures.deinit(); + + var block_scope: Block = .{ + .parent = null, + .sema = &sema, + .src_decl = decl, + .namespace = &union_obj.namespace, + .wip_capture_scope = wip_captures.scope, + .instructions = .{}, + .inlining = null, + .is_comptime = true, + }; + defer { + assert(block_scope.instructions.items.len == 0); + block_scope.params.deinit(gpa); + } if (body.len != 0) { - _ = try sema.analyzeBody(block, body); + _ = try sema.analyzeBody(&block_scope, body); } + + try wip_captures.finalize(); + + try union_obj.fields.ensureTotalCapacity(&decl_arena.allocator, fields_len); + var int_tag_ty: Type = undefined; var enum_field_names: ?*Module.EnumNumbered.NameMap = null; var enum_value_map: ?*Module.EnumNumbered.ValueMap = null; if (tag_type_ref != .none) { - const provided_ty = try sema.resolveType(block, src, tag_type_ref); + const provided_ty = try sema.resolveType(&block_scope, src, tag_type_ref); if (small.auto_enum_tag) { // The provided type is an integer type and we must construct the enum tag type here. int_tag_ty = provided_ty; - union_obj.tag_ty = try sema.generateUnionTagTypeNumbered(block, fields_len, provided_ty); + union_obj.tag_ty = try sema.generateUnionTagTypeNumbered(&block_scope, fields_len, provided_ty); enum_field_names = &union_obj.tag_ty.castTag(.enum_numbered).?.data.fields; enum_value_map = &union_obj.tag_ty.castTag(.enum_numbered).?.data.values; } else { @@ -12111,7 +12513,7 @@ fn analyzeUnionFields( // If auto_enum_tag is false, this is an untagged union. However, for semantic analysis // purposes, we still auto-generate an enum tag type the same way. That the union is // untagged is represented by the Type tag (union vs union_tagged). - union_obj.tag_ty = try sema.generateUnionTagTypeSimple(block, fields_len); + union_obj.tag_ty = try sema.generateUnionTagTypeSimple(&block_scope, fields_len); enum_field_names = &union_obj.tag_ty.castTag(.enum_simple).?.data.fields; } @@ -12160,8 +12562,8 @@ fn analyzeUnionFields( if (enum_value_map) |map| { const tag_src = src; // TODO better source location - const coerced = try sema.coerce(block, int_tag_ty, tag_ref, tag_src); - const val = try sema.resolveConstValue(block, tag_src, coerced); + const coerced = try sema.coerce(&block_scope, int_tag_ty, tag_ref, tag_src); + const val = try sema.resolveConstValue(&block_scope, tag_src, coerced); map.putAssumeCapacityContext(val, {}, .{ .ty = int_tag_ty }); } @@ -12177,7 +12579,7 @@ fn analyzeUnionFields( // TODO: if we need to report an error here, use a source location // that points to this type expression rather than the union. // But only resolve the source location if we need to emit a compile error. - try sema.resolveType(block, src, field_type_ref); + try sema.resolveType(&block_scope, src, field_type_ref); const gop = union_obj.fields.getOrPutAssumeCapacity(field_name); assert(!gop.found_existing); @@ -12190,7 +12592,7 @@ fn analyzeUnionFields( // TODO: if we need to report an error here, use a source location // that points to this alignment expression rather than the struct. // But only resolve the source location if we need to emit a compile error. - const abi_align_val = (try sema.resolveInstConst(block, src, align_ref)).val; + const abi_align_val = (try sema.resolveInstConst(&block_scope, src, align_ref)).val; gop.value_ptr.abi_align = try abi_align_val.copy(&decl_arena.allocator); } else { gop.value_ptr.abi_align = Value.initTag(.abi_align_default); @@ -12200,7 +12602,7 @@ fn analyzeUnionFields( fn generateUnionTagTypeNumbered( sema: *Sema, - block: *Scope.Block, + block: *Block, fields_len: u32, int_ty: Type, ) !Type { @@ -12218,12 +12620,12 @@ fn generateUnionTagTypeNumbered( const enum_ty = Type.initPayload(&enum_ty_payload.base); const enum_val = try Value.Tag.ty.create(&new_decl_arena.allocator, enum_ty); // TODO better type name - const new_decl = try mod.createAnonymousDecl(&block.base, .{ + const new_decl = try mod.createAnonymousDecl(block, .{ .ty = Type.initTag(.type), .val = enum_val, }); new_decl.owns_tv = true; - errdefer sema.mod.deleteAnonDecl(&block.base, new_decl); + errdefer mod.abortAnonDecl(new_decl); enum_obj.* = .{ .owner_decl = new_decl, @@ -12239,7 +12641,7 @@ fn generateUnionTagTypeNumbered( return enum_ty; } -fn generateUnionTagTypeSimple(sema: *Sema, block: *Scope.Block, fields_len: u32) !Type { +fn generateUnionTagTypeSimple(sema: *Sema, block: *Block, fields_len: u32) !Type { const mod = sema.mod; var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa); @@ -12254,12 +12656,12 @@ fn generateUnionTagTypeSimple(sema: *Sema, block: *Scope.Block, fields_len: u32) const enum_ty = Type.initPayload(&enum_ty_payload.base); const enum_val = try Value.Tag.ty.create(&new_decl_arena.allocator, enum_ty); // TODO better type name - const new_decl = try mod.createAnonymousDecl(&block.base, .{ + const new_decl = try mod.createAnonymousDecl(block, .{ .ty = Type.initTag(.type), .val = enum_val, }); new_decl.owns_tv = true; - errdefer sema.mod.deleteAnonDecl(&block.base, new_decl); + errdefer mod.abortAnonDecl(new_decl); enum_obj.* = .{ .owner_decl = new_decl, @@ -12274,7 +12676,7 @@ fn generateUnionTagTypeSimple(sema: *Sema, block: *Scope.Block, fields_len: u32) fn getBuiltin( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, name: []const u8, ) CompileError!Air.Inst.Ref { @@ -12284,7 +12686,7 @@ fn getBuiltin( const opt_builtin_inst = try sema.namespaceLookupRef( block, src, - std_file.root_decl.?.namespace, + std_file.root_decl.?.src_namespace, "builtin", ); const builtin_inst = try sema.analyzeLoad(block, src, opt_builtin_inst.?, src); @@ -12300,7 +12702,7 @@ fn getBuiltin( fn getBuiltinType( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, name: []const u8, ) CompileError!Type { @@ -12314,7 +12716,7 @@ fn getBuiltinType( /// that the types are already resolved. fn typeHasOnePossibleValue( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, starting_type: Type, ) CompileError!?Value { @@ -12477,8 +12879,8 @@ fn typeHasOnePossibleValue( }; } -fn getAstTree(sema: *Sema, block: *Scope.Block) CompileError!*const std.zig.Ast { - return block.src_decl.namespace.file_scope.getTree(sema.gpa) catch |err| { +fn getAstTree(sema: *Sema, block: *Block) CompileError!*const std.zig.Ast { + return block.namespace.file_scope.getTree(sema.gpa) catch |err| { log.err("unable to load AST to report compile error: {s}", .{@errorName(err)}); return error.AnalysisFail; }; @@ -12667,7 +13069,7 @@ fn getBreakBlock(sema: *Sema, inst_index: Air.Inst.Index) ?Air.Inst.Index { fn isComptimeKnown( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, inst: Air.Inst.Ref, ) !bool { @@ -12676,7 +13078,7 @@ fn isComptimeKnown( fn analyzeComptimeAlloc( sema: *Sema, - block: *Scope.Block, + block: *Block, var_type: Type, ) CompileError!Air.Inst.Ref { const ptr_type = try Type.ptr(sema.arena, .{ @@ -12719,7 +13121,7 @@ pub const AddressSpaceContext = enum { pub fn analyzeAddrspace( sema: *Sema, - block: *Scope.Block, + block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref, ctx: AddressSpaceContext, @@ -12743,8 +13145,8 @@ pub fn analyzeAddrspace( .pointer => "pointers", }; - return sema.mod.fail( - &block.base, + return sema.fail( + block, src, "{s} with address space '{s}' are not supported on {s}", .{ entity, @tagName(address_space), arch.genericName() }, diff --git a/src/codegen.zig b/src/codegen.zig index dfaedf041a..33492ad2d5 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -2584,7 +2584,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { fn genArgDbgInfo(self: *Self, inst: Air.Inst.Index, mcv: MCValue) !void { const ty_str = self.air.instructions.items(.data)[inst].ty_str; - const zir = &self.mod_fn.owner_decl.namespace.file_scope.zir; + const zir = &self.mod_fn.owner_decl.getFileScope().zir; const name = zir.nullTerminatedString(ty_str.str); const name_with_null = name.ptr[0 .. name.len + 1]; const ty = self.air.getRefType(ty_str.ty); @@ -3834,7 +3834,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { fn airAsm(self: *Self, inst: Air.Inst.Index) !void { const air_datas = self.air.instructions.items(.data); const air_extra = self.air.extraData(Air.Asm, air_datas[inst].ty_pl.payload); - const zir = self.mod_fn.owner_decl.namespace.file_scope.zir; + const zir = self.mod_fn.owner_decl.getFileScope().zir; const extended = zir.instructions.items(.data)[air_extra.data.zir_index].extended; const zir_extra = zir.extraData(Zir.Inst.Asm, extended.operand); const asm_source = zir.nullTerminatedString(zir_extra.data.asm_source); diff --git a/src/codegen/c.zig b/src/codegen/c.zig index d2ce9cc6de..8ba43b3125 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -246,7 +246,7 @@ pub const DeclGen = struct { fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } { @setCold(true); const src: LazySrcLoc = .{ .node_offset = 0 }; - const src_loc = src.toSrcLocWithDecl(dg.decl); + const src_loc = src.toSrcLoc(dg.decl); dg.error_msg = try Module.ErrorMsg.create(dg.module.gpa, src_loc, format, args); return error.AnalysisFail; } @@ -1696,7 +1696,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { const air_datas = f.air.instructions.items(.data); const air_extra = f.air.extraData(Air.Asm, air_datas[inst].ty_pl.payload); - const zir = f.object.dg.decl.namespace.file_scope.zir; + const zir = f.object.dg.decl.getFileScope().zir; const extended = zir.instructions.items(.data)[air_extra.data.zir_index].extended; const zir_extra = zir.extraData(Zir.Inst.Asm, extended.operand); const asm_source = zir.nullTerminatedString(zir_extra.data.asm_source); diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 98e12f5430..761dd2a8bc 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -557,7 +557,7 @@ pub const DeclGen = struct { fn todo(self: *DeclGen, comptime format: []const u8, args: anytype) error{ OutOfMemory, CodegenFail } { @setCold(true); assert(self.err_msg == null); - const src_loc = @as(LazySrcLoc, .{ .node_offset = 0 }).toSrcLocWithDecl(self.decl); + const src_loc = @as(LazySrcLoc, .{ .node_offset = 0 }).toSrcLoc(self.decl); self.err_msg = try Module.ErrorMsg.create(self.gpa, src_loc, "TODO (LLVM): " ++ format, args); return error.CodegenFail; } @@ -1819,7 +1819,7 @@ pub const FuncGen = struct { const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; const air_asm = self.air.extraData(Air.Asm, ty_pl.payload); - const zir = self.dg.decl.namespace.file_scope.zir; + const zir = self.dg.decl.getFileScope().zir; const extended = zir.instructions.items(.data)[air_asm.data.zir_index].extended; const zir_extra = zir.extraData(Zir.Inst.Asm, extended.operand); const asm_source = zir.nullTerminatedString(zir_extra.data.asm_source); diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 5826daa5a5..25a1d228e0 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -139,7 +139,7 @@ pub const SPIRVModule = struct { } fn resolveSourceFileName(self: *SPIRVModule, decl: *Decl) !ResultId { - const path = decl.namespace.file_scope.sub_file_path; + const path = decl.getFileScope().sub_file_path; const result = try self.file_names.getOrPut(path); if (!result.found_existing) { result.value_ptr.* = self.allocResultId(); @@ -295,7 +295,7 @@ pub const DeclGen = struct { fn fail(self: *DeclGen, comptime format: []const u8, args: anytype) Error { @setCold(true); const src: LazySrcLoc = .{ .node_offset = 0 }; - const src_loc = src.toSrcLocWithDecl(self.decl); + const src_loc = src.toSrcLoc(self.decl); self.error_msg = try Module.ErrorMsg.create(self.spv.module.gpa, src_loc, format, args); return error.AnalysisFail; } diff --git a/src/codegen/wasm.zig b/src/codegen/wasm.zig index 9bd80f7d84..6902553257 100644 --- a/src/codegen/wasm.zig +++ b/src/codegen/wasm.zig @@ -540,7 +540,7 @@ pub const Context = struct { /// Sets `err_msg` on `Context` and returns `error.CodegemFail` which is caught in link/Wasm.zig fn fail(self: *Context, comptime fmt: []const u8, args: anytype) InnerError { const src: LazySrcLoc = .{ .node_offset = 0 }; - const src_loc = src.toSrcLocWithDecl(self.decl); + const src_loc = src.toSrcLoc(self.decl); self.err_msg = try Module.ErrorMsg.create(self.gpa, src_loc, fmt, args); return error.CodegenFail; } diff --git a/src/crash_report.zig b/src/crash_report.zig index 84f4b8db84..88c5f704c1 100644 --- a/src/crash_report.zig +++ b/src/crash_report.zig @@ -8,6 +8,7 @@ const print_zir = @import("print_zir.zig"); const Module = @import("Module.zig"); const Sema = @import("Sema.zig"); const Zir = @import("Zir.zig"); +const Decl = Module.Decl; pub const is_enabled = builtin.mode == .Debug; @@ -36,7 +37,7 @@ fn en(val: anytype) En(@TypeOf(val)) { pub const AnalyzeBody = struct { parent: if (is_enabled) ?*AnalyzeBody else void, sema: En(*Sema), - block: En(*Module.Scope.Block), + block: En(*Sema.Block), body: En([]const Zir.Inst.Index), body_index: En(usize), @@ -64,7 +65,7 @@ pub const AnalyzeBody = struct { threadlocal var zir_state: ?*AnalyzeBody = if (is_enabled) null else @compileError("Cannot use zir_state if crash_report is disabled."); -pub fn prepAnalyzeBody(sema: *Sema, block: *Module.Scope.Block, body: []const Zir.Inst.Index) AnalyzeBody { +pub fn prepAnalyzeBody(sema: *Sema, block: *Sema.Block, body: []const Zir.Inst.Index) AnalyzeBody { if (is_enabled) { return .{ .parent = null, @@ -87,7 +88,7 @@ fn dumpStatusReport() !void { const allocator = &fba.allocator; const stderr = io.getStdErr().writer(); - const block: *Scope.Block = anal.block; + const block: *Sema.Block = anal.block; try stderr.writeAll("Analyzing "); try writeFullyQualifiedDeclWithFile(block.src_decl, stderr); @@ -97,7 +98,7 @@ fn dumpStatusReport() !void { allocator, anal.body, anal.body_index, - block.src_decl.getFileScope(), + block.namespace.file_scope, block.src_decl.src_node, 6, // indent stderr, @@ -106,7 +107,7 @@ fn dumpStatusReport() !void { else => |e| return e, }; try stderr.writeAll(" For full context, use the command\n zig ast-check -t "); - try writeFilePath(block.src_decl.getFileScope(), stderr); + try writeFilePath(block.namespace.file_scope, stderr); try stderr.writeAll("\n\n"); var parent = anal.parent; @@ -118,7 +119,7 @@ fn dumpStatusReport() !void { print_zir.renderSingleInstruction( allocator, curr.body[curr.body_index], - curr.block.src_decl.getFileScope(), + curr.block.namespace.file_scope, curr.block.src_decl.src_node, 6, // indent stderr, @@ -134,12 +135,9 @@ fn dumpStatusReport() !void { try stderr.writeAll("\n"); } -const Scope = Module.Scope; -const Decl = Module.Decl; - var crash_heap: [16 * 4096]u8 = undefined; -fn writeFilePath(file: *Scope.File, stream: anytype) !void { +fn writeFilePath(file: *Module.File, stream: anytype) !void { if (file.pkg.root_src_directory.path) |path| { try stream.writeAll(path); try stream.writeAll(std.fs.path.sep_str); @@ -150,7 +148,7 @@ fn writeFilePath(file: *Scope.File, stream: anytype) !void { fn writeFullyQualifiedDeclWithFile(decl: *Decl, stream: anytype) !void { try writeFilePath(decl.getFileScope(), stream); try stream.writeAll(": "); - try decl.namespace.renderFullyQualifiedName(std.mem.sliceTo(decl.name, 0), stream); + try decl.renderFullyQualifiedDebugName(stream); } fn compilerPanic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace) noreturn { diff --git a/src/link/Plan9.zig b/src/link/Plan9.zig index 384345ff67..51c5abb048 100644 --- a/src/link/Plan9.zig +++ b/src/link/Plan9.zig @@ -57,7 +57,7 @@ path_arena: std.heap.ArenaAllocator, /// of the function to know what file it came from. /// If we group the decls by file, it makes it really easy to do this (put the symbol in the correct place) fn_decl_table: std.AutoArrayHashMapUnmanaged( - *Module.Scope.File, + *Module.File, struct { sym_index: u32, functions: std.AutoArrayHashMapUnmanaged(*Module.Decl, FnDeclOutput) = .{} }, ) = .{}, data_decl_table: std.AutoArrayHashMapUnmanaged(*Module.Decl, []const u8) = .{}, @@ -163,11 +163,11 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*Plan9 { fn putFn(self: *Plan9, decl: *Module.Decl, out: FnDeclOutput) !void { const gpa = self.base.allocator; - const fn_map_res = try self.fn_decl_table.getOrPut(gpa, decl.namespace.file_scope); + const fn_map_res = try self.fn_decl_table.getOrPut(gpa, decl.getFileScope()); if (fn_map_res.found_existing) { try fn_map_res.value_ptr.functions.put(gpa, decl, out); } else { - const file = decl.namespace.file_scope; + const file = decl.getFileScope(); const arena = &self.path_arena.allocator; // each file gets a symbol fn_map_res.value_ptr.* = .{ @@ -548,7 +548,7 @@ pub fn freeDecl(self: *Plan9, decl: *Module.Decl) void { const is_fn = (decl.val.tag() == .function); if (is_fn) { var symidx_and_submap = - self.fn_decl_table.get(decl.namespace.file_scope).?; + self.fn_decl_table.get(decl.getFileScope()).?; var submap = symidx_and_submap.functions; _ = submap.swapRemove(decl); if (submap.count() == 0) { diff --git a/src/main.zig b/src/main.zig index e0be4b6021..e56f1ba07e 100644 --- a/src/main.zig +++ b/src/main.zig @@ -3233,7 +3233,7 @@ pub fn cmdFmt(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !voi const Module = @import("Module.zig"); const AstGen = @import("AstGen.zig"); - var file: Module.Scope.File = .{ + var file: Module.File = .{ .status = .never_loaded, .source_loaded = true, .zir_loaded = false, @@ -3429,7 +3429,7 @@ fn fmtPathFile( const Module = @import("Module.zig"); const AstGen = @import("AstGen.zig"); - var file: Module.Scope.File = .{ + var file: Module.File = .{ .status = .never_loaded, .source_loaded = true, .zir_loaded = false, @@ -4019,7 +4019,7 @@ pub fn cmdAstCheck( } } - var file: Module.Scope.File = .{ + var file: Module.File = .{ .status = .never_loaded, .source_loaded = false, .tree_loaded = false, @@ -4170,7 +4170,7 @@ pub fn cmdChangelist( if (stat.size > max_src_size) return error.FileTooBig; - var file: Module.Scope.File = .{ + var file: Module.File = .{ .status = .never_loaded, .source_loaded = false, .tree_loaded = false, diff --git a/src/print_zir.zig b/src/print_zir.zig index c53c92f6bf..15ab00464b 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -11,7 +11,7 @@ const LazySrcLoc = Module.LazySrcLoc; /// Write human-readable, debug formatted ZIR code to a file. pub fn renderAsTextToFile( gpa: *Allocator, - scope_file: *Module.Scope.File, + scope_file: *Module.File, fs_file: std.fs.File, ) !void { var arena = std.heap.ArenaAllocator.init(gpa); @@ -64,7 +64,7 @@ pub fn renderInstructionContext( gpa: *Allocator, block: []const Zir.Inst.Index, block_index: usize, - scope_file: *Module.Scope.File, + scope_file: *Module.File, parent_decl_node: Ast.Node.Index, indent: u32, stream: anytype, @@ -96,7 +96,7 @@ pub fn renderInstructionContext( pub fn renderSingleInstruction( gpa: *Allocator, inst: Zir.Inst.Index, - scope_file: *Module.Scope.File, + scope_file: *Module.File, parent_decl_node: Ast.Node.Index, indent: u32, stream: anytype, @@ -122,7 +122,7 @@ pub fn renderSingleInstruction( const Writer = struct { gpa: *Allocator, arena: *Allocator, - file: *Module.Scope.File, + file: *Module.File, code: Zir, indent: u32, parent_decl_node: Ast.Node.Index, diff --git a/src/type.zig b/src/type.zig index dacde84167..8f200c0f35 100644 --- a/src/type.zig +++ b/src/type.zig @@ -3067,7 +3067,7 @@ pub const Type = extern union { } /// Returns null if the type has no namespace. - pub fn getNamespace(self: Type) ?*Module.Scope.Namespace { + pub fn getNamespace(self: Type) ?*Module.Namespace { return switch (self.tag()) { .@"struct" => &self.castTag(.@"struct").?.data.namespace, .enum_full => &self.castTag(.enum_full).?.data.namespace, @@ -3833,12 +3833,12 @@ pub const Type = extern union { /// Most commonly used for files. pub const ContainerScope = struct { base: Payload, - data: *Module.Scope.Namespace, + data: *Module.Namespace, }; pub const Opaque = struct { base: Payload = .{ .tag = .@"opaque" }, - data: Module.Scope.Namespace, + data: Module.Namespace, }; pub const Struct = struct { diff --git a/src/value.zig b/src/value.zig index ac52654041..72fc46ef4c 100644 --- a/src/value.zig +++ b/src/value.zig @@ -1238,9 +1238,24 @@ pub const Value = extern union { const b_field_index = b.castTag(.enum_field_index).?.data; return a_field_index == b_field_index; }, + .elem_ptr => @panic("TODO: Implement more pointer eql cases"), + .field_ptr => @panic("TODO: Implement more pointer eql cases"), + .eu_payload_ptr => @panic("TODO: Implement more pointer eql cases"), + .opt_payload_ptr => @panic("TODO: Implement more pointer eql cases"), else => {}, } } + + if (a.pointerDecl()) |a_decl| { + if (b.pointerDecl()) |b_decl| { + return a_decl == b_decl; + } else { + return false; + } + } else if (b.pointerDecl()) |_| { + return false; + } + if (ty.zigTypeTag() == .Type) { var buf_a: ToTypeBuffer = undefined; var buf_b: ToTypeBuffer = undefined; @@ -1285,8 +1300,28 @@ pub const Value = extern union { const float = val.toFloat(f128); std.hash.autoHash(hasher, @bitCast(u128, float)); }, - .Pointer => { - @panic("TODO implement hashing pointer values"); + .Pointer => switch (val.tag()) { + .decl_ref_mut, + .extern_fn, + .decl_ref, + .function, + .variable, + => std.hash.autoHash(hasher, val.pointerDecl().?), + + .elem_ptr => @panic("TODO: Implement more pointer hashing cases"), + .field_ptr => @panic("TODO: Implement more pointer hashing cases"), + .eu_payload_ptr => @panic("TODO: Implement more pointer hashing cases"), + .opt_payload_ptr => @panic("TODO: Implement more pointer hashing cases"), + + .zero, + .one, + .int_u64, + .int_i64, + .int_big_positive, + .int_big_negative, + => @panic("TODO: Implement pointer hashing for int pointers"), + + else => unreachable, }, .Array, .Vector => { @panic("TODO implement hashing array/vector values"); @@ -1432,6 +1467,19 @@ pub const Value = extern union { return sub_val; } + /// Gets the decl referenced by this pointer. If the pointer does not point + /// to a decl, or if it points to some part of a decl (like field_ptr or element_ptr), + /// this function returns null. + pub fn pointerDecl(self: Value) ?*Module.Decl { + return switch (self.tag()) { + .decl_ref_mut => self.castTag(.decl_ref_mut).?.data.decl, + .extern_fn, .decl_ref => self.cast(Payload.Decl).?.data, + .function => self.castTag(.function).?.data.owner_decl, + .variable => self.castTag(.variable).?.data.owner_decl, + else => null, + }; + } + pub fn sliceLen(val: Value) u64 { return switch (val.tag()) { .empty_array => 0,