mirror of
https://github.com/ziglang/zig.git
synced 2026-01-02 19:43:29 +00:00
compiler: minor refactors to ZCU linking
* The `codegen_nav`, `codegen_func`, `codegen_type` tasks are renamed to `link_nav`, `link_func`, and `link_type`, to more accurately reflect their purpose of sending data to the *linker*. Currently, `link_func` remains responsible for codegen; this will change in an upcoming commit. * Don't go on a pointless detour through `PerThread` when linking ZCU functions/`Nav`s; so, the `linkerUpdateNav` etc logic now lives in `link.zig`. Currently, `linkerUpdateFunc` is an exception, because it has broader responsibilities including codegen, but this will be solved in an upcoming commit.
This commit is contained in:
parent
4a02e080d1
commit
424e6ac54b
@ -848,17 +848,18 @@ pub const RcIncludes = enum {
|
||||
const Job = union(enum) {
|
||||
/// Corresponds to the task in `link.Task`.
|
||||
/// Only needed for backends that haven't yet been updated to not race against Sema.
|
||||
codegen_nav: InternPool.Nav.Index,
|
||||
link_nav: InternPool.Nav.Index,
|
||||
/// Corresponds to the task in `link.Task`.
|
||||
/// TODO: this is currently also responsible for performing codegen.
|
||||
/// Only needed for backends that haven't yet been updated to not race against Sema.
|
||||
link_func: link.Task.CodegenFunc,
|
||||
/// Corresponds to the task in `link.Task`.
|
||||
/// Only needed for backends that haven't yet been updated to not race against Sema.
|
||||
codegen_func: link.Task.CodegenFunc,
|
||||
/// Corresponds to the task in `link.Task`.
|
||||
/// Only needed for backends that haven't yet been updated to not race against Sema.
|
||||
codegen_type: InternPool.Index,
|
||||
link_type: InternPool.Index,
|
||||
update_line_number: InternPool.TrackedInst.Index,
|
||||
/// The `AnalUnit`, which is *not* a `func`, must be semantically analyzed.
|
||||
/// This may be its first time being analyzed, or it may be outdated.
|
||||
/// If the unit is a function, a `codegen_func` job will then be queued.
|
||||
/// If the unit is a test function, an `analyze_func` job will then be queued.
|
||||
analyze_comptime_unit: InternPool.AnalUnit,
|
||||
/// This function must be semantically analyzed.
|
||||
/// This may be its first time being analyzed, or it may be outdated.
|
||||
@ -879,13 +880,13 @@ const Job = union(enum) {
|
||||
return switch (tag) {
|
||||
// Prioritize functions so that codegen can get to work on them on a
|
||||
// separate thread, while Sema goes back to its own work.
|
||||
.resolve_type_fully, .analyze_func, .codegen_func => 0,
|
||||
.resolve_type_fully, .analyze_func, .link_func => 0,
|
||||
else => 1,
|
||||
};
|
||||
}
|
||||
comptime {
|
||||
// Job dependencies
|
||||
assert(stage(.resolve_type_fully) <= stage(.codegen_func));
|
||||
assert(stage(.resolve_type_fully) <= stage(.link_func));
|
||||
}
|
||||
};
|
||||
|
||||
@ -4552,7 +4553,7 @@ pub fn queueJobs(comp: *Compilation, jobs: []const Job) !void {
|
||||
|
||||
fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void {
|
||||
switch (job) {
|
||||
.codegen_nav => |nav_index| {
|
||||
.link_nav => |nav_index| {
|
||||
const zcu = comp.zcu.?;
|
||||
const nav = zcu.intern_pool.getNav(nav_index);
|
||||
if (nav.analysis != null) {
|
||||
@ -4562,16 +4563,16 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void {
|
||||
}
|
||||
}
|
||||
assert(nav.status == .fully_resolved);
|
||||
comp.dispatchCodegenTask(tid, .{ .codegen_nav = nav_index });
|
||||
comp.dispatchLinkTask(tid, .{ .link_nav = nav_index });
|
||||
},
|
||||
.codegen_func => |func| {
|
||||
comp.dispatchCodegenTask(tid, .{ .codegen_func = func });
|
||||
.link_func => |func| {
|
||||
comp.dispatchLinkTask(tid, .{ .link_func = func });
|
||||
},
|
||||
.codegen_type => |ty| {
|
||||
comp.dispatchCodegenTask(tid, .{ .codegen_type = ty });
|
||||
.link_type => |ty| {
|
||||
comp.dispatchLinkTask(tid, .{ .link_type = ty });
|
||||
},
|
||||
.update_line_number => |ti| {
|
||||
comp.dispatchCodegenTask(tid, .{ .update_line_number = ti });
|
||||
comp.dispatchLinkTask(tid, .{ .update_line_number = ti });
|
||||
},
|
||||
.analyze_func => |func| {
|
||||
const named_frame = tracy.namedFrame("analyze_func");
|
||||
@ -4665,7 +4666,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job) JobError!void {
|
||||
|
||||
/// The reason for the double-queue here is that the first queue ensures any
|
||||
/// resolve_type_fully tasks are complete before this dispatch function is called.
|
||||
fn dispatchCodegenTask(comp: *Compilation, tid: usize, link_task: link.Task) void {
|
||||
fn dispatchLinkTask(comp: *Compilation, tid: usize, link_task: link.Task) void {
|
||||
if (comp.separateCodegenThreadOk()) {
|
||||
comp.queueLinkTasks(&.{link_task});
|
||||
} else {
|
||||
|
||||
16
src/Sema.zig
16
src/Sema.zig
@ -2991,7 +2991,7 @@ fn zirStructDecl(
|
||||
if (zcu.comp.config.use_llvm) break :codegen_type;
|
||||
if (block.ownerModule().strip) break :codegen_type;
|
||||
// This job depends on any resolve_type_fully jobs queued up before it.
|
||||
try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
|
||||
try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
|
||||
}
|
||||
try sema.declareDependency(.{ .interned = wip_ty.index });
|
||||
try sema.addTypeReferenceEntry(src, wip_ty.index);
|
||||
@ -3250,7 +3250,7 @@ fn zirEnumDecl(
|
||||
if (zcu.comp.config.use_llvm) break :codegen_type;
|
||||
if (block.ownerModule().strip) break :codegen_type;
|
||||
// This job depends on any resolve_type_fully jobs queued up before it.
|
||||
try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
|
||||
try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
|
||||
}
|
||||
return Air.internedToRef(wip_ty.index);
|
||||
}
|
||||
@ -3368,7 +3368,7 @@ fn zirUnionDecl(
|
||||
if (zcu.comp.config.use_llvm) break :codegen_type;
|
||||
if (block.ownerModule().strip) break :codegen_type;
|
||||
// This job depends on any resolve_type_fully jobs queued up before it.
|
||||
try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
|
||||
try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
|
||||
}
|
||||
try sema.declareDependency(.{ .interned = wip_ty.index });
|
||||
try sema.addTypeReferenceEntry(src, wip_ty.index);
|
||||
@ -3455,7 +3455,7 @@ fn zirOpaqueDecl(
|
||||
if (zcu.comp.config.use_llvm) break :codegen_type;
|
||||
if (block.ownerModule().strip) break :codegen_type;
|
||||
// This job depends on any resolve_type_fully jobs queued up before it.
|
||||
try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
|
||||
try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
|
||||
}
|
||||
try sema.addTypeReferenceEntry(src, wip_ty.index);
|
||||
if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
|
||||
@ -20086,7 +20086,7 @@ fn structInitAnon(
|
||||
codegen_type: {
|
||||
if (zcu.comp.config.use_llvm) break :codegen_type;
|
||||
if (block.ownerModule().strip) break :codegen_type;
|
||||
try zcu.comp.queueJob(.{ .codegen_type = wip.index });
|
||||
try zcu.comp.queueJob(.{ .link_type = wip.index });
|
||||
}
|
||||
if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip.index);
|
||||
break :ty wip.finish(ip, new_namespace_index);
|
||||
@ -21396,7 +21396,7 @@ fn reifyEnum(
|
||||
if (zcu.comp.config.use_llvm) break :codegen_type;
|
||||
if (block.ownerModule().strip) break :codegen_type;
|
||||
// This job depends on any resolve_type_fully jobs queued up before it.
|
||||
try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
|
||||
try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
|
||||
}
|
||||
return Air.internedToRef(wip_ty.index);
|
||||
}
|
||||
@ -21650,7 +21650,7 @@ fn reifyUnion(
|
||||
if (zcu.comp.config.use_llvm) break :codegen_type;
|
||||
if (block.ownerModule().strip) break :codegen_type;
|
||||
// This job depends on any resolve_type_fully jobs queued up before it.
|
||||
try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
|
||||
try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
|
||||
}
|
||||
try sema.declareDependency(.{ .interned = wip_ty.index });
|
||||
try sema.addTypeReferenceEntry(src, wip_ty.index);
|
||||
@ -22004,7 +22004,7 @@ fn reifyStruct(
|
||||
if (zcu.comp.config.use_llvm) break :codegen_type;
|
||||
if (block.ownerModule().strip) break :codegen_type;
|
||||
// This job depends on any resolve_type_fully jobs queued up before it.
|
||||
try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
|
||||
try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
|
||||
}
|
||||
try sema.declareDependency(.{ .interned = wip_ty.index });
|
||||
try sema.addTypeReferenceEntry(src, wip_ty.index);
|
||||
|
||||
@ -194,7 +194,7 @@ fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!Inter
|
||||
codegen_type: {
|
||||
if (pt.zcu.comp.config.use_llvm) break :codegen_type;
|
||||
if (self.block.ownerModule().strip) break :codegen_type;
|
||||
try pt.zcu.comp.queueJob(.{ .codegen_type = wip.index });
|
||||
try pt.zcu.comp.queueJob(.{ .link_type = wip.index });
|
||||
}
|
||||
break :ty wip.finish(ip, new_namespace_index);
|
||||
},
|
||||
|
||||
@ -1320,7 +1320,7 @@ fn analyzeNavVal(pt: Zcu.PerThread, nav_id: InternPool.Nav.Index) Zcu.CompileErr
|
||||
}
|
||||
|
||||
// This job depends on any resolve_type_fully jobs queued up before it.
|
||||
try zcu.comp.queueJob(.{ .codegen_nav = nav_id });
|
||||
try zcu.comp.queueJob(.{ .link_nav = nav_id });
|
||||
}
|
||||
|
||||
switch (old_nav.status) {
|
||||
@ -1716,7 +1716,7 @@ fn analyzeFuncBody(
|
||||
}
|
||||
|
||||
// This job depends on any resolve_type_fully jobs queued up before it.
|
||||
try comp.queueJob(.{ .codegen_func = .{
|
||||
try comp.queueJob(.{ .link_func = .{
|
||||
.func = func_index,
|
||||
.air = air,
|
||||
} });
|
||||
@ -1880,7 +1880,7 @@ fn createFileRootStruct(
|
||||
if (zcu.comp.config.use_llvm) break :codegen_type;
|
||||
if (file.mod.?.strip) break :codegen_type;
|
||||
// This job depends on any resolve_type_fully jobs queued up before it.
|
||||
try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
|
||||
try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
|
||||
}
|
||||
zcu.setFileRootType(file_index, wip_ty.index);
|
||||
if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
|
||||
@ -3457,73 +3457,8 @@ pub fn populateTestFunctions(
|
||||
zcu.codegen_prog_node = std.Progress.Node.none;
|
||||
}
|
||||
|
||||
try pt.linkerUpdateNav(nav_index);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn linkerUpdateNav(pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) error{OutOfMemory}!void {
|
||||
const zcu = pt.zcu;
|
||||
const comp = zcu.comp;
|
||||
const gpa = zcu.gpa;
|
||||
const ip = &zcu.intern_pool;
|
||||
|
||||
const nav = zcu.intern_pool.getNav(nav_index);
|
||||
const codegen_prog_node = zcu.codegen_prog_node.start(nav.fqn.toSlice(ip), 0);
|
||||
defer codegen_prog_node.end();
|
||||
|
||||
if (!Air.valFullyResolved(zcu.navValue(nav_index), zcu)) {
|
||||
// The value of this nav failed to resolve. This is a transitive failure.
|
||||
// TODO: do we need to mark this failure anywhere? I don't think so, since compilation
|
||||
// will fail due to the type error anyway.
|
||||
} else if (comp.bin_file) |lf| {
|
||||
lf.updateNav(pt, nav_index) catch |err| switch (err) {
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
error.CodegenFail => assert(zcu.failed_codegen.contains(nav_index)),
|
||||
error.Overflow, error.RelocationNotByteAligned => {
|
||||
try zcu.failed_codegen.putNoClobber(gpa, nav_index, try Zcu.ErrorMsg.create(
|
||||
gpa,
|
||||
zcu.navSrcLoc(nav_index),
|
||||
"unable to codegen: {s}",
|
||||
.{@errorName(err)},
|
||||
));
|
||||
// Not a retryable failure.
|
||||
},
|
||||
};
|
||||
} else if (zcu.llvm_object) |llvm_object| {
|
||||
llvm_object.updateNav(pt, nav_index) catch |err| switch (err) {
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn linkerUpdateContainerType(pt: Zcu.PerThread, ty: InternPool.Index) error{OutOfMemory}!void {
|
||||
const zcu = pt.zcu;
|
||||
const gpa = zcu.gpa;
|
||||
const comp = zcu.comp;
|
||||
const ip = &zcu.intern_pool;
|
||||
|
||||
const codegen_prog_node = zcu.codegen_prog_node.start(Type.fromInterned(ty).containerTypeName(ip).toSlice(ip), 0);
|
||||
defer codegen_prog_node.end();
|
||||
|
||||
if (zcu.failed_types.fetchSwapRemove(ty)) |*entry| entry.value.deinit(gpa);
|
||||
|
||||
if (!Air.typeFullyResolved(Type.fromInterned(ty), zcu)) {
|
||||
// This type failed to resolve. This is a transitive failure.
|
||||
return;
|
||||
}
|
||||
|
||||
if (comp.bin_file) |lf| lf.updateContainerType(pt, ty) catch |err| switch (err) {
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
error.TypeFailureReported => assert(zcu.failed_types.contains(ty)),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn linkerUpdateLineNumber(pt: Zcu.PerThread, ti: InternPool.TrackedInst.Index) !void {
|
||||
if (pt.zcu.comp.bin_file) |lf| {
|
||||
lf.updateLineNumber(pt, ti) catch |err| switch (err) {
|
||||
error.OutOfMemory => return error.OutOfMemory,
|
||||
else => |e| log.err("update line number failed: {s}", .{@errorName(e)}),
|
||||
};
|
||||
// The linker thread is not running, so we actually need to dispatch this task directly.
|
||||
@import("../link.zig").doTask(zcu.comp, @intFromEnum(pt.tid), .{ .link_nav = nav_index });
|
||||
}
|
||||
}
|
||||
|
||||
@ -3984,7 +3919,7 @@ pub fn getExtern(pt: Zcu.PerThread, key: InternPool.Key.Extern) Allocator.Error!
|
||||
const result = try pt.zcu.intern_pool.getExtern(pt.zcu.gpa, pt.tid, key);
|
||||
if (result.new_nav.unwrap()) |nav| {
|
||||
// This job depends on any resolve_type_fully jobs queued up before it.
|
||||
try pt.zcu.comp.queueJob(.{ .codegen_nav = nav });
|
||||
try pt.zcu.comp.queueJob(.{ .link_nav = nav });
|
||||
if (pt.zcu.comp.debugIncremental()) try pt.zcu.incremental_debug_state.newNav(pt.zcu, nav);
|
||||
}
|
||||
return result.index;
|
||||
@ -4132,7 +4067,7 @@ fn recreateStructType(
|
||||
if (zcu.comp.config.use_llvm) break :codegen_type;
|
||||
if (file.mod.?.strip) break :codegen_type;
|
||||
// This job depends on any resolve_type_fully jobs queued up before it.
|
||||
try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
|
||||
try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
|
||||
}
|
||||
|
||||
if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
|
||||
@ -4225,7 +4160,7 @@ fn recreateUnionType(
|
||||
if (zcu.comp.config.use_llvm) break :codegen_type;
|
||||
if (file.mod.?.strip) break :codegen_type;
|
||||
// This job depends on any resolve_type_fully jobs queued up before it.
|
||||
try zcu.comp.queueJob(.{ .codegen_type = wip_ty.index });
|
||||
try zcu.comp.queueJob(.{ .link_type = wip_ty.index });
|
||||
}
|
||||
|
||||
if (zcu.comp.debugIncremental()) try zcu.incremental_debug_state.newType(zcu, wip_ty.index);
|
||||
|
||||
112
src/link.zig
112
src/link.zig
@ -704,7 +704,7 @@ pub const File = struct {
|
||||
}
|
||||
|
||||
/// May be called before or after updateExports for any given Nav.
|
||||
pub fn updateNav(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) UpdateNavError!void {
|
||||
fn updateNav(base: *File, pt: Zcu.PerThread, nav_index: InternPool.Nav.Index) UpdateNavError!void {
|
||||
const nav = pt.zcu.intern_pool.getNav(nav_index);
|
||||
assert(nav.status == .fully_resolved);
|
||||
switch (base.tag) {
|
||||
@ -721,7 +721,7 @@ pub const File = struct {
|
||||
TypeFailureReported,
|
||||
};
|
||||
|
||||
pub fn updateContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index) UpdateContainerTypeError!void {
|
||||
fn updateContainerType(base: *File, pt: Zcu.PerThread, ty: InternPool.Index) UpdateContainerTypeError!void {
|
||||
switch (base.tag) {
|
||||
else => {},
|
||||
inline .elf => |tag| {
|
||||
@ -732,6 +732,7 @@ pub const File = struct {
|
||||
}
|
||||
|
||||
/// May be called before or after updateExports for any given Decl.
|
||||
/// TODO: currently `pub` because `Zcu.PerThread` is calling this.
|
||||
pub fn updateFunc(
|
||||
base: *File,
|
||||
pt: Zcu.PerThread,
|
||||
@ -755,7 +756,7 @@ pub const File = struct {
|
||||
|
||||
/// On an incremental update, fixup the line number of all `Nav`s at the given `TrackedInst`, because
|
||||
/// its line number has changed. The ZIR instruction `ti_id` has tag `.declaration`.
|
||||
pub fn updateLineNumber(base: *File, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) UpdateLineNumberError!void {
|
||||
fn updateLineNumber(base: *File, pt: Zcu.PerThread, ti_id: InternPool.TrackedInst.Index) UpdateLineNumberError!void {
|
||||
{
|
||||
const ti = ti_id.resolveFull(&pt.zcu.intern_pool).?;
|
||||
const file = pt.zcu.fileByIndex(ti.file);
|
||||
@ -1435,10 +1436,10 @@ pub const Task = union(enum) {
|
||||
load_input: Input,
|
||||
|
||||
/// Write the constant value for a Decl to the output file.
|
||||
codegen_nav: InternPool.Nav.Index,
|
||||
link_nav: InternPool.Nav.Index,
|
||||
/// Write the machine code for a function to the output file.
|
||||
codegen_func: CodegenFunc,
|
||||
codegen_type: InternPool.Index,
|
||||
link_func: CodegenFunc,
|
||||
link_type: InternPool.Index,
|
||||
|
||||
update_line_number: InternPool.TrackedInst.Index,
|
||||
|
||||
@ -1585,47 +1586,90 @@ pub fn doTask(comp: *Compilation, tid: usize, task: Task) void {
|
||||
},
|
||||
};
|
||||
},
|
||||
.codegen_nav => |nav_index| {
|
||||
if (comp.remaining_prelink_tasks == 0) {
|
||||
const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
|
||||
defer pt.deactivate();
|
||||
pt.linkerUpdateNav(nav_index) catch |err| switch (err) {
|
||||
.link_nav => |nav_index| {
|
||||
if (comp.remaining_prelink_tasks != 0) {
|
||||
comp.link_task_queue_postponed.appendAssumeCapacity(task);
|
||||
return;
|
||||
}
|
||||
const zcu = comp.zcu.?;
|
||||
const pt: Zcu.PerThread = .activate(zcu, @enumFromInt(tid));
|
||||
defer pt.deactivate();
|
||||
if (!Air.valFullyResolved(zcu.navValue(nav_index), zcu)) {
|
||||
// Type resolution failed in a way which affects this `Nav`. This is a transitive
|
||||
// failure, but it doesn't need recording, because this `Nav` semantically depends
|
||||
// on the failed type, so when it is changed the `Nav` will be updated.
|
||||
return;
|
||||
}
|
||||
if (comp.bin_file) |lf| {
|
||||
lf.updateNav(pt, nav_index) catch |err| switch (err) {
|
||||
error.OutOfMemory => diags.setAllocFailure(),
|
||||
error.CodegenFail => assert(zcu.failed_codegen.contains(nav_index)),
|
||||
error.Overflow, error.RelocationNotByteAligned => {
|
||||
zcu.failed_codegen.ensureUnusedCapacity(zcu.gpa, 1) catch return diags.setAllocFailure();
|
||||
const msg = Zcu.ErrorMsg.create(
|
||||
zcu.gpa,
|
||||
zcu.navSrcLoc(nav_index),
|
||||
"unable to codegen: {s}",
|
||||
.{@errorName(err)},
|
||||
) catch return diags.setAllocFailure();
|
||||
zcu.failed_codegen.putAssumeCapacityNoClobber(nav_index, msg);
|
||||
// Not a retryable failure.
|
||||
},
|
||||
};
|
||||
} else if (zcu.llvm_object) |llvm_object| {
|
||||
llvm_object.updateNav(pt, nav_index) catch |err| switch (err) {
|
||||
error.OutOfMemory => diags.setAllocFailure(),
|
||||
};
|
||||
} else {
|
||||
comp.link_task_queue_postponed.appendAssumeCapacity(task);
|
||||
}
|
||||
},
|
||||
.codegen_func => |func| {
|
||||
if (comp.remaining_prelink_tasks == 0) {
|
||||
const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
|
||||
defer pt.deactivate();
|
||||
var air = func.air;
|
||||
defer air.deinit(comp.gpa);
|
||||
pt.linkerUpdateFunc(func.func, &air) catch |err| switch (err) {
|
||||
error.OutOfMemory => diags.setAllocFailure(),
|
||||
};
|
||||
} else {
|
||||
.link_func => |func| {
|
||||
if (comp.remaining_prelink_tasks != 0) {
|
||||
comp.link_task_queue_postponed.appendAssumeCapacity(task);
|
||||
return;
|
||||
}
|
||||
const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
|
||||
defer pt.deactivate();
|
||||
var air = func.air;
|
||||
defer air.deinit(comp.gpa);
|
||||
pt.linkerUpdateFunc(func.func, &air) catch |err| switch (err) {
|
||||
error.OutOfMemory => diags.setAllocFailure(),
|
||||
};
|
||||
},
|
||||
.codegen_type => |ty| {
|
||||
if (comp.remaining_prelink_tasks == 0) {
|
||||
const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
|
||||
defer pt.deactivate();
|
||||
pt.linkerUpdateContainerType(ty) catch |err| switch (err) {
|
||||
error.OutOfMemory => diags.setAllocFailure(),
|
||||
};
|
||||
} else {
|
||||
.link_type => |ty| {
|
||||
if (comp.remaining_prelink_tasks != 0) {
|
||||
comp.link_task_queue_postponed.appendAssumeCapacity(task);
|
||||
return;
|
||||
}
|
||||
const zcu = comp.zcu.?;
|
||||
const pt: Zcu.PerThread = .activate(zcu, @enumFromInt(tid));
|
||||
defer pt.deactivate();
|
||||
if (zcu.failed_types.fetchSwapRemove(ty)) |*entry| entry.value.deinit(zcu.gpa);
|
||||
if (!Air.typeFullyResolved(.fromInterned(ty), zcu)) {
|
||||
// Type resolution failed in a way which affects this type. This is a transitive
|
||||
// failure, but it doesn't need recording, because this type semantically depends
|
||||
// on the failed type, so when that is changed, this type will be updated.
|
||||
return;
|
||||
}
|
||||
if (comp.bin_file) |lf| {
|
||||
lf.updateContainerType(pt, ty) catch |err| switch (err) {
|
||||
error.OutOfMemory => diags.setAllocFailure(),
|
||||
error.TypeFailureReported => assert(zcu.failed_types.contains(ty)),
|
||||
};
|
||||
}
|
||||
},
|
||||
.update_line_number => |ti| {
|
||||
if (comp.remaining_prelink_tasks != 0) {
|
||||
comp.link_task_queue_postponed.appendAssumeCapacity(task);
|
||||
return;
|
||||
}
|
||||
const pt: Zcu.PerThread = .activate(comp.zcu.?, @enumFromInt(tid));
|
||||
defer pt.deactivate();
|
||||
pt.linkerUpdateLineNumber(ti) catch |err| switch (err) {
|
||||
error.OutOfMemory => diags.setAllocFailure(),
|
||||
};
|
||||
if (comp.bin_file) |lf| {
|
||||
lf.updateLineNumber(pt, ti) catch |err| switch (err) {
|
||||
error.OutOfMemory => diags.setAllocFailure(),
|
||||
else => |e| log.err("update line number failed: {s}", .{@errorName(e)}),
|
||||
};
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user