aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/spirv/Module.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-11-24 17:48:39 -0500
committerGitHub <noreply@github.com>2022-11-24 17:48:39 -0500
commit972c0402411e19064139bc872a55fff55fbd95d6 (patch)
tree662b07eac29bdadba4128d0fb4e9863a7f684ce9 /src/codegen/spirv/Module.zig
parenta3552a6c5083a4a58223b38bc20df4ada0c736c1 (diff)
parentbd6a57109331a873bc3f73932a5b039152670ceb (diff)
downloadzig-972c0402411e19064139bc872a55fff55fbd95d6.tar.gz
zig-972c0402411e19064139bc872a55fff55fbd95d6.zip
Merge pull request #13611 from Snektron/spirv-assembler
spirv: assembler
Diffstat (limited to 'src/codegen/spirv/Module.zig')
-rw-r--r--src/codegen/spirv/Module.zig66
1 files changed, 56 insertions, 10 deletions
diff --git a/src/codegen/spirv/Module.zig b/src/codegen/spirv/Module.zig
index 59ed1b9b78..f37b04bff3 100644
--- a/src/codegen/spirv/Module.zig
+++ b/src/codegen/spirv/Module.zig
@@ -24,6 +24,37 @@ const Type = @import("type.zig").Type;
const TypeCache = std.ArrayHashMapUnmanaged(Type, IdResultType, Type.ShallowHashContext32, true);
+/// This structure represents a function that is in-progress of being emitted.
+/// Commonly, the contents of this structure will be merged with the appropriate
+/// sections of the module and re-used. Note that the SPIR-V module system makes
+/// no attempt of compacting result-id's, so any Fn instance should ultimately
+/// be merged into the module it's result-id's are allocated from.
+pub const Fn = struct {
+ /// The prologue of this function; this section contains the function's
+ /// OpFunction, OpFunctionParameter, OpLabel and OpVariable instructions, and
+ /// is separated from the actual function contents as OpVariable instructions
+ /// must appear in the first block of a function definition.
+ prologue: Section = .{},
+ /// The code of the body of this function.
+ /// This section should also contain the OpFunctionEnd instruction marking
+ /// the end of this function definition.
+ body: Section = .{},
+
+ /// Reset this function without deallocating resources, so that
+ /// it may be used to emit code for another function.
+ pub fn reset(self: *Fn) void {
+ self.prologue.reset();
+ self.body.reset();
+ }
+
+ /// Free the resources owned by this function.
+ pub fn deinit(self: *Fn, a: Allocator) void {
+ self.prologue.deinit(a);
+ self.body.deinit(a);
+ self.* = undefined;
+ }
+};
+
/// A general-purpose allocator which may be used to allocate resources for this module
gpa: Allocator,
@@ -40,7 +71,8 @@ sections: struct {
// memory model defined by target, not required here.
/// OpEntryPoint instructions.
entry_points: Section = .{},
- // OpExecutionMode and OpExecutionModeId instructions - skip for now.
+ /// OpExecutionMode and OpExecutionModeId instructions.
+ execution_modes: Section = .{},
/// OpString, OpSourcExtension, OpSource, OpSourceContinued.
debug_strings: Section = .{},
// OpName, OpMemberName - skip for now.
@@ -81,6 +113,7 @@ pub fn deinit(self: *Module) void {
self.sections.capabilities.deinit(self.gpa);
self.sections.extensions.deinit(self.gpa);
self.sections.entry_points.deinit(self.gpa);
+ self.sections.execution_modes.deinit(self.gpa);
self.sections.debug_strings.deinit(self.gpa);
self.sections.annotations.deinit(self.gpa);
self.sections.types_globals_constants.deinit(self.gpa);
@@ -107,7 +140,7 @@ pub fn flush(self: Module, file: std.fs.File) !void {
const header = [_]Word{
spec.magic_number,
- (spec.version.major << 16) | (spec.version.minor << 8),
+ (1 << 16) | (5 << 8),
0, // TODO: Register Zig compiler magic number.
self.idBound(),
0, // Schema (currently reserved for future use)
@@ -119,6 +152,7 @@ pub fn flush(self: Module, file: std.fs.File) !void {
self.sections.capabilities.toWords(),
self.sections.extensions.toWords(),
self.sections.entry_points.toWords(),
+ self.sections.execution_modes.toWords(),
self.sections.debug_strings.toWords(),
self.sections.annotations.toWords(),
self.sections.types_globals_constants.toWords(),
@@ -140,6 +174,12 @@ pub fn flush(self: Module, file: std.fs.File) !void {
try file.pwritevAll(&iovc_buffers, 0);
}
+/// Merge the sections making up a function declaration into this module.
+pub fn addFunction(self: *Module, func: Fn) !void {
+ try self.sections.functions.append(self.gpa, func.prologue);
+ try self.sections.functions.append(self.gpa, func.body);
+}
+
/// Fetch the result-id of an OpString instruction that encodes the path of the source
/// file of the decl. This function may also emit an OpSource with source-level information regarding
/// the decl.
@@ -175,11 +215,13 @@ pub fn resolveType(self: *Module, ty: Type) !Type.Ref {
if (!result.found_existing) {
result.value_ptr.* = try self.emitType(ty);
}
+
return result.index;
}
pub fn resolveTypeId(self: *Module, ty: Type) !IdRef {
- return self.typeResultId(try self.resolveType(ty));
+ const type_ref = try self.resolveType(ty);
+ return self.typeResultId(type_ref);
}
/// Get the result-id of a particular type, by reference. Asserts type_ref is valid.
@@ -208,14 +250,18 @@ pub fn emitType(self: *Module, ty: Type) !IdResultType {
switch (ty.tag()) {
.void => try types.emit(self.gpa, .OpTypeVoid, result_id_operand),
.bool => try types.emit(self.gpa, .OpTypeBool, result_id_operand),
- .int => try types.emit(self.gpa, .OpTypeInt, .{
- .id_result = result_id,
- .width = ty.payload(.int).width,
- .signedness = switch (ty.payload(.int).signedness) {
- .unsigned => @as(spec.LiteralInteger, 0),
+ .int => {
+ const signedness: spec.LiteralInteger = switch (ty.payload(.int).signedness) {
+ .unsigned => 0,
.signed => 1,
- },
- }),
+ };
+
+ try types.emit(self.gpa, .OpTypeInt, .{
+ .id_result = result_id,
+ .width = ty.payload(.int).width,
+ .signedness = signedness,
+ });
+ },
.float => try types.emit(self.gpa, .OpTypeFloat, .{
.id_result = result_id,
.width = ty.payload(.float).width,