Merge pull request #20570 from jacobly0/fix-races

InternPool: fix more races blocking a separate codegen/linker thread
This commit is contained in:
Matthew Lugg 2024-07-11 23:27:13 +01:00 committed by GitHub
commit 80d7e260d7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 1471 additions and 1003 deletions

View File

@ -1034,7 +1034,12 @@ pub const Inst = struct {
ty: Type,
arg: struct {
ty: Ref,
src_index: u32,
/// Index into `extra` of a null-terminated string representing the parameter name.
/// This is `.none` if debug info is stripped.
name: enum(u32) {
none = std.math.maxInt(u32),
_,
},
},
ty_op: struct {
ty: Ref,

View File

@ -1877,6 +1877,7 @@ pub fn destroy(comp: *Compilation) void {
if (comp.module) |zcu| zcu.deinit();
comp.cache_use.deinit();
comp.work_queue.deinit();
if (!InternPool.single_threaded) comp.codegen_work.queue.deinit();
comp.c_object_work_queue.deinit();
if (!build_options.only_core_functionality) {
comp.win32_resource_work_queue.deinit();
@ -2119,12 +2120,14 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
}
if (comp.module) |zcu| {
const pt: Zcu.PerThread = .{ .zcu = zcu, .tid = .main };
zcu.compile_log_text.shrinkAndFree(gpa, 0);
// Make sure std.zig is inside the import_table. We unconditionally need
// it for start.zig.
const std_mod = zcu.std_mod;
_ = try zcu.importPkg(std_mod);
_ = try pt.importPkg(std_mod);
// Normally we rely on importing std to in turn import the root source file
// in the start code, but when using the stage1 backend that won't happen,
@ -2133,20 +2136,19 @@ pub fn update(comp: *Compilation, main_progress_node: std.Progress.Node) !void {
// Likewise, in the case of `zig test`, the test runner is the root source file,
// and so there is nothing to import the main file.
if (comp.config.is_test) {
_ = try zcu.importPkg(zcu.main_mod);
_ = try pt.importPkg(zcu.main_mod);
}
if (zcu.root_mod.deps.get("compiler_rt")) |compiler_rt_mod| {
_ = try zcu.importPkg(compiler_rt_mod);
_ = try pt.importPkg(compiler_rt_mod);
}
// Put a work item in for every known source file to detect if
// it changed, and, if so, re-compute ZIR and then queue the job
// to update it.
try comp.astgen_work_queue.ensureUnusedCapacity(zcu.import_table.count());
for (zcu.import_table.values(), 0..) |file, file_index_usize| {
const file_index: Zcu.File.Index = @enumFromInt(file_index_usize);
if (file.mod.isBuiltin()) continue;
for (zcu.import_table.values()) |file_index| {
if (zcu.fileByIndex(file_index).mod.isBuiltin()) continue;
comp.astgen_work_queue.writeItemAssumeCapacity(file_index);
}
@ -2641,7 +2643,8 @@ fn resolveEmitLoc(
return slice.ptr;
}
fn reportMultiModuleErrors(zcu: *Zcu) !void {
fn reportMultiModuleErrors(pt: Zcu.PerThread) !void {
const zcu = pt.zcu;
const gpa = zcu.gpa;
const ip = &zcu.intern_pool;
// Some cases can give you a whole bunch of multi-module errors, which it's not helpful to
@ -2651,14 +2654,13 @@ fn reportMultiModuleErrors(zcu: *Zcu) !void {
// Attach the "some omitted" note to the final error message
var last_err: ?*Zcu.ErrorMsg = null;
for (zcu.import_table.values(), 0..) |file, file_index_usize| {
for (zcu.import_table.values()) |file_index| {
const file = zcu.fileByIndex(file_index);
if (!file.multi_pkg) continue;
num_errors += 1;
if (num_errors > max_errors) continue;
const file_index: Zcu.File.Index = @enumFromInt(file_index_usize);
const err = err_blk: {
// Like with errors, let's cap the number of notes to prevent a huge error spew.
const max_notes = 5;
@ -2674,7 +2676,10 @@ fn reportMultiModuleErrors(zcu: *Zcu) !void {
.import => |import| try Zcu.ErrorMsg.init(
gpa,
.{
.base_node_inst = try ip.trackZir(gpa, import.file, .main_struct_inst),
.base_node_inst = try ip.trackZir(gpa, pt.tid, .{
.file = import.file,
.inst = .main_struct_inst,
}),
.offset = .{ .token_abs = import.token },
},
"imported from module {s}",
@ -2683,7 +2688,10 @@ fn reportMultiModuleErrors(zcu: *Zcu) !void {
.root => |pkg| try Zcu.ErrorMsg.init(
gpa,
.{
.base_node_inst = try ip.trackZir(gpa, file_index, .main_struct_inst),
.base_node_inst = try ip.trackZir(gpa, pt.tid, .{
.file = file_index,
.inst = .main_struct_inst,
}),
.offset = .entire_file,
},
"root of module {s}",
@ -2697,7 +2705,10 @@ fn reportMultiModuleErrors(zcu: *Zcu) !void {
notes[num_notes] = try Zcu.ErrorMsg.init(
gpa,
.{
.base_node_inst = try ip.trackZir(gpa, file_index, .main_struct_inst),
.base_node_inst = try ip.trackZir(gpa, pt.tid, .{
.file = file_index,
.inst = .main_struct_inst,
}),
.offset = .entire_file,
},
"{} more references omitted",
@ -2709,7 +2720,10 @@ fn reportMultiModuleErrors(zcu: *Zcu) !void {
const err = try Zcu.ErrorMsg.create(
gpa,
.{
.base_node_inst = try ip.trackZir(gpa, file_index, .main_struct_inst),
.base_node_inst = try ip.trackZir(gpa, pt.tid, .{
.file = file_index,
.inst = .main_struct_inst,
}),
.offset = .entire_file,
},
"file exists in multiple modules",
@ -2749,8 +2763,9 @@ fn reportMultiModuleErrors(zcu: *Zcu) !void {
// to add this flag after reporting the errors however, as otherwise
// we'd get an error for every single downstream file, which wouldn't be
// very useful.
for (zcu.import_table.values()) |file| {
if (file.multi_pkg) file.recursiveMarkMultiPkg(zcu);
for (zcu.import_table.values()) |file_index| {
const file = zcu.fileByIndex(file_index);
if (file.multi_pkg) file.recursiveMarkMultiPkg(pt);
}
}
@ -2774,7 +2789,7 @@ const Header = extern struct {
//extra_len: u32,
//limbs_len: u32,
//string_bytes_len: u32,
tracked_insts_len: u32,
//tracked_insts_len: u32,
src_hash_deps_len: u32,
decl_val_deps_len: u32,
namespace_deps_len: u32,
@ -2782,7 +2797,7 @@ const Header = extern struct {
first_dependency_len: u32,
dep_entries_len: u32,
free_dep_entries_len: u32,
files_len: u32,
//files_len: u32,
},
};
@ -2803,7 +2818,7 @@ pub fn saveState(comp: *Compilation) !void {
//.extra_len = @intCast(ip.extra.items.len),
//.limbs_len = @intCast(ip.limbs.items.len),
//.string_bytes_len = @intCast(ip.string_bytes.items.len),
.tracked_insts_len = @intCast(ip.tracked_insts.count()),
//.tracked_insts_len = @intCast(ip.tracked_insts.count()),
.src_hash_deps_len = @intCast(ip.src_hash_deps.count()),
.decl_val_deps_len = @intCast(ip.decl_val_deps.count()),
.namespace_deps_len = @intCast(ip.namespace_deps.count()),
@ -2811,7 +2826,7 @@ pub fn saveState(comp: *Compilation) !void {
.first_dependency_len = @intCast(ip.first_dependency.count()),
.dep_entries_len = @intCast(ip.dep_entries.items.len),
.free_dep_entries_len = @intCast(ip.free_dep_entries.items.len),
.files_len = @intCast(ip.files.entries.len),
//.files_len = @intCast(ip.files.entries.len),
},
};
addBuf(&bufs_list, &bufs_len, mem.asBytes(&header));
@ -2820,7 +2835,7 @@ pub fn saveState(comp: *Compilation) !void {
//addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.items.items(.data)));
//addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.items.items(.tag)));
//addBuf(&bufs_list, &bufs_len, ip.string_bytes.items);
addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.tracked_insts.keys()));
//addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.tracked_insts.keys()));
addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.src_hash_deps.keys()));
addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.src_hash_deps.values()));
@ -2836,8 +2851,8 @@ pub fn saveState(comp: *Compilation) !void {
addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.dep_entries.items));
addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.free_dep_entries.items));
addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.files.keys()));
addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.files.values()));
//addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.files.keys()));
//addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.files.values()));
// TODO: compilation errors
// TODO: namespaces
@ -2929,7 +2944,7 @@ pub fn totalErrorCount(comp: *Compilation) u32 {
}
}
if (zcu.global_error_set.entries.len - 1 > zcu.error_limit) {
if (zcu.intern_pool.global_error_set.mutate.list.len > zcu.error_limit) {
total += 1;
}
}
@ -3058,7 +3073,7 @@ pub fn getAllErrorsAlloc(comp: *Compilation) !ErrorBundle {
try addModuleErrorMsg(zcu, &bundle, value.*, &all_references);
}
const actual_error_count = zcu.global_error_set.entries.len - 1;
const actual_error_count = zcu.intern_pool.global_error_set.mutate.list.len;
if (actual_error_count > zcu.error_limit) {
try bundle.addRootErrorMessage(.{
.msg = try bundle.printString("ZCU used more errors than possible: used {d}, max {d}", .{
@ -3443,11 +3458,12 @@ fn performAllTheWorkInner(
}
}
if (comp.module) |mod| {
try reportMultiModuleErrors(mod);
try mod.flushRetryableFailures();
mod.sema_prog_node = main_progress_node.start("Semantic Analysis", 0);
mod.codegen_prog_node = main_progress_node.start("Code Generation", 0);
if (comp.module) |zcu| {
const pt: Zcu.PerThread = .{ .zcu = comp.module.?, .tid = .main };
try reportMultiModuleErrors(pt);
try zcu.flushRetryableFailures();
zcu.sema_prog_node = main_progress_node.start("Semantic Analysis", 0);
zcu.codegen_prog_node = main_progress_node.start("Code Generation", 0);
}
if (!InternPool.single_threaded) comp.thread_pool.spawnWgId(&comp.work_queue_wait_group, codegenThread, .{comp});
@ -4131,14 +4147,6 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) anye
};
}
const AstGenSrc = union(enum) {
root,
import: struct {
importing_file: Zcu.File.Index,
import_tok: std.zig.Ast.TokenIndex,
},
};
fn workerAstGenFile(
tid: usize,
comp: *Compilation,
@ -4148,7 +4156,7 @@ fn workerAstGenFile(
root_decl: Zcu.Decl.OptionalIndex,
prog_node: std.Progress.Node,
wg: *WaitGroup,
src: AstGenSrc,
src: Zcu.AstGenSrc,
) void {
const child_prog_node = prog_node.start(file.sub_file_path, 0);
defer child_prog_node.end();
@ -4158,7 +4166,7 @@ fn workerAstGenFile(
error.AnalysisFail => return,
else => {
file.status = .retryable_failure;
comp.reportRetryableAstGenError(src, file_index, err) catch |oom| switch (oom) {
pt.reportRetryableAstGenError(src, file_index, err) catch |oom| switch (oom) {
// Swallowing this error is OK because it's implied to be OOM when
// there is a missing `failed_files` error message.
error.OutOfMemory => {},
@ -4189,9 +4197,9 @@ fn workerAstGenFile(
comp.mutex.lock();
defer comp.mutex.unlock();
const res = pt.zcu.importFile(file, import_path) catch continue;
const res = pt.importFile(file, import_path) catch continue;
if (!res.is_pkg) {
res.file.addReference(pt.zcu.*, .{ .import = .{
res.file.addReference(pt.zcu, .{ .import = .{
.file = file_index,
.token = item.data.token,
} }) catch continue;
@ -4204,7 +4212,7 @@ fn workerAstGenFile(
log.debug("AstGen of {s} has import '{s}'; queuing AstGen of {s}", .{
file.sub_file_path, import_path, import_result.file.sub_file_path,
});
const sub_src: AstGenSrc = .{ .import = .{
const sub_src: Zcu.AstGenSrc = .{ .import = .{
.importing_file = file_index,
.import_tok = item.data.token,
} };
@ -4557,41 +4565,6 @@ fn reportRetryableWin32ResourceError(
}
}
fn reportRetryableAstGenError(
comp: *Compilation,
src: AstGenSrc,
file_index: Zcu.File.Index,
err: anyerror,
) error{OutOfMemory}!void {
const zcu = comp.module.?;
const gpa = zcu.gpa;
const file = zcu.fileByIndex(file_index);
file.status = .retryable_failure;
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,
},
.import => |info| .{
.base_node_inst = try zcu.intern_pool.trackZir(gpa, info.importing_file, .main_struct_inst),
.offset = .{ .token_abs = info.import_tok },
},
};
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);
{
comp.mutex.lock();
defer comp.mutex.unlock();
try zcu.failed_files.putNoClobber(gpa, file, err_msg);
}
}
fn reportRetryableEmbedFileError(
comp: *Compilation,
embed_file: *Zcu.EmbedFile,

File diff suppressed because it is too large Load Diff

View File

@ -835,12 +835,11 @@ pub const Block = struct {
}
fn trackZir(block: *Block, inst: Zir.Inst.Index) Allocator.Error!InternPool.TrackedInst.Index {
const sema = block.sema;
const gpa = sema.gpa;
const zcu = sema.pt.zcu;
const ip = &zcu.intern_pool;
const file_index = block.getFileScopeIndex(zcu);
return ip.trackZir(gpa, file_index, inst);
const pt = block.sema.pt;
return pt.zcu.intern_pool.trackZir(pt.zcu.gpa, pt.tid, .{
.file = block.getFileScopeIndex(pt.zcu),
.inst = inst,
});
}
};
@ -2878,7 +2877,7 @@ fn createAnonymousDeclTypeNamed(
switch (name_strategy) {
.anon => {}, // handled after switch
.parent => {
try zcu.initNewAnonDecl(new_decl_index, val, block.type_name_ctx);
try pt.initNewAnonDecl(new_decl_index, val, block.type_name_ctx, .none);
return new_decl_index;
},
.func => func_strat: {
@ -2923,7 +2922,7 @@ fn createAnonymousDeclTypeNamed(
try writer.writeByte(')');
const name = try ip.getOrPutString(gpa, pt.tid, buf.items, .no_embedded_nulls);
try zcu.initNewAnonDecl(new_decl_index, val, name);
try pt.initNewAnonDecl(new_decl_index, val, name, .none);
return new_decl_index;
},
.dbg_var => {
@ -2937,7 +2936,7 @@ fn createAnonymousDeclTypeNamed(
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);
try pt.initNewAnonDecl(new_decl_index, val, name, .none);
return new_decl_index;
},
else => {},
@ -2958,7 +2957,7 @@ fn createAnonymousDeclTypeNamed(
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);
try pt.initNewAnonDecl(new_decl_index, val, name, .none);
return new_decl_index;
}
@ -3474,7 +3473,7 @@ fn zirErrorSetDecl(
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, pt.tid, name, .no_embedded_nulls);
_ = try mod.getErrorValue(name_ip);
_ = try pt.getErrorValue(name_ip);
const result = names.getOrPutAssumeCapacity(name_ip);
assert(!result.found_existing); // verified in AstGen
}
@ -5527,13 +5526,12 @@ fn failWithBadStructFieldAccess(
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
const decl = zcu.declPtr(struct_type.decl.unwrap().?);
const fqn = try decl.fullyQualifiedName(pt);
const msg = msg: {
const msg = try sema.errMsg(
field_src,
"no field named '{}' in struct '{}'",
.{ field_name.fmt(ip), fqn.fmt(ip) },
.{ field_name.fmt(ip), decl.fqn.fmt(ip) },
);
errdefer msg.destroy(sema.gpa);
try sema.errNote(struct_ty.srcLoc(zcu), msg, "struct declared here", .{});
@ -5554,15 +5552,13 @@ fn failWithBadUnionFieldAccess(
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(pt);
const msg = msg: {
const msg = try sema.errMsg(
field_src,
"no field named '{}' in union '{}'",
.{ field_name.fmt(ip), fqn.fmt(ip) },
.{ field_name.fmt(ip), decl.fqn.fmt(ip) },
);
errdefer msg.destroy(gpa);
try sema.errNote(union_ty.srcLoc(zcu), msg, "union declared here", .{});
@ -6059,7 +6055,7 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr
else => |e| return e,
};
const result = zcu.importPkg(c_import_mod) catch |err|
const result = pt.importPkg(c_import_mod) catch |err|
return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)});
const path_digest = zcu.filePathDigest(result.file_index);
@ -6721,13 +6717,7 @@ fn addDbgVar(
if (block.need_debug_scope) |ptr| ptr.* = true;
// Add the name to the AIR.
const name_extra_index: u32 = @intCast(sema.air_extra.items.len);
const elements_used = name.len / 4 + 1;
try sema.air_extra.ensureUnusedCapacity(sema.gpa, elements_used);
const buffer = mem.sliceAsBytes(sema.air_extra.unusedCapacitySlice());
@memcpy(buffer[0..name.len], name);
buffer[name.len] = 0;
sema.air_extra.items.len += elements_used;
const name_extra_index = try sema.appendAirString(name);
_ = try block.addInst(.{
.tag = air_tag,
@ -6738,6 +6728,16 @@ fn addDbgVar(
});
}
pub fn appendAirString(sema: *Sema, str: []const u8) Allocator.Error!u32 {
const str_extra_index: u32 = @intCast(sema.air_extra.items.len);
const elements_used = str.len / 4 + 1;
const elements = try sema.air_extra.addManyAsSlice(sema.gpa, elements_used);
const buffer = mem.sliceAsBytes(elements);
@memcpy(buffer[0..str.len], str);
buffer[str.len] = 0;
return str_extra_index;
}
fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
const pt = sema.pt;
const mod = pt.zcu;
@ -8357,13 +8357,6 @@ fn instantiateGenericCall(
}
} else {
// The parameter is runtime-known.
child_sema.inst_map.putAssumeCapacityNoClobber(param_inst, try child_block.addInst(.{
.tag = .arg,
.data = .{ .arg = .{
.ty = Air.internedToRef(arg_ty.toIntern()),
.src_index = @intCast(arg_index),
} },
}));
const param_name: Zir.NullTerminatedString = switch (param_tag) {
.param_anytype => fn_zir.instructions.items(.data)[@intFromEnum(param_inst)].str_tok.start,
.param => name: {
@ -8373,6 +8366,16 @@ fn instantiateGenericCall(
},
else => unreachable,
};
child_sema.inst_map.putAssumeCapacityNoClobber(param_inst, try child_block.addInst(.{
.tag = .arg,
.data = .{ .arg = .{
.ty = Air.internedToRef(arg_ty.toIntern()),
.name = if (child_block.ownerModule().strip)
.none
else
@enumFromInt(try sema.appendAirString(fn_zir.nullTerminatedString(param_name))),
} },
}));
try child_block.params.append(sema.arena, .{
.ty = arg_ty.toIntern(), // This is the type after coercion
.is_comptime = false, // We're adding only runtime args to the instantiation
@ -8702,7 +8705,7 @@ fn zirErrorValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
inst_data.get(sema.code),
.no_embedded_nulls,
);
_ = try pt.zcu.getErrorValue(name);
_ = try pt.getErrorValue(name);
// Create an error set type with only this error value, and return the value.
const error_set_type = try pt.singleErrorSetType(name);
return Air.internedToRef((try pt.intern(.{ .err = .{
@ -8732,7 +8735,7 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
const err_name = ip.indexToKey(val.toIntern()).err.name;
return Air.internedToRef((try pt.intValue(
err_int_ty,
try mod.getErrorValue(err_name),
try pt.getErrorValue(err_name),
)).toIntern());
}
@ -8743,10 +8746,7 @@ fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
const names = ip.indexToKey(err_set_ty_index).error_set_type.names;
switch (names.len) {
0 => return Air.internedToRef((try pt.intValue(err_int_ty, 0)).toIntern()),
1 => {
const int: Module.ErrorInt = @intCast(mod.global_error_set.getIndex(names.get(ip)[0]).?);
return pt.intRef(err_int_ty, int);
},
1 => return pt.intRef(err_int_ty, ip.getErrorValueIfExists(names.get(ip)[0]).?),
else => {},
}
},
@ -8762,6 +8762,7 @@ fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
const pt = sema.pt;
const mod = pt.zcu;
const ip = &mod.intern_pool;
const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data;
const src = block.nodeOffset(extra.node);
const operand_src = block.builtinCallArgSrc(extra.node, 0);
@ -8771,11 +8772,16 @@ fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstD
if (try sema.resolveDefinedValue(block, operand_src, operand)) |value| {
const int = try sema.usizeCast(block, operand_src, try value.toUnsignedIntSema(pt));
if (int > mod.global_error_set.count() or int == 0)
if (int > len: {
const mutate = &ip.global_error_set.mutate;
mutate.mutex.lock();
defer mutate.mutex.unlock();
break :len mutate.list.len;
} or int == 0)
return sema.fail(block, operand_src, "integer value '{d}' represents no error", .{int});
return Air.internedToRef((try pt.intern(.{ .err = .{
.ty = .anyerror_type,
.name = mod.global_error_set.keys()[int],
.name = ip.global_error_set.shared.names.acquire().view().items(.@"0")[int - 1],
} })));
}
try sema.requireRuntimeBlock(block, src, operand_src);
@ -13943,7 +13949,7 @@ fn zirImport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
const operand_src = block.tokenOffset(inst_data.src_tok);
const operand = inst_data.get(sema.code);
const result = zcu.importFile(block.getFileScope(zcu), operand) catch |err| switch (err) {
const result = pt.importFile(block.getFileScope(zcu), operand) catch |err| switch (err) {
error.ImportOutsideModulePath => {
return sema.fail(block, operand_src, "import of file outside module path: '{s}'", .{operand});
},
@ -14002,7 +14008,7 @@ fn zirRetErrValueCode(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.R
inst_data.get(sema.code),
.no_embedded_nulls,
);
_ = try mod.getErrorValue(name);
_ = try pt.getErrorValue(name);
const error_set_type = try pt.singleErrorSetType(name);
return Air.internedToRef((try pt.intern(.{ .err = .{
.ty = error_set_type.toIntern(),
@ -19561,7 +19567,7 @@ fn zirRetErrValue(
inst_data.get(sema.code),
.no_embedded_nulls,
);
_ = try mod.getErrorValue(err_name);
_ = try pt.getErrorValue(err_name);
// Return the error code from the function.
const error_set_type = try pt.singleErrorSetType(err_name);
const result_inst = Air.internedToRef((try pt.intern(.{ .err = .{
@ -21604,7 +21610,7 @@ fn zirReify(
const name = try sema.sliceToIpString(block, src, name_val, .{
.needed_comptime_reason = "error set contents must be comptime-known",
});
_ = try mod.getErrorValue(name);
_ = try pt.getErrorValue(name);
const gop = names.getOrPutAssumeCapacity(name);
if (gop.found_existing) {
return sema.fail(block, src, "duplicate error '{}'", .{
@ -26500,7 +26506,7 @@ fn zirBuiltinExtern(
const new_decl_index = try pt.allocateNewDecl(sema.owner_decl.src_namespace);
errdefer pt.destroyDecl(new_decl_index);
const new_decl = mod.declPtr(new_decl_index);
try mod.initNewAnonDecl(
try pt.initNewAnonDecl(
new_decl_index,
Value.fromInterned(
if (Type.fromInterned(ptr_info.child).zigTypeTag(mod) == .Fn)
@ -26522,6 +26528,7 @@ fn zirBuiltinExtern(
} }),
),
options.name,
.none,
);
new_decl.owns_tv = true;
// Note that this will queue the anon decl for codegen, so that the backend can
@ -27481,7 +27488,7 @@ fn fieldVal(
},
.simple_type => |t| {
assert(t == .anyerror);
_ = try mod.getErrorValue(field_name);
_ = try pt.getErrorValue(field_name);
},
else => unreachable,
}
@ -27721,7 +27728,7 @@ fn fieldPtr(
},
.simple_type => |t| {
assert(t == .anyerror);
_ = try mod.getErrorValue(field_name);
_ = try pt.getErrorValue(field_name);
},
else => unreachable,
}
@ -36735,24 +36742,23 @@ fn generateUnionTagTypeNumbered(
const new_decl_index = try pt.allocateNewDecl(block.namespace);
errdefer pt.destroyDecl(new_decl_index);
const fqn = try union_owner_decl.fullyQualifiedName(pt);
const name = try ip.getOrPutStringFmt(
gpa,
pt.tid,
"@typeInfo({}).Union.tag_type.?",
.{fqn.fmt(ip)},
.{union_owner_decl.fqn.fmt(ip)},
.no_embedded_nulls,
);
try mod.initNewAnonDecl(
try pt.initNewAnonDecl(
new_decl_index,
Value.@"unreachable",
name,
name.toOptional(),
);
errdefer pt.abortAnonDecl(new_decl_index);
const new_decl = mod.declPtr(new_decl_index);
new_decl.owns_tv = true;
new_decl.name_fully_qualified = true;
const enum_ty = try ip.getGeneratedTagEnumType(gpa, pt.tid, .{
.decl = new_decl_index,
@ -36784,22 +36790,21 @@ fn generateUnionTagTypeSimple(
const gpa = sema.gpa;
const new_decl_index = new_decl_index: {
const fqn = try union_owner_decl.fullyQualifiedName(pt);
const new_decl_index = try pt.allocateNewDecl(block.namespace);
errdefer pt.destroyDecl(new_decl_index);
const name = try ip.getOrPutStringFmt(
gpa,
pt.tid,
"@typeInfo({}).Union.tag_type.?",
.{fqn.fmt(ip)},
.{union_owner_decl.fqn.fmt(ip)},
.no_embedded_nulls,
);
try mod.initNewAnonDecl(
try pt.initNewAnonDecl(
new_decl_index,
Value.@"unreachable",
name,
name.toOptional(),
);
mod.declPtr(new_decl_index).name_fully_qualified = true;
break :new_decl_index new_decl_index;
};
errdefer pt.abortAnonDecl(new_decl_index);

View File

@ -268,10 +268,10 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error
return;
},
.inferred_error_set_type => |func_index| {
try writer.writeAll("@typeInfo(@typeInfo(@TypeOf(");
const owner_decl = mod.funcOwnerDeclPtr(func_index);
try owner_decl.renderFullyQualifiedName(mod, writer);
try writer.writeAll(")).Fn.return_type.?).ErrorUnion.error_set");
try writer.print("@typeInfo(@typeInfo(@TypeOf({})).Fn.return_type.?).ErrorUnion.error_set", .{
owner_decl.fqn.fmt(ip),
});
},
.error_set_type => |error_set_type| {
const names = error_set_type.names;
@ -334,10 +334,10 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error
const struct_type = ip.loadStructType(ty.toIntern());
if (struct_type.decl.unwrap()) |decl_index| {
const decl = mod.declPtr(decl_index);
try decl.renderFullyQualifiedName(mod, writer);
try writer.print("{}", .{decl.fqn.fmt(ip)});
} else if (ip.loadStructType(ty.toIntern()).namespace.unwrap()) |namespace_index| {
const namespace = mod.namespacePtr(namespace_index);
try namespace.renderFullyQualifiedName(mod, .empty, writer);
try namespace.renderFullyQualifiedName(ip, .empty, writer);
} else {
try writer.writeAll("@TypeOf(.{})");
}
@ -367,15 +367,15 @@ pub fn print(ty: Type, writer: anytype, pt: Zcu.PerThread) @TypeOf(writer).Error
.union_type => {
const decl = mod.declPtr(ip.loadUnionType(ty.toIntern()).decl);
try decl.renderFullyQualifiedName(mod, writer);
try writer.print("{}", .{decl.fqn.fmt(ip)});
},
.opaque_type => {
const decl = mod.declPtr(ip.loadOpaqueType(ty.toIntern()).decl);
try decl.renderFullyQualifiedName(mod, writer);
try writer.print("{}", .{decl.fqn.fmt(ip)});
},
.enum_type => {
const decl = mod.declPtr(ip.loadEnumType(ty.toIntern()).decl);
try decl.renderFullyQualifiedName(mod, writer);
try writer.print("{}", .{decl.fqn.fmt(ip)});
},
.func_type => |fn_info| {
if (fn_info.is_noinline) {
@ -3451,7 +3451,7 @@ pub fn typeDeclInst(ty: Type, zcu: *const Zcu) ?InternPool.TrackedInst.Index {
};
}
pub fn typeDeclSrcLine(ty: Type, zcu: *const Zcu) ?u32 {
pub fn typeDeclSrcLine(ty: Type, zcu: *Zcu) ?u32 {
const ip = &zcu.intern_pool;
const tracked = switch (ip.indexToKey(ty.toIntern())) {
.struct_type, .union_type, .opaque_type, .enum_type => |info| switch (info) {

View File

@ -417,7 +417,7 @@ pub fn writeToMemory(val: Value, ty: Type, pt: Zcu.PerThread, buffer: []u8) erro
var bigint_buffer: BigIntSpace = undefined;
const bigint = BigIntMutable.init(
&bigint_buffer.limbs,
mod.global_error_set.getIndex(name).?,
ip.getErrorValueIfExists(name).?,
).toConst();
bigint.writeTwosComplement(buffer[0..byte_count], endian);
},
@ -427,7 +427,7 @@ pub fn writeToMemory(val: Value, ty: Type, pt: Zcu.PerThread, buffer: []u8) erro
if (val.unionTag(mod)) |union_tag| {
const union_obj = mod.typeToUnion(ty).?;
const field_index = mod.unionTagFieldIndex(union_obj, union_tag).?;
const field_type = Type.fromInterned(union_obj.field_types.get(&mod.intern_pool)[field_index]);
const field_type = Type.fromInterned(union_obj.field_types.get(ip)[field_index]);
const field_val = try val.fieldValue(pt, field_index);
const byte_count: usize = @intCast(field_type.abiSize(pt));
return writeToMemory(field_val, field_type, pt, buffer[0..byte_count]);
@ -1455,9 +1455,9 @@ pub fn getErrorName(val: Value, mod: *const Module) InternPool.OptionalNullTermi
};
}
pub fn getErrorInt(val: Value, mod: *const Module) Module.ErrorInt {
return if (getErrorName(val, mod).unwrap()) |err_name|
@intCast(mod.global_error_set.getIndex(err_name).?)
pub fn getErrorInt(val: Value, zcu: *Zcu) Module.ErrorInt {
return if (getErrorName(val, zcu).unwrap()) |err_name|
zcu.intern_pool.getErrorValueIfExists(err_name).?
else
0;
}

View File

@ -102,7 +102,7 @@ multi_exports: std.AutoArrayHashMapUnmanaged(AnalUnit, extern struct {
/// `Compilation.update` of the process for a given `Compilation`.
///
/// Indexes correspond 1:1 to `files`.
import_table: std.StringArrayHashMapUnmanaged(*File) = .{},
import_table: std.StringArrayHashMapUnmanaged(File.Index) = .{},
/// The set of all the files which have been loaded with `@embedFile` in the Module.
/// We keep track of this in order to iterate over it and check which files have been
@ -141,9 +141,6 @@ failed_exports: std.AutoArrayHashMapUnmanaged(u32, *ErrorMsg) = .{},
/// are stored here.
cimport_errors: std.AutoArrayHashMapUnmanaged(AnalUnit, std.zig.ErrorBundle) = .{},
/// Key is the error name, index is the error tag value. Index 0 has a length-0 string.
global_error_set: GlobalErrorSet = .{},
/// Maximum amount of distinct error values, set by --error-limit
error_limit: ErrorInt,
@ -326,7 +323,10 @@ pub const Reference = struct {
};
pub const Decl = struct {
/// Equal to `fqn` if already fully qualified.
name: InternPool.NullTerminatedString,
/// Fully qualified name.
fqn: InternPool.NullTerminatedString,
/// The most recent Value of the Decl after a successful semantic analysis.
/// Populated when `has_tv`.
val: Value,
@ -384,8 +384,6 @@ pub const Decl = struct {
is_pub: bool,
/// Whether the corresponding AST decl has a `export` keyword.
is_exported: bool,
/// If true `name` is already fully qualified.
name_fully_qualified: bool = false,
/// What kind of a declaration is this.
kind: Kind,
@ -408,25 +406,6 @@ pub const Decl = struct {
return extra.data.getBodies(@intCast(extra.end), zir);
}
pub fn renderFullyQualifiedName(decl: Decl, zcu: *Zcu, writer: anytype) !void {
if (decl.name_fully_qualified) {
try writer.print("{}", .{decl.name.fmt(&zcu.intern_pool)});
} else {
try zcu.namespacePtr(decl.src_namespace).renderFullyQualifiedName(zcu, decl.name, writer);
}
}
pub fn renderFullyQualifiedDebugName(decl: Decl, zcu: *Zcu, writer: anytype) !void {
return zcu.namespacePtr(decl.src_namespace).renderFullyQualifiedDebugName(zcu, decl.name, writer);
}
pub fn fullyQualifiedName(decl: Decl, pt: Zcu.PerThread) !InternPool.NullTerminatedString {
return if (decl.name_fully_qualified)
decl.name
else
pt.zcu.namespacePtr(decl.src_namespace).fullyQualifiedName(pt, decl.name);
}
pub fn typeOf(decl: Decl, zcu: *const Zcu) Type {
assert(decl.has_tv);
return decl.val.typeOf(zcu);
@ -646,23 +625,27 @@ pub const Namespace = struct {
return zcu.fileByIndex(ns.file_scope);
}
pub fn fileScopeIp(ns: Namespace, ip: *InternPool) *File {
return ip.filePtr(ns.file_scope);
}
// This renders e.g. "std.fs.Dir.OpenOptions"
pub fn renderFullyQualifiedName(
ns: Namespace,
zcu: *Zcu,
ip: *InternPool,
name: InternPool.NullTerminatedString,
writer: anytype,
) @TypeOf(writer).Error!void {
if (ns.parent.unwrap()) |parent| {
try zcu.namespacePtr(parent).renderFullyQualifiedName(
zcu,
zcu.declPtr(ns.decl_index).name,
try ip.namespacePtr(parent).renderFullyQualifiedName(
ip,
ip.declPtr(ns.decl_index).name,
writer,
);
} else {
try ns.fileScope(zcu).renderFullyQualifiedName(writer);
try ns.fileScopeIp(ip).renderFullyQualifiedName(writer);
}
if (name != .empty) try writer.print(".{}", .{name.fmt(&zcu.intern_pool)});
if (name != .empty) try writer.print(".{}", .{name.fmt(ip)});
}
/// This renders e.g. "std/fs.zig:Dir.OpenOptions"
@ -686,46 +669,45 @@ pub const Namespace = struct {
if (name != .empty) try writer.print("{c}{}", .{ sep, name.fmt(&zcu.intern_pool) });
}
pub fn fullyQualifiedName(
pub fn internFullyQualifiedName(
ns: Namespace,
pt: Zcu.PerThread,
ip: *InternPool,
gpa: Allocator,
tid: Zcu.PerThread.Id,
name: InternPool.NullTerminatedString,
) !InternPool.NullTerminatedString {
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
const gpa = zcu.gpa;
const strings = ip.getLocal(pt.tid).getMutableStrings(gpa);
const strings = ip.getLocal(tid).getMutableStrings(gpa);
// Protects reads of interned strings from being reallocated during the call to
// renderFullyQualifiedName.
const slice = try strings.addManyAsSlice(count: {
var count: usize = name.length(ip) + 1;
var cur_ns = &ns;
while (true) {
const decl = zcu.declPtr(cur_ns.decl_index);
cur_ns = zcu.namespacePtr(cur_ns.parent.unwrap() orelse {
count += ns.fileScope(zcu).fullyQualifiedNameLen();
const decl = ip.declPtr(cur_ns.decl_index);
cur_ns = ip.namespacePtr(cur_ns.parent.unwrap() orelse {
count += ns.fileScopeIp(ip).fullyQualifiedNameLen();
break :count count;
});
count += decl.name.length(ip) + 1;
}
});
var fbs = std.io.fixedBufferStream(slice[0]);
ns.renderFullyQualifiedName(zcu, name, fbs.writer()) catch unreachable;
ns.renderFullyQualifiedName(ip, name, fbs.writer()) catch unreachable;
assert(fbs.pos == slice[0].len);
// Sanitize the name for nvptx which is more restrictive.
// TODO This should be handled by the backend, not the frontend. Have a
// look at how the C backend does it for inspiration.
const cpu_arch = zcu.root_mod.resolved_target.result.cpu.arch;
if (cpu_arch.isNvptx()) {
for (slice[0]) |*byte| switch (byte.*) {
'{', '}', '*', '[', ']', '(', ')', ',', ' ', '\'' => byte.* = '_',
else => {},
};
}
// FIXME This has bitrotted and is no longer able to be implemented here.
//const cpu_arch = zcu.root_mod.resolved_target.result.cpu.arch;
//if (cpu_arch.isNvptx()) {
// for (slice[0]) |*byte| switch (byte.*) {
// '{', '}', '*', '[', ']', '(', ')', ',', ' ', '\'' => byte.* = '_',
// else => {},
// };
//}
return ip.getOrPutTrailingString(gpa, pt.tid, @intCast(slice[0].len), .no_embedded_nulls);
return ip.getOrPutTrailingString(gpa, tid, @intCast(slice[0].len), .no_embedded_nulls);
}
pub fn getType(ns: Namespace, zcu: *Zcu) Type {
@ -882,7 +864,7 @@ pub const File = struct {
};
}
pub fn fullyQualifiedName(file: File, pt: Zcu.PerThread) !InternPool.NullTerminatedString {
pub fn internFullyQualifiedName(file: File, pt: Zcu.PerThread) !InternPool.NullTerminatedString {
const gpa = pt.zcu.gpa;
const ip = &pt.zcu.intern_pool;
const strings = ip.getLocal(pt.tid).getMutableStrings(gpa);
@ -910,7 +892,7 @@ pub const File = struct {
}
/// Add a reference to this file during AstGen.
pub fn addReference(file: *File, zcu: Zcu, ref: File.Reference) !void {
pub fn addReference(file: *File, zcu: *Zcu, ref: File.Reference) !void {
// Don't add the same module root twice. Note that since we always add module roots at the
// front of the references array (see below), this loop is actually O(1) on valid code.
if (ref == .root) {
@ -942,7 +924,7 @@ pub const File = struct {
/// Mark this file and every file referenced by it as multi_pkg and report an
/// astgen_failure error for them. AstGen must have completed in its entirety.
pub fn recursiveMarkMultiPkg(file: *File, mod: *Module) void {
pub fn recursiveMarkMultiPkg(file: *File, pt: Zcu.PerThread) void {
file.multi_pkg = true;
file.status = .astgen_failure;
@ -962,9 +944,9 @@ pub const File = struct {
const import_path = file.zir.nullTerminatedString(item.data.name);
if (mem.eql(u8, import_path, "builtin")) continue;
const res = mod.importFile(file, import_path) catch continue;
const res = pt.importFile(file, import_path) catch continue;
if (!res.is_pkg and !res.file.multi_pkg) {
res.file.recursiveMarkMultiPkg(mod);
res.file.recursiveMarkMultiPkg(pt);
}
}
}
@ -1033,6 +1015,14 @@ pub const ErrorMsg = struct {
}
};
pub const AstGenSrc = union(enum) {
root,
import: struct {
importing_file: Zcu.File.Index,
import_tok: std.zig.Ast.TokenIndex,
},
};
/// Canonical reference to a position within a source file.
pub const SrcLoc = struct {
file_scope: *File,
@ -2406,7 +2396,6 @@ pub const CompileError = error{
pub fn init(mod: *Module, thread_count: usize) !void {
const gpa = mod.gpa;
try mod.intern_pool.init(gpa, thread_count);
try mod.global_error_set.put(gpa, .empty, {});
}
pub fn deinit(zcu: *Zcu) void {
@ -2421,8 +2410,7 @@ pub fn deinit(zcu: *Zcu) void {
for (zcu.import_table.keys()) |key| {
gpa.free(key);
}
for (0..zcu.import_table.entries.len) |file_index_usize| {
const file_index: File.Index = @enumFromInt(file_index_usize);
for (zcu.import_table.values()) |file_index| {
pt.destroyFile(file_index);
}
zcu.import_table.deinit(gpa);
@ -2479,8 +2467,6 @@ pub fn deinit(zcu: *Zcu) void {
zcu.single_exports.deinit(gpa);
zcu.multi_exports.deinit(gpa);
zcu.global_error_set.deinit(gpa);
zcu.potentially_outdated.deinit(gpa);
zcu.outdated.deinit(gpa);
zcu.outdated_ready.deinit(gpa);
@ -3020,183 +3006,7 @@ pub const ImportFileResult = struct {
is_pkg: bool,
};
pub fn importPkg(zcu: *Zcu, mod: *Package.Module) !ImportFileResult {
const gpa = zcu.gpa;
// The resolved path is used as the key in the import table, to detect if
// an import refers to the same as another, despite different relative paths
// or differently mapped package names.
const resolved_path = try std.fs.path.resolve(gpa, &.{
mod.root.root_dir.path orelse ".",
mod.root.sub_path,
mod.root_src_path,
});
var keep_resolved_path = false;
defer if (!keep_resolved_path) gpa.free(resolved_path);
const gop = try zcu.import_table.getOrPut(gpa, resolved_path);
errdefer _ = zcu.import_table.pop();
if (gop.found_existing) {
try gop.value_ptr.*.addReference(zcu.*, .{ .root = mod });
return .{
.file = gop.value_ptr.*,
.file_index = @enumFromInt(gop.index),
.is_new = false,
.is_pkg = true,
};
}
const ip = &zcu.intern_pool;
try ip.files.ensureUnusedCapacity(gpa, 1);
if (mod.builtin_file) |builtin_file| {
keep_resolved_path = true; // It's now owned by import_table.
gop.value_ptr.* = builtin_file;
try builtin_file.addReference(zcu.*, .{ .root = mod });
const path_digest = computePathDigest(zcu, mod, builtin_file.sub_file_path);
ip.files.putAssumeCapacityNoClobber(path_digest, .none);
return .{
.file = builtin_file,
.file_index = @enumFromInt(ip.files.entries.len - 1),
.is_new = false,
.is_pkg = true,
};
}
const sub_file_path = try gpa.dupe(u8, mod.root_src_path);
errdefer gpa.free(sub_file_path);
const new_file = try gpa.create(File);
errdefer gpa.destroy(new_file);
keep_resolved_path = true; // It's now owned by import_table.
gop.value_ptr.* = new_file;
new_file.* = .{
.sub_file_path = sub_file_path,
.source = undefined,
.source_loaded = false,
.tree_loaded = false,
.zir_loaded = false,
.stat = undefined,
.tree = undefined,
.zir = undefined,
.status = .never_loaded,
.mod = mod,
};
const path_digest = computePathDigest(zcu, mod, sub_file_path);
try new_file.addReference(zcu.*, .{ .root = mod });
ip.files.putAssumeCapacityNoClobber(path_digest, .none);
return .{
.file = new_file,
.file_index = @enumFromInt(ip.files.entries.len - 1),
.is_new = true,
.is_pkg = true,
};
}
/// Called from a worker thread during AstGen.
/// Also called from Sema during semantic analysis.
pub fn importFile(
zcu: *Zcu,
cur_file: *File,
import_string: []const u8,
) !ImportFileResult {
const mod = cur_file.mod;
if (std.mem.eql(u8, import_string, "std")) {
return zcu.importPkg(zcu.std_mod);
}
if (std.mem.eql(u8, import_string, "root")) {
return zcu.importPkg(zcu.root_mod);
}
if (mod.deps.get(import_string)) |pkg| {
return zcu.importPkg(pkg);
}
if (!mem.endsWith(u8, import_string, ".zig")) {
return error.ModuleNotFound;
}
const gpa = zcu.gpa;
// The resolved path is used as the key in the import table, to detect if
// an import refers to the same as another, despite different relative paths
// or differently mapped package names.
const resolved_path = try std.fs.path.resolve(gpa, &.{
mod.root.root_dir.path orelse ".",
mod.root.sub_path,
cur_file.sub_file_path,
"..",
import_string,
});
var keep_resolved_path = false;
defer if (!keep_resolved_path) gpa.free(resolved_path);
const gop = try zcu.import_table.getOrPut(gpa, resolved_path);
errdefer _ = zcu.import_table.pop();
if (gop.found_existing) return .{
.file = gop.value_ptr.*,
.file_index = @enumFromInt(gop.index),
.is_new = false,
.is_pkg = false,
};
const ip = &zcu.intern_pool;
try ip.files.ensureUnusedCapacity(gpa, 1);
const new_file = try gpa.create(File);
errdefer gpa.destroy(new_file);
const resolved_root_path = try std.fs.path.resolve(gpa, &.{
mod.root.root_dir.path orelse ".",
mod.root.sub_path,
});
defer gpa.free(resolved_root_path);
const sub_file_path = p: {
const relative = try std.fs.path.relative(gpa, resolved_root_path, resolved_path);
errdefer gpa.free(relative);
if (!isUpDir(relative) and !std.fs.path.isAbsolute(relative)) {
break :p relative;
}
return error.ImportOutsideModulePath;
};
errdefer gpa.free(sub_file_path);
log.debug("new importFile. resolved_root_path={s}, resolved_path={s}, sub_file_path={s}, import_string={s}", .{
resolved_root_path, resolved_path, sub_file_path, import_string,
});
keep_resolved_path = true; // It's now owned by import_table.
gop.value_ptr.* = new_file;
new_file.* = .{
.sub_file_path = sub_file_path,
.source = undefined,
.source_loaded = false,
.tree_loaded = false,
.zir_loaded = false,
.stat = undefined,
.tree = undefined,
.zir = undefined,
.status = .never_loaded,
.mod = mod,
};
const path_digest = computePathDigest(zcu, mod, sub_file_path);
ip.files.putAssumeCapacityNoClobber(path_digest, .none);
return .{
.file = new_file,
.file_index = @enumFromInt(ip.files.entries.len - 1),
.is_new = true,
.is_pkg = false,
};
}
fn computePathDigest(zcu: *Zcu, mod: *Package.Module, sub_file_path: []const u8) Cache.BinDigest {
pub fn computePathDigest(zcu: *Zcu, mod: *Package.Module, sub_file_path: []const u8) Cache.BinDigest {
const want_local_cache = mod == zcu.main_mod;
var path_hash: Cache.HashHelper = .{};
path_hash.addBytes(build_options.version);
@ -3292,43 +3102,11 @@ pub fn addUnitReference(zcu: *Zcu, src_unit: AnalUnit, referenced_unit: AnalUnit
gop.value_ptr.* = @intCast(ref_idx);
}
pub fn getErrorValue(
mod: *Module,
name: InternPool.NullTerminatedString,
) Allocator.Error!ErrorInt {
const gop = try mod.global_error_set.getOrPut(mod.gpa, name);
return @as(ErrorInt, @intCast(gop.index));
}
pub fn getErrorValueFromSlice(
mod: *Module,
name: []const u8,
) Allocator.Error!ErrorInt {
const interned_name = try mod.intern_pool.getOrPutString(mod.gpa, name);
return getErrorValue(mod, interned_name);
}
pub fn errorSetBits(mod: *Module) u16 {
if (mod.error_limit == 0) return 0;
return std.math.log2_int_ceil(ErrorInt, mod.error_limit + 1); // +1 for no error
}
pub fn initNewAnonDecl(
mod: *Module,
new_decl_index: Decl.Index,
val: Value,
name: InternPool.NullTerminatedString,
) Allocator.Error!void {
const new_decl = mod.declPtr(new_decl_index);
new_decl.name = name;
new_decl.val = val;
new_decl.alignment = .none;
new_decl.@"linksection" = .none;
new_decl.has_tv = true;
new_decl.analysis = .complete;
}
pub fn errNote(
mod: *Module,
src_loc: LazySrcLoc,
@ -3394,41 +3172,6 @@ pub fn handleUpdateExports(
};
}
pub fn reportRetryableFileError(
zcu: *Zcu,
file_index: File.Index,
comptime format: []const u8,
args: anytype,
) error{OutOfMemory}!void {
const gpa = zcu.gpa;
const ip = &zcu.intern_pool;
const file = zcu.fileByIndex(file_index);
file.status = .retryable_failure;
const err_msg = try ErrorMsg.create(
gpa,
.{
.base_node_inst = try ip.trackZir(gpa, file_index, .main_struct_inst),
.offset = .entire_file,
},
format,
args,
);
errdefer err_msg.destroy(gpa);
zcu.comp.mutex.lock();
defer zcu.comp.mutex.unlock();
const gop = try zcu.failed_files.getOrPut(gpa, file);
if (gop.found_existing) {
if (gop.value_ptr.*) |old_err_msg| {
old_err_msg.destroy(gpa);
}
}
gop.value_ptr.* = err_msg;
}
pub fn addGlobalAssembly(mod: *Module, decl_index: Decl.Index, source: []const u8) !void {
const gop = try mod.global_assembly.getOrPut(mod.gpa, decl_index);
if (gop.found_existing) {
@ -3744,22 +3487,28 @@ pub fn resolveReferences(zcu: *Zcu) !std.AutoHashMapUnmanaged(AnalUnit, Resolved
return result;
}
pub fn fileByIndex(zcu: *const Zcu, i: File.Index) *File {
return zcu.import_table.values()[@intFromEnum(i)];
pub fn fileByIndex(zcu: *Zcu, file_index: File.Index) *File {
return zcu.intern_pool.filePtr(file_index);
}
/// Returns the `Decl` of the struct that represents this `File`.
pub fn fileRootDecl(zcu: *const Zcu, i: File.Index) Decl.OptionalIndex {
pub fn fileRootDecl(zcu: *const Zcu, file_index: File.Index) Decl.OptionalIndex {
const ip = &zcu.intern_pool;
return ip.files.values()[@intFromEnum(i)];
const file_index_unwrapped = file_index.unwrap(ip);
const files = ip.getLocalShared(file_index_unwrapped.tid).files.acquire();
return files.view().items(.root_decl)[file_index_unwrapped.index];
}
pub fn setFileRootDecl(zcu: *Zcu, i: File.Index, root_decl: Decl.OptionalIndex) void {
pub fn setFileRootDecl(zcu: *Zcu, file_index: File.Index, root_decl: Decl.OptionalIndex) void {
const ip = &zcu.intern_pool;
ip.files.values()[@intFromEnum(i)] = root_decl;
const file_index_unwrapped = file_index.unwrap(ip);
const files = ip.getLocalShared(file_index_unwrapped.tid).files.acquire();
files.view().items(.root_decl)[file_index_unwrapped.index] = root_decl;
}
pub fn filePathDigest(zcu: *const Zcu, i: File.Index) Cache.BinDigest {
pub fn filePathDigest(zcu: *const Zcu, file_index: File.Index) Cache.BinDigest {
const ip = &zcu.intern_pool;
return ip.files.keys()[@intFromEnum(i)];
const file_index_unwrapped = file_index.unwrap(ip);
const files = ip.getLocalShared(file_index_unwrapped.tid).files.acquire();
return files.view().items(.bin_digest)[file_index_unwrapped.index];
}

View File

@ -342,6 +342,7 @@ pub fn astGenFile(
/// 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 ip = &zcu.intern_pool;
const gpa = zcu.gpa;
const new_zir = file.zir;
@ -355,109 +356,117 @@ fn updateZirRefs(pt: Zcu.PerThread, file: *Zcu.File, file_index: Zcu.File.Index,
// 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;
};
for (ip.locals, 0..) |*local, tid| {
local.mutate.tracked_insts.mutex.lock();
defer local.mutate.tracked_insts.mutex.unlock();
const tracked_insts_list = local.getMutableTrackedInsts(gpa);
for (tracked_insts_list.view().items(.@"0"), 0..) |*tracked_inst, tracked_inst_unwrapped_index| {
if (tracked_inst.file != file_index) continue;
const old_inst = tracked_inst.inst;
const tracked_inst_index = (InternPool.TrackedInst.Index.Unwrapped{
.tid = @enumFromInt(tid),
.index = @intCast(tracked_inst_unwrapped_index),
}).wrap(ip);
tracked_inst.inst = inst_map.get(old_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 = tracked_inst_index });
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;
if (old_zir.getAssociatedSrcHash(old_inst)) |old_hash| hash_changed: {
if (new_zir.getAssociatedSrcHash(tracked_inst.inst)) |new_hash| {
if (std.zig.srcHashEql(old_hash, new_hash)) {
break :hash_changed;
}
log.debug("hash for (%{d} -> %{d}) changed: {} -> {}", .{
old_inst,
tracked_inst.inst,
std.fmt.fmtSliceHexLower(&old_hash),
std.fmt.fmtSliceHexLower(&new_hash),
});
}
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 = tracked_inst_index });
}
// 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,
// 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,
},
else => false,
};
if (!has_namespace) continue;
};
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,
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, {});
}
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,
var any_change = false;
{
var it = new_zir.declIterator(tracked_inst.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 = tracked_inst_index,
.name = name_ip,
} });
}
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
}
// 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,
.namespace = tracked_inst_index,
.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 });
if (any_change) {
zcu.comp.mutex.lock();
defer zcu.comp.mutex.unlock();
try zcu.markDependeeOutdated(.{ .namespace = tracked_inst_index });
}
}
}
}
@ -548,7 +557,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(pt)).toSlice(ip), 0);
const decl_prog_node = mod.sema_prog_node.start(decl.fqn.toSlice(ip), 0);
defer decl_prog_node.end();
break :blk pt.semaDecl(decl_index) catch |err| switch (err) {
@ -747,10 +756,9 @@ 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(pt);
std.debug.print("# Begin Function AIR: {}:\n", .{fqn.fmt(ip)});
std.debug.print("# Begin Function AIR: {}:\n", .{decl.fqn.fmt(ip)});
@import("../print_air.zig").dump(pt, air, liveness);
std.debug.print("# End Function AIR: {}\n\n", .{fqn.fmt(ip)});
std.debug.print("# End Function AIR: {}\n\n", .{decl.fqn.fmt(ip)});
}
if (std.debug.runtime_safety) {
@ -781,7 +789,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(pt)).toSlice(ip), 0);
const codegen_prog_node = zcu.codegen_prog_node.start(decl.fqn.toSlice(ip), 0);
defer codegen_prog_node.end();
if (!air.typesFullyResolved(zcu)) {
@ -818,7 +826,7 @@ pub fn linkerUpdateFunc(pt: Zcu.PerThread, func_index: InternPool.Index, air: Ai
/// https://github.com/ziglang/zig/issues/14307
pub fn semaPkg(pt: Zcu.PerThread, pkg: *Module) !void {
const import_file_result = try pt.zcu.importPkg(pkg);
const import_file_result = try pt.importPkg(pkg);
const root_decl_index = pt.zcu.fileRootDecl(import_file_result.file_index);
if (root_decl_index == .none) {
return pt.semaFile(import_file_result.file_index);
@ -855,7 +863,10 @@ fn getFileRootStruct(
const decls = file.zir.bodySlice(extra_index, decls_len);
extra_index += decls_len;
const tracked_inst = try ip.trackZir(gpa, file_index, .main_struct_inst);
const tracked_inst = try ip.trackZir(gpa, pt.tid, .{
.file = file_index,
.inst = .main_struct_inst,
});
const wip_ty = switch (try ip.getStructType(gpa, pt.tid, .{
.layout = .auto,
.fields_len = fields_len,
@ -996,8 +1007,8 @@ 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(pt);
new_decl.name_fully_qualified = true;
new_decl.fqn = try file.internFullyQualifiedName(pt);
new_decl.name = new_decl.fqn;
new_decl.is_pub = true;
new_decl.is_exported = false;
new_decl.alignment = .none;
@ -1016,7 +1027,7 @@ fn semaFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.SemaError!void {
switch (zcu.comp.cache_use) {
.whole => |whole| if (whole.cache_manifest) |man| {
const source = file.getSource(gpa) catch |err| {
try Zcu.reportRetryableFileError(zcu, file_index, "unable to load source: {s}", .{@errorName(err)});
try pt.reportRetryableFileError(file_index, "unable to load source: {s}", .{@errorName(err)});
return error.AnalysisFail;
};
@ -1025,7 +1036,7 @@ fn semaFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.SemaError!void {
file.mod.root.sub_path,
file.sub_file_path,
}) catch |err| {
try Zcu.reportRetryableFileError(zcu, file_index, "unable to resolve path: {s}", .{@errorName(err)});
try pt.reportRetryableFileError(file_index, "unable to resolve path: {s}", .{@errorName(err)});
return error.AnalysisFail;
};
errdefer gpa.free(resolved_path);
@ -1058,10 +1069,8 @@ 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(pt)).fmt(ip)});
defer blk: {
log.debug("finish decl name '{}'", .{(decl.fullyQualifiedName(pt) catch break :blk).fmt(ip)});
}
log.debug("decl name '{}'", .{decl.fqn.fmt(ip)});
defer log.debug("finish decl name '{}'", .{decl.fqn.fmt(ip)});
const old_has_tv = decl.has_tv;
// The following values are ignored if `!old_has_tv`
@ -1084,7 +1093,7 @@ fn semaDecl(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) !Zcu.SemaDeclResult {
const std_mod = zcu.std_mod;
if (decl.getFileScope(zcu).mod != std_mod) break :ip_index .none;
// We're in the std module.
const std_file_imported = try zcu.importPkg(std_mod);
const std_file_imported = try pt.importPkg(std_mod);
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).?;
@ -1151,11 +1160,10 @@ fn semaDecl(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) !Zcu.SemaDeclResult {
defer sema.deinit();
// Every Decl (other than file root Decls, which do not have a ZIR index) has a dependency on its own source.
try sema.declareDependency(.{ .src_hash = try ip.trackZir(
gpa,
decl.getFileScopeIndex(zcu),
decl_inst,
) });
try sema.declareDependency(.{ .src_hash = try ip.trackZir(gpa, pt.tid, .{
.file = decl.getFileScopeIndex(zcu),
.inst = decl_inst,
}) });
var block_scope: Sema.Block = .{
.parent = null,
@ -1359,6 +1367,195 @@ pub fn semaAnonOwnerDecl(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) !Zcu.Sem
};
}
pub fn importPkg(pt: Zcu.PerThread, mod: *Module) !Zcu.ImportFileResult {
const zcu = pt.zcu;
const gpa = zcu.gpa;
// The resolved path is used as the key in the import table, to detect if
// an import refers to the same as another, despite different relative paths
// or differently mapped package names.
const resolved_path = try std.fs.path.resolve(gpa, &.{
mod.root.root_dir.path orelse ".",
mod.root.sub_path,
mod.root_src_path,
});
var keep_resolved_path = false;
defer if (!keep_resolved_path) gpa.free(resolved_path);
const gop = try zcu.import_table.getOrPut(gpa, resolved_path);
errdefer _ = zcu.import_table.pop();
if (gop.found_existing) {
const file_index = gop.value_ptr.*;
const file = zcu.fileByIndex(file_index);
try file.addReference(zcu, .{ .root = mod });
return .{
.file = file,
.file_index = file_index,
.is_new = false,
.is_pkg = true,
};
}
const ip = &zcu.intern_pool;
if (mod.builtin_file) |builtin_file| {
const path_digest = Zcu.computePathDigest(zcu, mod, builtin_file.sub_file_path);
const file_index = try ip.createFile(gpa, pt.tid, .{
.bin_digest = path_digest,
.file = builtin_file,
.root_decl = .none,
});
keep_resolved_path = true; // It's now owned by import_table.
gop.value_ptr.* = file_index;
try builtin_file.addReference(zcu, .{ .root = mod });
return .{
.file = builtin_file,
.file_index = file_index,
.is_new = false,
.is_pkg = true,
};
}
const sub_file_path = try gpa.dupe(u8, mod.root_src_path);
errdefer gpa.free(sub_file_path);
const new_file = try gpa.create(Zcu.File);
errdefer gpa.destroy(new_file);
const path_digest = zcu.computePathDigest(mod, sub_file_path);
const new_file_index = try ip.createFile(gpa, pt.tid, .{
.bin_digest = path_digest,
.file = new_file,
.root_decl = .none,
});
keep_resolved_path = true; // It's now owned by import_table.
gop.value_ptr.* = new_file_index;
new_file.* = .{
.sub_file_path = sub_file_path,
.source = undefined,
.source_loaded = false,
.tree_loaded = false,
.zir_loaded = false,
.stat = undefined,
.tree = undefined,
.zir = undefined,
.status = .never_loaded,
.mod = mod,
};
try new_file.addReference(zcu, .{ .root = mod });
return .{
.file = new_file,
.file_index = new_file_index,
.is_new = true,
.is_pkg = true,
};
}
/// Called from a worker thread during AstGen.
/// Also called from Sema during semantic analysis.
pub fn importFile(
pt: Zcu.PerThread,
cur_file: *Zcu.File,
import_string: []const u8,
) !Zcu.ImportFileResult {
const zcu = pt.zcu;
const mod = cur_file.mod;
if (std.mem.eql(u8, import_string, "std")) {
return pt.importPkg(zcu.std_mod);
}
if (std.mem.eql(u8, import_string, "root")) {
return pt.importPkg(zcu.root_mod);
}
if (mod.deps.get(import_string)) |pkg| {
return pt.importPkg(pkg);
}
if (!std.mem.endsWith(u8, import_string, ".zig")) {
return error.ModuleNotFound;
}
const gpa = zcu.gpa;
// The resolved path is used as the key in the import table, to detect if
// an import refers to the same as another, despite different relative paths
// or differently mapped package names.
const resolved_path = try std.fs.path.resolve(gpa, &.{
mod.root.root_dir.path orelse ".",
mod.root.sub_path,
cur_file.sub_file_path,
"..",
import_string,
});
var keep_resolved_path = false;
defer if (!keep_resolved_path) gpa.free(resolved_path);
const gop = try zcu.import_table.getOrPut(gpa, resolved_path);
errdefer _ = zcu.import_table.pop();
if (gop.found_existing) {
const file_index = gop.value_ptr.*;
return .{
.file = zcu.fileByIndex(file_index),
.file_index = file_index,
.is_new = false,
.is_pkg = false,
};
}
const ip = &zcu.intern_pool;
const new_file = try gpa.create(Zcu.File);
errdefer gpa.destroy(new_file);
const resolved_root_path = try std.fs.path.resolve(gpa, &.{
mod.root.root_dir.path orelse ".",
mod.root.sub_path,
});
defer gpa.free(resolved_root_path);
const sub_file_path = p: {
const relative = try std.fs.path.relative(gpa, resolved_root_path, resolved_path);
errdefer gpa.free(relative);
if (!isUpDir(relative) and !std.fs.path.isAbsolute(relative)) {
break :p relative;
}
return error.ImportOutsideModulePath;
};
errdefer gpa.free(sub_file_path);
log.debug("new importFile. resolved_root_path={s}, resolved_path={s}, sub_file_path={s}, import_string={s}", .{
resolved_root_path, resolved_path, sub_file_path, import_string,
});
const path_digest = zcu.computePathDigest(mod, sub_file_path);
const new_file_index = try ip.createFile(gpa, pt.tid, .{
.bin_digest = path_digest,
.file = new_file,
.root_decl = .none,
});
keep_resolved_path = true; // It's now owned by import_table.
gop.value_ptr.* = new_file_index;
new_file.* = .{
.sub_file_path = sub_file_path,
.source = undefined,
.source_loaded = false,
.tree_loaded = false,
.zir_loaded = false,
.stat = undefined,
.tree = undefined,
.zir = undefined,
.status = .never_loaded,
.mod = mod,
};
return .{
.file = new_file,
.file_index = new_file_index,
.is_new = true,
.is_pkg = false,
};
}
pub fn embedFile(
pt: Zcu.PerThread,
cur_file: *Zcu.File,
@ -1432,20 +1629,6 @@ pub fn embedFile(
return pt.newEmbedFile(cur_file.mod, sub_file_path, resolved_path, gop.value_ptr, src_loc);
}
/// 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(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) void {
assert(!pt.zcu.declIsRoot(decl_index));
pt.destroyDecl(decl_index);
}
/// Finalize the creation of an anon decl.
pub fn finalizeAnonDecl(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) Allocator.Error!void {
if (pt.zcu.declPtr(decl_index).typeOf(pt.zcu).isFnOrHasRuntimeBits(pt)) {
try pt.zcu.comp.work_queue.writeItem(.{ .codegen_decl = decl_index });
}
}
/// https://github.com/ziglang/zig/issues/14307
fn newEmbedFile(
pt: Zcu.PerThread,
@ -1718,7 +1901,10 @@ const ScanDeclIter = struct {
}
const parent_file_scope_index = iter.parent_decl.getFileScopeIndex(zcu);
const tracked_inst = try ip.trackZir(gpa, parent_file_scope_index, decl_inst);
const tracked_inst = try ip.trackZir(gpa, pt.tid, .{
.file = parent_file_scope_index,
.inst = decl_inst,
});
// We create a Decl for it regardless of analysis status.
@ -1728,6 +1914,7 @@ const ScanDeclIter = struct {
const was_exported = decl.is_exported;
assert(decl.kind == kind); // ZIR tracking should preserve this
decl.name = decl_name;
decl.fqn = try namespace.internFullyQualifiedName(ip, gpa, pt.tid, decl_name);
decl.is_pub = declaration.flags.is_pub;
decl.is_exported = declaration.flags.is_export;
break :decl_index .{ was_exported, decl_index };
@ -1737,6 +1924,7 @@ const ScanDeclIter = struct {
const new_decl = zcu.declPtr(new_decl_index);
new_decl.kind = kind;
new_decl.name = decl_name;
new_decl.fqn = try namespace.internFullyQualifiedName(ip, gpa, pt.tid, 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();
@ -1761,10 +1949,9 @@ const ScanDeclIter = struct {
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);
const decl_fqn = decl.fqn.toSlice(ip);
for (comp.test_filters) |test_filter| {
if (std.mem.indexOf(u8, decl_fqn_slice, test_filter)) |_| break;
if (std.mem.indexOf(u8, decl_fqn, test_filter)) |_| break;
} else break :a false;
}
zcu.test_functions.putAssumeCapacity(decl_index, {}); // may clobber on incremental update
@ -1794,6 +1981,20 @@ const ScanDeclIter = struct {
}
};
/// 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(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) void {
assert(!pt.zcu.declIsRoot(decl_index));
pt.destroyDecl(decl_index);
}
/// Finalize the creation of an anon decl.
pub fn finalizeAnonDecl(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) Allocator.Error!void {
if (pt.zcu.declPtr(decl_index).typeOf(pt.zcu).isFnOrHasRuntimeBits(pt)) {
try pt.zcu.comp.work_queue.writeItem(.{ .codegen_decl = decl_index });
}
}
pub fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index, arena: Allocator) Zcu.SemaError!Air {
const tracy = trace(@src());
defer tracy.end();
@ -1805,12 +2006,10 @@ 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(pt)).fmt(ip)});
defer blk: {
log.debug("finish func name '{}'", .{(decl.fullyQualifiedName(pt) catch break :blk).fmt(ip)});
}
log.debug("func name '{}'", .{decl.fqn.fmt(ip)});
defer log.debug("finish func name '{}'", .{decl.fqn.fmt(ip)});
const decl_prog_node = mod.sema_prog_node.start((try decl.fullyQualifiedName(pt)).toSlice(ip), 0);
const decl_prog_node = mod.sema_prog_node.start(decl.fqn.toSlice(ip), 0);
defer decl_prog_node.end();
mod.intern_pool.removeDependenciesForDepender(gpa, InternPool.AnalUnit.wrap(.{ .func = func_index }));
@ -1911,10 +2110,17 @@ pub fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index, arena: All
runtime_params_len;
var runtime_param_index: usize = 0;
for (fn_info.param_body[0..src_params_len], 0..) |inst, src_param_index| {
for (fn_info.param_body[0..src_params_len]) |inst| {
const gop = sema.inst_map.getOrPutAssumeCapacity(inst);
if (gop.found_existing) continue; // provided above by comptime arg
const inst_info = sema.code.instructions.get(@intFromEnum(inst));
const param_name: Zir.NullTerminatedString = switch (inst_info.tag) {
.param_anytype => inst_info.data.str_tok.start,
.param => sema.code.extraData(Zir.Inst.Param, inst_info.data.pl_tok.payload_index).data.name,
else => unreachable,
};
const param_ty = fn_ty_info.param_types.get(ip)[runtime_param_index];
runtime_param_index += 1;
@ -1935,7 +2141,10 @@ pub fn analyzeFnBody(pt: Zcu.PerThread, func_index: InternPool.Index, arena: All
.tag = .arg,
.data = .{ .arg = .{
.ty = Air.internedToRef(param_ty),
.src_index = @intCast(src_param_index),
.name = if (inner_block.ownerModule().strip)
.none
else
@enumFromInt(try sema.appendAirString(sema.code.nullTerminatedString(param_name))),
} },
});
}
@ -2053,6 +2262,7 @@ pub fn allocateNewDecl(pt: Zcu.PerThread, namespace: Zcu.Namespace.Index) !Zcu.D
const gpa = zcu.gpa;
const decl_index = try zcu.intern_pool.createDecl(gpa, pt.tid, .{
.name = undefined,
.fqn = undefined,
.src_namespace = namespace,
.has_tv = false,
.owns_tv = false,
@ -2077,6 +2287,36 @@ pub fn allocateNewDecl(pt: Zcu.PerThread, namespace: Zcu.Namespace.Index) !Zcu.D
return decl_index;
}
pub fn getErrorValue(
pt: Zcu.PerThread,
name: InternPool.NullTerminatedString,
) Allocator.Error!Zcu.ErrorInt {
return pt.zcu.intern_pool.getErrorValue(pt.zcu.gpa, pt.tid, name);
}
pub fn getErrorValueFromSlice(pt: Zcu.PerThread, name: []const u8) Allocator.Error!Zcu.ErrorInt {
return pt.getErrorValue(try pt.zcu.intern_pool.getOrPutString(pt.zcu.gpa, name));
}
pub fn initNewAnonDecl(
pt: Zcu.PerThread,
new_decl_index: Zcu.Decl.Index,
val: Value,
name: InternPool.NullTerminatedString,
fqn: InternPool.OptionalNullTerminatedString,
) Allocator.Error!void {
const new_decl = pt.zcu.declPtr(new_decl_index);
new_decl.name = name;
new_decl.fqn = fqn.unwrap() orelse try pt.zcu.namespacePtr(new_decl.src_namespace)
.internFullyQualifiedName(&pt.zcu.intern_pool, pt.zcu.gpa, pt.tid, name);
new_decl.val = val;
new_decl.alignment = .none;
new_decl.@"linksection" = .none;
new_decl.has_tv = true;
new_decl.analysis = .complete;
}
fn lockAndClearFileCompileError(pt: Zcu.PerThread, file: *Zcu.File) void {
switch (file.status) {
.success_zir, .retryable_failure => {},
@ -2229,7 +2469,7 @@ pub fn populateTestFunctions(
const gpa = zcu.gpa;
const ip = &zcu.intern_pool;
const builtin_mod = zcu.root_mod.getBuiltinDependency();
const builtin_file_index = (zcu.importPkg(builtin_mod) catch unreachable).file_index;
const builtin_file_index = (pt.importPkg(builtin_mod) catch unreachable).file_index;
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);
@ -2260,7 +2500,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(pt);
const test_decl_name = test_decl.fqn;
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(.{
@ -2366,7 +2606,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(pt)).toSlice(&zcu.intern_pool), 0);
const codegen_prog_node = zcu.codegen_prog_node.start(decl.fqn.toSlice(&zcu.intern_pool), 0);
defer codegen_prog_node.end();
if (comp.bin_file) |lf| {
@ -2396,6 +2636,87 @@ pub fn linkerUpdateDecl(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) !void {
}
}
pub fn reportRetryableAstGenError(
pt: Zcu.PerThread,
src: Zcu.AstGenSrc,
file_index: Zcu.File.Index,
err: anyerror,
) error{OutOfMemory}!void {
const zcu = pt.zcu;
const gpa = zcu.gpa;
const ip = &zcu.intern_pool;
const file = zcu.fileByIndex(file_index);
file.status = .retryable_failure;
const src_loc: Zcu.LazySrcLoc = switch (src) {
.root => .{
.base_node_inst = try ip.trackZir(gpa, pt.tid, .{
.file = file_index,
.inst = .main_struct_inst,
}),
.offset = .entire_file,
},
.import => |info| .{
.base_node_inst = try ip.trackZir(gpa, pt.tid, .{
.file = info.importing_file,
.inst = .main_struct_inst,
}),
.offset = .{ .token_abs = info.import_tok },
},
};
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);
{
zcu.comp.mutex.lock();
defer zcu.comp.mutex.unlock();
try zcu.failed_files.putNoClobber(gpa, file, err_msg);
}
}
pub fn reportRetryableFileError(
pt: Zcu.PerThread,
file_index: Zcu.File.Index,
comptime format: []const u8,
args: anytype,
) error{OutOfMemory}!void {
const zcu = pt.zcu;
const gpa = zcu.gpa;
const ip = &zcu.intern_pool;
const file = zcu.fileByIndex(file_index);
file.status = .retryable_failure;
const err_msg = try Zcu.ErrorMsg.create(
gpa,
.{
.base_node_inst = try ip.trackZir(gpa, pt.tid, .{
.file = file_index,
.inst = .main_struct_inst,
}),
.offset = .entire_file,
},
format,
args,
);
errdefer err_msg.destroy(gpa);
zcu.comp.mutex.lock();
defer zcu.comp.mutex.unlock();
const gop = try zcu.failed_files.getOrPut(gpa, file);
if (gop.found_existing) {
if (gop.value_ptr.*) |old_err_msg| {
old_err_msg.destroy(gpa);
}
}
gop.value_ptr.* = err_msg;
}
/// Shortcut for calling `intern_pool.get`.
pub fn intern(pt: Zcu.PerThread, key: InternPool.Key) Allocator.Error!InternPool.Index {
return pt.zcu.intern_pool.get(pt.zcu.gpa, pt.tid, key);
@ -2897,7 +3218,7 @@ pub fn getBuiltinDecl(pt: Zcu.PerThread, name: []const u8) Allocator.Error!Inter
const zcu = pt.zcu;
const gpa = zcu.gpa;
const ip = &zcu.intern_pool;
const std_file_imported = zcu.importPkg(zcu.std_mod) catch @panic("failed to import lib/std.zig");
const std_file_imported = pt.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, pt.tid, "builtin", .no_embedded_nulls);

View File

@ -4231,19 +4231,19 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
while (self.args[arg_index] == .none) arg_index += 1;
self.arg_index = arg_index + 1;
const pt = self.pt;
const mod = pt.zcu;
const ty = self.typeOfIndex(inst);
const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];
const src_index = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.src_index;
const name = mod.getParamName(self.func_index, src_index);
try self.dbg_info_relocs.append(self.gpa, .{
.tag = tag,
.ty = ty,
.name = name,
.mcv = self.args[arg_index],
});
const name_nts = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.name;
if (name_nts != .none) {
const name = self.air.nullTerminatedString(@intFromEnum(name_nts));
try self.dbg_info_relocs.append(self.gpa, .{
.tag = tag,
.ty = ty,
.name = name,
.mcv = self.args[arg_index],
});
}
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else self.args[arg_index];
return self.finishAir(inst, result, .{ .none, .none, .none });

View File

@ -4206,19 +4206,19 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
while (self.args[arg_index] == .none) arg_index += 1;
self.arg_index = arg_index + 1;
const pt = self.pt;
const mod = pt.zcu;
const ty = self.typeOfIndex(inst);
const tag = self.air.instructions.items(.tag)[@intFromEnum(inst)];
const src_index = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.src_index;
const name = mod.getParamName(self.func_index, src_index);
try self.dbg_info_relocs.append(self.gpa, .{
.tag = tag,
.ty = ty,
.name = name,
.mcv = self.args[arg_index],
});
const name_nts = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.name;
if (name_nts != .none) {
const name = self.air.nullTerminatedString(@intFromEnum(name_nts));
try self.dbg_info_relocs.append(self.gpa, .{
.tag = tag,
.ty = ty,
.name = name,
.mcv = self.args[arg_index],
});
}
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else self.args[arg_index];
return self.finishAir(inst, result, .{ .none, .none, .none });

View File

@ -933,7 +933,7 @@ fn formatDecl(
_: std.fmt.FormatOptions,
writer: anytype,
) @TypeOf(writer).Error!void {
try data.mod.declPtr(data.decl_index).renderFullyQualifiedName(data.mod, writer);
try writer.print("{}", .{data.mod.declPtr(data.decl_index).fqn.fmt(&data.mod.intern_pool)});
}
fn fmtDecl(func: *Func, decl_index: InternPool.DeclIndex) std.fmt.Formatter(formatDecl) {
return .{ .data = .{
@ -4051,7 +4051,8 @@ fn genArgDbgInfo(func: Func, inst: Air.Inst.Index, mcv: MCValue) !void {
const arg = func.air.instructions.items(.data)[@intFromEnum(inst)].arg;
const ty = arg.ty.toType();
const owner_decl = zcu.funcOwnerDeclIndex(func.func_index);
const name = zcu.getParamName(func.func_index, arg.src_index);
if (arg.name == .none) return;
const name = func.air.nullTerminatedString(@intFromEnum(arg.name));
switch (func.debug_output) {
.dwarf => |dw| switch (mcv) {

View File

@ -3614,7 +3614,8 @@ fn genArgDbgInfo(self: Self, inst: Air.Inst.Index, mcv: MCValue) !void {
const arg = self.air.instructions.items(.data)[@intFromEnum(inst)].arg;
const ty = arg.ty.toType();
const owner_decl = mod.funcOwnerDeclIndex(self.func_index);
const name = mod.getParamName(self.func_index, arg.src_index);
if (arg.name == .none) return;
const name = self.air.nullTerminatedString(@intFromEnum(arg.name));
switch (self.debug_output) {
.dwarf => |dw| switch (mcv) {

View File

@ -2585,11 +2585,13 @@ fn airArg(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
switch (func.debug_output) {
.dwarf => |dwarf| {
const src_index = func.air.instructions.items(.data)[@intFromEnum(inst)].arg.src_index;
const name = mod.getParamName(func.func_index, src_index);
try dwarf.genArgDbgInfo(name, arg_ty, mod.funcOwnerDeclIndex(func.func_index), .{
.wasm_local = arg.local.value,
});
const name_nts = func.air.instructions.items(.data)[@intFromEnum(inst)].arg.name;
if (name_nts != .none) {
const name = func.air.nullTerminatedString(@intFromEnum(name_nts));
try dwarf.genArgDbgInfo(name, arg_ty, mod.funcOwnerDeclIndex(func.func_index), .{
.wasm_local = arg.local.value,
});
}
},
else => {},
}
@ -3302,7 +3304,7 @@ fn lowerConstant(func: *CodeGen, val: Value, ty: Type) InnerError!WValue {
}
},
.err => |err| {
const int = try mod.getErrorValue(err.name);
const int = try pt.getErrorValue(err.name);
return WValue{ .imm32 = int };
},
.error_union => |error_union| {
@ -3450,30 +3452,25 @@ fn emitUndefined(func: *CodeGen, ty: Type) InnerError!WValue {
/// Returns a `Value` as a signed 32 bit value.
/// It's illegal to provide a value with a type that cannot be represented
/// as an integer value.
fn valueAsI32(func: *const CodeGen, val: Value, ty: Type) i32 {
fn valueAsI32(func: *const CodeGen, val: Value) i32 {
const pt = func.pt;
const mod = pt.zcu;
const ip = &mod.intern_pool;
switch (val.ip_index) {
.none => {},
switch (val.toIntern()) {
.bool_true => return 1,
.bool_false => return 0,
else => return switch (mod.intern_pool.indexToKey(val.ip_index)) {
.enum_tag => |enum_tag| intIndexAsI32(&mod.intern_pool, enum_tag.int, pt),
else => return switch (ip.indexToKey(val.ip_index)) {
.enum_tag => |enum_tag| intIndexAsI32(ip, enum_tag.int, pt),
.int => |int| intStorageAsI32(int.storage, pt),
.ptr => |ptr| {
assert(ptr.base_addr == .int);
return @intCast(ptr.byte_offset);
},
.err => |err| @as(i32, @bitCast(@as(Zcu.ErrorInt, @intCast(mod.global_error_set.getIndex(err.name).?)))),
.err => |err| @bitCast(ip.getErrorValueIfExists(err.name).?),
else => unreachable,
},
}
return switch (ty.zigTypeTag(mod)) {
.ErrorSet => @as(i32, @bitCast(val.getErrorInt(mod))),
else => unreachable, // Programmer called this function for an illegal type
};
}
fn intIndexAsI32(ip: *const InternPool, int: InternPool.Index, pt: Zcu.PerThread) i32 {
@ -4096,7 +4093,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
for (items, 0..) |ref, i| {
const item_val = (try func.air.value(ref, pt)).?;
const int_val = func.valueAsI32(item_val, target_ty);
const int_val = func.valueAsI32(item_val);
if (lowest_maybe == null or int_val < lowest_maybe.?) {
lowest_maybe = int_val;
}
@ -7284,8 +7281,8 @@ 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(pt);
const func_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{}", .{fqn.fmt(ip)});
const decl = mod.declPtr(enum_decl_index);
const func_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{}", .{decl.fqn.fmt(ip)});
// check if we already generated code for this.
if (func.bin_file.findGlobalSymbol(func_name)) |loc| {
@ -7452,7 +7449,7 @@ fn airErrorSetHasValue(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
var lowest: ?u32 = null;
var highest: ?u32 = null;
for (0..names.len) |name_index| {
const err_int: Zcu.ErrorInt = @intCast(mod.global_error_set.getIndex(names.get(ip)[name_index]).?);
const err_int = ip.getErrorValueIfExists(names.get(ip)[name_index]).?;
if (lowest) |*l| {
if (err_int < l.*) {
l.* = err_int;

View File

@ -1077,7 +1077,7 @@ fn formatDecl(
_: std.fmt.FormatOptions,
writer: anytype,
) @TypeOf(writer).Error!void {
try data.zcu.declPtr(data.decl_index).renderFullyQualifiedName(data.zcu, writer);
try writer.print("{}", .{data.zcu.declPtr(data.decl_index).fqn.fmt(&data.zcu.intern_pool)});
}
fn fmtDecl(self: *Self, decl_index: InternPool.DeclIndex) std.fmt.Formatter(formatDecl) {
return .{ .data = .{
@ -11920,9 +11920,11 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
else => return self.fail("TODO implement arg for {}", .{src_mcv}),
};
const src_index = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.src_index;
const name = mod.getParamName(self.owner.func_index, src_index);
try self.genArgDbgInfo(arg_ty, name, src_mcv);
const name_nts = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.name;
switch (name_nts) {
.none => {},
_ => try self.genArgDbgInfo(arg_ty, self.air.nullTerminatedString(@intFromEnum(name_nts)), src_mcv),
}
break :result dst_mcv;
};
@ -16433,7 +16435,7 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {
.size = .dword,
.index = err_reg.to64(),
.scale = .@"4",
.disp = 4,
.disp = (1 - 1) * 4,
} },
},
);
@ -16446,7 +16448,7 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {
.size = .dword,
.index = err_reg.to64(),
.scale = .@"4",
.disp = 8,
.disp = (2 - 1) * 4,
} },
},
);

View File

@ -137,10 +137,10 @@ pub fn generateLazySymbol(
if (lazy_sym.ty.isAnyError(pt.zcu)) {
alignment.* = .@"4";
const err_names = pt.zcu.global_error_set.keys();
const err_names = ip.global_error_set.getNamesFromMainThread();
mem.writeInt(u32, try code.addManyAsArray(4), @intCast(err_names.len), endian);
var offset = code.items.len;
try code.resize((1 + err_names.len + 1) * 4);
try code.resize((err_names.len + 1) * 4);
for (err_names) |err_name_nts| {
const err_name = err_name_nts.toSlice(ip);
mem.writeInt(u32, code.items[offset..][0..4], @intCast(code.items.len), endian);
@ -243,13 +243,13 @@ pub fn generateSymbol(
int_val.writeTwosComplement(try code.addManyAsSlice(abi_size), endian);
},
.err => |err| {
const int = try mod.getErrorValue(err.name);
const int = try pt.getErrorValue(err.name);
try code.writer().writeInt(u16, @intCast(int), endian);
},
.error_union => |error_union| {
const payload_ty = ty.errorUnionPayload(mod);
const err_val: u16 = switch (error_union.val) {
.err_name => |err_name| @intCast(try mod.getErrorValue(err_name)),
.err_name => |err_name| @intCast(try pt.getErrorValue(err_name)),
.payload => 0,
};
@ -1058,7 +1058,7 @@ pub fn genTypedValue(
},
.ErrorSet => {
const err_name = ip.indexToKey(val.toIntern()).err.name;
const error_index = zcu.global_error_set.getIndex(err_name).?;
const error_index = try pt.getErrorValue(err_name);
return GenResult.mcv(.{ .immediate = error_index });
},
.ErrorUnion => {

View File

@ -2194,13 +2194,9 @@ pub const DeclGen = struct {
}) else {
// MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case),
// expand to 3x the length of its input, but let's cut it off at a much shorter limit.
var name: [100]u8 = undefined;
var name_stream = std.io.fixedBufferStream(&name);
decl.renderFullyQualifiedName(zcu, name_stream.writer()) catch |err| switch (err) {
error.NoSpaceLeft => {},
};
const fqn_slice = decl.fqn.toSlice(ip);
try writer.print("{}__{d}", .{
fmtIdent(name_stream.getWritten()),
fmtIdent(fqn_slice[0..@min(fqn_slice.len, 100)]),
@intFromEnum(decl_index),
});
}
@ -2587,11 +2583,9 @@ pub fn genTypeDecl(
try writer.writeByte(';');
const owner_decl = zcu.declPtr(owner_decl_index);
const owner_mod = zcu.namespacePtr(owner_decl.src_namespace).fileScope(zcu).mod;
if (!owner_mod.strip) {
try writer.writeAll(" /* ");
try owner_decl.renderFullyQualifiedName(zcu, writer);
try writer.writeAll(" */");
}
if (!owner_mod.strip) try writer.print(" /* {} */", .{
owner_decl.fqn.fmt(&zcu.intern_pool),
});
try writer.writeByte('\n');
},
},
@ -2628,10 +2622,11 @@ pub fn genErrDecls(o: *Object) !void {
var max_name_len: usize = 0;
// do not generate an invalid empty enum when the global error set is empty
if (zcu.global_error_set.keys().len > 1) {
const names = ip.global_error_set.getNamesFromMainThread();
if (names.len > 0) {
try writer.writeAll("enum {\n");
o.indent_writer.pushIndent();
for (zcu.global_error_set.keys()[1..], 1..) |name_nts, value| {
for (names, 1..) |name_nts, value| {
const name = name_nts.toSlice(ip);
max_name_len = @max(name.len, max_name_len);
const err_val = try pt.intern(.{ .err = .{
@ -2650,7 +2645,7 @@ pub fn genErrDecls(o: *Object) !void {
defer o.dg.gpa.free(name_buf);
@memcpy(name_buf[0..name_prefix.len], name_prefix);
for (zcu.global_error_set.keys()) |name| {
for (names) |name| {
const name_slice = name.toSlice(ip);
@memcpy(name_buf[name_prefix.len..][0..name_slice.len], name_slice);
const identifier = name_buf[0 .. name_prefix.len + name_slice.len];
@ -2680,7 +2675,7 @@ pub fn genErrDecls(o: *Object) !void {
}
const name_array_ty = try pt.arrayType(.{
.len = zcu.global_error_set.count(),
.len = 1 + names.len,
.child = .slice_const_u8_sentinel_0_type,
});
@ -2694,9 +2689,9 @@ pub fn genErrDecls(o: *Object) !void {
.complete,
);
try writer.writeAll(" = {");
for (zcu.global_error_set.keys(), 0..) |name_nts, value| {
for (names, 1..) |name_nts, val| {
const name = name_nts.toSlice(ip);
if (value != 0) try writer.writeByte(',');
if (val > 1) try writer.writeAll(", ");
try writer.print("{{" ++ name_prefix ++ "{}, {}}}", .{
fmtIdent(name),
try o.dg.fmtIntLiteral(try pt.intValue(Type.usize, name.len), .StaticInitializer),
@ -4563,9 +4558,7 @@ fn airDbgInlineBlock(f: *Function, inst: Air.Inst.Index) !CValue {
const extra = f.air.extraData(Air.DbgInlineBlock, ty_pl.payload);
const owner_decl = zcu.funcOwnerDeclPtr(extra.data.func);
const writer = f.object.writer();
try writer.writeAll("/* inline:");
try owner_decl.renderFullyQualifiedName(zcu, writer);
try writer.writeAll(" */\n");
try writer.print("/* inline:{} */\n", .{owner_decl.fqn.fmt(&zcu.intern_pool)});
return lowerBlock(f, inst, @ptrCast(f.air.extra[extra.end..][0..extra.data.body_len]));
}
@ -6881,7 +6874,7 @@ fn airErrorName(f: *Function, inst: Air.Inst.Index) !CValue {
try writer.writeAll(" = zig_errorName[");
try f.writeCValue(writer, operand, .Other);
try writer.writeAll("];\n");
try writer.writeAll(" - 1];\n");
return local;
}

View File

@ -1036,20 +1036,21 @@ pub const Object = struct {
const pt = o.pt;
const mod = pt.zcu;
const ip = &mod.intern_pool;
const error_name_list = mod.global_error_set.keys();
const llvm_errors = try mod.gpa.alloc(Builder.Constant, error_name_list.len);
const error_name_list = ip.global_error_set.getNamesFromMainThread();
const llvm_errors = try mod.gpa.alloc(Builder.Constant, 1 + error_name_list.len);
defer mod.gpa.free(llvm_errors);
// TODO: Address space
const slice_ty = Type.slice_const_u8_sentinel_0;
const llvm_usize_ty = try o.lowerType(Type.usize);
const llvm_slice_ty = try o.lowerType(slice_ty);
const llvm_table_ty = try o.builder.arrayType(error_name_list.len, llvm_slice_ty);
const llvm_table_ty = try o.builder.arrayType(1 + error_name_list.len, llvm_slice_ty);
llvm_errors[0] = try o.builder.undefConst(llvm_slice_ty);
for (llvm_errors[1..], error_name_list[1..]) |*llvm_error, name| {
const name_string = try o.builder.stringNull(name.toSlice(&mod.intern_pool));
for (llvm_errors[1..], error_name_list) |*llvm_error, name| {
const name_string = try o.builder.stringNull(name.toSlice(ip));
const name_init = try o.builder.stringConst(name_string);
const name_variable_index =
try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
@ -1085,7 +1086,7 @@ pub const Object = struct {
// If there is no such function in the module, it means the source code does not need it.
const name = o.builder.strtabStringIfExists(lt_errors_fn_name) orelse return;
const llvm_fn = o.builder.getGlobal(name) orelse return;
const errors_len = o.pt.zcu.global_error_set.count();
const errors_len = o.pt.zcu.intern_pool.global_error_set.mutate.list.len;
var wip = try Builder.WipFunction.init(&o.builder, .{
.function = llvm_fn.ptrConst(&o.builder).kind.function,
@ -1096,12 +1097,12 @@ pub const Object = struct {
// Example source of the following LLVM IR:
// fn __zig_lt_errors_len(index: u16) bool {
// return index < total_errors_len;
// return index <= total_errors_len;
// }
const lhs = wip.arg(0);
const rhs = try o.builder.intValue(try o.errorIntType(), errors_len);
const is_lt = try wip.icmp(.ult, lhs, rhs, "");
const is_lt = try wip.icmp(.ule, lhs, rhs, "");
_ = try wip.ret(is_lt);
try wip.finish();
}
@ -1744,7 +1745,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(pt)).toSlice(ip));
const fqn = try self.builder.strtabString(decl.fqn.toSlice(ip));
try global_index.rename(fqn, &self.builder);
global_index.setLinkage(.internal, &self.builder);
if (comp.config.dll_export_fns)
@ -2811,7 +2812,7 @@ pub const Object = struct {
const zcu = pt.zcu;
const std_mod = zcu.std_mod;
const std_file_imported = zcu.importPkg(std_mod) catch unreachable;
const std_file_imported = pt.importPkg(std_mod) catch unreachable;
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);
@ -2863,10 +2864,7 @@ pub const Object = struct {
const is_extern = decl.isExtern(zcu);
const function_index = try o.builder.addFunction(
try o.lowerType(zig_fn_type),
try o.builder.strtabString((if (is_extern)
decl.name
else
try decl.fullyQualifiedName(pt)).toSlice(ip)),
try o.builder.strtabString((if (is_extern) decl.name else decl.fqn).toSlice(ip)),
toLlvmAddressSpace(decl.@"addrspace", target),
);
gop.value_ptr.* = function_index.ptrConst(&o.builder).global;
@ -3077,14 +3075,12 @@ pub const Object = struct {
const pt = o.pt;
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
const decl = zcu.declPtr(decl_index);
const is_extern = decl.isExtern(zcu);
const variable_index = try o.builder.addVariable(
try o.builder.strtabString((if (is_extern)
decl.name
else
try decl.fullyQualifiedName(pt)).toSlice(&zcu.intern_pool)),
try o.builder.strtabString((if (is_extern) decl.name else decl.fqn).toSlice(ip)),
try o.lowerType(decl.typeOf(zcu)),
toLlvmGlobalAddressSpace(decl.@"addrspace", zcu.getTarget()),
);
@ -3312,7 +3308,7 @@ pub const Object = struct {
return int_ty;
}
const fqn = try mod.declPtr(struct_type.decl.unwrap().?).fullyQualifiedName(pt);
const decl = mod.declPtr(struct_type.decl.unwrap().?);
var llvm_field_types = std.ArrayListUnmanaged(Builder.Type){};
defer llvm_field_types.deinit(o.gpa);
@ -3377,7 +3373,7 @@ pub const Object = struct {
);
}
const ty = try o.builder.opaqueType(try o.builder.string(fqn.toSlice(ip)));
const ty = try o.builder.opaqueType(try o.builder.string(decl.fqn.toSlice(ip)));
try o.type_map.put(o.gpa, t.toIntern(), ty);
o.builder.namedTypeSetBody(
@ -3466,7 +3462,7 @@ pub const Object = struct {
return enum_tag_ty;
}
const fqn = try mod.declPtr(union_obj.decl).fullyQualifiedName(pt);
const decl = mod.declPtr(union_obj.decl);
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);
@ -3486,7 +3482,7 @@ pub const Object = struct {
};
if (layout.tag_size == 0) {
const ty = try o.builder.opaqueType(try o.builder.string(fqn.toSlice(ip)));
const ty = try o.builder.opaqueType(try o.builder.string(decl.fqn.toSlice(ip)));
try o.type_map.put(o.gpa, t.toIntern(), ty);
o.builder.namedTypeSetBody(
@ -3514,7 +3510,7 @@ pub const Object = struct {
llvm_fields_len += 1;
}
const ty = try o.builder.opaqueType(try o.builder.string(fqn.toSlice(ip)));
const ty = try o.builder.opaqueType(try o.builder.string(decl.fqn.toSlice(ip)));
try o.type_map.put(o.gpa, t.toIntern(), ty);
o.builder.namedTypeSetBody(
@ -3527,8 +3523,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(pt);
gop.value_ptr.* = try o.builder.opaqueType(try o.builder.string(fqn.toSlice(ip)));
gop.value_ptr.* = try o.builder.opaqueType(try o.builder.string(decl.fqn.toSlice(ip)));
}
return gop.value_ptr.*;
},
@ -3826,7 +3821,7 @@ pub const Object = struct {
return lowerBigInt(o, ty, bigint);
},
.err => |err| {
const int = try mod.getErrorValue(err.name);
const int = try pt.getErrorValue(err.name);
const llvm_int = try o.builder.intConst(try o.errorIntType(), int);
return llvm_int;
},
@ -4587,11 +4582,11 @@ 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(pt);
const decl = zcu.declPtr(enum_type.decl);
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),
try o.builder.strtabStringFmt("__zig_tag_name_{}", .{fqn.fmt(ip)}),
try o.builder.strtabStringFmt("__zig_tag_name_{}", .{decl.fqn.fmt(ip)}),
toLlvmAddressSpace(.generic, target),
);
@ -5175,8 +5170,6 @@ pub const FuncGen = struct {
const line_number = decl.navSrcLine(zcu) + 1;
self.inlined = self.wip.debug_location;
const fqn = try decl.fullyQualifiedName(pt);
const fn_ty = try pt.funcType(.{
.param_types = &.{},
.return_type = .void_type,
@ -5185,7 +5178,7 @@ pub const FuncGen = struct {
self.scope = try o.builder.debugSubprogram(
self.file,
try o.builder.metadataString(decl.name.toSlice(&zcu.intern_pool)),
try o.builder.metadataString(fqn.toSlice(&zcu.intern_pool)),
try o.builder.metadataString(decl.fqn.toSlice(&zcu.intern_pool)),
line_number,
line_number + func.lbrace_line,
try o.lowerDebugType(fn_ty),
@ -8867,19 +8860,21 @@ pub const FuncGen = struct {
self.arg_index += 1;
// llvm does not support debug info for naked function arguments
if (self.wip.strip or self.is_naked) return arg_val;
if (self.is_naked) return arg_val;
const inst_ty = self.typeOfIndex(inst);
if (needDbgVarWorkaround(o)) return arg_val;
const src_index = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.src_index;
const name = self.air.instructions.items(.data)[@intFromEnum(inst)].arg.name;
if (name == .none) return arg_val;
const func_index = self.dg.decl.getOwnedFunctionIndex();
const func = mod.funcInfo(func_index);
const lbrace_line = mod.declPtr(func.owner_decl).navSrcLine(mod) + func.lbrace_line + 1;
const lbrace_col = func.lbrace_column + 1;
const debug_parameter = try o.builder.debugParameter(
try o.builder.metadataString(mod.getParamName(func_index, src_index)),
try o.builder.metadataString(self.air.nullTerminatedString(@intFromEnum(name))),
self.file,
self.scope,
lbrace_line,
@ -9664,7 +9659,7 @@ pub const FuncGen = struct {
defer wip_switch.finish(&self.wip);
for (0..names.len) |name_index| {
const err_int = mod.global_error_set.getIndex(names.get(ip)[name_index]).?;
const err_int = ip.getErrorValueIfExists(names.get(ip)[name_index]).?;
const this_tag_int_value = try o.builder.intConst(try o.errorIntType(), err_int);
try wip_switch.addCase(this_tag_int_value, valid_block, &self.wip);
}
@ -9702,18 +9697,19 @@ pub const FuncGen = struct {
const o = self.dg.object;
const pt = o.pt;
const zcu = pt.zcu;
const enum_type = zcu.intern_pool.loadEnumType(enum_ty.toIntern());
const ip = &zcu.intern_pool;
const enum_type = ip.loadEnumType(enum_ty.toIntern());
// TODO: detect when the type changes and re-emit this function.
const gop = try o.named_enum_map.getOrPut(o.gpa, enum_type.decl);
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(pt);
const decl = zcu.declPtr(enum_type.decl);
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),
try o.builder.strtabStringFmt("__zig_is_named_enum_value_{}", .{fqn.fmt(&zcu.intern_pool)}),
try o.builder.strtabStringFmt("__zig_is_named_enum_value_{}", .{decl.fqn.fmt(ip)}),
toLlvmAddressSpace(.generic, target),
);

View File

@ -963,7 +963,7 @@ const DeclGen = struct {
break :cache result_id;
},
.err => |err| {
const value = try mod.getErrorValue(err.name);
const value = try pt.getErrorValue(err.name);
break :cache try self.constInt(ty, value, repr);
},
.error_union => |error_union| {
@ -3012,12 +3012,11 @@ 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);
try self.spv.debugName(result_id, fqn.toSlice(ip));
try self.spv.debugName(result_id, decl.fqn.toSlice(ip));
// Temporarily generate a test kernel declaration if this is a test function.
if (self.pt.zcu.test_functions.contains(self.decl_index)) {
try self.generateTestEntryPoint(fqn.toSlice(ip), spv_decl_index);
try self.generateTestEntryPoint(decl.fqn.toSlice(ip), spv_decl_index);
}
},
.global => {
@ -3041,8 +3040,7 @@ const DeclGen = struct {
.storage_class = final_storage_class,
});
const fqn = try decl.fullyQualifiedName(self.pt);
try self.spv.debugName(result_id, fqn.toSlice(ip));
try self.spv.debugName(result_id, decl.fqn.toSlice(ip));
try self.spv.declareDeclDeps(spv_decl_index, &.{});
},
.invocation_global => {
@ -3086,8 +3084,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);
try self.spv.debugNameFmt(initializer_id, "initializer of {}", .{fqn.fmt(ip)});
try self.spv.debugNameFmt(initializer_id, "initializer of {}", .{decl.fqn.fmt(ip)});
try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpExtInst, .{
.id_result_type = ptr_ty_id,

View File

@ -1176,9 +1176,10 @@ 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(pt);
const index = unnamed_consts.items.len;
const sym_name = try std.fmt.allocPrint(gpa, "__unnamed_{}_{d}", .{ decl_name.fmt(&mod.intern_pool), index });
const sym_name = try std.fmt.allocPrint(gpa, "__unnamed_{}_{d}", .{
decl.fqn.fmt(&mod.intern_pool), index,
});
defer gpa.free(sym_name);
const ty = val.typeOf(mod);
const atom_index = switch (try self.lowerConst(pt, sym_name, val, ty.abiAlignment(pt), self.rdata_section_index.?, decl.navSrcLoc(mod))) {
@ -1427,9 +1428,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(pt);
log.debug("updateDeclCode {}{*}", .{ decl_name.fmt(&mod.intern_pool), decl });
log.debug("updateDeclCode {}{*}", .{ decl.fqn.fmt(&mod.intern_pool), decl });
const required_alignment: u32 = @intCast(decl.getAlignment(pt).toByteUnits() orelse 0);
const decl_metadata = self.decls.get(decl_index).?;
@ -1441,7 +1440,7 @@ fn updateDeclCode(self: *Coff, pt: Zcu.PerThread, decl_index: InternPool.DeclInd
if (atom.size != 0) {
const sym = atom.getSymbolPtr(self);
try self.setSymbolName(sym, decl_name.toSlice(&mod.intern_pool));
try self.setSymbolName(sym, decl.fqn.toSlice(&mod.intern_pool));
sym.section_number = @as(coff.SectionNumber, @enumFromInt(sect_index + 1));
sym.type = .{ .complex_type = complex_type, .base_type = .NULL };
@ -1449,7 +1448,7 @@ fn updateDeclCode(self: *Coff, pt: Zcu.PerThread, decl_index: InternPool.DeclInd
const need_realloc = code.len > capacity or !mem.isAlignedGeneric(u64, sym.value, required_alignment);
if (need_realloc) {
const vaddr = try self.growAtom(atom_index, code_len, required_alignment);
log.debug("growing {} from 0x{x} to 0x{x}", .{ decl_name.fmt(&mod.intern_pool), sym.value, vaddr });
log.debug("growing {} from 0x{x} to 0x{x}", .{ decl.fqn.fmt(&mod.intern_pool), sym.value, vaddr });
log.debug(" (required alignment 0x{x}", .{required_alignment});
if (vaddr != sym.value) {
@ -1465,13 +1464,13 @@ fn updateDeclCode(self: *Coff, pt: Zcu.PerThread, decl_index: InternPool.DeclInd
self.getAtomPtr(atom_index).size = code_len;
} else {
const sym = atom.getSymbolPtr(self);
try self.setSymbolName(sym, decl_name.toSlice(&mod.intern_pool));
try self.setSymbolName(sym, decl.fqn.toSlice(&mod.intern_pool));
sym.section_number = @as(coff.SectionNumber, @enumFromInt(sect_index + 1));
sym.type = .{ .complex_type = complex_type, .base_type = .NULL };
const vaddr = try self.allocateAtom(atom_index, code_len, required_alignment);
errdefer self.freeAtom(atom_index);
log.debug("allocated atom for {} at 0x{x}", .{ decl_name.fmt(&mod.intern_pool), vaddr });
log.debug("allocated atom for {} at 0x{x}", .{ decl.fqn.fmt(&mod.intern_pool), vaddr });
self.getAtomPtr(atom_index).size = code_len;
sym.value = vaddr;

View File

@ -1082,9 +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);
log.debug("initDeclState {}{*}", .{ decl_linkage_name.fmt(&pt.zcu.intern_pool), decl });
log.debug("initDeclState {}{*}", .{ decl.fqn.fmt(&pt.zcu.intern_pool), decl });
const gpa = self.allocator;
var decl_state: DeclState = .{
@ -1157,7 +1155,7 @@ pub fn initDeclState(self: *Dwarf, pt: Zcu.PerThread, decl_index: InternPool.Dec
// .debug_info subprogram
const decl_name_slice = decl.name.toSlice(&pt.zcu.intern_pool);
const decl_linkage_name_slice = decl_linkage_name.toSlice(&pt.zcu.intern_pool);
const decl_linkage_name_slice = decl.fqn.toSlice(&pt.zcu.intern_pool);
try dbg_info_buffer.ensureUnusedCapacity(1 + ptr_width_bytes + 4 + 4 +
(decl_name_slice.len + 1) + (decl_linkage_name_slice.len + 1));
@ -2700,7 +2698,7 @@ pub fn flushModule(self: *Dwarf, pt: Zcu.PerThread) !void {
try addDbgInfoErrorSetNames(
pt,
Type.anyerror,
pt.zcu.global_error_set.keys(),
pt.zcu.intern_pool.global_error_set.getNamesFromMainThread(),
target,
&dbg_info_buffer,
);
@ -2869,7 +2867,7 @@ fn addDbgInfoErrorSetNames(
mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), 0, target_endian);
for (error_names) |error_name| {
const int = try pt.zcu.getErrorValue(error_name);
const int = try pt.getErrorValue(error_name);
const error_name_slice = error_name.toSlice(&pt.zcu.intern_pool);
// DW.AT.enumerator
try dbg_info_buffer.ensureUnusedCapacity(error_name_slice.len + 2 + @sizeOf(u64));

View File

@ -907,10 +907,10 @@ fn updateDeclCode(
) !void {
const gpa = elf_file.base.comp.gpa;
const mod = pt.zcu;
const ip = &mod.intern_pool;
const decl = mod.declPtr(decl_index);
const decl_name = try decl.fullyQualifiedName(pt);
log.debug("updateDeclCode {}{*}", .{ decl_name.fmt(&mod.intern_pool), decl });
log.debug("updateDeclCode {}{*}", .{ decl.fqn.fmt(ip), decl });
const required_alignment = decl.getAlignment(pt).max(
target_util.minFunctionAlignment(mod.getTarget()),
@ -923,7 +923,7 @@ fn updateDeclCode(
sym.output_section_index = shdr_index;
atom_ptr.output_section_index = shdr_index;
sym.name_offset = try self.strtab.insert(gpa, decl_name.toSlice(&mod.intern_pool));
sym.name_offset = try self.strtab.insert(gpa, decl.fqn.toSlice(ip));
atom_ptr.flags.alive = true;
atom_ptr.name_offset = sym.name_offset;
esym.st_name = sym.name_offset;
@ -940,7 +940,7 @@ fn updateDeclCode(
const need_realloc = code.len > capacity or !required_alignment.check(@intCast(atom_ptr.value));
if (need_realloc) {
try atom_ptr.grow(elf_file);
log.debug("growing {} from 0x{x} to 0x{x}", .{ decl_name.fmt(&mod.intern_pool), old_vaddr, atom_ptr.value });
log.debug("growing {} from 0x{x} to 0x{x}", .{ decl.fqn.fmt(ip), old_vaddr, atom_ptr.value });
if (old_vaddr != atom_ptr.value) {
sym.value = 0;
esym.st_value = 0;
@ -1007,11 +1007,11 @@ fn updateTlv(
code: []const u8,
) !void {
const mod = pt.zcu;
const ip = &mod.intern_pool;
const gpa = mod.gpa;
const decl = mod.declPtr(decl_index);
const decl_name = try decl.fullyQualifiedName(pt);
log.debug("updateTlv {} ({*})", .{ decl_name.fmt(&mod.intern_pool), decl });
log.debug("updateTlv {} ({*})", .{ decl.fqn.fmt(ip), decl });
const required_alignment = decl.getAlignment(pt);
@ -1023,7 +1023,7 @@ fn updateTlv(
sym.output_section_index = shndx;
atom_ptr.output_section_index = shndx;
sym.name_offset = try self.strtab.insert(gpa, decl_name.toSlice(&mod.intern_pool));
sym.name_offset = try self.strtab.insert(gpa, decl.fqn.toSlice(ip));
atom_ptr.flags.alive = true;
atom_ptr.name_offset = sym.name_offset;
esym.st_value = 0;
@ -1286,9 +1286,8 @@ pub fn lowerUnnamedConst(
}
const unnamed_consts = gop.value_ptr;
const decl = mod.declPtr(decl_index);
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 });
const name = try std.fmt.allocPrint(gpa, "__unnamed_{}_{d}", .{ decl.fqn.fmt(&mod.intern_pool), index });
defer gpa.free(name);
const ty = val.typeOf(mod);
const sym_index = switch (try self.lowerConst(
@ -1473,9 +1472,8 @@ pub fn updateDeclLineNumber(
defer tracy.end();
const decl = pt.zcu.declPtr(decl_index);
const decl_name = try decl.fullyQualifiedName(pt);
log.debug("updateDeclLineNumber {}{*}", .{ decl_name.fmt(&pt.zcu.intern_pool), decl });
log.debug("updateDeclLineNumber {}{*}", .{ decl.fqn.fmt(&pt.zcu.intern_pool), decl });
if (self.dwarf) |*dw| {
try dw.updateDeclLineNumber(pt.zcu, decl_index);

View File

@ -809,10 +809,10 @@ fn updateDeclCode(
) !void {
const gpa = macho_file.base.comp.gpa;
const mod = pt.zcu;
const ip = &mod.intern_pool;
const decl = mod.declPtr(decl_index);
const decl_name = try decl.fullyQualifiedName(pt);
log.debug("updateDeclCode {}{*}", .{ decl_name.fmt(&mod.intern_pool), decl });
log.debug("updateDeclCode {}{*}", .{ decl.fqn.fmt(ip), decl });
const required_alignment = decl.getAlignment(pt);
@ -824,7 +824,7 @@ fn updateDeclCode(
sym.out_n_sect = sect_index;
atom.out_n_sect = sect_index;
sym.name = try self.strtab.insert(gpa, decl_name.toSlice(&mod.intern_pool));
sym.name = try self.strtab.insert(gpa, decl.fqn.toSlice(ip));
atom.flags.alive = true;
atom.name = sym.name;
nlist.n_strx = sym.name;
@ -843,7 +843,7 @@ fn updateDeclCode(
if (need_realloc) {
try atom.grow(macho_file);
log.debug("growing {} from 0x{x} to 0x{x}", .{ decl_name.fmt(&mod.intern_pool), old_vaddr, atom.value });
log.debug("growing {} from 0x{x} to 0x{x}", .{ decl.fqn.fmt(ip), old_vaddr, atom.value });
if (old_vaddr != atom.value) {
sym.value = 0;
nlist.n_value = 0;
@ -893,25 +893,22 @@ fn updateTlv(
sect_index: u8,
code: []const u8,
) !void {
const ip = &pt.zcu.intern_pool;
const decl = pt.zcu.declPtr(decl_index);
const decl_name = try decl.fullyQualifiedName(pt);
log.debug("updateTlv {} ({*})", .{ decl_name.fmt(&pt.zcu.intern_pool), decl });
const decl_name_slice = decl_name.toSlice(&pt.zcu.intern_pool);
const required_alignment = decl.getAlignment(pt);
log.debug("updateTlv {} ({*})", .{ decl.fqn.fmt(&pt.zcu.intern_pool), decl });
// 1. Lower TLV initializer
const init_sym_index = try self.createTlvInitializer(
macho_file,
decl_name_slice,
required_alignment,
decl.fqn.toSlice(ip),
decl.getAlignment(pt),
sect_index,
code,
);
// 2. Create TLV descriptor
try self.createTlvDescriptor(macho_file, sym_index, init_sym_index, decl_name_slice);
try self.createTlvDescriptor(macho_file, sym_index, init_sym_index, decl.fqn.toSlice(ip));
}
fn createTlvInitializer(
@ -1099,9 +1096,8 @@ pub fn lowerUnnamedConst(
}
const unnamed_consts = gop.value_ptr;
const decl = mod.declPtr(decl_index);
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 });
const name = try std.fmt.allocPrint(gpa, "__unnamed_{}_{d}", .{ decl.fqn.fmt(&mod.intern_pool), index });
defer gpa.free(name);
const sym_index = switch (try self.lowerConst(
macho_file,

View File

@ -483,11 +483,9 @@ pub fn lowerUnnamedConst(self: *Plan9, pt: Zcu.PerThread, val: Value, decl_index
}
const unnamed_consts = gop.value_ptr;
const decl_name = try decl.fullyQualifiedName(pt);
const index = unnamed_consts.items.len;
// name is freed when the unnamed const is freed
const name = try std.fmt.allocPrint(gpa, "__unnamed_{}_{d}", .{ decl_name.fmt(&mod.intern_pool), index });
const name = try std.fmt.allocPrint(gpa, "__unnamed_{}_{d}", .{ decl.fqn.fmt(&mod.intern_pool), index });
const sym_index = try self.allocateSymbolIndex();
const new_atom_idx = try self.createAtom();

View File

@ -227,9 +227,9 @@ pub fn flushModule(self: *SpirV, arena: Allocator, tid: Zcu.PerThread.Id, prog_n
var error_info = std.ArrayList(u8).init(self.object.gpa);
defer error_info.deinit();
try error_info.appendSlice("zig_errors");
const mod = self.base.comp.module.?;
for (mod.global_error_set.keys()) |name| {
try error_info.appendSlice("zig_errors:");
const ip = &self.base.comp.module.?.intern_pool;
for (ip.global_error_set.getNamesFromMainThread()) |name| {
// Errors can contain pretty much any character - to encode them in a string we must escape
// them somehow. Easiest here is to use some established scheme, one which also preseves the
// name if it contains no strange characters is nice for debugging. URI encoding fits the bill.
@ -238,7 +238,7 @@ pub fn flushModule(self: *SpirV, arena: Allocator, tid: Zcu.PerThread.Id, prog_n
try error_info.append(':');
try std.Uri.Component.percentEncode(
error_info.writer(),
name.toSlice(&mod.intern_pool),
name.toSlice(ip),
struct {
fn isValidChar(c: u8) bool {
return switch (c) {

View File

@ -346,8 +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(pt);
sym.name = try zig_object.string_table.insert(gpa, full_name.toSlice(ip));
sym.name = try zig_object.string_table.insert(gpa, decl.fqn.toSlice(ip));
try atom.code.appendSlice(gpa, code);
atom.size = @intCast(code.len);
@ -387,7 +386,7 @@ fn finishUpdateDecl(
// Will be freed upon freeing of decl or after cleanup of Wasm binary.
const full_segment_name = try std.mem.concat(gpa, u8, &.{
segment_name,
full_name.toSlice(ip),
decl.fqn.toSlice(ip),
});
errdefer gpa.free(full_segment_name);
sym.tag = .data;
@ -436,9 +435,8 @@ pub fn getOrCreateAtomForDecl(
const sym_index = try zig_object.allocateSymbol(gpa);
gop.value_ptr.* = .{ .atom = try wasm_file.createAtom(sym_index, zig_object.index) };
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(&pt.zcu.intern_pool));
sym.name = try zig_object.string_table.insert(gpa, decl.fqn.toSlice(&pt.zcu.intern_pool));
}
return gop.value_ptr.atom;
}
@ -494,9 +492,8 @@ pub fn lowerUnnamedConst(
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(pt);
const name = try std.fmt.allocPrintZ(gpa, "__unnamed_{}_{d}", .{
fqn.fmt(&mod.intern_pool), local_index,
decl.fqn.fmt(&mod.intern_pool), local_index,
});
defer gpa.free(name);
@ -655,13 +652,22 @@ fn populateErrorNameTable(zig_object: *ZigObject, wasm_file: *Wasm, tid: Zcu.Per
// Addend for each relocation to the table
var addend: u32 = 0;
const pt: Zcu.PerThread = .{ .zcu = wasm_file.base.comp.module.?, .tid = tid };
for (pt.zcu.global_error_set.keys()) |error_name| {
const atom = wasm_file.getAtomPtr(atom_index);
const slice_ty = Type.slice_const_u8_sentinel_0;
const atom = wasm_file.getAtomPtr(atom_index);
{
// TODO: remove this unreachable entry
try atom.code.appendNTimes(gpa, 0, 4);
try atom.code.writer(gpa).writeInt(u32, 0, .little);
atom.size += @intCast(slice_ty.abiSize(pt));
addend += 1;
const error_name_slice = error_name.toSlice(&pt.zcu.intern_pool);
try names_atom.code.append(gpa, 0);
}
const ip = &pt.zcu.intern_pool;
for (ip.global_error_set.getNamesFromMainThread()) |error_name| {
const error_name_slice = error_name.toSlice(ip);
const len: u32 = @intCast(error_name_slice.len + 1); // names are 0-terminated
const slice_ty = Type.slice_const_u8_sentinel_0;
const offset = @as(u32, @intCast(atom.code.items.len));
// first we create the data for the slice of the name
try atom.code.appendNTimes(gpa, 0, 4); // ptr to name, will be relocated
@ -680,7 +686,7 @@ fn populateErrorNameTable(zig_object: *ZigObject, wasm_file: *Wasm, tid: Zcu.Per
try names_atom.code.ensureUnusedCapacity(gpa, len);
names_atom.code.appendSliceAssumeCapacity(error_name_slice[0..len]);
log.debug("Populated error name: '{}'", .{error_name.fmt(&pt.zcu.intern_pool)});
log.debug("Populated error name: '{}'", .{error_name.fmt(ip)});
}
names_atom.size = addend;
zig_object.error_names_atom = names_atom_index;
@ -1045,7 +1051,7 @@ fn setupErrorsLen(zig_object: *ZigObject, wasm_file: *Wasm) !void {
const gpa = wasm_file.base.comp.gpa;
const sym_index = zig_object.findGlobalSymbol("__zig_errors_len") orelse return;
const errors_len = wasm_file.base.comp.module.?.global_error_set.count();
const errors_len = 1 + wasm_file.base.comp.module.?.intern_pool.global_error_set.mutate.list.len;
// overwrite existing atom if it already exists (maybe the error set has increased)
// if not, allcoate a new atom.
const atom_index = if (wasm_file.symbol_atom.get(.{ .file = zig_object.index, .index = sym_index })) |index| blk: {
@ -1127,9 +1133,7 @@ pub fn updateDeclLineNumber(
) !void {
if (zig_object.dwarf) |*dw| {
const decl = pt.zcu.declPtr(decl_index);
const decl_name = try decl.fullyQualifiedName(pt);
log.debug("updateDeclLineNumber {}{*}", .{ decl_name.fmt(&pt.zcu.intern_pool), decl });
log.debug("updateDeclLineNumber {}{*}", .{ decl.fqn.fmt(&pt.zcu.intern_pool), decl });
try dw.updateDeclLineNumber(pt.zcu, decl_index);
}
}

View File

@ -356,7 +356,13 @@ const Writer = struct {
fn writeArg(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
const arg = w.air.instructions.items(.data)[@intFromEnum(inst)].arg;
try w.writeType(s, arg.ty.toType());
try s.print(", {d}", .{arg.src_index});
switch (arg.name) {
.none => {},
_ => {
const name = w.air.nullTerminatedString(@intFromEnum(arg.name));
try s.print(", \"{}\"", .{std.zig.fmtEscapes(name)});
},
}
}
fn writeTyOp(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {

View File

@ -299,8 +299,8 @@ fn printPtrDerivation(derivation: Value.PointerDeriveStep, writer: anytype, leve
int.ptr_ty.fmt(pt),
int.addr,
}),
.decl_ptr => |decl| {
try zcu.declPtr(decl).renderFullyQualifiedName(zcu, writer);
.decl_ptr => |decl_index| {
try writer.print("{}", .{zcu.declPtr(decl_index).fqn.fmt(ip)});
},
.anon_decl_ptr => |anon| {
const ty = Value.fromInterned(anon.val).typeOf(zcu);