diff options
| author | Robin Voetter <robin@voetter.nl> | 2022-01-21 20:14:31 +0100 |
|---|---|---|
| committer | Robin Voetter <robin@voetter.nl> | 2022-01-28 14:38:58 +0100 |
| commit | 1b6ebce0da45169979b0f51a07274ff6fb5590bc (patch) | |
| tree | 5e5e4c3c2eb9d87fec61e39b7a5f1d081a75ec88 /src/link | |
| parent | 72e67aaf05de06e5a7b74596e70ce5afd17b2919 (diff) | |
| download | zig-1b6ebce0da45169979b0f51a07274ff6fb5590bc.tar.gz zig-1b6ebce0da45169979b0f51a07274ff6fb5590bc.zip | |
spirv: new module
This introduces a dedicated struct that handles module-wide information.
Diffstat (limited to 'src/link')
| -rw-r--r-- | src/link/SpirV.zig | 101 |
1 files changed, 37 insertions, 64 deletions
diff --git a/src/link/SpirV.zig b/src/link/SpirV.zig index 7c70260f0d..ee3205c9f5 100644 --- a/src/link/SpirV.zig +++ b/src/link/SpirV.zig @@ -32,20 +32,21 @@ const Module = @import("../Module.zig"); const Compilation = @import("../Compilation.zig"); const link = @import("../link.zig"); const codegen = @import("../codegen/spirv.zig"); -const Word = codegen.Word; -const ResultId = codegen.ResultId; const trace = @import("../tracy.zig").trace; const build_options = @import("build_options"); -const spec = @import("../codegen/spirv/spec.zig"); const Air = @import("../Air.zig"); const Liveness = @import("../Liveness.zig"); const Value = @import("../value.zig").Value; +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: ResultId = undefined, + id: IdResult = undefined, }; base: link.File, @@ -194,7 +195,10 @@ pub fn flushModule(self: *SpirV, comp: *Compilation) !void { const module = self.base.options.module.?; const target = comp.getTarget(); - var spv = codegen.SPIRVModule.init(self.base.allocator, module); + var arena = std.heap.ArenaAllocator.init(self.base.allocator); + defer arena.deinit(); + + var spv = SpvModule.init(self.base.allocator, arena.allocator()); defer spv.deinit(); // Allocate an ID for every declaration before generating code, @@ -202,73 +206,38 @@ pub fn flushModule(self: *SpirV, comp: *Compilation) !void { // 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. - { - for (self.decl_table.keys()) |decl| { - if (!decl.has_tv) continue; - - decl.fn_link.spirv.id = spv.allocResultId(); + for (self.decl_table.keys()) |decl| { + if (decl.has_tv) { + decl.fn_link.spirv.id = spv.allocId(); } } // Now, actually generate the code for all declarations. - { - var decl_gen = codegen.DeclGen.init(&spv); - defer decl_gen.deinit(); - - var it = self.decl_table.iterator(); - while (it.next()) |entry| { - const decl = entry.key_ptr.*; - if (!decl.has_tv) continue; - - const air = entry.value_ptr.air; - const liveness = entry.value_ptr.liveness; - - if (try decl_gen.gen(decl, air, liveness)) |msg| { - try module.failed_decls.put(module.gpa, decl, msg); - return; // TODO: Attempt to generate more decls? - } - } - } + var decl_gen = codegen.DeclGen.init(module, &spv); + defer decl_gen.deinit(); - try writeCapabilities(&spv.binary.capabilities_and_extensions, target); - try writeMemoryModel(&spv.binary.capabilities_and_extensions, target); + var it = self.decl_table.iterator(); + while (it.next()) |entry| { + const decl = entry.key_ptr.*; + if (!decl.has_tv) continue; - const header = [_]Word{ - spec.magic_number, - (spec.version.major << 16) | (spec.version.minor << 8), - 0, // TODO: Register Zig compiler magic number. - spv.resultIdBound(), - 0, // Schema (currently reserved for future use in the SPIR-V spec). - }; - - // Note: The order of adding sections to the final binary - // follows the SPIR-V logical module format! - const buffers = &[_][]const Word{ - &header, - spv.binary.capabilities_and_extensions.items, - spv.binary.debug_strings.items, - spv.binary.types_globals_constants.items, - spv.binary.fn_decls.items, - }; + const air = entry.value_ptr.air; + const liveness = entry.value_ptr.liveness; - var iovc_buffers: [buffers.len]std.os.iovec_const = undefined; - for (iovc_buffers) |*iovc, i| { - const bytes = std.mem.sliceAsBytes(buffers[i]); - iovc.* = .{ .iov_base = bytes.ptr, .iov_len = bytes.len }; + // Note, if `decl` is not a function, air/liveness may be undefined. + if (try decl_gen.gen(decl, air, liveness)) |msg| { + try module.failed_decls.put(module.gpa, decl, msg); + return; // TODO: Attempt to generate more decls? + } } - var file_size: u64 = 0; - for (iovc_buffers) |iov| { - file_size += iov.iov_len; - } + try writeCapabilities(&spv, target); + try writeMemoryModel(&spv, target); - const file = self.base.file.?; - try file.seekTo(0); - try file.setEndPos(file_size); - try file.pwritevAll(&iovc_buffers, 0); + try spv.flush(self.base.file.?); } -fn writeCapabilities(binary: *std.ArrayList(Word), target: std.Target) !void { +fn writeCapabilities(spv: *SpvModule, target: std.Target) !void { // TODO: Integrate with a hypothetical feature system const cap: spec.Capability = switch (target.os.tag) { .opencl => .Kernel, @@ -277,10 +246,12 @@ fn writeCapabilities(binary: *std.ArrayList(Word), target: std.Target) !void { else => unreachable, // TODO }; - try codegen.writeInstruction(binary, .OpCapability, &[_]Word{@enumToInt(cap)}); + try spv.sections.capabilities.emit(spv.gpa, .OpCapability, .{ + .capability = cap, + }); } -fn writeMemoryModel(binary: *std.ArrayList(Word), target: std.Target) !void { +fn writeMemoryModel(spv: *SpvModule, target: std.Target) !void { const addressing_model = switch (target.os.tag) { .opencl => switch (target.cpu.arch) { .spirv32 => spec.AddressingModel.Physical32, @@ -298,8 +269,10 @@ fn writeMemoryModel(binary: *std.ArrayList(Word), target: std.Target) !void { else => unreachable, }; - try codegen.writeInstruction(binary, .OpMemoryModel, &[_]Word{ - @enumToInt(addressing_model), @enumToInt(memory_model), + // TODO: Put this in a proper section. + try spv.sections.capabilities.emit(spv.gpa, .OpMemoryModel, .{ + .addressing_model = addressing_model, + .memory_model = memory_model, }); } |
