aboutsummaryrefslogtreecommitdiff
path: root/src/codegen/spirv/Assembler.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/codegen/spirv/Assembler.zig')
-rw-r--r--src/codegen/spirv/Assembler.zig36
1 files changed, 36 insertions, 0 deletions
diff --git a/src/codegen/spirv/Assembler.zig b/src/codegen/spirv/Assembler.zig
index 2cfb590273..0713a63a7e 100644
--- a/src/codegen/spirv/Assembler.zig
+++ b/src/codegen/spirv/Assembler.zig
@@ -135,6 +135,9 @@ const AsmValue = union(enum) {
/// This is a pre-supplied constant integer value.
constant: u32,
+ /// This is a pre-supplied constant string value.
+ string: []const u8,
+
/// Retrieve the result-id of this AsmValue. Asserts that this AsmValue
/// is of a variant that allows the result to be obtained (not an unresolved
/// forward declaration, not in the process of being declared, etc).
@@ -144,6 +147,7 @@ const AsmValue = union(enum) {
.unresolved_forward_reference,
// TODO: Lower this value as constant?
.constant,
+ .string,
=> unreachable,
.value => |result| result,
.ty => |result| result,
@@ -274,6 +278,16 @@ fn processInstruction(self: *Assembler) !void {
.OpEntryPoint => {
return self.fail(0, "cannot export entry points via OpEntryPoint, export the kernel using callconv(.Kernel)", .{});
},
+ .OpCapability => {
+ try self.spv.addCapability(@enumFromInt(self.inst.operands.items[0].value));
+ return;
+ },
+ .OpExtension => {
+ const ext_name_offset = self.inst.operands.items[0].string;
+ const ext_name = std.mem.sliceTo(self.inst.string_bytes.items[ext_name_offset..], 0);
+ try self.spv.addExtension(ext_name);
+ return;
+ },
.OpExtInstImport => blk: {
const set_name_offset = self.inst.operands.items[1].string;
const set_name = std.mem.sliceTo(self.inst.string_bytes.items[set_name_offset..], 0);
@@ -635,6 +649,28 @@ fn parseBitEnum(self: *Assembler, kind: spec.OperandKind) !void {
/// Also handles parsing any required extra operands.
fn parseValueEnum(self: *Assembler, kind: spec.OperandKind) !void {
const tok = self.currentToken();
+ if (self.eatToken(.placeholder)) {
+ const name = self.tokenText(tok)[1..];
+ const value = self.value_map.get(name) orelse {
+ return self.fail(tok.start, "invalid placeholder '${s}'", .{name});
+ };
+ switch (value) {
+ .constant => |literal32| {
+ try self.inst.operands.append(self.gpa, .{ .value = literal32 });
+ },
+ .string => |str| {
+ const enumerant = for (kind.enumerants()) |enumerant| {
+ if (std.mem.eql(u8, enumerant.name, str)) break enumerant;
+ } else {
+ return self.fail(tok.start, "'{s}' is not a valid value for enumeration {s}", .{ str, @tagName(kind) });
+ };
+ try self.inst.operands.append(self.gpa, .{ .value = enumerant.value });
+ },
+ else => return self.fail(tok.start, "value '{s}' cannot be used as placeholder", .{name}),
+ }
+ return;
+ }
+
try self.expectToken(.value);
const text = self.tokenText(tok);