Zcu: pass PerThread to intern pool string functions

This commit is contained in:
Jacob Young 2024-06-15 19:57:47 -04:00
parent 525f341f33
commit ca02266157
22 changed files with 1025 additions and 963 deletions

View File

@ -29,8 +29,6 @@ const wasi_libc = @import("wasi_libc.zig");
const fatal = @import("main.zig").fatal;
const clangMain = @import("main.zig").clangMain;
const Zcu = @import("Zcu.zig");
/// Deprecated; use `Zcu`.
const Module = Zcu;
const Sema = @import("Sema.zig");
const InternPool = @import("InternPool.zig");
const Cache = std.Build.Cache;
@ -50,7 +48,7 @@ gpa: Allocator,
arena: Allocator,
/// Not every Compilation compiles .zig code! For example you could do `zig build-exe foo.o`.
/// TODO: rename to zcu: ?*Zcu
module: ?*Module,
module: ?*Zcu,
/// Contains different state depending on whether the Compilation uses
/// incremental or whole cache mode.
cache_use: CacheUse,
@ -120,7 +118,7 @@ astgen_work_queue: std.fifo.LinearFifo(Zcu.File.Index, .Dynamic),
/// These jobs are to inspect the file system stat() and if the embedded file has changed
/// on disk, mark the corresponding Decl outdated and queue up an `analyze_decl`
/// task for it.
embed_file_work_queue: std.fifo.LinearFifo(*Module.EmbedFile, .Dynamic),
embed_file_work_queue: std.fifo.LinearFifo(*Zcu.EmbedFile, .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`.
@ -252,7 +250,7 @@ pub const Emit = struct {
};
pub const default_stack_protector_buffer_size = target_util.default_stack_protector_buffer_size;
pub const SemaError = Module.SemaError;
pub const SemaError = Zcu.SemaError;
pub const CRTFile = struct {
lock: Cache.Lock,
@ -1138,7 +1136,7 @@ pub const CreateOptions = struct {
pdb_source_path: ?[]const u8 = null,
/// (Windows) PDB output path
pdb_out_path: ?[]const u8 = null,
error_limit: ?Compilation.Module.ErrorInt = null,
error_limit: ?Zcu.ErrorInt = null,
global_cc_argv: []const []const u8 = &.{},
pub const Entry = link.File.OpenOptions.Entry;
@ -1344,7 +1342,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
const main_mod = options.main_mod orelse options.root_mod;
const comp = try arena.create(Compilation);
const opt_zcu: ?*Module = if (have_zcu) blk: {
const opt_zcu: ?*Zcu = if (have_zcu) blk: {
// Pre-open the directory handles for cached ZIR code so that it does not need
// to redundantly happen for each AstGen operation.
const zir_sub_dir = "z";
@ -1362,8 +1360,8 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
.path = try options.global_cache_directory.join(arena, &[_][]const u8{zir_sub_dir}),
};
const emit_h: ?*Module.GlobalEmitH = if (options.emit_h) |loc| eh: {
const eh = try arena.create(Module.GlobalEmitH);
const emit_h: ?*Zcu.GlobalEmitH = if (options.emit_h) |loc| eh: {
const eh = try arena.create(Zcu.GlobalEmitH);
eh.* = .{ .loc = loc };
break :eh eh;
} else null;
@ -1386,7 +1384,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
.builtin_modules = null, // `builtin_mod` is set
});
const zcu = try arena.create(Module);
const zcu = try arena.create(Zcu);
zcu.* = .{
.gpa = gpa,
.comp = comp,
@ -1434,7 +1432,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
.c_object_work_queue = std.fifo.LinearFifo(*CObject, .Dynamic).init(gpa),
.win32_resource_work_queue = if (build_options.only_core_functionality) {} else std.fifo.LinearFifo(*Win32Resource, .Dynamic).init(gpa),
.astgen_work_queue = std.fifo.LinearFifo(Zcu.File.Index, .Dynamic).init(gpa),
.embed_file_work_queue = std.fifo.LinearFifo(*Module.EmbedFile, .Dynamic).init(gpa),
.embed_file_work_queue = std.fifo.LinearFifo(*Zcu.EmbedFile, .Dynamic).init(gpa),
.c_source_files = options.c_source_files,
.rc_source_files = options.rc_source_files,
.cache_parent = cache,
@ -2626,7 +2624,7 @@ fn reportMultiModuleErrors(zcu: *Zcu) !void {
var num_errors: u32 = 0;
const max_errors = 5;
// Attach the "some omitted" note to the final error message
var last_err: ?*Module.ErrorMsg = null;
var last_err: ?*Zcu.ErrorMsg = null;
for (zcu.import_table.values(), 0..) |file, file_index_usize| {
if (!file.multi_pkg) continue;
@ -2642,13 +2640,13 @@ fn reportMultiModuleErrors(zcu: *Zcu) !void {
const omitted = file.references.items.len -| max_notes;
const num_notes = file.references.items.len - omitted;
const notes = try gpa.alloc(Module.ErrorMsg, if (omitted > 0) num_notes + 1 else num_notes);
const notes = try gpa.alloc(Zcu.ErrorMsg, if (omitted > 0) num_notes + 1 else num_notes);
errdefer gpa.free(notes);
for (notes[0..num_notes], file.references.items[0..num_notes], 0..) |*note, ref, i| {
errdefer for (notes[0..i]) |*n| n.deinit(gpa);
note.* = switch (ref) {
.import => |import| try Module.ErrorMsg.init(
.import => |import| try Zcu.ErrorMsg.init(
gpa,
.{
.base_node_inst = try ip.trackZir(gpa, import.file, .main_struct_inst),
@ -2657,7 +2655,7 @@ fn reportMultiModuleErrors(zcu: *Zcu) !void {
"imported from module {s}",
.{zcu.fileByIndex(import.file).mod.fully_qualified_name},
),
.root => |pkg| try Module.ErrorMsg.init(
.root => |pkg| try Zcu.ErrorMsg.init(
gpa,
.{
.base_node_inst = try ip.trackZir(gpa, file_index, .main_struct_inst),
@ -2671,7 +2669,7 @@ fn reportMultiModuleErrors(zcu: *Zcu) !void {
errdefer for (notes[0..num_notes]) |*n| n.deinit(gpa);
if (omitted > 0) {
notes[num_notes] = try Module.ErrorMsg.init(
notes[num_notes] = try Zcu.ErrorMsg.init(
gpa,
.{
.base_node_inst = try ip.trackZir(gpa, file_index, .main_struct_inst),
@ -2683,7 +2681,7 @@ fn reportMultiModuleErrors(zcu: *Zcu) !void {
}
errdefer if (omitted > 0) notes[num_notes].deinit(gpa);
const err = try Module.ErrorMsg.create(
const err = try Zcu.ErrorMsg.create(
gpa,
.{
.base_node_inst = try ip.trackZir(gpa, file_index, .main_struct_inst),
@ -2706,7 +2704,7 @@ fn reportMultiModuleErrors(zcu: *Zcu) !void {
// There isn't really any meaningful place to put this note, so just attach it to the
// last failed file
var note = try Module.ErrorMsg.init(
var note = try Zcu.ErrorMsg.init(
gpa,
err.src_loc,
"{} more errors omitted",
@ -3095,10 +3093,10 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
const values = zcu.compile_log_sources.values();
// First one will be the error; subsequent ones will be notes.
const src_loc = values[0].src();
const err_msg: Module.ErrorMsg = .{
const err_msg: Zcu.ErrorMsg = .{
.src_loc = src_loc,
.msg = "found compile log statement",
.notes = try gpa.alloc(Module.ErrorMsg, zcu.compile_log_sources.count() - 1),
.notes = try gpa.alloc(Zcu.ErrorMsg, zcu.compile_log_sources.count() - 1),
};
defer gpa.free(err_msg.notes);
@ -3166,9 +3164,9 @@ pub const ErrorNoteHashContext = struct {
};
pub fn addModuleErrorMsg(
mod: *Module,
mod: *Zcu,
eb: *ErrorBundle.Wip,
module_err_msg: Module.ErrorMsg,
module_err_msg: Zcu.ErrorMsg,
all_references: *const std.AutoHashMapUnmanaged(InternPool.AnalUnit, Zcu.ResolvedReference),
) !void {
const gpa = eb.gpa;
@ -3299,7 +3297,7 @@ pub fn addModuleErrorMsg(
}
}
pub fn addZirErrorMessages(eb: *ErrorBundle.Wip, file: *Module.File) !void {
pub fn addZirErrorMessages(eb: *ErrorBundle.Wip, file: *Zcu.File) !void {
assert(file.zir_loaded);
assert(file.tree_loaded);
assert(file.source_loaded);
@ -3378,7 +3376,7 @@ pub fn performAllTheWork(
const path_digest = zcu.filePathDigest(file_index);
const root_decl = zcu.fileRootDecl(file_index);
const file = zcu.fileByIndex(file_index);
comp.thread_pool.spawnWg(&comp.astgen_wait_group, workerAstGenFile, .{
comp.thread_pool.spawnWgId(&comp.astgen_wait_group, workerAstGenFile, .{
comp, file, file_index, path_digest, root_decl, zir_prog_node, &comp.astgen_wait_group, .root,
});
}
@ -3587,22 +3585,22 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre
defer named_frame.end();
const gpa = comp.gpa;
const zcu = comp.module.?;
const decl = zcu.declPtr(decl_index);
const pt: Zcu.PerThread = .{ .zcu = comp.module.?, .tid = @enumFromInt(tid) };
const decl = pt.zcu.declPtr(decl_index);
const lf = comp.bin_file.?;
lf.updateDeclLineNumber(zcu, decl_index) catch |err| {
try zcu.failed_analysis.ensureUnusedCapacity(gpa, 1);
zcu.failed_analysis.putAssumeCapacityNoClobber(
lf.updateDeclLineNumber(pt, decl_index) catch |err| {
try pt.zcu.failed_analysis.ensureUnusedCapacity(gpa, 1);
pt.zcu.failed_analysis.putAssumeCapacityNoClobber(
InternPool.AnalUnit.wrap(.{ .decl = decl_index }),
try Zcu.ErrorMsg.create(
gpa,
decl.navSrcLoc(zcu),
decl.navSrcLoc(pt.zcu),
"unable to update line number: {s}",
.{@errorName(err)},
),
);
decl.analysis = .codegen_failure;
try zcu.retryable_failures.append(gpa, InternPool.AnalUnit.wrap(.{ .decl = decl_index }));
try pt.zcu.retryable_failures.append(gpa, InternPool.AnalUnit.wrap(.{ .decl = decl_index }));
};
},
.analyze_mod => |mod| {
@ -4049,6 +4047,7 @@ const AstGenSrc = union(enum) {
};
fn workerAstGenFile(
tid: usize,
comp: *Compilation,
file: *Zcu.File,
file_index: Zcu.File.Index,
@ -4061,8 +4060,8 @@ fn workerAstGenFile(
const child_prog_node = prog_node.start(file.sub_file_path, 0);
defer child_prog_node.end();
const zcu = comp.module.?;
zcu.astGenFile(file, file_index, path_digest, root_decl) catch |err| switch (err) {
const pt: Zcu.PerThread = .{ .zcu = comp.module.?, .tid = @enumFromInt(tid) };
pt.astGenFile(file, file_index, path_digest, root_decl) catch |err| switch (err) {
error.AnalysisFail => return,
else => {
file.status = .retryable_failure;
@ -4097,15 +4096,15 @@ fn workerAstGenFile(
comp.mutex.lock();
defer comp.mutex.unlock();
const res = zcu.importFile(file, import_path) catch continue;
const res = pt.zcu.importFile(file, import_path) catch continue;
if (!res.is_pkg) {
res.file.addReference(zcu.*, .{ .import = .{
res.file.addReference(pt.zcu.*, .{ .import = .{
.file = file_index,
.token = item.data.token,
} }) catch continue;
}
const imported_path_digest = zcu.filePathDigest(res.file_index);
const imported_root_decl = zcu.fileRootDecl(res.file_index);
const imported_path_digest = pt.zcu.filePathDigest(res.file_index);
const imported_root_decl = pt.zcu.fileRootDecl(res.file_index);
break :blk .{ res, imported_path_digest, imported_root_decl };
};
if (import_result.is_new) {
@ -4116,7 +4115,7 @@ fn workerAstGenFile(
.importing_file = file_index,
.import_tok = item.data.token,
} };
comp.thread_pool.spawnWg(wg, workerAstGenFile, .{
comp.thread_pool.spawnWgId(wg, workerAstGenFile, .{
comp, import_result.file, import_result.file_index, imported_path_digest, imported_root_decl, prog_node, wg, sub_src,
});
}
@ -4127,7 +4126,7 @@ fn workerAstGenFile(
fn workerUpdateBuiltinZigFile(
comp: *Compilation,
mod: *Package.Module,
file: *Module.File,
file: *Zcu.File,
) void {
Builtin.populateFile(comp, mod, file) catch |err| {
comp.mutex.lock();
@ -4139,7 +4138,7 @@ fn workerUpdateBuiltinZigFile(
};
}
fn workerCheckEmbedFile(comp: *Compilation, embed_file: *Module.EmbedFile) void {
fn workerCheckEmbedFile(comp: *Compilation, embed_file: *Zcu.EmbedFile) void {
comp.detectEmbedFileUpdate(embed_file) catch |err| {
comp.reportRetryableEmbedFileError(embed_file, err) catch |oom| switch (oom) {
// Swallowing this error is OK because it's implied to be OOM when
@ -4150,7 +4149,7 @@ fn workerCheckEmbedFile(comp: *Compilation, embed_file: *Module.EmbedFile) void
};
}
fn detectEmbedFileUpdate(comp: *Compilation, embed_file: *Module.EmbedFile) !void {
fn detectEmbedFileUpdate(comp: *Compilation, embed_file: *Zcu.EmbedFile) !void {
const mod = comp.module.?;
const ip = &mod.intern_pool;
var file = try embed_file.owner.root.openFile(embed_file.sub_file_path.toSlice(ip), .{});
@ -4477,7 +4476,7 @@ fn reportRetryableAstGenError(
const file = zcu.fileByIndex(file_index);
file.status = .retryable_failure;
const src_loc: Module.LazySrcLoc = switch (src) {
const src_loc: Zcu.LazySrcLoc = switch (src) {
.root => .{
.base_node_inst = try zcu.intern_pool.trackZir(gpa, file_index, .main_struct_inst),
.offset = .entire_file,
@ -4488,7 +4487,7 @@ fn reportRetryableAstGenError(
},
};
const err_msg = try Module.ErrorMsg.create(gpa, src_loc, "unable to load '{}{s}': {s}", .{
const err_msg = try Zcu.ErrorMsg.create(gpa, src_loc, "unable to load '{}{s}': {s}", .{
file.mod.root, file.sub_file_path, @errorName(err),
});
errdefer err_msg.destroy(gpa);
@ -4502,14 +4501,14 @@ fn reportRetryableAstGenError(
fn reportRetryableEmbedFileError(
comp: *Compilation,
embed_file: *Module.EmbedFile,
embed_file: *Zcu.EmbedFile,
err: anyerror,
) error{OutOfMemory}!void {
const mod = comp.module.?;
const gpa = mod.gpa;
const src_loc = embed_file.src_loc;
const ip = &mod.intern_pool;
const err_msg = try Module.ErrorMsg.create(gpa, src_loc, "unable to load '{}{s}': {s}", .{
const err_msg = try Zcu.ErrorMsg.create(gpa, src_loc, "unable to load '{}{s}': {s}", .{
embed_file.owner.root,
embed_file.sub_file_path.toSlice(ip),
@errorName(err),

View File

@ -4539,7 +4539,7 @@ pub fn init(ip: *InternPool, gpa: Allocator) !void {
assert(ip.items.len == 0);
// Reserve string index 0 for an empty string.
assert((try ip.getOrPutString(gpa, "", .no_embedded_nulls)) == .empty);
assert((try ip.getOrPutString(gpa, .main, "", .no_embedded_nulls)) == .empty);
// So that we can use `catch unreachable` below.
try ip.items.ensureUnusedCapacity(gpa, static_keys.len);
@ -5986,6 +5986,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, tid: Zcu.PerThread.Id, key: Key) All
);
const string = try ip.getOrPutTrailingString(
gpa,
tid,
@intCast(len_including_sentinel),
.maybe_embedded_nulls,
);
@ -6865,6 +6866,7 @@ pub fn getFuncInstance(
return finishFuncInstance(
ip,
gpa,
tid,
generic_owner,
func_index,
func_extra_index,
@ -6879,7 +6881,7 @@ pub fn getFuncInstance(
pub fn getFuncInstanceIes(
ip: *InternPool,
gpa: Allocator,
_: Zcu.PerThread.Id,
tid: Zcu.PerThread.Id,
arg: GetFuncInstanceKey,
) Allocator.Error!Index {
// Validate input parameters.
@ -6994,6 +6996,7 @@ pub fn getFuncInstanceIes(
return finishFuncInstance(
ip,
gpa,
tid,
generic_owner,
func_index,
func_extra_index,
@ -7005,6 +7008,7 @@ pub fn getFuncInstanceIes(
fn finishFuncInstance(
ip: *InternPool,
gpa: Allocator,
tid: Zcu.PerThread.Id,
generic_owner: Index,
func_index: Index,
func_extra_index: u32,
@ -7036,7 +7040,7 @@ fn finishFuncInstance(
// TODO: improve this name
const decl = ip.declPtr(decl_index);
decl.name = try ip.getOrPutStringFmt(gpa, "{}__anon_{d}", .{
decl.name = try ip.getOrPutStringFmt(gpa, tid, "{}__anon_{d}", .{
fn_owner_decl.name.fmt(ip), @intFromEnum(decl_index),
}, .no_embedded_nulls);
@ -8782,18 +8786,20 @@ const EmbeddedNulls = enum {
pub fn getOrPutString(
ip: *InternPool,
gpa: Allocator,
tid: Zcu.PerThread.Id,
slice: []const u8,
comptime embedded_nulls: EmbeddedNulls,
) Allocator.Error!embedded_nulls.StringType() {
try ip.string_bytes.ensureUnusedCapacity(gpa, slice.len + 1);
ip.string_bytes.appendSliceAssumeCapacity(slice);
ip.string_bytes.appendAssumeCapacity(0);
return ip.getOrPutTrailingString(gpa, slice.len + 1, embedded_nulls);
return ip.getOrPutTrailingString(gpa, tid, slice.len + 1, embedded_nulls);
}
pub fn getOrPutStringFmt(
ip: *InternPool,
gpa: Allocator,
tid: Zcu.PerThread.Id,
comptime format: []const u8,
args: anytype,
comptime embedded_nulls: EmbeddedNulls,
@ -8803,16 +8809,17 @@ pub fn getOrPutStringFmt(
try ip.string_bytes.ensureUnusedCapacity(gpa, len);
ip.string_bytes.writer(undefined).print(format, args) catch unreachable;
ip.string_bytes.appendAssumeCapacity(0);
return ip.getOrPutTrailingString(gpa, len, embedded_nulls);
return ip.getOrPutTrailingString(gpa, tid, len, embedded_nulls);
}
pub fn getOrPutStringOpt(
ip: *InternPool,
gpa: Allocator,
tid: Zcu.PerThread.Id,
slice: ?[]const u8,
comptime embedded_nulls: EmbeddedNulls,
) Allocator.Error!embedded_nulls.OptionalStringType() {
const string = try getOrPutString(ip, gpa, slice orelse return .none, embedded_nulls);
const string = try getOrPutString(ip, gpa, tid, slice orelse return .none, embedded_nulls);
return string.toOptional();
}
@ -8820,9 +8827,11 @@ pub fn getOrPutStringOpt(
pub fn getOrPutTrailingString(
ip: *InternPool,
gpa: Allocator,
tid: Zcu.PerThread.Id,
len: usize,
comptime embedded_nulls: EmbeddedNulls,
) Allocator.Error!embedded_nulls.StringType() {
_ = tid;
const string_bytes = &ip.string_bytes;
const str_index: u32 = @intCast(string_bytes.items.len - len);
if (len > 0 and string_bytes.getLast() == 0) {

View File

@ -2093,12 +2093,12 @@ pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize)
const st_ptr = try err_trace_block.addTy(.alloc, try pt.singleMutPtrType(stack_trace_ty));
// st.instruction_addresses = &addrs;
const instruction_addresses_field_name = try ip.getOrPutString(gpa, "instruction_addresses", .no_embedded_nulls);
const instruction_addresses_field_name = try ip.getOrPutString(gpa, pt.tid, "instruction_addresses", .no_embedded_nulls);
const addr_field_ptr = try sema.fieldPtr(&err_trace_block, src, st_ptr, instruction_addresses_field_name, src, true);
try sema.storePtr2(&err_trace_block, src, addr_field_ptr, src, addrs_ptr, src, .store);
// st.index = 0;
const index_field_name = try ip.getOrPutString(gpa, "index", .no_embedded_nulls);
const index_field_name = try ip.getOrPutString(gpa, pt.tid, "index", .no_embedded_nulls);
const index_field_ptr = try sema.fieldPtr(&err_trace_block, src, st_ptr, index_field_name, src, true);
try sema.storePtr2(&err_trace_block, src, index_field_ptr, src, .zero_usize, src, .store);
@ -2691,6 +2691,7 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us
.decl_val => |str| capture: {
const decl_name = try ip.getOrPutString(
sema.gpa,
pt.tid,
sema.code.nullTerminatedString(str),
.no_embedded_nulls,
);
@ -2700,6 +2701,7 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us
.decl_ref => |str| capture: {
const decl_name = try ip.getOrPutString(
sema.gpa,
pt.tid,
sema.code.nullTerminatedString(str),
.no_embedded_nulls,
);
@ -2847,7 +2849,7 @@ fn zirStructDecl(
if (new_namespace_index.unwrap()) |ns| {
const decls = sema.code.bodySlice(extra_index, decls_len);
try mod.scanNamespace(ns, decls, mod.declPtr(new_decl_index));
try pt.scanNamespace(ns, decls, mod.declPtr(new_decl_index));
}
try pt.finalizeAnonDecl(new_decl_index);
@ -2919,7 +2921,7 @@ fn createAnonymousDeclTypeNamed(
};
try writer.writeByte(')');
const name = try ip.getOrPutString(gpa, buf.items, .no_embedded_nulls);
const name = try ip.getOrPutString(gpa, pt.tid, buf.items, .no_embedded_nulls);
try zcu.initNewAnonDecl(new_decl_index, val, name);
return new_decl_index;
},
@ -2931,7 +2933,7 @@ fn createAnonymousDeclTypeNamed(
.dbg_var_ptr, .dbg_var_val => {
if (zir_data[i].str_op.operand != ref) continue;
const name = try ip.getOrPutStringFmt(gpa, "{}.{s}", .{
const name = try ip.getOrPutStringFmt(gpa, pt.tid, "{}.{s}", .{
block.type_name_ctx.fmt(ip), zir_data[i].str_op.getStr(sema.code),
}, .no_embedded_nulls);
try zcu.initNewAnonDecl(new_decl_index, val, name);
@ -2952,7 +2954,7 @@ fn createAnonymousDeclTypeNamed(
// This name is also used as the key in the parent namespace so it cannot be
// renamed.
const name = ip.getOrPutStringFmt(gpa, "{}__{s}_{d}", .{
const name = ip.getOrPutStringFmt(gpa, pt.tid, "{}__{s}_{d}", .{
block.type_name_ctx.fmt(ip), anon_prefix, @intFromEnum(new_decl_index),
}, .no_embedded_nulls) catch unreachable;
try zcu.initNewAnonDecl(new_decl_index, val, name);
@ -3084,7 +3086,7 @@ fn zirEnumDecl(
errdefer if (!done) if (new_namespace_index.unwrap()) |ns| mod.destroyNamespace(ns);
if (new_namespace_index.unwrap()) |ns| {
try mod.scanNamespace(ns, decls, new_decl);
try pt.scanNamespace(ns, decls, new_decl);
}
// We've finished the initial construction of this type, and are about to perform analysis.
@ -3169,7 +3171,7 @@ fn zirEnumDecl(
const field_name_zir = sema.code.nullTerminatedString(field_name_index);
extra_index += 2; // field name, doc comment
const field_name = try mod.intern_pool.getOrPutString(gpa, field_name_zir, .no_embedded_nulls);
const field_name = try mod.intern_pool.getOrPutString(gpa, pt.tid, field_name_zir, .no_embedded_nulls);
const value_src: LazySrcLoc = .{
.base_node_inst = tracked_inst,
@ -3352,7 +3354,7 @@ fn zirUnionDecl(
if (new_namespace_index.unwrap()) |ns| {
const decls = sema.code.bodySlice(extra_index, decls_len);
try mod.scanNamespace(ns, decls, mod.declPtr(new_decl_index));
try pt.scanNamespace(ns, decls, mod.declPtr(new_decl_index));
}
try pt.finalizeAnonDecl(new_decl_index);
@ -3441,7 +3443,7 @@ fn zirOpaqueDecl(
if (new_namespace_index.unwrap()) |ns| {
const decls = sema.code.bodySlice(extra_index, decls_len);
try mod.scanNamespace(ns, decls, mod.declPtr(new_decl_index));
try pt.scanNamespace(ns, decls, mod.declPtr(new_decl_index));
}
try pt.finalizeAnonDecl(new_decl_index);
@ -3470,7 +3472,7 @@ fn zirErrorSetDecl(
while (extra_index < extra_index_end) : (extra_index += 2) { // +2 to skip over doc_string
const name_index: Zir.NullTerminatedString = @enumFromInt(sema.code.extra[extra_index]);
const name = sema.code.nullTerminatedString(name_index);
const name_ip = try mod.intern_pool.getOrPutString(gpa, name, .no_embedded_nulls);
const name_ip = try mod.intern_pool.getOrPutString(gpa, pt.tid, name, .no_embedded_nulls);
_ = try mod.getErrorValue(name_ip);
const result = names.getOrPutAssumeCapacity(name_ip);
assert(!result.found_existing); // verified in AstGen
@ -3634,7 +3636,7 @@ fn indexablePtrLen(
const is_pointer_to = object_ty.isSinglePointer(mod);
const indexable_ty = if (is_pointer_to) object_ty.childType(mod) else object_ty;
try checkIndexable(sema, block, src, indexable_ty);
const field_name = try mod.intern_pool.getOrPutString(sema.gpa, "len", .no_embedded_nulls);
const field_name = try mod.intern_pool.getOrPutString(sema.gpa, pt.tid, "len", .no_embedded_nulls);
return sema.fieldVal(block, src, object, field_name, src);
}
@ -3649,7 +3651,7 @@ fn indexablePtrLenOrNone(
const operand_ty = sema.typeOf(operand);
try checkMemOperand(sema, block, src, operand_ty);
if (operand_ty.ptrSize(mod) == .Many) return .none;
const field_name = try mod.intern_pool.getOrPutString(sema.gpa, "len", .no_embedded_nulls);
const field_name = try mod.intern_pool.getOrPutString(sema.gpa, pt.tid, "len", .no_embedded_nulls);
return sema.fieldVal(block, src, operand, field_name, src);
}
@ -4405,7 +4407,7 @@ fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
}
if (!object_ty.indexableHasLen(mod)) continue;
break :l try sema.fieldVal(block, arg_src, object, try ip.getOrPutString(gpa, "len", .no_embedded_nulls), arg_src);
break :l try sema.fieldVal(block, arg_src, object, try ip.getOrPutString(gpa, pt.tid, "len", .no_embedded_nulls), arg_src);
};
const arg_len = try sema.coerce(block, Type.usize, arg_len_uncoerced, arg_src);
if (len == .none) {
@ -4797,6 +4799,7 @@ fn validateUnionInit(
const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data;
const field_name = try mod.intern_pool.getOrPutString(
gpa,
pt.tid,
sema.code.nullTerminatedString(field_ptr_extra.field_name_start),
.no_embedded_nulls,
);
@ -4942,6 +4945,7 @@ fn validateStructInit(
struct_ptr_zir_ref = field_ptr_extra.lhs;
const field_name = try ip.getOrPutString(
gpa,
pt.tid,
sema.code.nullTerminatedString(field_ptr_extra.field_name_start),
.no_embedded_nulls,
);
@ -5518,10 +5522,11 @@ fn failWithBadStructFieldAccess(
field_src: LazySrcLoc,
field_name: InternPool.NullTerminatedString,
) CompileError {
const zcu = sema.pt.zcu;
const pt = sema.pt;
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
const decl = zcu.declPtr(struct_type.decl.unwrap().?);
const fqn = try decl.fullyQualifiedName(zcu);
const fqn = try decl.fullyQualifiedName(pt);
const msg = msg: {
const msg = try sema.errMsg(
@ -5544,12 +5549,13 @@ fn failWithBadUnionFieldAccess(
field_src: LazySrcLoc,
field_name: InternPool.NullTerminatedString,
) CompileError {
const zcu = sema.pt.zcu;
const pt = sema.pt;
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
const gpa = sema.gpa;
const decl = zcu.declPtr(union_obj.decl);
const fqn = try decl.fullyQualifiedName(zcu);
const fqn = try decl.fullyQualifiedName(pt);
const msg = msg: {
const msg = try sema.errMsg(
@ -5715,7 +5721,7 @@ fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!v
fn zirStr(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
const bytes = sema.code.instructions.items(.data)[@intFromEnum(inst)].str.get(sema.code);
return sema.addStrLit(
try sema.pt.zcu.intern_pool.getOrPutString(sema.gpa, bytes, .maybe_embedded_nulls),
try sema.pt.zcu.intern_pool.getOrPutString(sema.gpa, sema.pt.tid, bytes, .maybe_embedded_nulls),
bytes.len,
);
}
@ -6057,7 +6063,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr
const path_digest = zcu.filePathDigest(result.file_index);
const root_decl = zcu.fileRootDecl(result.file_index);
zcu.astGenFile(result.file, result.file_index, path_digest, root_decl) catch |err|
pt.astGenFile(result.file, result.file_index, path_digest, root_decl) catch |err|
return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)});
try pt.ensureFileAnalyzed(result.file_index);
@ -6418,6 +6424,7 @@ fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
const options_src = block.builtinCallArgSrc(inst_data.src_node, 1);
const decl_name = try mod.intern_pool.getOrPutString(
mod.gpa,
pt.tid,
sema.code.nullTerminatedString(extra.decl_name),
.no_embedded_nulls,
);
@ -6737,6 +6744,7 @@ fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
const src = block.tokenOffset(inst_data.src_tok);
const decl_name = try mod.intern_pool.getOrPutString(
sema.gpa,
pt.tid,
inst_data.get(sema.code),
.no_embedded_nulls,
);
@ -6751,6 +6759,7 @@ fn zirDeclVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
const src = block.tokenOffset(inst_data.src_tok);
const decl_name = try mod.intern_pool.getOrPutString(
sema.gpa,
pt.tid,
inst_data.get(sema.code),
.no_embedded_nulls,
);
@ -6907,7 +6916,7 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref
const stack_trace_ty = try pt.getBuiltinType("StackTrace");
try stack_trace_ty.resolveFields(pt);
const field_name = try mod.intern_pool.getOrPutString(gpa, "index", .no_embedded_nulls);
const field_name = try mod.intern_pool.getOrPutString(gpa, pt.tid, "index", .no_embedded_nulls);
const field_index = sema.structFieldIndex(block, stack_trace_ty, field_name, LazySrcLoc.unneeded) catch |err| switch (err) {
error.AnalysisFail => @panic("std.builtin.StackTrace is corrupt"),
error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable,
@ -6951,7 +6960,7 @@ fn popErrorReturnTrace(
try stack_trace_ty.resolveFields(pt);
const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty);
const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty);
const field_name = try mod.intern_pool.getOrPutString(gpa, "index", .no_embedded_nulls);
const field_name = try mod.intern_pool.getOrPutString(gpa, pt.tid, "index", .no_embedded_nulls);
const field_ptr = try sema.structFieldPtr(block, src, err_return_trace, field_name, src, stack_trace_ty, true);
try sema.storePtr2(block, src, field_ptr, src, saved_error_trace_index, src, .store);
} else if (is_non_error == null) {
@ -6977,7 +6986,7 @@ fn popErrorReturnTrace(
try stack_trace_ty.resolveFields(pt);
const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty);
const err_return_trace = try then_block.addTy(.err_return_trace, ptr_stack_trace_ty);
const field_name = try mod.intern_pool.getOrPutString(gpa, "index", .no_embedded_nulls);
const field_name = try mod.intern_pool.getOrPutString(gpa, pt.tid, "index", .no_embedded_nulls);
const field_ptr = try sema.structFieldPtr(&then_block, src, err_return_trace, field_name, src, stack_trace_ty, true);
try sema.storePtr2(&then_block, src, field_ptr, src, saved_error_trace_index, src, .store);
_ = try then_block.addBr(cond_block_inst, .void_value);
@ -7038,6 +7047,7 @@ fn zirCall(
const object_ptr = try sema.resolveInst(extra.data.obj_ptr);
const field_name = try mod.intern_pool.getOrPutString(
sema.gpa,
pt.tid,
sema.code.nullTerminatedString(extra.data.field_name_start),
.no_embedded_nulls,
);
@ -7103,7 +7113,7 @@ fn zirCall(
if (input_is_error or (pop_error_return_trace and return_ty.isError(mod))) {
const stack_trace_ty = try pt.getBuiltinType("StackTrace");
try stack_trace_ty.resolveFields(pt);
const field_name = try mod.intern_pool.getOrPutString(sema.gpa, "index", .no_embedded_nulls);
const field_name = try mod.intern_pool.getOrPutString(sema.gpa, pt.tid, "index", .no_embedded_nulls);
const field_index = try sema.structFieldIndex(block, stack_trace_ty, field_name, call_src);
// Insert a save instruction before the arg resolution + call instructions we just generated
@ -8687,6 +8697,7 @@ fn zirErrorValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;
const name = try pt.zcu.intern_pool.getOrPutString(
sema.gpa,
pt.tid,
inst_data.get(sema.code),
.no_embedded_nulls,
);
@ -8849,7 +8860,7 @@ fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;
const name = inst_data.get(sema.code);
return Air.internedToRef((try pt.intern(.{
.enum_literal = try mod.intern_pool.getOrPutString(sema.gpa, name, .no_embedded_nulls),
.enum_literal = try mod.intern_pool.getOrPutString(sema.gpa, pt.tid, name, .no_embedded_nulls),
})));
}
@ -9820,7 +9831,7 @@ fn funcCommon(
const func_index = try ip.getExternFunc(gpa, pt.tid, .{
.ty = func_ty,
.decl = sema.owner_decl_index,
.lib_name = try mod.intern_pool.getOrPutStringOpt(gpa, opt_lib_name, .no_embedded_nulls),
.lib_name = try mod.intern_pool.getOrPutStringOpt(gpa, pt.tid, opt_lib_name, .no_embedded_nulls),
});
return finishFunc(
sema,
@ -10281,6 +10292,7 @@ fn zirFieldVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;
const field_name = try mod.intern_pool.getOrPutString(
sema.gpa,
pt.tid,
sema.code.nullTerminatedString(extra.field_name_start),
.no_embedded_nulls,
);
@ -10300,6 +10312,7 @@ fn zirFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;
const field_name = try mod.intern_pool.getOrPutString(
sema.gpa,
pt.tid,
sema.code.nullTerminatedString(extra.field_name_start),
.no_embedded_nulls,
);
@ -10319,6 +10332,7 @@ fn zirStructInitFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi
const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data;
const field_name = try mod.intern_pool.getOrPutString(
sema.gpa,
pt.tid,
sema.code.nullTerminatedString(extra.field_name_start),
.no_embedded_nulls,
);
@ -13983,6 +13997,7 @@ fn zirRetErrValueCode(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.R
const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok;
const name = try mod.intern_pool.getOrPutString(
sema.gpa,
pt.tid,
inst_data.get(sema.code),
.no_embedded_nulls,
);
@ -17716,7 +17731,7 @@ fn zirBuiltinSrc(
.val = try pt.intern(.{ .aggregate = .{
.ty = array_ty,
.storage = .{
.bytes = try ip.getOrPutString(gpa, file_name, .maybe_embedded_nulls),
.bytes = try ip.getOrPutString(gpa, pt.tid, file_name, .maybe_embedded_nulls),
},
} }),
} },
@ -17778,7 +17793,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
block,
src,
type_info_ty.getNamespaceIndex(mod),
try ip.getOrPutString(gpa, "Fn", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "Fn", .no_embedded_nulls),
)).?;
try sema.ensureDeclAnalyzed(fn_info_decl_index);
const fn_info_decl = mod.declPtr(fn_info_decl_index);
@ -17788,7 +17803,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
block,
src,
fn_info_ty.getNamespaceIndex(mod),
try ip.getOrPutString(gpa, "Param", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "Param", .no_embedded_nulls),
)).?;
try sema.ensureDeclAnalyzed(param_info_decl_index);
const param_info_decl = mod.declPtr(param_info_decl_index);
@ -17890,7 +17905,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
block,
src,
type_info_ty.getNamespaceIndex(mod),
try ip.getOrPutString(gpa, "Int", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "Int", .no_embedded_nulls),
)).?;
try sema.ensureDeclAnalyzed(int_info_decl_index);
const int_info_decl = mod.declPtr(int_info_decl_index);
@ -17918,7 +17933,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
block,
src,
type_info_ty.getNamespaceIndex(mod),
try ip.getOrPutString(gpa, "Float", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "Float", .no_embedded_nulls),
)).?;
try sema.ensureDeclAnalyzed(float_info_decl_index);
const float_info_decl = mod.declPtr(float_info_decl_index);
@ -17950,7 +17965,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
block,
src,
(try pt.getBuiltinType("Type")).getNamespaceIndex(mod),
try ip.getOrPutString(gpa, "Pointer", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "Pointer", .no_embedded_nulls),
)).?;
try sema.ensureDeclAnalyzed(decl_index);
const decl = mod.declPtr(decl_index);
@ -17961,7 +17976,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
block,
src,
pointer_ty.getNamespaceIndex(mod),
try ip.getOrPutString(gpa, "Size", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "Size", .no_embedded_nulls),
)).?;
try sema.ensureDeclAnalyzed(decl_index);
const decl = mod.declPtr(decl_index);
@ -18004,7 +18019,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
block,
src,
type_info_ty.getNamespaceIndex(mod),
try ip.getOrPutString(gpa, "Array", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "Array", .no_embedded_nulls),
)).?;
try sema.ensureDeclAnalyzed(array_field_ty_decl_index);
const array_field_ty_decl = mod.declPtr(array_field_ty_decl_index);
@ -18035,7 +18050,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
block,
src,
type_info_ty.getNamespaceIndex(mod),
try ip.getOrPutString(gpa, "Vector", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "Vector", .no_embedded_nulls),
)).?;
try sema.ensureDeclAnalyzed(vector_field_ty_decl_index);
const vector_field_ty_decl = mod.declPtr(vector_field_ty_decl_index);
@ -18064,7 +18079,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
block,
src,
type_info_ty.getNamespaceIndex(mod),
try ip.getOrPutString(gpa, "Optional", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "Optional", .no_embedded_nulls),
)).?;
try sema.ensureDeclAnalyzed(optional_field_ty_decl_index);
const optional_field_ty_decl = mod.declPtr(optional_field_ty_decl_index);
@ -18091,7 +18106,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
block,
src,
type_info_ty.getNamespaceIndex(mod),
try ip.getOrPutString(gpa, "Error", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "Error", .no_embedded_nulls),
)).?;
try sema.ensureDeclAnalyzed(set_field_ty_decl_index);
const set_field_ty_decl = mod.declPtr(set_field_ty_decl_index);
@ -18197,7 +18212,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
block,
src,
type_info_ty.getNamespaceIndex(mod),
try ip.getOrPutString(gpa, "ErrorUnion", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "ErrorUnion", .no_embedded_nulls),
)).?;
try sema.ensureDeclAnalyzed(error_union_field_ty_decl_index);
const error_union_field_ty_decl = mod.declPtr(error_union_field_ty_decl_index);
@ -18227,7 +18242,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
block,
src,
type_info_ty.getNamespaceIndex(mod),
try ip.getOrPutString(gpa, "EnumField", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "EnumField", .no_embedded_nulls),
)).?;
try sema.ensureDeclAnalyzed(enum_field_ty_decl_index);
const enum_field_ty_decl = mod.declPtr(enum_field_ty_decl_index);
@ -18324,7 +18339,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
block,
src,
type_info_ty.getNamespaceIndex(mod),
try ip.getOrPutString(gpa, "Enum", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "Enum", .no_embedded_nulls),
)).?;
try sema.ensureDeclAnalyzed(type_enum_ty_decl_index);
const type_enum_ty_decl = mod.declPtr(type_enum_ty_decl_index);
@ -18356,7 +18371,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
block,
src,
type_info_ty.getNamespaceIndex(mod),
try ip.getOrPutString(gpa, "Union", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "Union", .no_embedded_nulls),
)).?;
try sema.ensureDeclAnalyzed(type_union_ty_decl_index);
const type_union_ty_decl = mod.declPtr(type_union_ty_decl_index);
@ -18368,7 +18383,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
block,
src,
type_info_ty.getNamespaceIndex(mod),
try ip.getOrPutString(gpa, "UnionField", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "UnionField", .no_embedded_nulls),
)).?;
try sema.ensureDeclAnalyzed(union_field_ty_decl_index);
const union_field_ty_decl = mod.declPtr(union_field_ty_decl_index);
@ -18473,7 +18488,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
block,
src,
(try pt.getBuiltinType("Type")).getNamespaceIndex(mod),
try ip.getOrPutString(gpa, "ContainerLayout", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "ContainerLayout", .no_embedded_nulls),
)).?;
try sema.ensureDeclAnalyzed(decl_index);
const decl = mod.declPtr(decl_index);
@ -18506,7 +18521,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
block,
src,
type_info_ty.getNamespaceIndex(mod),
try ip.getOrPutString(gpa, "Struct", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "Struct", .no_embedded_nulls),
)).?;
try sema.ensureDeclAnalyzed(type_struct_ty_decl_index);
const type_struct_ty_decl = mod.declPtr(type_struct_ty_decl_index);
@ -18518,7 +18533,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
block,
src,
type_info_ty.getNamespaceIndex(mod),
try ip.getOrPutString(gpa, "StructField", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "StructField", .no_embedded_nulls),
)).?;
try sema.ensureDeclAnalyzed(struct_field_ty_decl_index);
const struct_field_ty_decl = mod.declPtr(struct_field_ty_decl_index);
@ -18540,7 +18555,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
const field_name = if (anon_struct_type.names.len != 0)
anon_struct_type.names.get(ip)[field_index]
else
try ip.getOrPutStringFmt(gpa, "{d}", .{field_index}, .no_embedded_nulls);
try ip.getOrPutStringFmt(gpa, pt.tid, "{d}", .{field_index}, .no_embedded_nulls);
const field_name_len = field_name.length(ip);
const new_decl_ty = try pt.arrayType(.{
.len = field_name_len,
@ -18600,7 +18615,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
const field_name = if (struct_type.fieldName(ip, field_index).unwrap()) |field_name|
field_name
else
try ip.getOrPutStringFmt(gpa, "{d}", .{field_index}, .no_embedded_nulls);
try ip.getOrPutStringFmt(gpa, pt.tid, "{d}", .{field_index}, .no_embedded_nulls);
const field_name_len = field_name.length(ip);
const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]);
const field_init = struct_type.fieldInit(ip, field_index);
@ -18706,7 +18721,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
block,
src,
(try pt.getBuiltinType("Type")).getNamespaceIndex(mod),
try ip.getOrPutString(gpa, "ContainerLayout", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "ContainerLayout", .no_embedded_nulls),
)).?;
try sema.ensureDeclAnalyzed(decl_index);
const decl = mod.declPtr(decl_index);
@ -18742,7 +18757,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
block,
src,
type_info_ty.getNamespaceIndex(mod),
try ip.getOrPutString(gpa, "Opaque", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "Opaque", .no_embedded_nulls),
)).?;
try sema.ensureDeclAnalyzed(type_opaque_ty_decl_index);
const type_opaque_ty_decl = mod.declPtr(type_opaque_ty_decl_index);
@ -18786,7 +18801,7 @@ fn typeInfoDecls(
block,
src,
type_info_ty.getNamespaceIndex(mod),
try mod.intern_pool.getOrPutString(gpa, "Declaration", .no_embedded_nulls),
try mod.intern_pool.getOrPutString(gpa, pt.tid, "Declaration", .no_embedded_nulls),
)).?;
try sema.ensureDeclAnalyzed(declaration_ty_decl_index);
const declaration_ty_decl = mod.declPtr(declaration_ty_decl_index);
@ -19541,6 +19556,7 @@ fn zirRetErrValue(
const src = block.tokenOffset(inst_data.src_tok);
const err_name = try mod.intern_pool.getOrPutString(
sema.gpa,
pt.tid,
inst_data.get(sema.code),
.no_embedded_nulls,
);
@ -20251,6 +20267,7 @@ fn zirStructInit(
const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data;
const field_name = try ip.getOrPutString(
gpa,
pt.tid,
sema.code.nullTerminatedString(field_type_extra.name_start),
.no_embedded_nulls,
);
@ -20292,6 +20309,7 @@ fn zirStructInit(
const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data;
const field_name = try ip.getOrPutString(
gpa,
pt.tid,
sema.code.nullTerminatedString(field_type_extra.name_start),
.no_embedded_nulls,
);
@ -20581,7 +20599,7 @@ fn structInitAnon(
},
};
field_name.* = try mod.intern_pool.getOrPutString(gpa, name, .no_embedded_nulls);
field_name.* = try mod.intern_pool.getOrPutString(gpa, pt.tid, name, .no_embedded_nulls);
const init = try sema.resolveInst(item.data.init);
field_ty.* = sema.typeOf(init).toIntern();
@ -20958,7 +20976,7 @@ fn zirStructInitFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Comp
};
const aggregate_ty = wrapped_aggregate_ty.optEuBaseType(mod);
const zir_field_name = sema.code.nullTerminatedString(extra.name_start);
const field_name = try ip.getOrPutString(sema.gpa, zir_field_name, .no_embedded_nulls);
const field_name = try ip.getOrPutString(sema.gpa, pt.tid, zir_field_name, .no_embedded_nulls);
return sema.fieldType(block, aggregate_ty, field_name, field_name_src, ty_src);
}
@ -21344,11 +21362,11 @@ fn zirReify(
const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
const signedness_val = try Value.fromInterned(union_val.val).fieldValue(
pt,
struct_type.nameIndex(ip, try ip.getOrPutString(gpa, "signedness", .no_embedded_nulls)).?,
struct_type.nameIndex(ip, try ip.getOrPutString(gpa, pt.tid, "signedness", .no_embedded_nulls)).?,
);
const bits_val = try Value.fromInterned(union_val.val).fieldValue(
pt,
struct_type.nameIndex(ip, try ip.getOrPutString(gpa, "bits", .no_embedded_nulls)).?,
struct_type.nameIndex(ip, try ip.getOrPutString(gpa, pt.tid, "bits", .no_embedded_nulls)).?,
);
const signedness = mod.toEnum(std.builtin.Signedness, signedness_val);
@ -21360,11 +21378,11 @@ fn zirReify(
const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
const len_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "len", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "len", .no_embedded_nulls),
).?);
const child_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "child", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "child", .no_embedded_nulls),
).?);
const len: u32 = @intCast(try len_val.toUnsignedIntSema(pt));
@ -21382,7 +21400,7 @@ fn zirReify(
const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
const bits_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "bits", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "bits", .no_embedded_nulls),
).?);
const bits: u16 = @intCast(try bits_val.toUnsignedIntSema(pt));
@ -21400,35 +21418,35 @@ fn zirReify(
const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
const size_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "size", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "size", .no_embedded_nulls),
).?);
const is_const_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "is_const", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "is_const", .no_embedded_nulls),
).?);
const is_volatile_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "is_volatile", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "is_volatile", .no_embedded_nulls),
).?);
const alignment_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "alignment", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "alignment", .no_embedded_nulls),
).?);
const address_space_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "address_space", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "address_space", .no_embedded_nulls),
).?);
const child_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "child", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "child", .no_embedded_nulls),
).?);
const is_allowzero_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "is_allowzero", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "is_allowzero", .no_embedded_nulls),
).?);
const sentinel_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "sentinel", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "sentinel", .no_embedded_nulls),
).?);
if (!try sema.intFitsInType(alignment_val, Type.u32, null)) {
@ -21505,15 +21523,15 @@ fn zirReify(
const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
const len_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "len", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "len", .no_embedded_nulls),
).?);
const child_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "child", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "child", .no_embedded_nulls),
).?);
const sentinel_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "sentinel", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "sentinel", .no_embedded_nulls),
).?);
const len = try len_val.toUnsignedIntSema(pt);
@ -21534,7 +21552,7 @@ fn zirReify(
const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
const child_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "child", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "child", .no_embedded_nulls),
).?);
const child_ty = child_val.toType();
@ -21546,11 +21564,11 @@ fn zirReify(
const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
const error_set_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "error_set", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "error_set", .no_embedded_nulls),
).?);
const payload_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "payload", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "payload", .no_embedded_nulls),
).?);
const error_set_ty = error_set_val.toType();
@ -21579,7 +21597,7 @@ fn zirReify(
const elem_struct_type = ip.loadStructType(ip.typeOf(elem_val.toIntern()));
const name_val = try elem_val.fieldValue(pt, elem_struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "name", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "name", .no_embedded_nulls),
).?);
const name = try sema.sliceToIpString(block, src, name_val, .{
@ -21601,23 +21619,23 @@ fn zirReify(
const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
const layout_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "layout", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "layout", .no_embedded_nulls),
).?);
const backing_integer_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "backing_integer", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "backing_integer", .no_embedded_nulls),
).?);
const fields_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "fields", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "fields", .no_embedded_nulls),
).?);
const decls_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "decls", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "decls", .no_embedded_nulls),
).?);
const is_tuple_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "is_tuple", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "is_tuple", .no_embedded_nulls),
).?);
const layout = mod.toEnum(std.builtin.Type.ContainerLayout, layout_val);
@ -21641,19 +21659,19 @@ fn zirReify(
const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
const tag_type_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "tag_type", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "tag_type", .no_embedded_nulls),
).?);
const fields_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "fields", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "fields", .no_embedded_nulls),
).?);
const decls_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "decls", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "decls", .no_embedded_nulls),
).?);
const is_exhaustive_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "is_exhaustive", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "is_exhaustive", .no_embedded_nulls),
).?);
if (try decls_val.sliceLen(pt) > 0) {
@ -21670,7 +21688,7 @@ fn zirReify(
const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
const decls_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "decls", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "decls", .no_embedded_nulls),
).?);
// Decls
@ -21707,19 +21725,19 @@ fn zirReify(
const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
const layout_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "layout", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "layout", .no_embedded_nulls),
).?);
const tag_type_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "tag_type", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "tag_type", .no_embedded_nulls),
).?);
const fields_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "fields", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "fields", .no_embedded_nulls),
).?);
const decls_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "decls", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "decls", .no_embedded_nulls),
).?);
if (try decls_val.sliceLen(pt) > 0) {
@ -21737,23 +21755,23 @@ fn zirReify(
const struct_type = ip.loadStructType(ip.typeOf(union_val.val));
const calling_convention_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "calling_convention", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "calling_convention", .no_embedded_nulls),
).?);
const is_generic_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "is_generic", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "is_generic", .no_embedded_nulls),
).?);
const is_var_args_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "is_var_args", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "is_var_args", .no_embedded_nulls),
).?);
const return_type_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "return_type", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "return_type", .no_embedded_nulls),
).?);
const params_slice_val = try Value.fromInterned(union_val.val).fieldValue(pt, struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "params", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "params", .no_embedded_nulls),
).?);
const is_generic = is_generic_val.toBool();
@ -21783,15 +21801,15 @@ fn zirReify(
const elem_struct_type = ip.loadStructType(ip.typeOf(elem_val.toIntern()));
const param_is_generic_val = try elem_val.fieldValue(pt, elem_struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "is_generic", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "is_generic", .no_embedded_nulls),
).?);
const param_is_noalias_val = try elem_val.fieldValue(pt, elem_struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "is_noalias", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "is_noalias", .no_embedded_nulls),
).?);
const opt_param_type_val = try elem_val.fieldValue(pt, elem_struct_type.nameIndex(
ip,
try ip.getOrPutString(gpa, "type", .no_embedded_nulls),
try ip.getOrPutString(gpa, pt.tid, "type", .no_embedded_nulls),
).?);
if (param_is_generic_val.toBool()) {
@ -22535,7 +22553,7 @@ fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
const ty_src = block.builtinCallArgSrc(inst_data.src_node, 0);
const ty = try sema.resolveType(block, ty_src, inst_data.operand);
const type_name = try ip.getOrPutStringFmt(sema.gpa, "{}", .{ty.fmt(pt)}, .no_embedded_nulls);
const type_name = try ip.getOrPutStringFmt(sema.gpa, pt.tid, "{}", .{ty.fmt(pt)}, .no_embedded_nulls);
return sema.addNullTerminatedStrLit(type_name);
}
@ -24143,18 +24161,18 @@ fn resolveExportOptions(
const section_src = block.src(.{ .init_field_section = src.offset.node_offset_builtin_call_arg.builtin_call_node });
const visibility_src = block.src(.{ .init_field_visibility = src.offset.node_offset_builtin_call_arg.builtin_call_node });
const name_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "name", .no_embedded_nulls), name_src);
const name_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "name", .no_embedded_nulls), name_src);
const name = try sema.toConstString(block, name_src, name_operand, .{
.needed_comptime_reason = "name of exported value must be comptime-known",
});
const linkage_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "linkage", .no_embedded_nulls), linkage_src);
const linkage_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "linkage", .no_embedded_nulls), linkage_src);
const linkage_val = try sema.resolveConstDefinedValue(block, linkage_src, linkage_operand, .{
.needed_comptime_reason = "linkage of exported value must be comptime-known",
});
const linkage = mod.toEnum(std.builtin.GlobalLinkage, linkage_val);
const section_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "section", .no_embedded_nulls), section_src);
const section_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "section", .no_embedded_nulls), section_src);
const section_opt_val = try sema.resolveConstDefinedValue(block, section_src, section_operand, .{
.needed_comptime_reason = "linksection of exported value must be comptime-known",
});
@ -24165,7 +24183,7 @@ fn resolveExportOptions(
else
null;
const visibility_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "visibility", .no_embedded_nulls), visibility_src);
const visibility_operand = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "visibility", .no_embedded_nulls), visibility_src);
const visibility_val = try sema.resolveConstDefinedValue(block, visibility_src, visibility_operand, .{
.needed_comptime_reason = "visibility of exported value must be comptime-known",
});
@ -24182,9 +24200,9 @@ fn resolveExportOptions(
}
return .{
.name = try ip.getOrPutString(gpa, name, .no_embedded_nulls),
.name = try ip.getOrPutString(gpa, pt.tid, name, .no_embedded_nulls),
.linkage = linkage,
.section = try ip.getOrPutStringOpt(gpa, section, .no_embedded_nulls),
.section = try ip.getOrPutStringOpt(gpa, pt.tid, section, .no_embedded_nulls),
.visibility = visibility,
};
}
@ -25821,7 +25839,7 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
const runtime_src = rs: {
const ptr_val = try sema.resolveDefinedValue(block, dest_src, dest_ptr) orelse break :rs dest_src;
const len_air_ref = try sema.fieldVal(block, src, dest_ptr, try ip.getOrPutString(gpa, "len", .no_embedded_nulls), dest_src);
const len_air_ref = try sema.fieldVal(block, src, dest_ptr, try ip.getOrPutString(gpa, pt.tid, "len", .no_embedded_nulls), dest_src);
const len_val = (try sema.resolveDefinedValue(block, dest_src, len_air_ref)) orelse break :rs dest_src;
const len_u64 = (try len_val.getUnsignedIntAdvanced(pt, .sema)).?;
const len = try sema.usizeCast(block, dest_src, len_u64);
@ -25952,7 +25970,7 @@ fn zirVarExtended(
.ty = var_ty.toIntern(),
.init = init_val,
.decl = sema.owner_decl_index,
.lib_name = try mod.intern_pool.getOrPutStringOpt(sema.gpa, lib_name, .no_embedded_nulls),
.lib_name = try mod.intern_pool.getOrPutStringOpt(sema.gpa, pt.tid, lib_name, .no_embedded_nulls),
.is_extern = small.is_extern,
.is_const = small.is_const,
.is_threadlocal = small.is_threadlocal,
@ -26323,17 +26341,17 @@ fn resolvePrefetchOptions(
const locality_src = block.src(.{ .init_field_locality = src.offset.node_offset_builtin_call_arg.builtin_call_node });
const cache_src = block.src(.{ .init_field_cache = src.offset.node_offset_builtin_call_arg.builtin_call_node });
const rw = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "rw", .no_embedded_nulls), rw_src);
const rw = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "rw", .no_embedded_nulls), rw_src);
const rw_val = try sema.resolveConstDefinedValue(block, rw_src, rw, .{
.needed_comptime_reason = "prefetch read/write must be comptime-known",
});
const locality = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "locality", .no_embedded_nulls), locality_src);
const locality = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "locality", .no_embedded_nulls), locality_src);
const locality_val = try sema.resolveConstDefinedValue(block, locality_src, locality, .{
.needed_comptime_reason = "prefetch locality must be comptime-known",
});
const cache = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "cache", .no_embedded_nulls), cache_src);
const cache = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "cache", .no_embedded_nulls), cache_src);
const cache_val = try sema.resolveConstDefinedValue(block, cache_src, cache, .{
.needed_comptime_reason = "prefetch cache must be comptime-known",
});
@ -26397,23 +26415,23 @@ fn resolveExternOptions(
const linkage_src = block.src(.{ .init_field_linkage = src.offset.node_offset_builtin_call_arg.builtin_call_node });
const thread_local_src = block.src(.{ .init_field_thread_local = src.offset.node_offset_builtin_call_arg.builtin_call_node });
const name_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "name", .no_embedded_nulls), name_src);
const name_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "name", .no_embedded_nulls), name_src);
const name = try sema.toConstString(block, name_src, name_ref, .{
.needed_comptime_reason = "name of the extern symbol must be comptime-known",
});
const library_name_inst = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "library_name", .no_embedded_nulls), library_src);
const library_name_inst = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "library_name", .no_embedded_nulls), library_src);
const library_name_val = try sema.resolveConstDefinedValue(block, library_src, library_name_inst, .{
.needed_comptime_reason = "library in which extern symbol is must be comptime-known",
});
const linkage_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "linkage", .no_embedded_nulls), linkage_src);
const linkage_ref = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "linkage", .no_embedded_nulls), linkage_src);
const linkage_val = try sema.resolveConstDefinedValue(block, linkage_src, linkage_ref, .{
.needed_comptime_reason = "linkage of the extern symbol must be comptime-known",
});
const linkage = mod.toEnum(std.builtin.GlobalLinkage, linkage_val);
const is_thread_local = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, "is_thread_local", .no_embedded_nulls), thread_local_src);
const is_thread_local = try sema.fieldVal(block, src, options, try ip.getOrPutString(gpa, pt.tid, "is_thread_local", .no_embedded_nulls), thread_local_src);
const is_thread_local_val = try sema.resolveConstDefinedValue(block, thread_local_src, is_thread_local, .{
.needed_comptime_reason = "threadlocality of the extern symbol must be comptime-known",
});
@ -26438,8 +26456,8 @@ fn resolveExternOptions(
}
return .{
.name = try ip.getOrPutString(gpa, name, .no_embedded_nulls),
.library_name = try ip.getOrPutStringOpt(gpa, library_name, .no_embedded_nulls),
.name = try ip.getOrPutString(gpa, pt.tid, name, .no_embedded_nulls),
.library_name = try ip.getOrPutStringOpt(gpa, pt.tid, library_name, .no_embedded_nulls),
.linkage = linkage,
.is_thread_local = is_thread_local_val.toBool(),
};
@ -27052,7 +27070,7 @@ fn preparePanicId(sema: *Sema, block: *Block, panic_id: Module.PanicId) !InternP
block,
LazySrcLoc.unneeded,
panic_messages_ty.getNamespaceIndex(mod),
try mod.intern_pool.getOrPutString(gpa, @tagName(panic_id), .no_embedded_nulls),
try mod.intern_pool.getOrPutString(gpa, pt.tid, @tagName(panic_id), .no_embedded_nulls),
) catch |err| switch (err) {
error.AnalysisFail => @panic("std.builtin.panic_messages is corrupt"),
error.GenericPoison, error.ComptimeReturn, error.ComptimeBreak => unreachable,
@ -31745,7 +31763,7 @@ fn coerceTupleToStruct(
.anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len > 0)
anon_struct_type.names.get(ip)[tuple_field_index]
else
try ip.getOrPutStringFmt(sema.gpa, "{d}", .{tuple_field_index}, .no_embedded_nulls),
try ip.getOrPutStringFmt(sema.gpa, pt.tid, "{d}", .{tuple_field_index}, .no_embedded_nulls),
.struct_type => ip.loadStructType(inst_ty.toIntern()).field_names.get(ip)[tuple_field_index],
else => unreachable,
};
@ -31858,13 +31876,13 @@ fn coerceTupleToTuple(
.anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len > 0)
anon_struct_type.names.get(ip)[field_i]
else
try ip.getOrPutStringFmt(sema.gpa, "{d}", .{field_i}, .no_embedded_nulls),
try ip.getOrPutStringFmt(sema.gpa, pt.tid, "{d}", .{field_i}, .no_embedded_nulls),
.struct_type => s: {
const struct_type = ip.loadStructType(inst_ty.toIntern());
if (struct_type.field_names.len > 0) {
break :s struct_type.field_names.get(ip)[field_i];
} else {
break :s try ip.getOrPutStringFmt(sema.gpa, "{d}", .{field_i}, .no_embedded_nulls);
break :s try ip.getOrPutStringFmt(sema.gpa, pt.tid, "{d}", .{field_i}, .no_embedded_nulls);
}
},
else => unreachable,
@ -34849,7 +34867,7 @@ fn resolvePeerTypesInner(
const result_buf = try sema.arena.create(PeerResolveResult);
result_buf.* = result;
const field_name = if (is_tuple)
try ip.getOrPutStringFmt(sema.gpa, "{d}", .{field_index}, .no_embedded_nulls)
try ip.getOrPutStringFmt(sema.gpa, pt.tid, "{d}", .{field_index}, .no_embedded_nulls)
else
field_names[field_index];
@ -36066,7 +36084,7 @@ fn semaStructFields(
// This string needs to outlive the ZIR code.
if (opt_field_name_zir) |field_name_zir| {
const field_name = try ip.getOrPutString(gpa, field_name_zir, .no_embedded_nulls);
const field_name = try ip.getOrPutString(gpa, pt.tid, field_name_zir, .no_embedded_nulls);
assert(struct_type.addFieldName(ip, field_name) == null);
}
@ -36567,7 +36585,7 @@ fn semaUnionFields(pt: Zcu.PerThread, arena: Allocator, union_type: InternPool.L
}
// This string needs to outlive the ZIR code.
const field_name = try ip.getOrPutString(gpa, field_name_zir, .no_embedded_nulls);
const field_name = try ip.getOrPutString(gpa, pt.tid, field_name_zir, .no_embedded_nulls);
if (enum_field_names.len != 0) {
enum_field_names[field_i] = field_name;
}
@ -36716,9 +36734,10 @@ fn generateUnionTagTypeNumbered(
const new_decl_index = try mod.allocateNewDecl(block.namespace);
errdefer mod.destroyDecl(new_decl_index);
const fqn = try union_owner_decl.fullyQualifiedName(mod);
const fqn = try union_owner_decl.fullyQualifiedName(pt);
const name = try ip.getOrPutStringFmt(
gpa,
pt.tid,
"@typeInfo({}).Union.tag_type.?",
.{fqn.fmt(ip)},
.no_embedded_nulls,
@ -36764,11 +36783,12 @@ fn generateUnionTagTypeSimple(
const gpa = sema.gpa;
const new_decl_index = new_decl_index: {
const fqn = try union_owner_decl.fullyQualifiedName(mod);
const fqn = try union_owner_decl.fullyQualifiedName(pt);
const new_decl_index = try mod.allocateNewDecl(block.namespace);
errdefer mod.destroyDecl(new_decl_index);
const name = try ip.getOrPutStringFmt(
gpa,
pt.tid,
"@typeInfo({}).Union.tag_type.?",
.{fqn.fmt(ip)},
.no_embedded_nulls,

View File

@ -67,7 +67,7 @@ pub fn toIpString(val: Value, ty: Type, pt: Zcu.PerThread) !InternPool.NullTermi
const byte: u8 = @intCast(Value.fromInterned(elem).toUnsignedInt(pt));
const len: usize = @intCast(ty.arrayLen(mod));
try ip.string_bytes.appendNTimes(mod.gpa, byte, len);
return ip.getOrPutTrailingString(mod.gpa, len, .no_embedded_nulls);
return ip.getOrPutTrailingString(mod.gpa, pt.tid, len, .no_embedded_nulls);
},
}
}
@ -118,7 +118,7 @@ fn arrayToIpString(val: Value, len_u64: u64, pt: Zcu.PerThread) !InternPool.Null
const byte: u8 = @intCast(elem_val.toUnsignedInt(pt));
ip.string_bytes.appendAssumeCapacity(byte);
}
return ip.getOrPutTrailingString(gpa, len, .no_embedded_nulls);
return ip.getOrPutTrailingString(gpa, pt.tid, len, .no_embedded_nulls);
}
pub fn fromInterned(i: InternPool.Index) Value {

View File

@ -420,11 +420,11 @@ pub const Decl = struct {
return zcu.namespacePtr(decl.src_namespace).renderFullyQualifiedDebugName(zcu, decl.name, writer);
}
pub fn fullyQualifiedName(decl: Decl, zcu: *Zcu) !InternPool.NullTerminatedString {
pub fn fullyQualifiedName(decl: Decl, pt: Zcu.PerThread) !InternPool.NullTerminatedString {
return if (decl.name_fully_qualified)
decl.name
else
zcu.namespacePtr(decl.src_namespace).fullyQualifiedName(zcu, decl.name);
pt.zcu.namespacePtr(decl.src_namespace).fullyQualifiedName(pt, decl.name);
}
pub fn typeOf(decl: Decl, zcu: *const Zcu) Type {
@ -688,9 +688,10 @@ pub const Namespace = struct {
pub fn fullyQualifiedName(
ns: Namespace,
zcu: *Zcu,
pt: Zcu.PerThread,
name: InternPool.NullTerminatedString,
) !InternPool.NullTerminatedString {
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
const count = count: {
var count: usize = name.length(ip) + 1;
@ -723,7 +724,7 @@ pub const Namespace = struct {
};
}
return ip.getOrPutTrailingString(gpa, ip.string_bytes.items.len - start, .no_embedded_nulls);
return ip.getOrPutTrailingString(gpa, pt.tid, ip.string_bytes.items.len - start, .no_embedded_nulls);
}
pub fn getType(ns: Namespace, zcu: *Zcu) Type {
@ -875,11 +876,12 @@ pub const File = struct {
};
}
pub fn fullyQualifiedName(file: File, mod: *Module) !InternPool.NullTerminatedString {
const ip = &mod.intern_pool;
pub fn fullyQualifiedName(file: File, pt: Zcu.PerThread) !InternPool.NullTerminatedString {
const gpa = pt.zcu.gpa;
const ip = &pt.zcu.intern_pool;
const start = ip.string_bytes.items.len;
try file.renderFullyQualifiedName(ip.string_bytes.writer(mod.gpa));
return ip.getOrPutTrailingString(mod.gpa, ip.string_bytes.items.len - start, .no_embedded_nulls);
try file.renderFullyQualifiedName(ip.string_bytes.writer(gpa));
return ip.getOrPutTrailingString(gpa, pt.tid, ip.string_bytes.items.len - start, .no_embedded_nulls);
}
pub fn fullPath(file: File, ally: Allocator) ![]u8 {
@ -2569,8 +2571,8 @@ pub fn declIsRoot(mod: *Module, decl_index: Decl.Index) bool {
}
// TODO https://github.com/ziglang/zig/issues/8643
const data_has_safety_tag = @sizeOf(Zir.Inst.Data) != 8;
const HackDataLayout = extern struct {
pub const data_has_safety_tag = @sizeOf(Zir.Inst.Data) != 8;
pub const HackDataLayout = extern struct {
data: [8]u8 align(@alignOf(Zir.Inst.Data)),
safety_tag: u8,
};
@ -2580,291 +2582,11 @@ comptime {
}
}
pub fn astGenFile(
zcu: *Zcu,
file: *File,
/// This parameter is provided separately from `file` because it is not
/// safe to access `import_table` without a lock, and this index is needed
/// in the call to `updateZirRefs`.
file_index: File.Index,
path_digest: Cache.BinDigest,
opt_root_decl: Zcu.Decl.OptionalIndex,
) !void {
assert(!file.mod.isBuiltin());
const tracy = trace(@src());
defer tracy.end();
const comp = zcu.comp;
const gpa = zcu.gpa;
// In any case we need to examine the stat of the file to determine the course of action.
var source_file = try file.mod.root.openFile(file.sub_file_path, .{});
defer source_file.close();
const stat = try source_file.stat();
const want_local_cache = file.mod == zcu.main_mod;
const hex_digest = Cache.binToHex(path_digest);
const cache_directory = if (want_local_cache) zcu.local_zir_cache else zcu.global_zir_cache;
const zir_dir = cache_directory.handle;
// Determine whether we need to reload the file from disk and redo parsing and AstGen.
var lock: std.fs.File.Lock = switch (file.status) {
.never_loaded, .retryable_failure => lock: {
// First, load the cached ZIR code, if any.
log.debug("AstGen checking cache: {s} (local={}, digest={s})", .{
file.sub_file_path, want_local_cache, &hex_digest,
});
break :lock .shared;
},
.parse_failure, .astgen_failure, .success_zir => lock: {
const unchanged_metadata =
stat.size == file.stat.size and
stat.mtime == file.stat.mtime and
stat.inode == file.stat.inode;
if (unchanged_metadata) {
log.debug("unmodified metadata of file: {s}", .{file.sub_file_path});
return;
}
log.debug("metadata changed: {s}", .{file.sub_file_path});
break :lock .exclusive;
},
};
// We ask for a lock in order to coordinate with other zig processes.
// If another process is already working on this file, we will get the cached
// version. Likewise if we're working on AstGen and another process asks for
// the cached file, they'll get it.
const cache_file = while (true) {
break zir_dir.createFile(&hex_digest, .{
.read = true,
.truncate = false,
.lock = lock,
}) catch |err| switch (err) {
error.NotDir => unreachable, // no dir components
error.InvalidUtf8 => unreachable, // it's a hex encoded name
error.InvalidWtf8 => unreachable, // it's a hex encoded name
error.BadPathName => unreachable, // it's a hex encoded name
error.NameTooLong => unreachable, // it's a fixed size name
error.PipeBusy => unreachable, // it's not a pipe
error.WouldBlock => unreachable, // not asking for non-blocking I/O
// There are no dir components, so you would think that this was
// unreachable, however we have observed on macOS two processes racing
// to do openat() with O_CREAT manifest in ENOENT.
error.FileNotFound => continue,
else => |e| return e, // Retryable errors are handled at callsite.
};
};
defer cache_file.close();
while (true) {
update: {
// First we read the header to determine the lengths of arrays.
const header = cache_file.reader().readStruct(Zir.Header) catch |err| switch (err) {
// This can happen if Zig bails out of this function between creating
// the cached file and writing it.
error.EndOfStream => break :update,
else => |e| return e,
};
const unchanged_metadata =
stat.size == header.stat_size and
stat.mtime == header.stat_mtime and
stat.inode == header.stat_inode;
if (!unchanged_metadata) {
log.debug("AstGen cache stale: {s}", .{file.sub_file_path});
break :update;
}
log.debug("AstGen cache hit: {s} instructions_len={d}", .{
file.sub_file_path, header.instructions_len,
});
file.zir = loadZirCacheBody(gpa, header, cache_file) catch |err| switch (err) {
error.UnexpectedFileSize => {
log.warn("unexpected EOF reading cached ZIR for {s}", .{file.sub_file_path});
break :update;
},
else => |e| return e,
};
file.zir_loaded = true;
file.stat = .{
.size = header.stat_size,
.inode = header.stat_inode,
.mtime = header.stat_mtime,
};
file.status = .success_zir;
log.debug("AstGen cached success: {s}", .{file.sub_file_path});
// TODO don't report compile errors until Sema @importFile
if (file.zir.hasCompileErrors()) {
{
comp.mutex.lock();
defer comp.mutex.unlock();
try zcu.failed_files.putNoClobber(gpa, file, null);
}
file.status = .astgen_failure;
return error.AnalysisFail;
}
return;
}
// If we already have the exclusive lock then it is our job to update.
if (builtin.os.tag == .wasi or lock == .exclusive) break;
// Otherwise, unlock to give someone a chance to get the exclusive lock
// and then upgrade to an exclusive lock.
cache_file.unlock();
lock = .exclusive;
try cache_file.lock(lock);
}
// The cache is definitely stale so delete the contents to avoid an underwrite later.
cache_file.setEndPos(0) catch |err| switch (err) {
error.FileTooBig => unreachable, // 0 is not too big
else => |e| return e,
};
zcu.lockAndClearFileCompileError(file);
// If the previous ZIR does not have compile errors, keep it around
// in case parsing or new ZIR fails. In case of successful ZIR update
// at the end of this function we will free it.
// We keep the previous ZIR loaded so that we can use it
// for the update next time it does not have any compile errors. This avoids
// needlessly tossing out semantic analysis work when an error is
// temporarily introduced.
if (file.zir_loaded and !file.zir.hasCompileErrors()) {
assert(file.prev_zir == null);
const prev_zir_ptr = try gpa.create(Zir);
file.prev_zir = prev_zir_ptr;
prev_zir_ptr.* = file.zir;
file.zir = undefined;
file.zir_loaded = false;
}
file.unload(gpa);
if (stat.size > std.math.maxInt(u32))
return error.FileTooBig;
const source = try gpa.allocSentinel(u8, @as(usize, @intCast(stat.size)), 0);
defer if (!file.source_loaded) gpa.free(source);
const amt = try source_file.readAll(source);
if (amt != stat.size)
return error.UnexpectedEndOfFile;
file.stat = .{
.size = stat.size,
.inode = stat.inode,
.mtime = stat.mtime,
};
file.source = source;
file.source_loaded = true;
file.tree = try Ast.parse(gpa, source, .zig);
file.tree_loaded = true;
// Any potential AST errors are converted to ZIR errors here.
file.zir = try AstGen.generate(gpa, file.tree);
file.zir_loaded = true;
file.status = .success_zir;
log.debug("AstGen fresh success: {s}", .{file.sub_file_path});
const safety_buffer = if (data_has_safety_tag)
try gpa.alloc([8]u8, file.zir.instructions.len)
else
undefined;
defer if (data_has_safety_tag) gpa.free(safety_buffer);
const data_ptr = if (data_has_safety_tag)
if (file.zir.instructions.len == 0)
@as([*]const u8, undefined)
else
@as([*]const u8, @ptrCast(safety_buffer.ptr))
else
@as([*]const u8, @ptrCast(file.zir.instructions.items(.data).ptr));
if (data_has_safety_tag) {
// The `Data` union has a safety tag but in the file format we store it without.
for (file.zir.instructions.items(.data), 0..) |*data, i| {
const as_struct = @as(*const HackDataLayout, @ptrCast(data));
safety_buffer[i] = as_struct.data;
}
}
const header: Zir.Header = .{
.instructions_len = @as(u32, @intCast(file.zir.instructions.len)),
.string_bytes_len = @as(u32, @intCast(file.zir.string_bytes.len)),
.extra_len = @as(u32, @intCast(file.zir.extra.len)),
.stat_size = stat.size,
.stat_inode = stat.inode,
.stat_mtime = stat.mtime,
};
var iovecs = [_]std.posix.iovec_const{
.{
.base = @as([*]const u8, @ptrCast(&header)),
.len = @sizeOf(Zir.Header),
},
.{
.base = @as([*]const u8, @ptrCast(file.zir.instructions.items(.tag).ptr)),
.len = file.zir.instructions.len,
},
.{
.base = data_ptr,
.len = file.zir.instructions.len * 8,
},
.{
.base = file.zir.string_bytes.ptr,
.len = file.zir.string_bytes.len,
},
.{
.base = @as([*]const u8, @ptrCast(file.zir.extra.ptr)),
.len = file.zir.extra.len * 4,
},
};
cache_file.writevAll(&iovecs) catch |err| {
log.warn("unable to write cached ZIR code for {}{s} to {}{s}: {s}", .{
file.mod.root, file.sub_file_path, cache_directory, &hex_digest, @errorName(err),
});
};
if (file.zir.hasCompileErrors()) {
{
comp.mutex.lock();
defer comp.mutex.unlock();
try zcu.failed_files.putNoClobber(gpa, file, null);
}
file.status = .astgen_failure;
return error.AnalysisFail;
}
if (file.prev_zir) |prev_zir| {
try updateZirRefs(zcu, file, file_index, prev_zir.*);
// No need to keep previous ZIR.
prev_zir.deinit(gpa);
gpa.destroy(prev_zir);
file.prev_zir = null;
}
if (opt_root_decl.unwrap()) |root_decl| {
// The root of this file must be re-analyzed, since the file has changed.
comp.mutex.lock();
defer comp.mutex.unlock();
log.debug("outdated root Decl: {}", .{root_decl});
try zcu.outdated_file_root.put(gpa, root_decl, {});
}
}
pub fn loadZirCache(gpa: Allocator, cache_file: std.fs.File) !Zir {
return loadZirCacheBody(gpa, try cache_file.reader().readStruct(Zir.Header), cache_file);
}
fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_file: std.fs.File) !Zir {
pub fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_file: std.fs.File) !Zir {
var instructions: std.MultiArrayList(Zir.Inst) = .{};
errdefer instructions.deinit(gpa);
@ -2930,127 +2652,6 @@ fn loadZirCacheBody(gpa: Allocator, header: Zir.Header, cache_file: std.fs.File)
return zir;
}
/// This is called from the AstGen thread pool, so must acquire
/// the Compilation mutex when acting on shared state.
fn updateZirRefs(zcu: *Module, file: *File, file_index: File.Index, old_zir: Zir) !void {
const gpa = zcu.gpa;
const new_zir = file.zir;
var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{};
defer inst_map.deinit(gpa);
try mapOldZirToNew(gpa, old_zir, new_zir, &inst_map);
const old_tag = old_zir.instructions.items(.tag);
const old_data = old_zir.instructions.items(.data);
// TODO: this should be done after all AstGen workers complete, to avoid
// iterating over this full set for every updated file.
for (zcu.intern_pool.tracked_insts.keys(), 0..) |*ti, idx_raw| {
const ti_idx: InternPool.TrackedInst.Index = @enumFromInt(idx_raw);
if (ti.file != file_index) continue;
const old_inst = ti.inst;
ti.inst = inst_map.get(ti.inst) orelse {
// Tracking failed for this instruction. Invalidate associated `src_hash` deps.
zcu.comp.mutex.lock();
defer zcu.comp.mutex.unlock();
log.debug("tracking failed for %{d}", .{old_inst});
try zcu.markDependeeOutdated(.{ .src_hash = ti_idx });
continue;
};
if (old_zir.getAssociatedSrcHash(old_inst)) |old_hash| hash_changed: {
if (new_zir.getAssociatedSrcHash(ti.inst)) |new_hash| {
if (std.zig.srcHashEql(old_hash, new_hash)) {
break :hash_changed;
}
log.debug("hash for (%{d} -> %{d}) changed: {} -> {}", .{
old_inst,
ti.inst,
std.fmt.fmtSliceHexLower(&old_hash),
std.fmt.fmtSliceHexLower(&new_hash),
});
}
// The source hash associated with this instruction changed - invalidate relevant dependencies.
zcu.comp.mutex.lock();
defer zcu.comp.mutex.unlock();
try zcu.markDependeeOutdated(.{ .src_hash = ti_idx });
}
// If this is a `struct_decl` etc, we must invalidate any outdated namespace dependencies.
const has_namespace = switch (old_tag[@intFromEnum(old_inst)]) {
.extended => switch (old_data[@intFromEnum(old_inst)].extended.opcode) {
.struct_decl, .union_decl, .opaque_decl, .enum_decl => true,
else => false,
},
else => false,
};
if (!has_namespace) continue;
var old_names: std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void) = .{};
defer old_names.deinit(zcu.gpa);
{
var it = old_zir.declIterator(old_inst);
while (it.next()) |decl_inst| {
const decl_name = old_zir.getDeclaration(decl_inst)[0].name;
switch (decl_name) {
.@"comptime", .@"usingnamespace", .unnamed_test, .decltest => continue,
_ => if (decl_name.isNamedTest(old_zir)) continue,
}
const name_zir = decl_name.toString(old_zir).?;
const name_ip = try zcu.intern_pool.getOrPutString(
zcu.gpa,
old_zir.nullTerminatedString(name_zir),
.no_embedded_nulls,
);
try old_names.put(zcu.gpa, name_ip, {});
}
}
var any_change = false;
{
var it = new_zir.declIterator(ti.inst);
while (it.next()) |decl_inst| {
const decl_name = old_zir.getDeclaration(decl_inst)[0].name;
switch (decl_name) {
.@"comptime", .@"usingnamespace", .unnamed_test, .decltest => continue,
_ => if (decl_name.isNamedTest(old_zir)) continue,
}
const name_zir = decl_name.toString(old_zir).?;
const name_ip = try zcu.intern_pool.getOrPutString(
zcu.gpa,
old_zir.nullTerminatedString(name_zir),
.no_embedded_nulls,
);
if (!old_names.swapRemove(name_ip)) continue;
// Name added
any_change = true;
zcu.comp.mutex.lock();
defer zcu.comp.mutex.unlock();
try zcu.markDependeeOutdated(.{ .namespace_name = .{
.namespace = ti_idx,
.name = name_ip,
} });
}
}
// The only elements remaining in `old_names` now are any names which were removed.
for (old_names.keys()) |name_ip| {
any_change = true;
zcu.comp.mutex.lock();
defer zcu.comp.mutex.unlock();
try zcu.markDependeeOutdated(.{ .namespace_name = .{
.namespace = ti_idx,
.name = name_ip,
} });
}
if (any_change) {
zcu.comp.mutex.lock();
defer zcu.comp.mutex.unlock();
try zcu.markDependeeOutdated(.{ .namespace = ti_idx });
}
}
}
pub fn markDependeeOutdated(zcu: *Zcu, dependee: InternPool.Dependee) !void {
log.debug("outdated dependee: {}", .{dependee});
var it = zcu.intern_pool.dependencyIterator(dependee);
@ -3695,268 +3296,6 @@ fn computePathDigest(zcu: *Zcu, mod: *Package.Module, sub_file_path: []const u8)
return bin;
}
pub fn scanNamespace(
zcu: *Zcu,
namespace_index: Namespace.Index,
decls: []const Zir.Inst.Index,
parent_decl: *Decl,
) Allocator.Error!void {
const tracy = trace(@src());
defer tracy.end();
const gpa = zcu.gpa;
const namespace = zcu.namespacePtr(namespace_index);
// For incremental updates, `scanDecl` wants to look up existing decls by their ZIR index rather
// than their name. We'll build an efficient mapping now, then discard the current `decls`.
var existing_by_inst: std.AutoHashMapUnmanaged(InternPool.TrackedInst.Index, Decl.Index) = .{};
defer existing_by_inst.deinit(gpa);
try existing_by_inst.ensureTotalCapacity(gpa, @intCast(namespace.decls.count()));
for (namespace.decls.keys()) |decl_index| {
const decl = zcu.declPtr(decl_index);
existing_by_inst.putAssumeCapacityNoClobber(decl.zir_decl_index.unwrap().?, decl_index);
}
var seen_decls: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void) = .{};
defer seen_decls.deinit(gpa);
try zcu.comp.work_queue.ensureUnusedCapacity(decls.len);
namespace.decls.clearRetainingCapacity();
try namespace.decls.ensureTotalCapacity(gpa, decls.len);
namespace.usingnamespace_set.clearRetainingCapacity();
var scan_decl_iter: ScanDeclIter = .{
.zcu = zcu,
.namespace_index = namespace_index,
.parent_decl = parent_decl,
.seen_decls = &seen_decls,
.existing_by_inst = &existing_by_inst,
.pass = .named,
};
for (decls) |decl_inst| {
try scanDecl(&scan_decl_iter, decl_inst);
}
scan_decl_iter.pass = .unnamed;
for (decls) |decl_inst| {
try scanDecl(&scan_decl_iter, decl_inst);
}
if (seen_decls.count() != namespace.decls.count()) {
// Do a pass over the namespace contents and remove any decls from the last update
// which were removed in this one.
var i: usize = 0;
while (i < namespace.decls.count()) {
const decl_index = namespace.decls.keys()[i];
const decl = zcu.declPtr(decl_index);
if (!seen_decls.contains(decl.name)) {
// We must preserve namespace ordering for @typeInfo.
namespace.decls.orderedRemoveAt(i);
i -= 1;
}
}
}
}
const ScanDeclIter = struct {
zcu: *Zcu,
namespace_index: Namespace.Index,
parent_decl: *Decl,
seen_decls: *std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void),
existing_by_inst: *const std.AutoHashMapUnmanaged(InternPool.TrackedInst.Index, Decl.Index),
/// Decl scanning is run in two passes, so that we can detect when a generated
/// name would clash with an explicit name and use a different one.
pass: enum { named, unnamed },
usingnamespace_index: usize = 0,
comptime_index: usize = 0,
unnamed_test_index: usize = 0,
fn avoidNameConflict(iter: *ScanDeclIter, comptime fmt: []const u8, args: anytype) !InternPool.NullTerminatedString {
const zcu = iter.zcu;
const gpa = zcu.gpa;
const ip = &zcu.intern_pool;
var name = try ip.getOrPutStringFmt(gpa, fmt, args, .no_embedded_nulls);
var gop = try iter.seen_decls.getOrPut(gpa, name);
var next_suffix: u32 = 0;
while (gop.found_existing) {
name = try ip.getOrPutStringFmt(gpa, "{}_{d}", .{ name.fmt(ip), next_suffix }, .no_embedded_nulls);
gop = try iter.seen_decls.getOrPut(gpa, name);
next_suffix += 1;
}
return name;
}
};
fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void {
const tracy = trace(@src());
defer tracy.end();
const zcu = iter.zcu;
const namespace_index = iter.namespace_index;
const namespace = zcu.namespacePtr(namespace_index);
const gpa = zcu.gpa;
const zir = namespace.fileScope(zcu).zir;
const ip = &zcu.intern_pool;
const inst_data = zir.instructions.items(.data)[@intFromEnum(decl_inst)].declaration;
const extra = zir.extraData(Zir.Inst.Declaration, inst_data.payload_index);
const declaration = extra.data;
// Every Decl needs a name.
const decl_name: InternPool.NullTerminatedString, const kind: Decl.Kind, const is_named_test: bool = switch (declaration.name) {
.@"comptime" => info: {
if (iter.pass != .unnamed) return;
const i = iter.comptime_index;
iter.comptime_index += 1;
break :info .{
try iter.avoidNameConflict("comptime_{d}", .{i}),
.@"comptime",
false,
};
},
.@"usingnamespace" => info: {
// TODO: this isn't right! These should be considered unnamed. Name conflicts can happen here.
// The problem is, we need to preserve the decl ordering for `@typeInfo`.
// I'm not bothering to fix this now, since some upcoming changes will change this code significantly anyway.
if (iter.pass != .named) return;
const i = iter.usingnamespace_index;
iter.usingnamespace_index += 1;
break :info .{
try iter.avoidNameConflict("usingnamespace_{d}", .{i}),
.@"usingnamespace",
false,
};
},
.unnamed_test => info: {
if (iter.pass != .unnamed) return;
const i = iter.unnamed_test_index;
iter.unnamed_test_index += 1;
break :info .{
try iter.avoidNameConflict("test_{d}", .{i}),
.@"test",
false,
};
},
.decltest => info: {
// We consider these to be unnamed since the decl name can be adjusted to avoid conflicts if necessary.
if (iter.pass != .unnamed) return;
assert(declaration.flags.has_doc_comment);
const name = zir.nullTerminatedString(@enumFromInt(zir.extra[extra.end]));
break :info .{
try iter.avoidNameConflict("decltest.{s}", .{name}),
.@"test",
true,
};
},
_ => if (declaration.name.isNamedTest(zir)) info: {
// We consider these to be unnamed since the decl name can be adjusted to avoid conflicts if necessary.
if (iter.pass != .unnamed) return;
break :info .{
try iter.avoidNameConflict("test.{s}", .{zir.nullTerminatedString(declaration.name.toString(zir).?)}),
.@"test",
true,
};
} else info: {
if (iter.pass != .named) return;
const name = try ip.getOrPutString(
gpa,
zir.nullTerminatedString(declaration.name.toString(zir).?),
.no_embedded_nulls,
);
try iter.seen_decls.putNoClobber(gpa, name, {});
break :info .{
name,
.named,
false,
};
},
};
switch (kind) {
.@"usingnamespace" => try namespace.usingnamespace_set.ensureUnusedCapacity(gpa, 1),
.@"test" => try zcu.test_functions.ensureUnusedCapacity(gpa, 1),
else => {},
}
const parent_file_scope_index = iter.parent_decl.getFileScopeIndex(zcu);
const tracked_inst = try ip.trackZir(gpa, parent_file_scope_index, decl_inst);
// We create a Decl for it regardless of analysis status.
const prev_exported, const decl_index = if (iter.existing_by_inst.get(tracked_inst)) |decl_index| decl_index: {
// We need only update this existing Decl.
const decl = zcu.declPtr(decl_index);
const was_exported = decl.is_exported;
assert(decl.kind == kind); // ZIR tracking should preserve this
decl.name = decl_name;
decl.is_pub = declaration.flags.is_pub;
decl.is_exported = declaration.flags.is_export;
break :decl_index .{ was_exported, decl_index };
} else decl_index: {
// Create and set up a new Decl.
const new_decl_index = try zcu.allocateNewDecl(namespace_index);
const new_decl = zcu.declPtr(new_decl_index);
new_decl.kind = kind;
new_decl.name = decl_name;
new_decl.is_pub = declaration.flags.is_pub;
new_decl.is_exported = declaration.flags.is_export;
new_decl.zir_decl_index = tracked_inst.toOptional();
break :decl_index .{ false, new_decl_index };
};
const decl = zcu.declPtr(decl_index);
namespace.decls.putAssumeCapacityNoClobberContext(decl_index, {}, .{ .zcu = zcu });
const comp = zcu.comp;
const decl_mod = namespace.fileScope(zcu).mod;
const want_analysis = declaration.flags.is_export or switch (kind) {
.anon => unreachable,
.@"comptime" => true,
.@"usingnamespace" => a: {
namespace.usingnamespace_set.putAssumeCapacityNoClobber(decl_index, declaration.flags.is_pub);
break :a true;
},
.named => false,
.@"test" => a: {
if (!comp.config.is_test) break :a false;
if (decl_mod != zcu.main_mod) break :a false;
if (is_named_test and comp.test_filters.len > 0) {
const decl_fqn = try namespace.fullyQualifiedName(zcu, decl_name);
const decl_fqn_slice = decl_fqn.toSlice(ip);
for (comp.test_filters) |test_filter| {
if (mem.indexOf(u8, decl_fqn_slice, test_filter)) |_| break;
} else break :a false;
}
zcu.test_functions.putAssumeCapacity(decl_index, {}); // may clobber on incremental update
break :a true;
},
};
if (want_analysis) {
// We will not queue analysis if the decl has been analyzed on a previous update and
// `is_export` is unchanged. In this case, the incremental update mechanism will handle
// re-analysis for us if necessary.
if (prev_exported != declaration.flags.is_export or decl.analysis == .unreferenced) {
log.debug("scanDecl queue analyze_decl file='{s}' decl_name='{}' decl_index={d}", .{
namespace.fileScope(zcu).sub_file_path, decl_name.fmt(ip), decl_index,
});
comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = decl_index });
}
}
if (decl.getOwnedFunction(zcu) != null) {
// TODO this logic is insufficient; namespaces we don't re-scan may still require
// updated line numbers. Look into this!
// TODO Look into detecting when this would be unnecessary by storing enough state
// in `Decl` to notice that the line number did not change.
comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl_index });
}
}
/// 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_index: Decl.Index) void {

View File

@ -5,6 +5,411 @@ tid: Id,
pub const Id = if (builtin.single_threaded) enum { main } else enum(usize) { main, _ };
pub fn astGenFile(
pt: Zcu.PerThread,
file: *Zcu.File,
/// This parameter is provided separately from `file` because it is not
/// safe to access `import_table` without a lock, and this index is needed
/// in the call to `updateZirRefs`.
file_index: Zcu.File.Index,
path_digest: Cache.BinDigest,
opt_root_decl: Zcu.Decl.OptionalIndex,
) !void {
assert(!file.mod.isBuiltin());
const tracy = trace(@src());
defer tracy.end();
const zcu = pt.zcu;
const comp = zcu.comp;
const gpa = zcu.gpa;
// In any case we need to examine the stat of the file to determine the course of action.
var source_file = try file.mod.root.openFile(file.sub_file_path, .{});
defer source_file.close();
const stat = try source_file.stat();
const want_local_cache = file.mod == zcu.main_mod;
const hex_digest = Cache.binToHex(path_digest);
const cache_directory = if (want_local_cache) zcu.local_zir_cache else zcu.global_zir_cache;
const zir_dir = cache_directory.handle;
// Determine whether we need to reload the file from disk and redo parsing and AstGen.
var lock: std.fs.File.Lock = switch (file.status) {
.never_loaded, .retryable_failure => lock: {
// First, load the cached ZIR code, if any.
log.debug("AstGen checking cache: {s} (local={}, digest={s})", .{
file.sub_file_path, want_local_cache, &hex_digest,
});
break :lock .shared;
},
.parse_failure, .astgen_failure, .success_zir => lock: {
const unchanged_metadata =
stat.size == file.stat.size and
stat.mtime == file.stat.mtime and
stat.inode == file.stat.inode;
if (unchanged_metadata) {
log.debug("unmodified metadata of file: {s}", .{file.sub_file_path});
return;
}
log.debug("metadata changed: {s}", .{file.sub_file_path});
break :lock .exclusive;
},
};
// We ask for a lock in order to coordinate with other zig processes.
// If another process is already working on this file, we will get the cached
// version. Likewise if we're working on AstGen and another process asks for
// the cached file, they'll get it.
const cache_file = while (true) {
break zir_dir.createFile(&hex_digest, .{
.read = true,
.truncate = false,
.lock = lock,
}) catch |err| switch (err) {
error.NotDir => unreachable, // no dir components
error.InvalidUtf8 => unreachable, // it's a hex encoded name
error.InvalidWtf8 => unreachable, // it's a hex encoded name
error.BadPathName => unreachable, // it's a hex encoded name
error.NameTooLong => unreachable, // it's a fixed size name
error.PipeBusy => unreachable, // it's not a pipe
error.WouldBlock => unreachable, // not asking for non-blocking I/O
// There are no dir components, so you would think that this was
// unreachable, however we have observed on macOS two processes racing
// to do openat() with O_CREAT manifest in ENOENT.
error.FileNotFound => continue,
else => |e| return e, // Retryable errors are handled at callsite.
};
};
defer cache_file.close();
while (true) {
update: {
// First we read the header to determine the lengths of arrays.
const header = cache_file.reader().readStruct(Zir.Header) catch |err| switch (err) {
// This can happen if Zig bails out of this function between creating
// the cached file and writing it.
error.EndOfStream => break :update,
else => |e| return e,
};
const unchanged_metadata =
stat.size == header.stat_size and
stat.mtime == header.stat_mtime and
stat.inode == header.stat_inode;
if (!unchanged_metadata) {
log.debug("AstGen cache stale: {s}", .{file.sub_file_path});
break :update;
}
log.debug("AstGen cache hit: {s} instructions_len={d}", .{
file.sub_file_path, header.instructions_len,
});
file.zir = Zcu.loadZirCacheBody(gpa, header, cache_file) catch |err| switch (err) {
error.UnexpectedFileSize => {
log.warn("unexpected EOF reading cached ZIR for {s}", .{file.sub_file_path});
break :update;
},
else => |e| return e,
};
file.zir_loaded = true;
file.stat = .{
.size = header.stat_size,
.inode = header.stat_inode,
.mtime = header.stat_mtime,
};
file.status = .success_zir;
log.debug("AstGen cached success: {s}", .{file.sub_file_path});
// TODO don't report compile errors until Sema @importFile
if (file.zir.hasCompileErrors()) {
{
comp.mutex.lock();
defer comp.mutex.unlock();
try zcu.failed_files.putNoClobber(gpa, file, null);
}
file.status = .astgen_failure;
return error.AnalysisFail;
}
return;
}
// If we already have the exclusive lock then it is our job to update.
if (builtin.os.tag == .wasi or lock == .exclusive) break;
// Otherwise, unlock to give someone a chance to get the exclusive lock
// and then upgrade to an exclusive lock.
cache_file.unlock();
lock = .exclusive;
try cache_file.lock(lock);
}
// The cache is definitely stale so delete the contents to avoid an underwrite later.
cache_file.setEndPos(0) catch |err| switch (err) {
error.FileTooBig => unreachable, // 0 is not too big
else => |e| return e,
};
pt.lockAndClearFileCompileError(file);
// If the previous ZIR does not have compile errors, keep it around
// in case parsing or new ZIR fails. In case of successful ZIR update
// at the end of this function we will free it.
// We keep the previous ZIR loaded so that we can use it
// for the update next time it does not have any compile errors. This avoids
// needlessly tossing out semantic analysis work when an error is
// temporarily introduced.
if (file.zir_loaded and !file.zir.hasCompileErrors()) {
assert(file.prev_zir == null);
const prev_zir_ptr = try gpa.create(Zir);
file.prev_zir = prev_zir_ptr;
prev_zir_ptr.* = file.zir;
file.zir = undefined;
file.zir_loaded = false;
}
file.unload(gpa);
if (stat.size > std.math.maxInt(u32))
return error.FileTooBig;
const source = try gpa.allocSentinel(u8, @as(usize, @intCast(stat.size)), 0);
defer if (!file.source_loaded) gpa.free(source);
const amt = try source_file.readAll(source);
if (amt != stat.size)
return error.UnexpectedEndOfFile;
file.stat = .{
.size = stat.size,
.inode = stat.inode,
.mtime = stat.mtime,
};
file.source = source;
file.source_loaded = true;
file.tree = try Ast.parse(gpa, source, .zig);
file.tree_loaded = true;
// Any potential AST errors are converted to ZIR errors here.
file.zir = try AstGen.generate(gpa, file.tree);
file.zir_loaded = true;
file.status = .success_zir;
log.debug("AstGen fresh success: {s}", .{file.sub_file_path});
const safety_buffer = if (Zcu.data_has_safety_tag)
try gpa.alloc([8]u8, file.zir.instructions.len)
else
undefined;
defer if (Zcu.data_has_safety_tag) gpa.free(safety_buffer);
const data_ptr = if (Zcu.data_has_safety_tag)
if (file.zir.instructions.len == 0)
@as([*]const u8, undefined)
else
@as([*]const u8, @ptrCast(safety_buffer.ptr))
else
@as([*]const u8, @ptrCast(file.zir.instructions.items(.data).ptr));
if (Zcu.data_has_safety_tag) {
// The `Data` union has a safety tag but in the file format we store it without.
for (file.zir.instructions.items(.data), 0..) |*data, i| {
const as_struct: *const Zcu.HackDataLayout = @ptrCast(data);
safety_buffer[i] = as_struct.data;
}
}
const header: Zir.Header = .{
.instructions_len = @as(u32, @intCast(file.zir.instructions.len)),
.string_bytes_len = @as(u32, @intCast(file.zir.string_bytes.len)),
.extra_len = @as(u32, @intCast(file.zir.extra.len)),
.stat_size = stat.size,
.stat_inode = stat.inode,
.stat_mtime = stat.mtime,
};
var iovecs = [_]std.posix.iovec_const{
.{
.base = @as([*]const u8, @ptrCast(&header)),
.len = @sizeOf(Zir.Header),
},
.{
.base = @as([*]const u8, @ptrCast(file.zir.instructions.items(.tag).ptr)),
.len = file.zir.instructions.len,
},
.{
.base = data_ptr,
.len = file.zir.instructions.len * 8,
},
.{
.base = file.zir.string_bytes.ptr,
.len = file.zir.string_bytes.len,
},
.{
.base = @as([*]const u8, @ptrCast(file.zir.extra.ptr)),
.len = file.zir.extra.len * 4,
},
};
cache_file.writevAll(&iovecs) catch |err| {
log.warn("unable to write cached ZIR code for {}{s} to {}{s}: {s}", .{
file.mod.root, file.sub_file_path, cache_directory, &hex_digest, @errorName(err),
});
};
if (file.zir.hasCompileErrors()) {
{
comp.mutex.lock();
defer comp.mutex.unlock();
try zcu.failed_files.putNoClobber(gpa, file, null);
}
file.status = .astgen_failure;
return error.AnalysisFail;
}
if (file.prev_zir) |prev_zir| {
try pt.updateZirRefs(file, file_index, prev_zir.*);
// No need to keep previous ZIR.
prev_zir.deinit(gpa);
gpa.destroy(prev_zir);
file.prev_zir = null;
}
if (opt_root_decl.unwrap()) |root_decl| {
// The root of this file must be re-analyzed, since the file has changed.
comp.mutex.lock();
defer comp.mutex.unlock();
log.debug("outdated root Decl: {}", .{root_decl});
try zcu.outdated_file_root.put(gpa, root_decl, {});
}
}
/// This is called from the AstGen thread pool, so must acquire
/// the Compilation mutex when acting on shared state.
fn updateZirRefs(pt: Zcu.PerThread, file: *Zcu.File, file_index: Zcu.File.Index, old_zir: Zir) !void {
const zcu = pt.zcu;
const gpa = zcu.gpa;
const new_zir = file.zir;
var inst_map: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{};
defer inst_map.deinit(gpa);
try Zcu.mapOldZirToNew(gpa, old_zir, new_zir, &inst_map);
const old_tag = old_zir.instructions.items(.tag);
const old_data = old_zir.instructions.items(.data);
// TODO: this should be done after all AstGen workers complete, to avoid
// iterating over this full set for every updated file.
for (zcu.intern_pool.tracked_insts.keys(), 0..) |*ti, idx_raw| {
const ti_idx: InternPool.TrackedInst.Index = @enumFromInt(idx_raw);
if (ti.file != file_index) continue;
const old_inst = ti.inst;
ti.inst = inst_map.get(ti.inst) orelse {
// Tracking failed for this instruction. Invalidate associated `src_hash` deps.
zcu.comp.mutex.lock();
defer zcu.comp.mutex.unlock();
log.debug("tracking failed for %{d}", .{old_inst});
try zcu.markDependeeOutdated(.{ .src_hash = ti_idx });
continue;
};
if (old_zir.getAssociatedSrcHash(old_inst)) |old_hash| hash_changed: {
if (new_zir.getAssociatedSrcHash(ti.inst)) |new_hash| {
if (std.zig.srcHashEql(old_hash, new_hash)) {
break :hash_changed;
}
log.debug("hash for (%{d} -> %{d}) changed: {} -> {}", .{
old_inst,
ti.inst,
std.fmt.fmtSliceHexLower(&old_hash),
std.fmt.fmtSliceHexLower(&new_hash),
});
}
// The source hash associated with this instruction changed - invalidate relevant dependencies.
zcu.comp.mutex.lock();
defer zcu.comp.mutex.unlock();
try zcu.markDependeeOutdated(.{ .src_hash = ti_idx });
}
// If this is a `struct_decl` etc, we must invalidate any outdated namespace dependencies.
const has_namespace = switch (old_tag[@intFromEnum(old_inst)]) {
.extended => switch (old_data[@intFromEnum(old_inst)].extended.opcode) {
.struct_decl, .union_decl, .opaque_decl, .enum_decl => true,
else => false,
},
else => false,
};
if (!has_namespace) continue;
var old_names: std.AutoArrayHashMapUnmanaged(InternPool.NullTerminatedString, void) = .{};
defer old_names.deinit(zcu.gpa);
{
var it = old_zir.declIterator(old_inst);
while (it.next()) |decl_inst| {
const decl_name = old_zir.getDeclaration(decl_inst)[0].name;
switch (decl_name) {
.@"comptime", .@"usingnamespace", .unnamed_test, .decltest => continue,
_ => if (decl_name.isNamedTest(old_zir)) continue,
}
const name_zir = decl_name.toString(old_zir).?;
const name_ip = try zcu.intern_pool.getOrPutString(
zcu.gpa,
pt.tid,
old_zir.nullTerminatedString(name_zir),
.no_embedded_nulls,
);
try old_names.put(zcu.gpa, name_ip, {});
}
}
var any_change = false;
{
var it = new_zir.declIterator(ti.inst);
while (it.next()) |decl_inst| {
const decl_name = old_zir.getDeclaration(decl_inst)[0].name;
switch (decl_name) {
.@"comptime", .@"usingnamespace", .unnamed_test, .decltest => continue,
_ => if (decl_name.isNamedTest(old_zir)) continue,
}
const name_zir = decl_name.toString(old_zir).?;
const name_ip = try zcu.intern_pool.getOrPutString(
zcu.gpa,
pt.tid,
old_zir.nullTerminatedString(name_zir),
.no_embedded_nulls,
);
if (!old_names.swapRemove(name_ip)) continue;
// Name added
any_change = true;
zcu.comp.mutex.lock();
defer zcu.comp.mutex.unlock();
try zcu.markDependeeOutdated(.{ .namespace_name = .{
.namespace = ti_idx,
.name = name_ip,
} });
}
}
// The only elements remaining in `old_names` now are any names which were removed.
for (old_names.keys()) |name_ip| {
any_change = true;
zcu.comp.mutex.lock();
defer zcu.comp.mutex.unlock();
try zcu.markDependeeOutdated(.{ .namespace_name = .{
.namespace = ti_idx,
.name = name_ip,
} });
}
if (any_change) {
zcu.comp.mutex.lock();
defer zcu.comp.mutex.unlock();
try zcu.markDependeeOutdated(.{ .namespace = ti_idx });
}
}
}
/// Like `ensureDeclAnalyzed`, but the Decl is a file's root Decl.
pub fn ensureFileAnalyzed(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.SemaError!void {
if (pt.zcu.fileRootDecl(file_index).unwrap()) |existing_root| {
@ -91,7 +496,7 @@ pub fn ensureDeclAnalyzed(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) Zcu.Sem
};
}
const decl_prog_node = mod.sema_prog_node.start((try decl.fullyQualifiedName(mod)).toSlice(ip), 0);
const decl_prog_node = mod.sema_prog_node.start((try decl.fullyQualifiedName(pt)).toSlice(ip), 0);
defer decl_prog_node.end();
break :blk pt.semaDecl(decl_index) catch |err| switch (err) {
@ -290,7 +695,7 @@ pub fn linkerUpdateFunc(pt: Zcu.PerThread, func_index: InternPool.Index, air: Ai
defer liveness.deinit(gpa);
if (build_options.enable_debug_extensions and comp.verbose_air) {
const fqn = try decl.fullyQualifiedName(zcu);
const fqn = try decl.fullyQualifiedName(pt);
std.debug.print("# Begin Function AIR: {}:\n", .{fqn.fmt(ip)});
@import("../print_air.zig").dump(pt, air, liveness);
std.debug.print("# End Function AIR: {}\n\n", .{fqn.fmt(ip)});
@ -324,7 +729,7 @@ pub fn linkerUpdateFunc(pt: Zcu.PerThread, func_index: InternPool.Index, air: Ai
};
}
const codegen_prog_node = zcu.codegen_prog_node.start((try decl.fullyQualifiedName(zcu)).toSlice(ip), 0);
const codegen_prog_node = zcu.codegen_prog_node.start((try decl.fullyQualifiedName(pt)).toSlice(ip), 0);
defer codegen_prog_node.end();
if (!air.typesFullyResolved(zcu)) {
@ -434,7 +839,7 @@ fn getFileRootStruct(
decl.owns_tv = true;
decl.analysis = .complete;
try zcu.scanNamespace(namespace_index, decls, decl);
try pt.scanNamespace(namespace_index, decls, decl);
try zcu.comp.work_queue.writeItem(.{ .resolve_type_fully = wip_ty.index });
return wip_ty.finish(ip, decl_index, namespace_index.toOptional());
}
@ -502,7 +907,7 @@ fn semaFileUpdate(pt: Zcu.PerThread, file_index: Zcu.File.Index, type_outdated:
const decls = file.zir.bodySlice(extra_index, decls_len);
if (!type_outdated) {
try zcu.scanNamespace(decl.src_namespace, decls, decl);
try pt.scanNamespace(decl.src_namespace, decls, decl);
}
return false;
@ -539,7 +944,7 @@ fn semaFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.SemaError!void {
zcu.setFileRootDecl(file_index, new_decl_index.toOptional());
zcu.namespacePtr(new_namespace_index).decl_index = new_decl_index;
new_decl.name = try file.fullyQualifiedName(zcu);
new_decl.name = try file.fullyQualifiedName(pt);
new_decl.name_fully_qualified = true;
new_decl.is_pub = true;
new_decl.is_exported = false;
@ -601,9 +1006,9 @@ fn semaDecl(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) !Zcu.SemaDeclResult {
}
log.debug("semaDecl '{d}'", .{@intFromEnum(decl_index)});
log.debug("decl name '{}'", .{(try decl.fullyQualifiedName(zcu)).fmt(ip)});
log.debug("decl name '{}'", .{(try decl.fullyQualifiedName(pt)).fmt(ip)});
defer blk: {
log.debug("finish decl name '{}'", .{(decl.fullyQualifiedName(zcu) catch break :blk).fmt(ip)});
log.debug("finish decl name '{}'", .{(decl.fullyQualifiedName(pt) catch break :blk).fmt(ip)});
}
const old_has_tv = decl.has_tv;
@ -631,7 +1036,7 @@ fn semaDecl(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) !Zcu.SemaDeclResult {
const std_file_root_decl_index = zcu.fileRootDecl(std_file_imported.file_index);
const std_decl = zcu.declPtr(std_file_root_decl_index.unwrap().?);
const std_namespace = std_decl.getInnerNamespace(zcu).?;
const builtin_str = try ip.getOrPutString(gpa, "builtin", .no_embedded_nulls);
const builtin_str = try ip.getOrPutString(gpa, pt.tid, "builtin", .no_embedded_nulls);
const builtin_decl = zcu.declPtr(std_namespace.decls.getKeyAdapted(builtin_str, Zcu.DeclAdapter{ .zcu = zcu }) orelse break :ip_index .none);
const builtin_namespace = builtin_decl.getInnerNamespaceIndex(zcu).unwrap() orelse break :ip_index .none;
if (decl.src_namespace != builtin_namespace) break :ip_index .none;
@ -802,7 +1207,7 @@ fn semaDecl(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) !Zcu.SemaDeclResult {
} else if (bytes.len == 0) {
return sema.fail(&block_scope, section_src, "linksection cannot be empty", .{});
}
break :blk try ip.getOrPutStringOpt(gpa, bytes, .no_embedded_nulls);
break :blk try ip.getOrPutStringOpt(gpa, pt.tid, bytes, .no_embedded_nulls);
};
decl.@"addrspace" = blk: {
const addrspace_ctx: Sema.AddressSpaceContext = switch (ip.indexToKey(decl_val.toIntern())) {
@ -996,7 +1401,7 @@ fn newEmbedFile(
} });
const array_val = try pt.intern(.{ .aggregate = .{
.ty = array_ty,
.storage = .{ .bytes = try ip.getOrPutTrailingString(gpa, bytes.len, .maybe_embedded_nulls) },
.storage = .{ .bytes = try ip.getOrPutTrailingString(gpa, pt.tid, bytes.len, .maybe_embedded_nulls) },
} });
const ptr_ty = (try pt.ptrType(.{
@ -1018,7 +1423,7 @@ fn newEmbedFile(
result.* = new_file;
new_file.* = .{
.sub_file_path = try ip.getOrPutString(gpa, sub_file_path, .no_embedded_nulls),
.sub_file_path = try ip.getOrPutString(gpa, pt.tid, sub_file_path, .no_embedded_nulls),
.owner = pkg,
.stat = stat,
.val = ptr_val,
@ -1027,6 +1432,271 @@ fn newEmbedFile(
return ptr_val;
}
pub fn scanNamespace(
pt: Zcu.PerThread,
namespace_index: Zcu.Namespace.Index,
decls: []const Zir.Inst.Index,
parent_decl: *Zcu.Decl,
) Allocator.Error!void {
const tracy = trace(@src());
defer tracy.end();
const zcu = pt.zcu;
const gpa = zcu.gpa;
const namespace = zcu.namespacePtr(namespace_index);
// For incremental updates, `scanDecl` wants to look up existing decls by their ZIR index rather
// than their name. We'll build an efficient mapping now, then discard the current `decls`.
var existing_by_inst: std.AutoHashMapUnmanaged(InternPool.TrackedInst.Index, Zcu.Decl.Index) = .{};
defer existing_by_inst.deinit(gpa);
try existing_by_inst.ensureTotalCapacity(gpa, @intCast(namespace.decls.count()));
for (namespace.decls.keys()) |decl_index| {
const decl = zcu.declPtr(decl_index);
existing_by_inst.putAssumeCapacityNoClobber(decl.zir_decl_index.unwrap().?, decl_index);
}
var seen_decls: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void) = .{};
defer seen_decls.deinit(gpa);
try zcu.comp.work_queue.ensureUnusedCapacity(decls.len);
namespace.decls.clearRetainingCapacity();
try namespace.decls.ensureTotalCapacity(gpa, decls.len);
namespace.usingnamespace_set.clearRetainingCapacity();
var scan_decl_iter: ScanDeclIter = .{
.pt = pt,
.namespace_index = namespace_index,
.parent_decl = parent_decl,
.seen_decls = &seen_decls,
.existing_by_inst = &existing_by_inst,
.pass = .named,
};
for (decls) |decl_inst| {
try scan_decl_iter.scanDecl(decl_inst);
}
scan_decl_iter.pass = .unnamed;
for (decls) |decl_inst| {
try scan_decl_iter.scanDecl(decl_inst);
}
if (seen_decls.count() != namespace.decls.count()) {
// Do a pass over the namespace contents and remove any decls from the last update
// which were removed in this one.
var i: usize = 0;
while (i < namespace.decls.count()) {
const decl_index = namespace.decls.keys()[i];
const decl = zcu.declPtr(decl_index);
if (!seen_decls.contains(decl.name)) {
// We must preserve namespace ordering for @typeInfo.
namespace.decls.orderedRemoveAt(i);
i -= 1;
}
}
}
}
const ScanDeclIter = struct {
pt: Zcu.PerThread,
namespace_index: Zcu.Namespace.Index,
parent_decl: *Zcu.Decl,
seen_decls: *std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, void),
existing_by_inst: *const std.AutoHashMapUnmanaged(InternPool.TrackedInst.Index, Zcu.Decl.Index),
/// Decl scanning is run in two passes, so that we can detect when a generated
/// name would clash with an explicit name and use a different one.
pass: enum { named, unnamed },
usingnamespace_index: usize = 0,
comptime_index: usize = 0,
unnamed_test_index: usize = 0,
fn avoidNameConflict(iter: *ScanDeclIter, comptime fmt: []const u8, args: anytype) !InternPool.NullTerminatedString {
const pt = iter.pt;
const gpa = pt.zcu.gpa;
const ip = &pt.zcu.intern_pool;
var name = try ip.getOrPutStringFmt(gpa, pt.tid, fmt, args, .no_embedded_nulls);
var gop = try iter.seen_decls.getOrPut(gpa, name);
var next_suffix: u32 = 0;
while (gop.found_existing) {
name = try ip.getOrPutStringFmt(gpa, pt.tid, "{}_{d}", .{ name.fmt(ip), next_suffix }, .no_embedded_nulls);
gop = try iter.seen_decls.getOrPut(gpa, name);
next_suffix += 1;
}
return name;
}
fn scanDecl(iter: *ScanDeclIter, decl_inst: Zir.Inst.Index) Allocator.Error!void {
const tracy = trace(@src());
defer tracy.end();
const pt = iter.pt;
const zcu = pt.zcu;
const namespace_index = iter.namespace_index;
const namespace = zcu.namespacePtr(namespace_index);
const gpa = zcu.gpa;
const zir = namespace.fileScope(zcu).zir;
const ip = &zcu.intern_pool;
const inst_data = zir.instructions.items(.data)[@intFromEnum(decl_inst)].declaration;
const extra = zir.extraData(Zir.Inst.Declaration, inst_data.payload_index);
const declaration = extra.data;
// Every Decl needs a name.
const decl_name: InternPool.NullTerminatedString, const kind: Zcu.Decl.Kind, const is_named_test: bool = switch (declaration.name) {
.@"comptime" => info: {
if (iter.pass != .unnamed) return;
const i = iter.comptime_index;
iter.comptime_index += 1;
break :info .{
try iter.avoidNameConflict("comptime_{d}", .{i}),
.@"comptime",
false,
};
},
.@"usingnamespace" => info: {
// TODO: this isn't right! These should be considered unnamed. Name conflicts can happen here.
// The problem is, we need to preserve the decl ordering for `@typeInfo`.
// I'm not bothering to fix this now, since some upcoming changes will change this code significantly anyway.
if (iter.pass != .named) return;
const i = iter.usingnamespace_index;
iter.usingnamespace_index += 1;
break :info .{
try iter.avoidNameConflict("usingnamespace_{d}", .{i}),
.@"usingnamespace",
false,
};
},
.unnamed_test => info: {
if (iter.pass != .unnamed) return;
const i = iter.unnamed_test_index;
iter.unnamed_test_index += 1;
break :info .{
try iter.avoidNameConflict("test_{d}", .{i}),
.@"test",
false,
};
},
.decltest => info: {
// We consider these to be unnamed since the decl name can be adjusted to avoid conflicts if necessary.
if (iter.pass != .unnamed) return;
assert(declaration.flags.has_doc_comment);
const name = zir.nullTerminatedString(@enumFromInt(zir.extra[extra.end]));
break :info .{
try iter.avoidNameConflict("decltest.{s}", .{name}),
.@"test",
true,
};
},
_ => if (declaration.name.isNamedTest(zir)) info: {
// We consider these to be unnamed since the decl name can be adjusted to avoid conflicts if necessary.
if (iter.pass != .unnamed) return;
break :info .{
try iter.avoidNameConflict("test.{s}", .{zir.nullTerminatedString(declaration.name.toString(zir).?)}),
.@"test",
true,
};
} else info: {
if (iter.pass != .named) return;
const name = try ip.getOrPutString(
gpa,
pt.tid,
zir.nullTerminatedString(declaration.name.toString(zir).?),
.no_embedded_nulls,
);
try iter.seen_decls.putNoClobber(gpa, name, {});
break :info .{
name,
.named,
false,
};
},
};
switch (kind) {
.@"usingnamespace" => try namespace.usingnamespace_set.ensureUnusedCapacity(gpa, 1),
.@"test" => try zcu.test_functions.ensureUnusedCapacity(gpa, 1),
else => {},
}
const parent_file_scope_index = iter.parent_decl.getFileScopeIndex(zcu);
const tracked_inst = try ip.trackZir(gpa, parent_file_scope_index, decl_inst);
// We create a Decl for it regardless of analysis status.
const prev_exported, const decl_index = if (iter.existing_by_inst.get(tracked_inst)) |decl_index| decl_index: {
// We need only update this existing Decl.
const decl = zcu.declPtr(decl_index);
const was_exported = decl.is_exported;
assert(decl.kind == kind); // ZIR tracking should preserve this
decl.name = decl_name;
decl.is_pub = declaration.flags.is_pub;
decl.is_exported = declaration.flags.is_export;
break :decl_index .{ was_exported, decl_index };
} else decl_index: {
// Create and set up a new Decl.
const new_decl_index = try zcu.allocateNewDecl(namespace_index);
const new_decl = zcu.declPtr(new_decl_index);
new_decl.kind = kind;
new_decl.name = decl_name;
new_decl.is_pub = declaration.flags.is_pub;
new_decl.is_exported = declaration.flags.is_export;
new_decl.zir_decl_index = tracked_inst.toOptional();
break :decl_index .{ false, new_decl_index };
};
const decl = zcu.declPtr(decl_index);
namespace.decls.putAssumeCapacityNoClobberContext(decl_index, {}, .{ .zcu = zcu });
const comp = zcu.comp;
const decl_mod = namespace.fileScope(zcu).mod;
const want_analysis = declaration.flags.is_export or switch (kind) {
.anon => unreachable,
.@"comptime" => true,
.@"usingnamespace" => a: {
namespace.usingnamespace_set.putAssumeCapacityNoClobber(decl_index, declaration.flags.is_pub);
break :a true;
},
.named => false,
.@"test" => a: {
if (!comp.config.is_test) break :a false;
if (decl_mod != zcu.main_mod) break :a false;
if (is_named_test and comp.test_filters.len > 0) {
const decl_fqn = try namespace.fullyQualifiedName(pt, decl_name);
const decl_fqn_slice = decl_fqn.toSlice(ip);
for (comp.test_filters) |test_filter| {
if (std.mem.indexOf(u8, decl_fqn_slice, test_filter)) |_| break;
} else break :a false;
}
zcu.test_functions.putAssumeCapacity(decl_index, {}); // may clobber on incremental update
break :a true;
},
};
if (want_analysis) {
// We will not queue analysis if the decl has been analyzed on a previous update and
// `is_export` is unchanged. In this case, the incremental update mechanism will handle
// re-analysis for us if necessary.
if (prev_exported != declaration.flags.is_export or decl.analysis == .unreferenced) {
log.debug("scanDecl queue analyze_decl file='{s}' decl_name='{}' decl_index={d}", .{
namespace.fileScope(zcu).sub_file_path, decl_name.fmt(ip), decl_index,
});
comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = decl_index });
}
}
if (decl.getOwnedFunction(zcu) != null) {
// TODO this logic is insufficient; namespaces we don't re-scan may still require
// updated line numbers. Look into this!
// TODO Look into detecting when this would be unnecessary by storing enough state
// in `Decl` to notice that the line number did not change.
comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl_index });
}
}
};
pub fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index, arena: Allocator) Zcu.SemaError!Air {
const tracy = trace(@src());
defer tracy.end();
@ -1038,12 +1708,12 @@ pub fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index, arena: All
const decl_index = func.owner_decl;
const decl = mod.declPtr(decl_index);
log.debug("func name '{}'", .{(try decl.fullyQualifiedName(mod)).fmt(ip)});
log.debug("func name '{}'", .{(try decl.fullyQualifiedName(pt)).fmt(ip)});
defer blk: {
log.debug("finish func name '{}'", .{(decl.fullyQualifiedName(mod) catch break :blk).fmt(ip)});
log.debug("finish func name '{}'", .{(decl.fullyQualifiedName(pt) catch break :blk).fmt(ip)});
}
const decl_prog_node = mod.sema_prog_node.start((try decl.fullyQualifiedName(mod)).toSlice(ip), 0);
const decl_prog_node = mod.sema_prog_node.start((try decl.fullyQualifiedName(pt)).toSlice(ip), 0);
defer decl_prog_node.end();
mod.intern_pool.removeDependenciesForDepender(gpa, InternPool.AnalUnit.wrap(.{ .func = func_index }));
@ -1273,6 +1943,19 @@ pub fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index, arena: All
};
}
fn lockAndClearFileCompileError(pt: Zcu.PerThread, file: *Zcu.File) void {
switch (file.status) {
.success_zir, .retryable_failure => {},
.never_loaded, .parse_failure, .astgen_failure => {
pt.zcu.comp.mutex.lock();
defer pt.zcu.comp.mutex.unlock();
if (pt.zcu.failed_files.fetchSwapRemove(file)) |kv| {
if (kv.value) |msg| msg.destroy(pt.zcu.gpa); // Delete previous error message.
}
},
}
}
/// Called from `Compilation.update`, after everything is done, just before
/// reporting compile errors. In this function we emit exported symbol collision
/// errors and communicate exported symbols to the linker backend.
@ -1397,7 +2080,7 @@ pub fn populateTestFunctions(
const root_decl_index = zcu.fileRootDecl(builtin_file_index);
const root_decl = zcu.declPtr(root_decl_index.unwrap().?);
const builtin_namespace = zcu.namespacePtr(root_decl.src_namespace);
const test_functions_str = try ip.getOrPutString(gpa, "test_functions", .no_embedded_nulls);
const test_functions_str = try ip.getOrPutString(gpa, pt.tid, "test_functions", .no_embedded_nulls);
const decl_index = builtin_namespace.decls.getKeyAdapted(
test_functions_str,
Zcu.DeclAdapter{ .zcu = zcu },
@ -1424,7 +2107,7 @@ pub fn populateTestFunctions(
for (test_fn_vals, zcu.test_functions.keys()) |*test_fn_val, test_decl_index| {
const test_decl = zcu.declPtr(test_decl_index);
const test_decl_name = try test_decl.fullyQualifiedName(zcu);
const test_decl_name = try test_decl.fullyQualifiedName(pt);
const test_decl_name_len = test_decl_name.length(ip);
const test_name_anon_decl: InternPool.Key.Ptr.BaseAddr.AnonDecl = n: {
const test_name_ty = try pt.arrayType(.{
@ -1530,7 +2213,7 @@ pub fn linkerUpdateDecl(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) !void {
const decl = zcu.declPtr(decl_index);
const codegen_prog_node = zcu.codegen_prog_node.start((try decl.fullyQualifiedName(zcu)).toSlice(&zcu.intern_pool), 0);
const codegen_prog_node = zcu.codegen_prog_node.start((try decl.fullyQualifiedName(pt)).toSlice(&zcu.intern_pool), 0);
defer codegen_prog_node.end();
if (comp.bin_file) |lf| {
@ -2064,11 +2747,11 @@ pub fn getBuiltinDecl(pt: Zcu.PerThread, name: []const u8) Allocator.Error!Inter
const std_file_imported = zcu.importPkg(zcu.std_mod) catch @panic("failed to import lib/std.zig");
const std_file_root_decl = zcu.fileRootDecl(std_file_imported.file_index).unwrap().?;
const std_namespace = zcu.declPtr(std_file_root_decl).getOwnedInnerNamespace(zcu).?;
const builtin_str = try ip.getOrPutString(gpa, "builtin", .no_embedded_nulls);
const builtin_str = try ip.getOrPutString(gpa, pt.tid, "builtin", .no_embedded_nulls);
const builtin_decl = std_namespace.decls.getKeyAdapted(builtin_str, Zcu.DeclAdapter{ .zcu = zcu }) orelse @panic("lib/std.zig is corrupt and missing 'builtin'");
pt.ensureDeclAnalyzed(builtin_decl) catch @panic("std.builtin is corrupt");
const builtin_namespace = zcu.declPtr(builtin_decl).getInnerNamespace(zcu) orelse @panic("std.builtin is corrupt");
const name_str = try ip.getOrPutString(gpa, name, .no_embedded_nulls);
const name_str = try ip.getOrPutString(gpa, pt.tid, name, .no_embedded_nulls);
return builtin_namespace.decls.getKeyAdapted(name_str, Zcu.DeclAdapter{ .zcu = zcu }) orelse @panic("lib/std/builtin.zig is corrupt");
}
@ -2082,6 +2765,8 @@ pub fn getBuiltinType(pt: Zcu.PerThread, name: []const u8) Allocator.Error!Type
const Air = @import("../Air.zig");
const Allocator = std.mem.Allocator;
const assert = std.debug.assert;
const Ast = std.zig.Ast;
const AstGen = std.zig.AstGen;
const BigIntConst = std.math.big.int.Const;
const BigIntMutable = std.math.big.int.Mutable;
const build_options = @import("build_options");

View File

@ -2204,14 +2204,14 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
const func_val = (try func.air.value(pl_op.operand, pt)) orelse break :blk null;
if (func_val.getFunction(mod)) |function| {
_ = try func.bin_file.getOrCreateAtomForDecl(function.owner_decl);
_ = try func.bin_file.getOrCreateAtomForDecl(pt, function.owner_decl);
break :blk function.owner_decl;
} else if (func_val.getExternFunc(mod)) |extern_func| {
const ext_decl = mod.declPtr(extern_func.decl);
const ext_info = mod.typeToFunc(ext_decl.typeOf(mod)).?;
var func_type = try genFunctype(func.gpa, ext_info.cc, ext_info.param_types.get(ip), Type.fromInterned(ext_info.return_type), pt);
defer func_type.deinit(func.gpa);
const atom_index = try func.bin_file.getOrCreateAtomForDecl(extern_func.decl);
const atom_index = try func.bin_file.getOrCreateAtomForDecl(pt, extern_func.decl);
const atom = func.bin_file.getAtomPtr(atom_index);
const type_index = try func.bin_file.storeDeclType(extern_func.decl, func_type);
try func.bin_file.addOrUpdateImport(
@ -2224,7 +2224,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
} else switch (mod.intern_pool.indexToKey(func_val.ip_index)) {
.ptr => |ptr| if (ptr.byte_offset == 0) switch (ptr.base_addr) {
.decl => |decl| {
_ = try func.bin_file.getOrCreateAtomForDecl(decl);
_ = try func.bin_file.getOrCreateAtomForDecl(pt, decl);
break :blk decl;
},
else => {},
@ -3227,7 +3227,7 @@ fn lowerDeclRefValue(func: *CodeGen, decl_index: InternPool.DeclIndex, offset: u
return WValue{ .imm32 = 0xaaaaaaaa };
}
const atom_index = try func.bin_file.getOrCreateAtomForDecl(decl_index);
const atom_index = try func.bin_file.getOrCreateAtomForDecl(pt, decl_index);
const atom = func.bin_file.getAtom(atom_index);
const target_sym_index = @intFromEnum(atom.sym_index);
@ -7284,7 +7284,7 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {
defer arena_allocator.deinit();
const arena = arena_allocator.allocator();
const fqn = try mod.declPtr(enum_decl_index).fullyQualifiedName(mod);
const fqn = try mod.declPtr(enum_decl_index).fullyQualifiedName(pt);
const func_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{}", .{fqn.fmt(ip)});
// check if we already generated code for this.

View File

@ -756,7 +756,7 @@ fn lowerDeclRef(
return Result.ok;
}
const vaddr = try lf.getDeclVAddr(decl_index, .{
const vaddr = try lf.getDeclVAddr(pt, decl_index, .{
.parent_atom_index = reloc_info.parent_atom_index,
.offset = code.items.len,
.addend = @intCast(offset),

View File

@ -1744,7 +1744,7 @@ pub const Object = struct {
if (export_indices.len != 0) {
return updateExportedGlobal(self, zcu, global_index, export_indices);
} else {
const fqn = try self.builder.strtabString((try decl.fullyQualifiedName(zcu)).toSlice(ip));
const fqn = try self.builder.strtabString((try decl.fullyQualifiedName(pt)).toSlice(ip));
try global_index.rename(fqn, &self.builder);
global_index.setLinkage(.internal, &self.builder);
if (comp.config.dll_export_fns)
@ -2520,7 +2520,7 @@ pub const Object = struct {
const field_offset = ty.structFieldOffset(field_index, pt);
const field_name = struct_type.fieldName(ip, field_index).unwrap() orelse
try ip.getOrPutStringFmt(gpa, "{d}", .{field_index}, .no_embedded_nulls);
try ip.getOrPutStringFmt(gpa, pt.tid, "{d}", .{field_index}, .no_embedded_nulls);
fields.appendAssumeCapacity(try o.builder.debugMemberType(
try o.builder.metadataString(field_name.toSlice(ip)),
@ -2807,17 +2807,18 @@ pub const Object = struct {
}
fn getStackTraceType(o: *Object) Allocator.Error!Type {
const zcu = o.pt.zcu;
const pt = o.pt;
const zcu = pt.zcu;
const std_mod = zcu.std_mod;
const std_file_imported = zcu.importPkg(std_mod) catch unreachable;
const builtin_str = try zcu.intern_pool.getOrPutString(zcu.gpa, "builtin", .no_embedded_nulls);
const builtin_str = try zcu.intern_pool.getOrPutString(zcu.gpa, pt.tid, "builtin", .no_embedded_nulls);
const std_file_root_decl = zcu.fileRootDecl(std_file_imported.file_index);
const std_namespace = zcu.namespacePtr(zcu.declPtr(std_file_root_decl.unwrap().?).src_namespace);
const builtin_decl = std_namespace.decls.getKeyAdapted(builtin_str, Zcu.DeclAdapter{ .zcu = zcu }).?;
const stack_trace_str = try zcu.intern_pool.getOrPutString(zcu.gpa, "StackTrace", .no_embedded_nulls);
const stack_trace_str = try zcu.intern_pool.getOrPutString(zcu.gpa, pt.tid, "StackTrace", .no_embedded_nulls);
// buffer is only used for int_type, `builtin` is a struct.
const builtin_ty = zcu.declPtr(builtin_decl).val.toType();
const builtin_namespace = zcu.namespacePtrUnwrap(builtin_ty.getNamespaceIndex(zcu)).?;
@ -2865,7 +2866,7 @@ pub const Object = struct {
try o.builder.strtabString((if (is_extern)
decl.name
else
try decl.fullyQualifiedName(zcu)).toSlice(ip)),
try decl.fullyQualifiedName(pt)).toSlice(ip)),
toLlvmAddressSpace(decl.@"addrspace", target),
);
gop.value_ptr.* = function_index.ptrConst(&o.builder).global;
@ -3074,7 +3075,8 @@ pub const Object = struct {
if (gop.found_existing) return gop.value_ptr.ptr(&o.builder).kind.variable;
errdefer assert(o.decl_map.remove(decl_index));
const zcu = o.pt.zcu;
const pt = o.pt;
const zcu = pt.zcu;
const decl = zcu.declPtr(decl_index);
const is_extern = decl.isExtern(zcu);
@ -3082,7 +3084,7 @@ pub const Object = struct {
try o.builder.strtabString((if (is_extern)
decl.name
else
try decl.fullyQualifiedName(zcu)).toSlice(&zcu.intern_pool)),
try decl.fullyQualifiedName(pt)).toSlice(&zcu.intern_pool)),
try o.lowerType(decl.typeOf(zcu)),
toLlvmGlobalAddressSpace(decl.@"addrspace", zcu.getTarget()),
);
@ -3310,7 +3312,7 @@ pub const Object = struct {
return int_ty;
}
const fqn = try mod.declPtr(struct_type.decl.unwrap().?).fullyQualifiedName(mod);
const fqn = try mod.declPtr(struct_type.decl.unwrap().?).fullyQualifiedName(pt);
var llvm_field_types = std.ArrayListUnmanaged(Builder.Type){};
defer llvm_field_types.deinit(o.gpa);
@ -3464,7 +3466,7 @@ pub const Object = struct {
return enum_tag_ty;
}
const fqn = try mod.declPtr(union_obj.decl).fullyQualifiedName(mod);
const fqn = try mod.declPtr(union_obj.decl).fullyQualifiedName(pt);
const aligned_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[layout.most_aligned_field]);
const aligned_field_llvm_ty = try o.lowerType(aligned_field_ty);
@ -3525,7 +3527,7 @@ pub const Object = struct {
const gop = try o.type_map.getOrPut(o.gpa, t.toIntern());
if (!gop.found_existing) {
const decl = mod.declPtr(ip.loadOpaqueType(t.toIntern()).decl);
const fqn = try decl.fullyQualifiedName(mod);
const fqn = try decl.fullyQualifiedName(pt);
gop.value_ptr.* = try o.builder.opaqueType(try o.builder.string(fqn.toSlice(ip)));
}
return gop.value_ptr.*;
@ -4585,7 +4587,7 @@ pub const Object = struct {
const usize_ty = try o.lowerType(Type.usize);
const ret_ty = try o.lowerType(Type.slice_const_u8_sentinel_0);
const fqn = try zcu.declPtr(enum_type.decl).fullyQualifiedName(zcu);
const fqn = try zcu.declPtr(enum_type.decl).fullyQualifiedName(pt);
const target = zcu.root_mod.resolved_target.result;
const function_index = try o.builder.addFunction(
try o.builder.fnType(ret_ty, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal),
@ -5173,7 +5175,7 @@ pub const FuncGen = struct {
const line_number = decl.navSrcLine(zcu) + 1;
self.inlined = self.wip.debug_location;
const fqn = try decl.fullyQualifiedName(zcu);
const fqn = try decl.fullyQualifiedName(pt);
const fn_ty = try pt.funcType(.{
.param_types = &.{},
@ -9707,7 +9709,7 @@ pub const FuncGen = struct {
if (gop.found_existing) return gop.value_ptr.*;
errdefer assert(o.named_enum_map.remove(enum_type.decl));
const fqn = try zcu.declPtr(enum_type.decl).fullyQualifiedName(zcu);
const fqn = try zcu.declPtr(enum_type.decl).fullyQualifiedName(pt);
const target = zcu.root_mod.resolved_target.result;
const function_index = try o.builder.addFunction(
try o.builder.fnType(.i1, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal),

View File

@ -1753,7 +1753,7 @@ const DeclGen = struct {
}
const field_name = struct_type.fieldName(ip, field_index).unwrap() orelse
try ip.getOrPutStringFmt(mod.gpa, "{d}", .{field_index}, .no_embedded_nulls);
try ip.getOrPutStringFmt(mod.gpa, pt.tid, "{d}", .{field_index}, .no_embedded_nulls);
try member_types.append(try self.resolveType(field_ty, .indirect));
try member_names.append(field_name.toSlice(ip));
}
@ -3012,7 +3012,7 @@ const DeclGen = struct {
// Append the actual code into the functions section.
try self.spv.addFunction(spv_decl_index, self.func);
const fqn = try decl.fullyQualifiedName(self.pt.zcu);
const fqn = try decl.fullyQualifiedName(self.pt);
try self.spv.debugName(result_id, fqn.toSlice(ip));
// Temporarily generate a test kernel declaration if this is a test function.
@ -3041,7 +3041,7 @@ const DeclGen = struct {
.storage_class = final_storage_class,
});
const fqn = try decl.fullyQualifiedName(self.pt.zcu);
const fqn = try decl.fullyQualifiedName(self.pt);
try self.spv.debugName(result_id, fqn.toSlice(ip));
try self.spv.declareDeclDeps(spv_decl_index, &.{});
},
@ -3086,7 +3086,7 @@ const DeclGen = struct {
try self.func.body.emit(self.spv.gpa, .OpFunctionEnd, {});
try self.spv.addFunction(spv_decl_index, self.func);
const fqn = try decl.fullyQualifiedName(self.pt.zcu);
const fqn = try decl.fullyQualifiedName(self.pt);
try self.spv.debugNameFmt(initializer_id, "initializer of {}", .{fqn.fmt(ip)});
try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpExtInst, .{

View File

@ -424,14 +424,14 @@ pub const File = struct {
}
}
pub fn updateDeclLineNumber(base: *File, module: *Zcu, decl_index: InternPool.DeclIndex) UpdateDeclError!void {
const decl = module.declPtr(decl_index);
pub fn updateDeclLineNumber(base: *File, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) UpdateDeclError!void {
const decl = pt.zcu.declPtr(decl_index);
assert(decl.has_tv);
switch (base.tag) {
.spirv, .nvptx => {},
inline else => |tag| {
if (tag != .c and build_options.only_c) unreachable;
return @as(*tag.Type(), @fieldParentPtr("base", base)).updateDeclLineNumber(module, decl_index);
return @as(*tag.Type(), @fieldParentPtr("base", base)).updateDeclLineNumber(pt, decl_index);
},
}
}
@ -626,14 +626,14 @@ pub const File = struct {
/// `Decl`'s address was not yet resolved, or the containing atom gets moved in virtual memory.
/// May be called before or after updateFunc/updateDecl therefore it is up to the linker to allocate
/// the block/atom.
pub fn getDeclVAddr(base: *File, decl_index: InternPool.DeclIndex, reloc_info: RelocInfo) !u64 {
pub fn getDeclVAddr(base: *File, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex, reloc_info: RelocInfo) !u64 {
if (build_options.only_c) @compileError("unreachable");
switch (base.tag) {
.c => unreachable,
.spirv => unreachable,
.nvptx => unreachable,
inline else => |tag| {
return @as(*tag.Type(), @fieldParentPtr("base", base)).getDeclVAddr(decl_index, reloc_info);
return @as(*tag.Type(), @fieldParentPtr("base", base)).getDeclVAddr(pt, decl_index, reloc_info);
},
}
}

View File

@ -383,11 +383,11 @@ pub fn updateDecl(self: *C, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex)
gop.value_ptr.fwd_decl = try self.addString(object.dg.fwd_decl.items);
}
pub fn updateDeclLineNumber(self: *C, zcu: *Zcu, decl_index: InternPool.DeclIndex) !void {
pub fn updateDeclLineNumber(self: *C, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) !void {
// The C backend does not have the ability to fix line numbers without re-generating
// the entire Decl.
_ = self;
_ = zcu;
_ = pt;
_ = decl_index;
}

View File

@ -1176,7 +1176,7 @@ pub fn lowerUnnamedConst(self: *Coff, pt: Zcu.PerThread, val: Value, decl_index:
gop.value_ptr.* = .{};
}
const unnamed_consts = gop.value_ptr;
const decl_name = try decl.fullyQualifiedName(mod);
const decl_name = try decl.fullyQualifiedName(pt);
const index = unnamed_consts.items.len;
const sym_name = try std.fmt.allocPrint(gpa, "__unnamed_{}_{d}", .{ decl_name.fmt(&mod.intern_pool), index });
defer gpa.free(sym_name);
@ -1427,7 +1427,7 @@ fn updateDeclCode(self: *Coff, pt: Zcu.PerThread, decl_index: InternPool.DeclInd
const mod = pt.zcu;
const decl = mod.declPtr(decl_index);
const decl_name = try decl.fullyQualifiedName(mod);
const decl_name = try decl.fullyQualifiedName(pt);
log.debug("updateDeclCode {}{*}", .{ decl_name.fmt(&mod.intern_pool), decl });
const required_alignment: u32 = @intCast(decl.getAlignment(pt).toByteUnits() orelse 0);
@ -1855,7 +1855,7 @@ pub fn flushModule(self: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_no
assert(!self.imports_count_dirty);
}
pub fn getDeclVAddr(self: *Coff, decl_index: InternPool.DeclIndex, reloc_info: link.File.RelocInfo) !u64 {
pub fn getDeclVAddr(self: *Coff, _: Zcu.PerThread, decl_index: InternPool.DeclIndex, reloc_info: link.File.RelocInfo) !u64 {
assert(self.llvm_object == null);
const this_atom_index = try self.getOrCreateAtomForDecl(decl_index);
@ -1972,9 +1972,9 @@ pub fn getGlobalSymbol(self: *Coff, name: []const u8, lib_name_name: ?[]const u8
return global_index;
}
pub fn updateDeclLineNumber(self: *Coff, module: *Module, decl_index: InternPool.DeclIndex) !void {
pub fn updateDeclLineNumber(self: *Coff, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) !void {
_ = self;
_ = module;
_ = pt;
_ = decl_index;
log.debug("TODO implement updateDeclLineNumber", .{});
}

View File

@ -1082,7 +1082,7 @@ pub fn initDeclState(self: *Dwarf, pt: Zcu.PerThread, decl_index: InternPool.Dec
defer tracy.end();
const decl = pt.zcu.declPtr(decl_index);
const decl_linkage_name = try decl.fullyQualifiedName(pt.zcu);
const decl_linkage_name = try decl.fullyQualifiedName(pt);
log.debug("initDeclState {}{*}", .{ decl_linkage_name.fmt(&pt.zcu.intern_pool), decl });

View File

@ -543,7 +543,7 @@ pub fn deinit(self: *Elf) void {
self.comdat_group_sections.deinit(gpa);
}
pub fn getDeclVAddr(self: *Elf, decl_index: InternPool.DeclIndex, reloc_info: link.File.RelocInfo) !u64 {
pub fn getDeclVAddr(self: *Elf, _: Zcu.PerThread, decl_index: InternPool.DeclIndex, reloc_info: link.File.RelocInfo) !u64 {
assert(self.llvm_object == null);
return self.zigObjectPtr().?.getDeclVAddr(self, decl_index, reloc_info);
}
@ -3021,9 +3021,9 @@ pub fn updateExports(
return self.zigObjectPtr().?.updateExports(self, pt, exported, export_indices);
}
pub fn updateDeclLineNumber(self: *Elf, mod: *Module, decl_index: InternPool.DeclIndex) !void {
pub fn updateDeclLineNumber(self: *Elf, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) !void {
if (self.llvm_object) |_| return;
return self.zigObjectPtr().?.updateDeclLineNumber(mod, decl_index);
return self.zigObjectPtr().?.updateDeclLineNumber(pt, decl_index);
}
pub fn deleteExport(

View File

@ -908,7 +908,7 @@ fn updateDeclCode(
const gpa = elf_file.base.comp.gpa;
const mod = pt.zcu;
const decl = mod.declPtr(decl_index);
const decl_name = try decl.fullyQualifiedName(mod);
const decl_name = try decl.fullyQualifiedName(pt);
log.debug("updateDeclCode {}{*}", .{ decl_name.fmt(&mod.intern_pool), decl });
@ -1009,7 +1009,7 @@ fn updateTlv(
const mod = pt.zcu;
const gpa = mod.gpa;
const decl = mod.declPtr(decl_index);
const decl_name = try decl.fullyQualifiedName(mod);
const decl_name = try decl.fullyQualifiedName(pt);
log.debug("updateTlv {} ({*})", .{ decl_name.fmt(&mod.intern_pool), decl });
@ -1286,7 +1286,7 @@ pub fn lowerUnnamedConst(
}
const unnamed_consts = gop.value_ptr;
const decl = mod.declPtr(decl_index);
const decl_name = try decl.fullyQualifiedName(mod);
const decl_name = try decl.fullyQualifiedName(pt);
const index = unnamed_consts.items.len;
const name = try std.fmt.allocPrint(gpa, "__unnamed_{}_{d}", .{ decl_name.fmt(&mod.intern_pool), index });
defer gpa.free(name);
@ -1466,19 +1466,19 @@ pub fn updateExports(
/// Must be called only after a successful call to `updateDecl`.
pub fn updateDeclLineNumber(
self: *ZigObject,
mod: *Module,
pt: Zcu.PerThread,
decl_index: InternPool.DeclIndex,
) !void {
const tracy = trace(@src());
defer tracy.end();
const decl = mod.declPtr(decl_index);
const decl_name = try decl.fullyQualifiedName(mod);
const decl = pt.zcu.declPtr(decl_index);
const decl_name = try decl.fullyQualifiedName(pt);
log.debug("updateDeclLineNumber {}{*}", .{ decl_name.fmt(&mod.intern_pool), decl });
log.debug("updateDeclLineNumber {}{*}", .{ decl_name.fmt(&pt.zcu.intern_pool), decl });
if (self.dwarf) |*dw| {
try dw.updateDeclLineNumber(mod, decl_index);
try dw.updateDeclLineNumber(pt.zcu, decl_index);
}
}

View File

@ -3198,9 +3198,9 @@ pub fn updateDecl(self: *MachO, pt: Zcu.PerThread, decl_index: InternPool.DeclIn
return self.getZigObject().?.updateDecl(self, pt, decl_index);
}
pub fn updateDeclLineNumber(self: *MachO, module: *Module, decl_index: InternPool.DeclIndex) !void {
pub fn updateDeclLineNumber(self: *MachO, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) !void {
if (self.llvm_object) |_| return;
return self.getZigObject().?.updateDeclLineNumber(module, decl_index);
return self.getZigObject().?.updateDeclLineNumber(pt, decl_index);
}
pub fn updateExports(
@ -3230,7 +3230,7 @@ pub fn freeDecl(self: *MachO, decl_index: InternPool.DeclIndex) void {
return self.getZigObject().?.freeDecl(decl_index);
}
pub fn getDeclVAddr(self: *MachO, decl_index: InternPool.DeclIndex, reloc_info: link.File.RelocInfo) !u64 {
pub fn getDeclVAddr(self: *MachO, _: Zcu.PerThread, decl_index: InternPool.DeclIndex, reloc_info: link.File.RelocInfo) !u64 {
assert(self.llvm_object == null);
return self.getZigObject().?.getDeclVAddr(self, decl_index, reloc_info);
}

View File

@ -810,7 +810,7 @@ fn updateDeclCode(
const gpa = macho_file.base.comp.gpa;
const mod = pt.zcu;
const decl = mod.declPtr(decl_index);
const decl_name = try decl.fullyQualifiedName(mod);
const decl_name = try decl.fullyQualifiedName(pt);
log.debug("updateDeclCode {}{*}", .{ decl_name.fmt(&mod.intern_pool), decl });
@ -893,13 +893,12 @@ fn updateTlv(
sect_index: u8,
code: []const u8,
) !void {
const mod = pt.zcu;
const decl = mod.declPtr(decl_index);
const decl_name = try decl.fullyQualifiedName(mod);
const decl = pt.zcu.declPtr(decl_index);
const decl_name = try decl.fullyQualifiedName(pt);
log.debug("updateTlv {} ({*})", .{ decl_name.fmt(&mod.intern_pool), decl });
log.debug("updateTlv {} ({*})", .{ decl_name.fmt(&pt.zcu.intern_pool), decl });
const decl_name_slice = decl_name.toSlice(&mod.intern_pool);
const decl_name_slice = decl_name.toSlice(&pt.zcu.intern_pool);
const required_alignment = decl.getAlignment(pt);
// 1. Lower TLV initializer
@ -1100,7 +1099,7 @@ pub fn lowerUnnamedConst(
}
const unnamed_consts = gop.value_ptr;
const decl = mod.declPtr(decl_index);
const decl_name = try decl.fullyQualifiedName(mod);
const decl_name = try decl.fullyQualifiedName(pt);
const index = unnamed_consts.items.len;
const name = try std.fmt.allocPrint(gpa, "__unnamed_{}_{d}", .{ decl_name.fmt(&mod.intern_pool), index });
defer gpa.free(name);
@ -1363,9 +1362,9 @@ fn updateLazySymbol(
}
/// Must be called only after a successful call to `updateDecl`.
pub fn updateDeclLineNumber(self: *ZigObject, mod: *Module, decl_index: InternPool.DeclIndex) !void {
pub fn updateDeclLineNumber(self: *ZigObject, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) !void {
if (self.dwarf) |*dw| {
try dw.updateDeclLineNumber(mod, decl_index);
try dw.updateDeclLineNumber(pt.zcu, decl_index);
}
}

View File

@ -483,7 +483,7 @@ pub fn lowerUnnamedConst(self: *Plan9, pt: Zcu.PerThread, val: Value, decl_index
}
const unnamed_consts = gop.value_ptr;
const decl_name = try decl.fullyQualifiedName(mod);
const decl_name = try decl.fullyQualifiedName(pt);
const index = unnamed_consts.items.len;
// name is freed when the unnamed const is freed
@ -1496,22 +1496,22 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {
}
/// Must be called only after a successful call to `updateDecl`.
pub fn updateDeclLineNumber(self: *Plan9, mod: *Zcu, decl_index: InternPool.DeclIndex) !void {
pub fn updateDeclLineNumber(self: *Plan9, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) !void {
_ = self;
_ = mod;
_ = pt;
_ = decl_index;
}
pub fn getDeclVAddr(
self: *Plan9,
pt: Zcu.PerThread,
decl_index: InternPool.DeclIndex,
reloc_info: link.File.RelocInfo,
) !u64 {
const mod = self.base.comp.module.?;
const ip = &mod.intern_pool;
const decl = mod.declPtr(decl_index);
const ip = &pt.zcu.intern_pool;
const decl = pt.zcu.declPtr(decl_index);
log.debug("getDeclVAddr for {}", .{decl.name.fmt(ip)});
if (decl.isExtern(mod)) {
if (decl.isExtern(pt.zcu)) {
if (decl.name.eqlSlice("etext", ip)) {
try self.addReloc(reloc_info.parent_atom_index, .{
.target = undefined,

View File

@ -1457,9 +1457,9 @@ pub fn updateDecl(wasm: *Wasm, pt: Zcu.PerThread, decl_index: InternPool.DeclInd
try wasm.zigObjectPtr().?.updateDecl(wasm, pt, decl_index);
}
pub fn updateDeclLineNumber(wasm: *Wasm, mod: *Zcu, decl_index: InternPool.DeclIndex) !void {
pub fn updateDeclLineNumber(wasm: *Wasm, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) !void {
if (wasm.llvm_object) |_| return;
try wasm.zigObjectPtr().?.updateDeclLineNumber(mod, decl_index);
try wasm.zigObjectPtr().?.updateDeclLineNumber(pt, decl_index);
}
/// From a given symbol location, returns its `wasm.GlobalType`.
@ -1521,10 +1521,11 @@ pub fn getGlobalSymbol(wasm: *Wasm, name: []const u8, lib_name: ?[]const u8) !Sy
/// Returns the given pointer address
pub fn getDeclVAddr(
wasm: *Wasm,
pt: Zcu.PerThread,
decl_index: InternPool.DeclIndex,
reloc_info: link.File.RelocInfo,
) !u64 {
return wasm.zigObjectPtr().?.getDeclVAddr(wasm, decl_index, reloc_info);
return wasm.zigObjectPtr().?.getDeclVAddr(wasm, pt, decl_index, reloc_info);
}
pub fn lowerAnonDecl(
@ -4016,8 +4017,8 @@ pub fn getErrorTableSymbol(wasm_file: *Wasm, pt: Zcu.PerThread) !u32 {
/// For a given `InternPool.DeclIndex` returns its corresponding `Atom.Index`.
/// When the index was not found, a new `Atom` will be created, and its index will be returned.
/// The newly created Atom is empty with default fields as specified by `Atom.empty`.
pub fn getOrCreateAtomForDecl(wasm_file: *Wasm, decl_index: InternPool.DeclIndex) !Atom.Index {
return wasm_file.zigObjectPtr().?.getOrCreateAtomForDecl(wasm_file, decl_index);
pub fn getOrCreateAtomForDecl(wasm_file: *Wasm, pt: Zcu.PerThread, decl_index: InternPool.DeclIndex) !Atom.Index {
return wasm_file.zigObjectPtr().?.getOrCreateAtomForDecl(wasm_file, pt, decl_index);
}
/// Verifies all resolved symbols and checks whether itself needs to be marked alive,

View File

@ -253,7 +253,7 @@ pub fn updateDecl(
}
const gpa = wasm_file.base.comp.gpa;
const atom_index = try zig_object.getOrCreateAtomForDecl(wasm_file, decl_index);
const atom_index = try zig_object.getOrCreateAtomForDecl(wasm_file, pt, decl_index);
const atom = wasm_file.getAtomPtr(atom_index);
atom.clear();
@ -302,7 +302,7 @@ pub fn updateFunc(
const func = pt.zcu.funcInfo(func_index);
const decl_index = func.owner_decl;
const decl = pt.zcu.declPtr(decl_index);
const atom_index = try zig_object.getOrCreateAtomForDecl(wasm_file, decl_index);
const atom_index = try zig_object.getOrCreateAtomForDecl(wasm_file, pt, decl_index);
const atom = wasm_file.getAtomPtr(atom_index);
atom.clear();
@ -346,7 +346,7 @@ fn finishUpdateDecl(
const atom_index = decl_info.atom;
const atom = wasm_file.getAtomPtr(atom_index);
const sym = zig_object.symbol(atom.sym_index);
const full_name = try decl.fullyQualifiedName(zcu);
const full_name = try decl.fullyQualifiedName(pt);
sym.name = try zig_object.string_table.insert(gpa, full_name.toSlice(ip));
try atom.code.appendSlice(gpa, code);
atom.size = @intCast(code.len);
@ -424,17 +424,21 @@ fn createDataSegment(
/// For a given `InternPool.DeclIndex` returns its corresponding `Atom.Index`.
/// When the index was not found, a new `Atom` will be created, and its index will be returned.
/// The newly created Atom is empty with default fields as specified by `Atom.empty`.
pub fn getOrCreateAtomForDecl(zig_object: *ZigObject, wasm_file: *Wasm, decl_index: InternPool.DeclIndex) !Atom.Index {
const gpa = wasm_file.base.comp.gpa;
pub fn getOrCreateAtomForDecl(
zig_object: *ZigObject,
wasm_file: *Wasm,
pt: Zcu.PerThread,
decl_index: InternPool.DeclIndex,
) !Atom.Index {
const gpa = pt.zcu.gpa;
const gop = try zig_object.decls_map.getOrPut(gpa, decl_index);
if (!gop.found_existing) {
const sym_index = try zig_object.allocateSymbol(gpa);
gop.value_ptr.* = .{ .atom = try wasm_file.createAtom(sym_index, zig_object.index) };
const mod = wasm_file.base.comp.module.?;
const decl = mod.declPtr(decl_index);
const full_name = try decl.fullyQualifiedName(mod);
const decl = pt.zcu.declPtr(decl_index);
const full_name = try decl.fullyQualifiedName(pt);
const sym = zig_object.symbol(sym_index);
sym.name = try zig_object.string_table.insert(gpa, full_name.toSlice(&mod.intern_pool));
sym.name = try zig_object.string_table.insert(gpa, full_name.toSlice(&pt.zcu.intern_pool));
}
return gop.value_ptr.atom;
}
@ -487,10 +491,10 @@ pub fn lowerUnnamedConst(
std.debug.assert(val.typeOf(mod).zigTypeTag(mod) != .Fn); // cannot create local symbols for functions
const decl = mod.declPtr(decl_index);
const parent_atom_index = try zig_object.getOrCreateAtomForDecl(wasm_file, decl_index);
const parent_atom_index = try zig_object.getOrCreateAtomForDecl(wasm_file, pt, decl_index);
const parent_atom = wasm_file.getAtom(parent_atom_index);
const local_index = parent_atom.locals.items.len;
const fqn = try decl.fullyQualifiedName(mod);
const fqn = try decl.fullyQualifiedName(pt);
const name = try std.fmt.allocPrintZ(gpa, "__unnamed_{}_{d}", .{
fqn.fmt(&mod.intern_pool), local_index,
});
@ -775,22 +779,22 @@ pub fn getGlobalSymbol(zig_object: *ZigObject, gpa: std.mem.Allocator, name: []c
pub fn getDeclVAddr(
zig_object: *ZigObject,
wasm_file: *Wasm,
pt: Zcu.PerThread,
decl_index: InternPool.DeclIndex,
reloc_info: link.File.RelocInfo,
) !u64 {
const target = wasm_file.base.comp.root_mod.resolved_target.result;
const gpa = wasm_file.base.comp.gpa;
const mod = wasm_file.base.comp.module.?;
const decl = mod.declPtr(decl_index);
const gpa = pt.zcu.gpa;
const decl = pt.zcu.declPtr(decl_index);
const target_atom_index = try zig_object.getOrCreateAtomForDecl(wasm_file, decl_index);
const target_atom_index = try zig_object.getOrCreateAtomForDecl(wasm_file, pt, decl_index);
const target_symbol_index = @intFromEnum(wasm_file.getAtom(target_atom_index).sym_index);
std.debug.assert(reloc_info.parent_atom_index != 0);
const atom_index = wasm_file.symbol_atom.get(.{ .file = zig_object.index, .index = @enumFromInt(reloc_info.parent_atom_index) }).?;
const atom = wasm_file.getAtomPtr(atom_index);
const is_wasm32 = target.cpu.arch == .wasm32;
if (decl.typeOf(mod).zigTypeTag(mod) == .Fn) {
if (decl.typeOf(pt.zcu).zigTypeTag(pt.zcu) == .Fn) {
std.debug.assert(reloc_info.addend == 0); // addend not allowed for function relocations
try atom.relocs.append(gpa, .{
.index = target_symbol_index,
@ -890,7 +894,7 @@ pub fn updateExports(
},
};
const decl = mod.declPtr(decl_index);
const atom_index = try zig_object.getOrCreateAtomForDecl(wasm_file, decl_index);
const atom_index = try zig_object.getOrCreateAtomForDecl(wasm_file, pt, decl_index);
const decl_info = zig_object.decls_map.getPtr(decl_index).?;
const atom = wasm_file.getAtom(atom_index);
const atom_sym = atom.symbolLoc().getSymbol(wasm_file).*;
@ -1116,13 +1120,17 @@ pub fn createDebugSectionForIndex(zig_object: *ZigObject, wasm_file: *Wasm, inde
return atom_index;
}
pub fn updateDeclLineNumber(zig_object: *ZigObject, mod: *Zcu, decl_index: InternPool.DeclIndex) !void {
pub fn updateDeclLineNumber(
zig_object: *ZigObject,
pt: Zcu.PerThread,
decl_index: InternPool.DeclIndex,
) !void {
if (zig_object.dwarf) |*dw| {
const decl = mod.declPtr(decl_index);
const decl_name = try decl.fullyQualifiedName(mod);
const decl = pt.zcu.declPtr(decl_index);
const decl_name = try decl.fullyQualifiedName(pt);
log.debug("updateDeclLineNumber {}{*}", .{ decl_name.fmt(&mod.intern_pool), decl });
try dw.updateDeclLineNumber(mod, decl_index);
log.debug("updateDeclLineNumber {}{*}", .{ decl_name.fmt(&pt.zcu.intern_pool), decl });
try dw.updateDeclLineNumber(pt.zcu, decl_index);
}
}

View File

@ -71,7 +71,7 @@ pub const MutableValue = union(enum) {
} }),
.bytes => |b| try pt.intern(.{ .aggregate = .{
.ty = b.ty,
.storage = .{ .bytes = try pt.zcu.intern_pool.getOrPutString(pt.zcu.gpa, b.data, .maybe_embedded_nulls) },
.storage = .{ .bytes = try pt.zcu.intern_pool.getOrPutString(pt.zcu.gpa, pt.tid, b.data, .maybe_embedded_nulls) },
} }),
.aggregate => |a| {
const elems = try arena.alloc(InternPool.Index, a.elems.len);