mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 12:59:04 +00:00
link: make SpirV atoms fully owned by the linker
This commit is contained in:
parent
5de2aae63c
commit
e0f3975fc8
@ -5183,20 +5183,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) Allocator.Err
|
||||
decl.zir_decl_index = @intCast(u32, decl_sub_index);
|
||||
if (decl.getFunction()) |_| {
|
||||
switch (comp.bin_file.tag) {
|
||||
.coff => {
|
||||
// TODO Implement for COFF
|
||||
},
|
||||
.elf => {
|
||||
// TODO Look into detecting when this would be unnecessary by storing enough state
|
||||
// in `Decl` to notice that the line number did not change.
|
||||
comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl_index });
|
||||
},
|
||||
.macho => {
|
||||
// TODO Look into detecting when this would be unnecessary by storing enough state
|
||||
// in `Decl` to notice that the line number did not change.
|
||||
comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl_index });
|
||||
},
|
||||
.plan9 => {
|
||||
.coff, .elf, .macho, .plan9 => {
|
||||
// TODO Look into detecting when this would be unnecessary by storing enough state
|
||||
// in `Decl` to notice that the line number did not change.
|
||||
comp.work_queue.writeItemAssumeCapacity(.{ .update_line_number = decl_index });
|
||||
@ -5290,7 +5277,7 @@ pub fn clearDecl(
|
||||
.plan9 => .{ .plan9 = {} },
|
||||
.c => .{ .c = {} },
|
||||
.wasm => .{ .wasm = link.File.Wasm.FnData.empty },
|
||||
.spirv => .{ .spirv = .{} },
|
||||
.spirv => .{ .spirv = {} },
|
||||
.nvptx => .{ .nvptx = {} },
|
||||
};
|
||||
}
|
||||
@ -5710,7 +5697,7 @@ pub fn allocateNewDecl(
|
||||
.plan9 => .{ .plan9 = {} },
|
||||
.c => .{ .c = {} },
|
||||
.wasm => .{ .wasm = link.File.Wasm.FnData.empty },
|
||||
.spirv => .{ .spirv = .{} },
|
||||
.spirv => .{ .spirv = {} },
|
||||
.nvptx => .{ .nvptx = {} },
|
||||
},
|
||||
.generation = 0,
|
||||
|
||||
@ -49,7 +49,7 @@ pub const DeclGen = struct {
|
||||
spv: *SpvModule,
|
||||
|
||||
/// The decl we are currently generating code for.
|
||||
decl: *Decl,
|
||||
decl_index: Decl.Index,
|
||||
|
||||
/// The intermediate code of the declaration we are currently generating. Note: If
|
||||
/// the declaration is not a function, this value will be undefined!
|
||||
@ -59,6 +59,8 @@ pub const DeclGen = struct {
|
||||
/// Note: If the declaration is not a function, this value will be undefined!
|
||||
liveness: Liveness,
|
||||
|
||||
ids: *const std.AutoHashMap(Decl.Index, IdResult),
|
||||
|
||||
/// An array of function argument result-ids. Each index corresponds with the
|
||||
/// function argument of the same index.
|
||||
args: std.ArrayListUnmanaged(IdRef) = .{},
|
||||
@ -133,14 +135,20 @@ pub const DeclGen = struct {
|
||||
|
||||
/// Initialize the common resources of a DeclGen. Some fields are left uninitialized,
|
||||
/// only set when `gen` is called.
|
||||
pub fn init(allocator: Allocator, module: *Module, spv: *SpvModule) DeclGen {
|
||||
pub fn init(
|
||||
allocator: Allocator,
|
||||
module: *Module,
|
||||
spv: *SpvModule,
|
||||
ids: *const std.AutoHashMap(Decl.Index, IdResult),
|
||||
) DeclGen {
|
||||
return .{
|
||||
.gpa = allocator,
|
||||
.module = module,
|
||||
.spv = spv,
|
||||
.decl = undefined,
|
||||
.decl_index = undefined,
|
||||
.air = undefined,
|
||||
.liveness = undefined,
|
||||
.ids = ids,
|
||||
.next_arg_index = undefined,
|
||||
.current_block_label_id = undefined,
|
||||
.error_msg = undefined,
|
||||
@ -150,9 +158,9 @@ pub const DeclGen = struct {
|
||||
/// Generate the code for `decl`. If a reportable error occurred during code generation,
|
||||
/// a message is returned by this function. Callee owns the memory. If this function
|
||||
/// returns such a reportable error, it is valid to be called again for a different decl.
|
||||
pub fn gen(self: *DeclGen, decl: *Decl, air: Air, liveness: Liveness) !?*Module.ErrorMsg {
|
||||
pub fn gen(self: *DeclGen, decl_index: Decl.Index, air: Air, liveness: Liveness) !?*Module.ErrorMsg {
|
||||
// Reset internal resources, we don't want to re-allocate these.
|
||||
self.decl = decl;
|
||||
self.decl_index = decl_index;
|
||||
self.air = air;
|
||||
self.liveness = liveness;
|
||||
self.args.items.len = 0;
|
||||
@ -194,7 +202,7 @@ pub const DeclGen = struct {
|
||||
pub fn fail(self: *DeclGen, comptime format: []const u8, args: anytype) Error {
|
||||
@setCold(true);
|
||||
const src = LazySrcLoc.nodeOffset(0);
|
||||
const src_loc = src.toSrcLoc(self.decl);
|
||||
const src_loc = src.toSrcLoc(self.module.declPtr(self.decl_index));
|
||||
assert(self.error_msg == null);
|
||||
self.error_msg = try Module.ErrorMsg.create(self.module.gpa, src_loc, format, args);
|
||||
return error.CodegenFail;
|
||||
@ -332,7 +340,7 @@ pub const DeclGen = struct {
|
||||
};
|
||||
const decl = self.module.declPtr(fn_decl_index);
|
||||
self.module.markDeclAlive(decl);
|
||||
return decl.fn_link.spirv.id.toRef();
|
||||
return self.ids.get(fn_decl_index).?.toRef();
|
||||
}
|
||||
|
||||
const target = self.getTarget();
|
||||
@ -553,8 +561,8 @@ pub const DeclGen = struct {
|
||||
}
|
||||
|
||||
fn genDecl(self: *DeclGen) !void {
|
||||
const decl = self.decl;
|
||||
const result_id = decl.fn_link.spirv.id;
|
||||
const result_id = self.ids.get(self.decl_index).?;
|
||||
const decl = self.module.declPtr(self.decl_index);
|
||||
|
||||
if (decl.val.castTag(.function)) |_| {
|
||||
assert(decl.ty.zigTypeTag() == .Fn);
|
||||
@ -945,7 +953,7 @@ pub const DeclGen = struct {
|
||||
|
||||
fn airDbgStmt(self: *DeclGen, inst: Air.Inst.Index) !void {
|
||||
const dbg_stmt = self.air.instructions.items(.data)[inst].dbg_stmt;
|
||||
const src_fname_id = try self.spv.resolveSourceFileName(self.decl);
|
||||
const src_fname_id = try self.spv.resolveSourceFileName(self.module.declPtr(self.decl_index));
|
||||
try self.func.body.emit(self.spv.gpa, .OpLine, .{
|
||||
.file = src_fname_id,
|
||||
.line = dbg_stmt.line,
|
||||
@ -1106,7 +1114,7 @@ pub const DeclGen = struct {
|
||||
assert(as.errors.items.len != 0);
|
||||
assert(self.error_msg == null);
|
||||
const loc = LazySrcLoc.nodeOffset(0);
|
||||
const src_loc = loc.toSrcLoc(self.decl);
|
||||
const src_loc = loc.toSrcLoc(self.module.declPtr(self.decl_index));
|
||||
self.error_msg = try Module.ErrorMsg.create(self.module.gpa, src_loc, "failed to assemble SPIR-V inline assembly", .{});
|
||||
const notes = try self.module.gpa.alloc(Module.ErrorMsg, as.errors.items.len);
|
||||
|
||||
|
||||
@ -279,7 +279,7 @@ pub const File = struct {
|
||||
plan9: void,
|
||||
c: void,
|
||||
wasm: Wasm.FnData,
|
||||
spirv: SpirV.FnData,
|
||||
spirv: void,
|
||||
nvptx: void,
|
||||
};
|
||||
|
||||
|
||||
@ -42,13 +42,6 @@ const SpvModule = @import("../codegen/spirv/Module.zig");
|
||||
const spec = @import("../codegen/spirv/spec.zig");
|
||||
const IdResult = spec.IdResult;
|
||||
|
||||
// TODO: Should this struct be used at all rather than just a hashmap of aux data for every decl?
|
||||
pub const FnData = struct {
|
||||
// We're going to fill these in flushModule, and we're going to fill them unconditionally,
|
||||
// so just set it to undefined.
|
||||
id: IdResult = undefined,
|
||||
};
|
||||
|
||||
base: link.File,
|
||||
|
||||
/// This linker backend does not try to incrementally link output SPIR-V code.
|
||||
@ -209,16 +202,19 @@ pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.No
|
||||
// so that we can access them before processing them.
|
||||
// TODO: We're allocating an ID unconditionally now, are there
|
||||
// declarations which don't generate a result?
|
||||
// TODO: fn_link is used here, but thats probably not the right field. It will work anyway though.
|
||||
var ids = std.AutoHashMap(Module.Decl.Index, IdResult).init(self.base.allocator);
|
||||
defer ids.deinit();
|
||||
try ids.ensureTotalCapacity(@intCast(u32, self.decl_table.count()));
|
||||
|
||||
for (self.decl_table.keys()) |decl_index| {
|
||||
const decl = module.declPtr(decl_index);
|
||||
if (decl.has_tv) {
|
||||
decl.fn_link.spirv.id = spv.allocId();
|
||||
ids.putAssumeCapacityNoClobber(decl_index, spv.allocId());
|
||||
}
|
||||
}
|
||||
|
||||
// Now, actually generate the code for all declarations.
|
||||
var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &spv);
|
||||
var decl_gen = codegen.DeclGen.init(self.base.allocator, module, &spv, &ids);
|
||||
defer decl_gen.deinit();
|
||||
|
||||
var it = self.decl_table.iterator();
|
||||
@ -231,7 +227,7 @@ pub fn flushModule(self: *SpirV, comp: *Compilation, prog_node: *std.Progress.No
|
||||
const liveness = entry.value_ptr.liveness;
|
||||
|
||||
// Note, if `decl` is not a function, air/liveness may be undefined.
|
||||
if (try decl_gen.gen(decl, air, liveness)) |msg| {
|
||||
if (try decl_gen.gen(decl_index, air, liveness)) |msg| {
|
||||
try module.failed_decls.put(module.gpa, decl_index, msg);
|
||||
return; // TODO: Attempt to generate more decls?
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user