aboutsummaryrefslogtreecommitdiff
path: root/src/link
diff options
context:
space:
mode:
authorRobin Voetter <robin@voetter.nl>2022-01-21 20:14:31 +0100
committerRobin Voetter <robin@voetter.nl>2022-01-28 14:38:58 +0100
commit1b6ebce0da45169979b0f51a07274ff6fb5590bc (patch)
tree5e5e4c3c2eb9d87fec61e39b7a5f1d081a75ec88 /src/link
parent72e67aaf05de06e5a7b74596e70ce5afd17b2919 (diff)
downloadzig-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.zig101
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,
});
}