From cd4b03c5ed1bc5b48ad9c353679b309ead75551d Mon Sep 17 00:00:00 2001 From: Ali Cheraghi Date: Sun, 3 Aug 2025 17:02:51 +0330 Subject: [PATCH] spirv: define and use extended instruction set opcodes --- src/codegen/spirv/Assembler.zig | 579 +++--- src/codegen/spirv/CodeGen.zig | 600 +++--- src/codegen/spirv/Module.zig | 26 +- src/codegen/spirv/Section.zig | 12 +- src/codegen/spirv/spec.zig | 3254 +++---------------------------- src/link/SpirV.zig | 40 +- tools/gen_spirv_spec.zig | 145 +- 7 files changed, 977 insertions(+), 3679 deletions(-) diff --git a/src/codegen/spirv/Assembler.zig b/src/codegen/spirv/Assembler.zig index 6e4e5ca558..a47cd49644 100644 --- a/src/codegen/spirv/Assembler.zig +++ b/src/codegen/spirv/Assembler.zig @@ -16,7 +16,7 @@ const Assembler = @This(); cg: *CodeGen, errors: std.ArrayListUnmanaged(ErrorMsg) = .empty, src: []const u8 = undefined, -/// `self.src` tokenized. +/// `ass.src` tokenized. tokens: std.ArrayListUnmanaged(Token) = .empty, current_token: u32 = 0, /// The instruction that is currently being parsed or has just been parsed. @@ -25,8 +25,8 @@ inst: struct { operands: std.ArrayListUnmanaged(Operand) = .empty, string_bytes: std.ArrayListUnmanaged(u8) = .empty, - fn result(self: @This()) ?AsmValue.Ref { - for (self.operands.items[0..@min(self.operands.items.len, 2)]) |op| { + fn result(ass: @This()) ?AsmValue.Ref { + for (ass.operands.items[0..@min(ass.operands.items.len, 2)]) |op| { switch (op) { .result_id => |index| return index, else => {}, @@ -55,42 +55,42 @@ const Operand = union(enum) { string: u32, }; -pub fn deinit(self: *Assembler) void { - const gpa = self.cg.module.gpa; - for (self.errors.items) |err| gpa.free(err.msg); - self.tokens.deinit(gpa); - self.errors.deinit(gpa); - self.inst.operands.deinit(gpa); - self.inst.string_bytes.deinit(gpa); - self.value_map.deinit(gpa); - self.inst_map.deinit(gpa); +pub fn deinit(ass: *Assembler) void { + const gpa = ass.cg.module.gpa; + for (ass.errors.items) |err| gpa.free(err.msg); + ass.tokens.deinit(gpa); + ass.errors.deinit(gpa); + ass.inst.operands.deinit(gpa); + ass.inst.string_bytes.deinit(gpa); + ass.value_map.deinit(gpa); + ass.inst_map.deinit(gpa); } const Error = error{ AssembleFail, OutOfMemory }; -pub fn assemble(self: *Assembler, src: []const u8) Error!void { - const gpa = self.cg.module.gpa; +pub fn assemble(ass: *Assembler, src: []const u8) Error!void { + const gpa = ass.cg.module.gpa; - self.src = src; - self.errors.clearRetainingCapacity(); + ass.src = src; + ass.errors.clearRetainingCapacity(); // Populate the opcode map if it isn't already - if (self.inst_map.count() == 0) { + if (ass.inst_map.count() == 0) { const instructions = spec.InstructionSet.core.instructions(); - try self.inst_map.ensureUnusedCapacity(gpa, @intCast(instructions.len)); + try ass.inst_map.ensureUnusedCapacity(gpa, @intCast(instructions.len)); for (spec.InstructionSet.core.instructions(), 0..) |inst, i| { - const entry = try self.inst_map.getOrPut(gpa, inst.name); + const entry = try ass.inst_map.getOrPut(gpa, inst.name); assert(entry.index == i); } } - try self.tokenize(); - while (!self.testToken(.eof)) { - try self.parseInstruction(); - try self.processInstruction(); + try ass.tokenize(); + while (!ass.testToken(.eof)) { + try ass.parseInstruction(); + try ass.processInstruction(); } - if (self.errors.items.len > 0) return error.AssembleFail; + if (ass.errors.items.len > 0) return error.AssembleFail; } const ErrorMsg = struct { @@ -99,23 +99,23 @@ const ErrorMsg = struct { msg: []const u8, }; -fn addError(self: *Assembler, offset: u32, comptime fmt: []const u8, args: anytype) !void { - const gpa = self.cg.module.gpa; +fn addError(ass: *Assembler, offset: u32, comptime fmt: []const u8, args: anytype) !void { + const gpa = ass.cg.module.gpa; const msg = try std.fmt.allocPrint(gpa, fmt, args); errdefer gpa.free(msg); - try self.errors.append(gpa, .{ + try ass.errors.append(gpa, .{ .byte_offset = offset, .msg = msg, }); } -fn fail(self: *Assembler, offset: u32, comptime fmt: []const u8, args: anytype) Error { - try self.addError(offset, fmt, args); +fn fail(ass: *Assembler, offset: u32, comptime fmt: []const u8, args: anytype) Error { + try ass.addError(offset, fmt, args); return error.AssembleFail; } -fn todo(self: *Assembler, comptime fmt: []const u8, args: anytype) Error { - return self.fail(0, "todo: " ++ fmt, args); +fn todo(ass: *Assembler, comptime fmt: []const u8, args: anytype) Error { + return ass.fail(0, "todo: " ++ fmt, args); } const AsmValue = union(enum) { @@ -139,8 +139,8 @@ const AsmValue = union(enum) { /// 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). - pub fn resultId(self: AsmValue) Id { - return switch (self) { + pub fn resultId(value: AsmValue) Id { + return switch (value) { .just_declared, .unresolved_forward_reference, // TODO: Lower this value as constant? @@ -153,61 +153,62 @@ const AsmValue = union(enum) { } }; -/// Attempt to process the instruction currently in `self.inst`. +/// Attempt to process the instruction currently in `ass.inst`. /// This for example emits the instruction in the module or function, or /// records type definitions. /// If this function returns `error.AssembleFail`, an explanatory -/// error message has already been emitted into `self.errors`. -fn processInstruction(self: *Assembler) !void { - const module = self.cg.module; - const result: AsmValue = switch (self.inst.opcode) { +/// error message has already been emitted into `ass.errors`. +fn processInstruction(ass: *Assembler) !void { + const module = ass.cg.module; + const result: AsmValue = switch (ass.inst.opcode) { .OpEntryPoint => { - return self.fail(self.currentToken().start, "cannot export entry points in assembly", .{}); + return ass.fail(ass.currentToken().start, "cannot export entry points in assembly", .{}); }, .OpExecutionMode, .OpExecutionModeId => { - return self.fail(self.currentToken().start, "cannot set execution mode in assembly", .{}); + return ass.fail(ass.currentToken().start, "cannot set execution mode in assembly", .{}); }, .OpCapability => { - try module.addCapability(@enumFromInt(self.inst.operands.items[0].value)); + try module.addCapability(@enumFromInt(ass.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); + const ext_name_offset = ass.inst.operands.items[0].string; + const ext_name = std.mem.sliceTo(ass.inst.string_bytes.items[ext_name_offset..], 0); try module.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); + const set_name_offset = ass.inst.operands.items[1].string; + const set_name = std.mem.sliceTo(ass.inst.string_bytes.items[set_name_offset..], 0); const set_tag = std.meta.stringToEnum(spec.InstructionSet, set_name) orelse { - return self.fail(set_name_offset, "unknown instruction set: {s}", .{set_name}); + return ass.fail(set_name_offset, "unknown instruction set: {s}", .{set_name}); }; break :blk .{ .value = try module.importInstructionSet(set_tag) }; }, - else => switch (self.inst.opcode.class()) { - .type_declaration => try self.processTypeInstruction(), - else => (try self.processGenericInstruction()) orelse return, + else => switch (ass.inst.opcode.class()) { + .type_declaration => try ass.processTypeInstruction(), + else => (try ass.processGenericInstruction()) orelse return, }, }; - const result_ref = self.inst.result().?; - switch (self.value_map.values()[result_ref]) { - .just_declared => self.value_map.values()[result_ref] = result, + const result_ref = ass.inst.result().?; + switch (ass.value_map.values()[result_ref]) { + .just_declared => ass.value_map.values()[result_ref] = result, else => { // TODO: Improve source location. - const name = self.value_map.keys()[result_ref]; - return self.fail(0, "duplicate definition of %{s}", .{name}); + const name = ass.value_map.keys()[result_ref]; + return ass.fail(0, "duplicate definition of %{s}", .{name}); }, } } -fn processTypeInstruction(self: *Assembler) !AsmValue { - const gpa = self.cg.module.gpa; - const module = self.cg.module; - const operands = self.inst.operands.items; +fn processTypeInstruction(ass: *Assembler) !AsmValue { + const cg = ass.cg; + const gpa = cg.module.gpa; + const module = cg.module; + const operands = ass.inst.operands.items; const section = &module.sections.globals; - const id = switch (self.inst.opcode) { + const id = switch (ass.inst.opcode) { .OpTypeVoid => try module.voidType(), .OpTypeBool => try module.boolType(), .OpTypeInt => blk: { @@ -216,11 +217,11 @@ fn processTypeInstruction(self: *Assembler) !AsmValue { 1 => .signed, else => { // TODO: Improve source location. - return self.fail(0, "{} is not a valid signedness (expected 0 or 1)", .{operands[2].literal32}); + return ass.fail(0, "{} is not a valid signedness (expected 0 or 1)", .{operands[2].literal32}); }, }; const width = std.math.cast(u16, operands[1].literal32) orelse { - return self.fail(0, "int type of {} bits is too large", .{operands[1].literal32}); + return ass.fail(0, "int type of {} bits is too large", .{operands[1].literal32}); }; break :blk try module.intType(signedness, width); }, @@ -229,22 +230,22 @@ fn processTypeInstruction(self: *Assembler) !AsmValue { switch (bits) { 16, 32, 64 => {}, else => { - return self.fail(0, "{} is not a valid bit count for floats (expected 16, 32 or 64)", .{bits}); + return ass.fail(0, "{} is not a valid bit count for floats (expected 16, 32 or 64)", .{bits}); }, } break :blk try module.floatType(@intCast(bits)); }, .OpTypeVector => blk: { - const child_type = try self.resolveRefId(operands[1].ref_id); + const child_type = try ass.resolveRefId(operands[1].ref_id); break :blk try module.vectorType(operands[2].literal32, child_type); }, .OpTypeArray => { // TODO: The length of an OpTypeArray is determined by a constant (which may be a spec constant), // and so some consideration must be taken when entering this in the type system. - return self.todo("process OpTypeArray", .{}); + return ass.todo("process OpTypeArray", .{}); }, .OpTypeRuntimeArray => blk: { - const element_type = try self.resolveRefId(operands[1].ref_id); + const element_type = try ass.resolveRefId(operands[1].ref_id); const result_id = module.allocId(); try section.emit(module.gpa, .OpTypeRuntimeArray, .{ .id_result = result_id, @@ -254,7 +255,7 @@ fn processTypeInstruction(self: *Assembler) !AsmValue { }, .OpTypePointer => blk: { const storage_class: StorageClass = @enumFromInt(operands[1].value); - const child_type = try self.resolveRefId(operands[2].ref_id); + const child_type = try ass.resolveRefId(operands[2].ref_id); const result_id = module.allocId(); try section.emit(module.gpa, .OpTypePointer, .{ .id_result = result_id, @@ -264,13 +265,14 @@ fn processTypeInstruction(self: *Assembler) !AsmValue { break :blk result_id; }, .OpTypeStruct => blk: { - const ids = try gpa.alloc(Id, operands[1..].len); - defer gpa.free(ids); - for (operands[1..], ids) |op, *id| id.* = try self.resolveRefId(op.ref_id); + const scratch_top = cg.id_scratch.items.len; + defer cg.id_scratch.shrinkRetainingCapacity(scratch_top); + const ids = try cg.id_scratch.addManyAsSlice(gpa, operands[1..].len); + for (operands[1..], ids) |op, *id| id.* = try ass.resolveRefId(op.ref_id); break :blk try module.structType(ids, null, null, .none); }, .OpTypeImage => blk: { - const sampled_type = try self.resolveRefId(operands[1].ref_id); + const sampled_type = try ass.resolveRefId(operands[1].ref_id); const result_id = module.allocId(); try section.emit(gpa, .OpTypeImage, .{ .id_result = result_id, @@ -290,19 +292,21 @@ fn processTypeInstruction(self: *Assembler) !AsmValue { break :blk result_id; }, .OpTypeSampledImage => blk: { - const image_type = try self.resolveRefId(operands[1].ref_id); + const image_type = try ass.resolveRefId(operands[1].ref_id); const result_id = module.allocId(); try section.emit(gpa, .OpTypeSampledImage, .{ .id_result = result_id, .image_type = image_type }); break :blk result_id; }, .OpTypeFunction => blk: { const param_operands = operands[2..]; - const return_type = try self.resolveRefId(operands[1].ref_id); + const return_type = try ass.resolveRefId(operands[1].ref_id); + + const scratch_top = cg.id_scratch.items.len; + defer cg.id_scratch.shrinkRetainingCapacity(scratch_top); + const param_types = try cg.id_scratch.addManyAsSlice(gpa, param_operands.len); - const param_types = try module.gpa.alloc(Id, param_operands.len); - defer module.gpa.free(param_types); for (param_types, param_operands) |*param, operand| { - param.* = try self.resolveRefId(operand.ref_id); + param.* = try ass.resolveRefId(operand.ref_id); } const result_id = module.allocId(); try section.emit(module.gpa, .OpTypeFunction, .{ @@ -312,7 +316,7 @@ fn processTypeInstruction(self: *Assembler) !AsmValue { }); break :blk result_id; }, - else => return self.todo("process type instruction {s}", .{@tagName(self.inst.opcode)}), + else => return ass.todo("process type instruction {s}", .{@tagName(ass.inst.opcode)}), }; return .{ .ty = id }; @@ -320,31 +324,30 @@ fn processTypeInstruction(self: *Assembler) !AsmValue { /// - No forward references are allowed in operands. /// - Target section is determined from instruction type. -fn processGenericInstruction(self: *Assembler) !?AsmValue { - const module = self.cg.module; +fn processGenericInstruction(ass: *Assembler) !?AsmValue { + const module = ass.cg.module; const target = module.zcu.getTarget(); - const operands = self.inst.operands.items; + const operands = ass.inst.operands.items; var maybe_spv_decl_index: ?Decl.Index = null; - const section = switch (self.inst.opcode.class()) { + const section = switch (ass.inst.opcode.class()) { .constant_creation => &module.sections.globals, .annotation => &module.sections.annotations, .type_declaration => unreachable, // Handled elsewhere. - else => switch (self.inst.opcode) { + else => switch (ass.inst.opcode) { .OpEntryPoint => unreachable, .OpExecutionMode, .OpExecutionModeId => &module.sections.execution_modes, .OpVariable => section: { const storage_class: spec.StorageClass = @enumFromInt(operands[2].value); - if (storage_class == .function) break :section &self.cg.prologue; + if (storage_class == .function) break :section &ass.cg.prologue; maybe_spv_decl_index = try module.allocDecl(.global); if (!target.cpu.has(.spirv, .v1_4) and storage_class != .input and storage_class != .output) { // Before version 1.4, the interface’s storage classes are limited to the Input and Output break :section &module.sections.globals; } - try self.cg.decl_deps.put(module.gpa, maybe_spv_decl_index.?, {}); - try module.declareDeclDeps(maybe_spv_decl_index.?, &.{}); + try ass.cg.module.decl_deps.append(module.gpa, maybe_spv_decl_index.?); break :section &module.sections.globals; }, - else => &self.cg.body, + else => &ass.cg.body, }, }; @@ -374,12 +377,12 @@ fn processGenericInstruction(self: *Assembler) !?AsmValue { section.writeOperand(Id, maybe_result_id.?); }, .ref_id => |index| { - const result = try self.resolveRef(index); + const result = try ass.resolveRef(index); try section.ensureUnusedCapacity(module.gpa, 1); section.writeOperand(spec.Id, result.resultId()); }, .string => |offset| { - const text = std.mem.sliceTo(self.inst.string_bytes.items[offset..], 0); + const text = std.mem.sliceTo(ass.inst.string_bytes.items[offset..], 0); const size = std.math.divCeil(usize, text.len + 1, @sizeOf(Word)) catch unreachable; try section.ensureUnusedCapacity(module.gpa, size); section.writeOperand(spec.LiteralString, text); @@ -388,74 +391,74 @@ fn processGenericInstruction(self: *Assembler) !?AsmValue { } const actual_word_count = section.instructions.items.len - first_word; - section.instructions.items[first_word] |= @as(u32, @as(u16, @intCast(actual_word_count))) << 16 | @intFromEnum(self.inst.opcode); + section.instructions.items[first_word] |= @as(u32, @as(u16, @intCast(actual_word_count))) << 16 | @intFromEnum(ass.inst.opcode); if (maybe_result_id) |result| return .{ .value = result }; return null; } -fn resolveMaybeForwardRef(self: *Assembler, ref: AsmValue.Ref) !AsmValue { - const value = self.value_map.values()[ref]; +fn resolveMaybeForwardRef(ass: *Assembler, ref: AsmValue.Ref) !AsmValue { + const value = ass.value_map.values()[ref]; switch (value) { .just_declared => { - const name = self.value_map.keys()[ref]; + const name = ass.value_map.keys()[ref]; // TODO: Improve source location. - return self.fail(0, "self-referential parameter %{s}", .{name}); + return ass.fail(0, "ass-referential parameter %{s}", .{name}); }, else => return value, } } -fn resolveRef(self: *Assembler, ref: AsmValue.Ref) !AsmValue { - const value = try self.resolveMaybeForwardRef(ref); +fn resolveRef(ass: *Assembler, ref: AsmValue.Ref) !AsmValue { + const value = try ass.resolveMaybeForwardRef(ref); switch (value) { .just_declared => unreachable, .unresolved_forward_reference => { - const name = self.value_map.keys()[ref]; + const name = ass.value_map.keys()[ref]; // TODO: Improve source location. - return self.fail(0, "reference to undeclared result-id %{s}", .{name}); + return ass.fail(0, "reference to undeclared result-id %{s}", .{name}); }, else => return value, } } -fn resolveRefId(self: *Assembler, ref: AsmValue.Ref) !Id { - const value = try self.resolveRef(ref); +fn resolveRefId(ass: *Assembler, ref: AsmValue.Ref) !Id { + const value = try ass.resolveRef(ref); return value.resultId(); } -fn parseInstruction(self: *Assembler) !void { - const gpa = self.cg.module.gpa; +fn parseInstruction(ass: *Assembler) !void { + const gpa = ass.cg.module.gpa; - self.inst.opcode = undefined; - self.inst.operands.clearRetainingCapacity(); - self.inst.string_bytes.clearRetainingCapacity(); + ass.inst.opcode = undefined; + ass.inst.operands.clearRetainingCapacity(); + ass.inst.string_bytes.clearRetainingCapacity(); - const lhs_result_tok = self.currentToken(); - const maybe_lhs_result: ?AsmValue.Ref = if (self.eatToken(.result_id_assign)) blk: { - const name = self.tokenText(lhs_result_tok)[1..]; - const entry = try self.value_map.getOrPut(gpa, name); - try self.expectToken(.equals); + const lhs_result_tok = ass.currentToken(); + const maybe_lhs_result: ?AsmValue.Ref = if (ass.eatToken(.result_id_assign)) blk: { + const name = ass.tokenText(lhs_result_tok)[1..]; + const entry = try ass.value_map.getOrPut(gpa, name); + try ass.expectToken(.equals); if (!entry.found_existing) { entry.value_ptr.* = .just_declared; } break :blk @intCast(entry.index); } else null; - const opcode_tok = self.currentToken(); + const opcode_tok = ass.currentToken(); if (maybe_lhs_result != null) { - try self.expectToken(.opcode); - } else if (!self.eatToken(.opcode)) { - return self.fail(opcode_tok.start, "expected start of instruction, found {s}", .{opcode_tok.tag.name()}); + try ass.expectToken(.opcode); + } else if (!ass.eatToken(.opcode)) { + return ass.fail(opcode_tok.start, "expected start of instruction, found {s}", .{opcode_tok.tag.name()}); } - const opcode_text = self.tokenText(opcode_tok); - const index = self.inst_map.getIndex(opcode_text) orelse { - return self.fail(opcode_tok.start, "invalid opcode '{s}'", .{opcode_text}); + const opcode_text = ass.tokenText(opcode_tok); + const index = ass.inst_map.getIndex(opcode_text) orelse { + return ass.fail(opcode_tok.start, "invalid opcode '{s}'", .{opcode_text}); }; const inst = spec.InstructionSet.core.instructions()[index]; - self.inst.opcode = @enumFromInt(inst.opcode); + ass.inst.opcode = @enumFromInt(inst.opcode); const expected_operands = inst.operands; // This is a loop because the result-id is not always the first operand. @@ -464,67 +467,67 @@ fn parseInstruction(self: *Assembler) !void { } else false; if (requires_lhs_result and maybe_lhs_result == null) { - return self.fail(opcode_tok.start, "opcode '{s}' expects result on left-hand side", .{@tagName(self.inst.opcode)}); + return ass.fail(opcode_tok.start, "opcode '{s}' expects result on left-hand side", .{@tagName(ass.inst.opcode)}); } else if (!requires_lhs_result and maybe_lhs_result != null) { - return self.fail( + return ass.fail( lhs_result_tok.start, "opcode '{s}' does not expect a result-id on the left-hand side", - .{@tagName(self.inst.opcode)}, + .{@tagName(ass.inst.opcode)}, ); } for (expected_operands) |operand| { if (operand.kind == .id_result) { - try self.inst.operands.append(gpa, .{ .result_id = maybe_lhs_result.? }); + try ass.inst.operands.append(gpa, .{ .result_id = maybe_lhs_result.? }); continue; } switch (operand.quantifier) { - .required => if (self.isAtInstructionBoundary()) { - return self.fail( - self.currentToken().start, + .required => if (ass.isAtInstructionBoundary()) { + return ass.fail( + ass.currentToken().start, "missing required operand", // TODO: Operand name? .{}, ); } else { - try self.parseOperand(operand.kind); + try ass.parseOperand(operand.kind); }, - .optional => if (!self.isAtInstructionBoundary()) { - try self.parseOperand(operand.kind); + .optional => if (!ass.isAtInstructionBoundary()) { + try ass.parseOperand(operand.kind); }, - .variadic => while (!self.isAtInstructionBoundary()) { - try self.parseOperand(operand.kind); + .variadic => while (!ass.isAtInstructionBoundary()) { + try ass.parseOperand(operand.kind); }, } } } -fn parseOperand(self: *Assembler, kind: spec.OperandKind) Error!void { +fn parseOperand(ass: *Assembler, kind: spec.OperandKind) Error!void { switch (kind.category()) { - .bit_enum => try self.parseBitEnum(kind), - .value_enum => try self.parseValueEnum(kind), - .id => try self.parseRefId(), + .bit_enum => try ass.parseBitEnum(kind), + .value_enum => try ass.parseValueEnum(kind), + .id => try ass.parseRefId(), else => switch (kind) { - .literal_integer => try self.parseLiteralInteger(), - .literal_string => try self.parseString(), - .literal_context_dependent_number => try self.parseContextDependentNumber(), - .literal_ext_inst_integer => try self.parseLiteralExtInstInteger(), - .pair_id_ref_id_ref => try self.parsePhiSource(), - else => return self.todo("parse operand of type {s}", .{@tagName(kind)}), + .literal_integer => try ass.parseLiteralInteger(), + .literal_string => try ass.parseString(), + .literal_context_dependent_number => try ass.parseContextDependentNumber(), + .literal_ext_inst_integer => try ass.parseLiteralExtInstInteger(), + .pair_id_ref_id_ref => try ass.parsePhiSource(), + else => return ass.todo("parse operand of type {s}", .{@tagName(kind)}), }, } } /// Also handles parsing any required extra operands. -fn parseBitEnum(self: *Assembler, kind: spec.OperandKind) !void { - const gpa = self.cg.module.gpa; +fn parseBitEnum(ass: *Assembler, kind: spec.OperandKind) !void { + const gpa = ass.cg.module.gpa; - var tok = self.currentToken(); - try self.expectToken(.value); + var tok = ass.currentToken(); + try ass.expectToken(.value); - var text = self.tokenText(tok); + var text = ass.tokenText(tok); if (std.mem.eql(u8, text, "None")) { - try self.inst.operands.append(gpa, .{ .value = 0 }); + try ass.inst.operands.append(gpa, .{ .value = 0 }); return; } @@ -535,18 +538,18 @@ fn parseBitEnum(self: *Assembler, kind: spec.OperandKind) !void { if (std.mem.eql(u8, enumerant.name, text)) break enumerant; } else { - return self.fail(tok.start, "'{s}' is not a valid flag for bitmask {s}", .{ text, @tagName(kind) }); + return ass.fail(tok.start, "'{s}' is not a valid flag for bitmask {s}", .{ text, @tagName(kind) }); }; mask |= enumerant.value; - if (!self.eatToken(.pipe)) + if (!ass.eatToken(.pipe)) break; - tok = self.currentToken(); - try self.expectToken(.value); - text = self.tokenText(tok); + tok = ass.currentToken(); + try ass.expectToken(.value); + text = ass.tokenText(tok); } - try self.inst.operands.append(gpa, .{ .value = mask }); + try ass.inst.operands.append(gpa, .{ .value = mask }); // Assume values are sorted. // TODO: ensure in generator. @@ -555,45 +558,45 @@ fn parseBitEnum(self: *Assembler, kind: spec.OperandKind) !void { continue; for (enumerant.parameters) |param_kind| { - if (self.isAtInstructionBoundary()) { - return self.fail(self.currentToken().start, "missing required parameter for bit flag '{s}'", .{enumerant.name}); + if (ass.isAtInstructionBoundary()) { + return ass.fail(ass.currentToken().start, "missing required parameter for bit flag '{s}'", .{enumerant.name}); } - try self.parseOperand(param_kind); + try ass.parseOperand(param_kind); } } } /// Also handles parsing any required extra operands. -fn parseValueEnum(self: *Assembler, kind: spec.OperandKind) !void { - const gpa = self.cg.module.gpa; +fn parseValueEnum(ass: *Assembler, kind: spec.OperandKind) !void { + const gpa = ass.cg.module.gpa; - 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}); + const tok = ass.currentToken(); + if (ass.eatToken(.placeholder)) { + const name = ass.tokenText(tok)[1..]; + const value = ass.value_map.get(name) orelse { + return ass.fail(tok.start, "invalid placeholder '${s}'", .{name}); }; switch (value) { .constant => |literal32| { - try self.inst.operands.append(gpa, .{ .value = literal32 }); + try ass.inst.operands.append(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) }); + return ass.fail(tok.start, "'{s}' is not a valid value for enumeration {s}", .{ str, @tagName(kind) }); }; - try self.inst.operands.append(gpa, .{ .value = enumerant.value }); + try ass.inst.operands.append(gpa, .{ .value = enumerant.value }); }, - else => return self.fail(tok.start, "value '{s}' cannot be used as placeholder", .{name}), + else => return ass.fail(tok.start, "value '{s}' cannot be used as placeholder", .{name}), } return; } - try self.expectToken(.value); + try ass.expectToken(.value); - const text = self.tokenText(tok); + const text = ass.tokenText(tok); const int_value = std.fmt.parseInt(u32, text, 0) catch null; const enumerant = for (kind.enumerants()) |enumerant| { if (int_value) |v| { @@ -602,131 +605,131 @@ fn parseValueEnum(self: *Assembler, kind: spec.OperandKind) !void { if (std.mem.eql(u8, enumerant.name, text)) break enumerant; } } else { - return self.fail(tok.start, "'{s}' is not a valid value for enumeration {s}", .{ text, @tagName(kind) }); + return ass.fail(tok.start, "'{s}' is not a valid value for enumeration {s}", .{ text, @tagName(kind) }); }; - try self.inst.operands.append(gpa, .{ .value = enumerant.value }); + try ass.inst.operands.append(gpa, .{ .value = enumerant.value }); for (enumerant.parameters) |param_kind| { - if (self.isAtInstructionBoundary()) { - return self.fail(self.currentToken().start, "missing required parameter for enum variant '{s}'", .{enumerant.name}); + if (ass.isAtInstructionBoundary()) { + return ass.fail(ass.currentToken().start, "missing required parameter for enum variant '{s}'", .{enumerant.name}); } - try self.parseOperand(param_kind); + try ass.parseOperand(param_kind); } } -fn parseRefId(self: *Assembler) !void { - const gpa = self.cg.module.gpa; +fn parseRefId(ass: *Assembler) !void { + const gpa = ass.cg.module.gpa; - const tok = self.currentToken(); - try self.expectToken(.result_id); + const tok = ass.currentToken(); + try ass.expectToken(.result_id); - const name = self.tokenText(tok)[1..]; - const entry = try self.value_map.getOrPut(gpa, name); + const name = ass.tokenText(tok)[1..]; + const entry = try ass.value_map.getOrPut(gpa, name); if (!entry.found_existing) { entry.value_ptr.* = .unresolved_forward_reference; } const index: AsmValue.Ref = @intCast(entry.index); - try self.inst.operands.append(gpa, .{ .ref_id = index }); + try ass.inst.operands.append(gpa, .{ .ref_id = index }); } -fn parseLiteralInteger(self: *Assembler) !void { - const gpa = self.cg.module.gpa; +fn parseLiteralInteger(ass: *Assembler) !void { + const gpa = ass.cg.module.gpa; - 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}); + const tok = ass.currentToken(); + if (ass.eatToken(.placeholder)) { + const name = ass.tokenText(tok)[1..]; + const value = ass.value_map.get(name) orelse { + return ass.fail(tok.start, "invalid placeholder '${s}'", .{name}); }; switch (value) { .constant => |literal32| { - try self.inst.operands.append(gpa, .{ .literal32 = literal32 }); + try ass.inst.operands.append(gpa, .{ .literal32 = literal32 }); }, else => { - return self.fail(tok.start, "value '{s}' cannot be used as placeholder", .{name}); + return ass.fail(tok.start, "value '{s}' cannot be used as placeholder", .{name}); }, } return; } - try self.expectToken(.value); + try ass.expectToken(.value); // According to the SPIR-V machine readable grammar, a LiteralInteger // may consist of one or more words. From the SPIR-V docs it seems like there // only one instruction where multiple words are allowed, the literals that make up the // switch cases of OpSwitch. This case is handled separately, and so we just assume // everything is a 32-bit integer in this function. - const text = self.tokenText(tok); + const text = ass.tokenText(tok); const value = std.fmt.parseInt(u32, text, 0) catch { - return self.fail(tok.start, "'{s}' is not a valid 32-bit integer literal", .{text}); + return ass.fail(tok.start, "'{s}' is not a valid 32-bit integer literal", .{text}); }; - try self.inst.operands.append(gpa, .{ .literal32 = value }); + try ass.inst.operands.append(gpa, .{ .literal32 = value }); } -fn parseLiteralExtInstInteger(self: *Assembler) !void { - const gpa = self.cg.module.gpa; +fn parseLiteralExtInstInteger(ass: *Assembler) !void { + const gpa = ass.cg.module.gpa; - 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}); + const tok = ass.currentToken(); + if (ass.eatToken(.placeholder)) { + const name = ass.tokenText(tok)[1..]; + const value = ass.value_map.get(name) orelse { + return ass.fail(tok.start, "invalid placeholder '${s}'", .{name}); }; switch (value) { .constant => |literal32| { - try self.inst.operands.append(gpa, .{ .literal32 = literal32 }); + try ass.inst.operands.append(gpa, .{ .literal32 = literal32 }); }, else => { - return self.fail(tok.start, "value '{s}' cannot be used as placeholder", .{name}); + return ass.fail(tok.start, "value '{s}' cannot be used as placeholder", .{name}); }, } return; } - try self.expectToken(.value); - const text = self.tokenText(tok); + try ass.expectToken(.value); + const text = ass.tokenText(tok); const value = std.fmt.parseInt(u32, text, 0) catch { - return self.fail(tok.start, "'{s}' is not a valid 32-bit integer literal", .{text}); + return ass.fail(tok.start, "'{s}' is not a valid 32-bit integer literal", .{text}); }; - try self.inst.operands.append(gpa, .{ .literal32 = value }); + try ass.inst.operands.append(gpa, .{ .literal32 = value }); } -fn parseString(self: *Assembler) !void { - const gpa = self.cg.module.gpa; +fn parseString(ass: *Assembler) !void { + const gpa = ass.cg.module.gpa; - const tok = self.currentToken(); - try self.expectToken(.string); + const tok = ass.currentToken(); + try ass.expectToken(.string); // Note, the string might not have a closing quote. In this case, // an error is already emitted but we are trying to continue processing // anyway, so in this function we have to deal with that situation. - const text = self.tokenText(tok); + const text = ass.tokenText(tok); assert(text.len > 0 and text[0] == '"'); const literal = if (text.len != 1 and text[text.len - 1] == '"') text[1 .. text.len - 1] else text[1..]; - const string_offset: u32 = @intCast(self.inst.string_bytes.items.len); - try self.inst.string_bytes.ensureUnusedCapacity(gpa, literal.len + 1); - self.inst.string_bytes.appendSliceAssumeCapacity(literal); - self.inst.string_bytes.appendAssumeCapacity(0); + const string_offset: u32 = @intCast(ass.inst.string_bytes.items.len); + try ass.inst.string_bytes.ensureUnusedCapacity(gpa, literal.len + 1); + ass.inst.string_bytes.appendSliceAssumeCapacity(literal); + ass.inst.string_bytes.appendAssumeCapacity(0); - try self.inst.operands.append(gpa, .{ .string = string_offset }); + try ass.inst.operands.append(gpa, .{ .string = string_offset }); } -fn parseContextDependentNumber(self: *Assembler) !void { - const module = self.cg.module; +fn parseContextDependentNumber(ass: *Assembler) !void { + const module = ass.cg.module; // For context dependent numbers, the actual type to parse is determined by the instruction. // Currently, this operand appears in OpConstant and OpSpecConstant, where the too-be-parsed type // is determined by the result type. That means that in this instructions we have to resolve the // operand type early and look at the result to see how we need to proceed. - assert(self.inst.opcode == .OpConstant or self.inst.opcode == .OpSpecConstant); + assert(ass.inst.opcode == .OpConstant or ass.inst.opcode == .OpSpecConstant); - const tok = self.currentToken(); - const result = try self.resolveRef(self.inst.operands.items[0].ref_id); + const tok = ass.currentToken(); + const result = try ass.resolveRef(ass.inst.operands.items[0].ref_id); const result_id = result.resultId(); // We are going to cheat a little bit: The types we are interested in, int and float, // are added to the module and cached via module.intType and module.floatType. Therefore, @@ -741,7 +744,7 @@ fn parseContextDependentNumber(self: *Assembler) !void { const id = entry.value_ptr.*; if (id != result_id) continue; const info = entry.key_ptr.*; - return try self.parseContextDependentInt(info.signedness, info.bits); + return try ass.parseContextDependentInt(info.signedness, info.bits); } } @@ -752,44 +755,44 @@ fn parseContextDependentNumber(self: *Assembler) !void { if (id != result_id) continue; const info = entry.key_ptr.*; switch (info.bits) { - 16 => try self.parseContextDependentFloat(16), - 32 => try self.parseContextDependentFloat(32), - 64 => try self.parseContextDependentFloat(64), - else => return self.fail(tok.start, "cannot parse {}-bit info literal", .{info.bits}), + 16 => try ass.parseContextDependentFloat(16), + 32 => try ass.parseContextDependentFloat(32), + 64 => try ass.parseContextDependentFloat(64), + else => return ass.fail(tok.start, "cannot parse {}-bit info literal", .{info.bits}), } } } - return self.fail(tok.start, "cannot parse literal constant", .{}); + return ass.fail(tok.start, "cannot parse literal constant", .{}); } -fn parseContextDependentInt(self: *Assembler, signedness: std.builtin.Signedness, width: u32) !void { - const gpa = self.cg.module.gpa; +fn parseContextDependentInt(ass: *Assembler, signedness: std.builtin.Signedness, width: u32) !void { + const gpa = ass.cg.module.gpa; - 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}); + const tok = ass.currentToken(); + if (ass.eatToken(.placeholder)) { + const name = ass.tokenText(tok)[1..]; + const value = ass.value_map.get(name) orelse { + return ass.fail(tok.start, "invalid placeholder '${s}'", .{name}); }; switch (value) { .constant => |literal32| { - try self.inst.operands.append(gpa, .{ .literal32 = literal32 }); + try ass.inst.operands.append(gpa, .{ .literal32 = literal32 }); }, else => { - return self.fail(tok.start, "value '{s}' cannot be used as placeholder", .{name}); + return ass.fail(tok.start, "value '{s}' cannot be used as placeholder", .{name}); }, } return; } - try self.expectToken(.value); + try ass.expectToken(.value); if (width == 0 or width > 2 * @bitSizeOf(spec.Word)) { - return self.fail(tok.start, "cannot parse {}-bit integer literal", .{width}); + return ass.fail(tok.start, "cannot parse {}-bit integer literal", .{width}); } - const text = self.tokenText(tok); + const text = ass.tokenText(tok); invalid: { // Just parse the integer as the next larger integer type, and check if it overflows afterwards. const int = std.fmt.parseInt(i128, text, 0) catch break :invalid; @@ -804,104 +807,104 @@ fn parseContextDependentInt(self: *Assembler, signedness: std.builtin.Signedness // Note, we store the sign-extended version here. if (width <= @bitSizeOf(spec.Word)) { - try self.inst.operands.append(gpa, .{ .literal32 = @truncate(@as(u128, @bitCast(int))) }); + try ass.inst.operands.append(gpa, .{ .literal32 = @truncate(@as(u128, @bitCast(int))) }); } else { - try self.inst.operands.append(gpa, .{ .literal64 = @truncate(@as(u128, @bitCast(int))) }); + try ass.inst.operands.append(gpa, .{ .literal64 = @truncate(@as(u128, @bitCast(int))) }); } return; } - return self.fail(tok.start, "'{s}' is not a valid {s} {}-bit int literal", .{ text, @tagName(signedness), width }); + return ass.fail(tok.start, "'{s}' is not a valid {s} {}-bit int literal", .{ text, @tagName(signedness), width }); } -fn parseContextDependentFloat(self: *Assembler, comptime width: u16) !void { - const gpa = self.cg.module.gpa; +fn parseContextDependentFloat(ass: *Assembler, comptime width: u16) !void { + const gpa = ass.cg.module.gpa; const Float = std.meta.Float(width); const Int = std.meta.Int(.unsigned, width); - const tok = self.currentToken(); - try self.expectToken(.value); + const tok = ass.currentToken(); + try ass.expectToken(.value); - const text = self.tokenText(tok); + const text = ass.tokenText(tok); const value = std.fmt.parseFloat(Float, text) catch { - return self.fail(tok.start, "'{s}' is not a valid {}-bit float literal", .{ text, width }); + return ass.fail(tok.start, "'{s}' is not a valid {}-bit float literal", .{ text, width }); }; const float_bits: Int = @bitCast(value); if (width <= @bitSizeOf(spec.Word)) { - try self.inst.operands.append(gpa, .{ .literal32 = float_bits }); + try ass.inst.operands.append(gpa, .{ .literal32 = float_bits }); } else { assert(width <= 2 * @bitSizeOf(spec.Word)); - try self.inst.operands.append(gpa, .{ .literal64 = float_bits }); + try ass.inst.operands.append(gpa, .{ .literal64 = float_bits }); } } -fn parsePhiSource(self: *Assembler) !void { - try self.parseRefId(); - if (self.isAtInstructionBoundary()) { - return self.fail(self.currentToken().start, "missing phi block parent", .{}); +fn parsePhiSource(ass: *Assembler) !void { + try ass.parseRefId(); + if (ass.isAtInstructionBoundary()) { + return ass.fail(ass.currentToken().start, "missing phi block parent", .{}); } - try self.parseRefId(); + try ass.parseRefId(); } /// Returns whether the `current_token` cursor /// is currently pointing at the start of a new instruction. -fn isAtInstructionBoundary(self: Assembler) bool { - return switch (self.currentToken().tag) { +fn isAtInstructionBoundary(ass: Assembler) bool { + return switch (ass.currentToken().tag) { .opcode, .result_id_assign, .eof => true, else => false, }; } -fn expectToken(self: *Assembler, tag: Token.Tag) !void { - if (self.eatToken(tag)) +fn expectToken(ass: *Assembler, tag: Token.Tag) !void { + if (ass.eatToken(tag)) return; - return self.fail(self.currentToken().start, "unexpected {s}, expected {s}", .{ - self.currentToken().tag.name(), + return ass.fail(ass.currentToken().start, "unexpected {s}, expected {s}", .{ + ass.currentToken().tag.name(), tag.name(), }); } -fn eatToken(self: *Assembler, tag: Token.Tag) bool { - if (self.testToken(tag)) { - self.current_token += 1; +fn eatToken(ass: *Assembler, tag: Token.Tag) bool { + if (ass.testToken(tag)) { + ass.current_token += 1; return true; } return false; } -fn testToken(self: Assembler, tag: Token.Tag) bool { - return self.currentToken().tag == tag; +fn testToken(ass: Assembler, tag: Token.Tag) bool { + return ass.currentToken().tag == tag; } -fn currentToken(self: Assembler) Token { - return self.tokens.items[self.current_token]; +fn currentToken(ass: Assembler) Token { + return ass.tokens.items[ass.current_token]; } -fn tokenText(self: Assembler, tok: Token) []const u8 { - return self.src[tok.start..tok.end]; +fn tokenText(ass: Assembler, tok: Token) []const u8 { + return ass.src[tok.start..tok.end]; } -/// Tokenize `self.src` and put the tokens in `self.tokens`. -/// Any errors encountered are appended to `self.errors`. -fn tokenize(self: *Assembler) !void { - const gpa = self.cg.module.gpa; +/// Tokenize `ass.src` and put the tokens in `ass.tokens`. +/// Any errors encountered are appended to `ass.errors`. +fn tokenize(ass: *Assembler) !void { + const gpa = ass.cg.module.gpa; - self.tokens.clearRetainingCapacity(); + ass.tokens.clearRetainingCapacity(); var offset: u32 = 0; while (true) { - const tok = try self.nextToken(offset); + const tok = try ass.nextToken(offset); // Resolve result-id assignment now. // NOTE: If the previous token wasn't a result-id, just ignore it, // we will catch it while parsing. - if (tok.tag == .equals and self.tokens.items[self.tokens.items.len - 1].tag == .result_id) { - self.tokens.items[self.tokens.items.len - 1].tag = .result_id_assign; + if (tok.tag == .equals and ass.tokens.items[ass.tokens.items.len - 1].tag == .result_id) { + ass.tokens.items[ass.tokens.items.len - 1].tag = .result_id_assign; } - try self.tokens.append(gpa, tok); + try ass.tokens.append(gpa, tok); if (tok.tag == .eof) break; offset = tok.end; @@ -943,8 +946,8 @@ const Token = struct { /// These can be used in place of a normal `value`. placeholder, - fn name(self: Tag) []const u8 { - return switch (self) { + fn name(tag: Tag) []const u8 { + return switch (tag) { .eof => "", .result_id => "", .result_id_assign => "", @@ -963,7 +966,7 @@ const Token = struct { /// that the token is surrounded by whitespace if required, but will not /// interpret the token yet. /// NOTE: This function doesn't handle .result_id_assign - this is handled in tokenize(). -fn nextToken(self: *Assembler, start_offset: u32) !Token { +fn nextToken(ass: *Assembler, start_offset: u32) !Token { // We generally separate the input into the following types: // - Whitespace. Generally ignored, but also used as delimiter for some // tokens. @@ -989,8 +992,8 @@ fn nextToken(self: *Assembler, start_offset: u32) !Token { var token_start = start_offset; var offset = start_offset; var tag = Token.Tag.eof; - while (offset < self.src.len) : (offset += 1) { - const c = self.src[offset]; + while (offset < ass.src.len) : (offset += 1) { + const c = ass.src[offset]; switch (state) { .start => switch (c) { ' ', '\t', '\r', '\n' => token_start = offset + 1, @@ -1023,7 +1026,7 @@ fn nextToken(self: *Assembler, start_offset: u32) !Token { }, .value => switch (c) { '"' => { - try self.addError(offset, "unexpected string literal", .{}); + try ass.addError(offset, "unexpected string literal", .{}); // The user most likely just forgot a delimiter here - keep // the tag as value. break; @@ -1035,7 +1038,7 @@ fn nextToken(self: *Assembler, start_offset: u32) !Token { '_', 'a'...'z', 'A'...'Z', '0'...'9' => {}, ' ', '\t', '\r', '\n', '=', '|' => break, else => { - try self.addError(offset, "illegal character in result-id or placeholder", .{}); + try ass.addError(offset, "illegal character in result-id or placeholder", .{}); // Again, probably a forgotten delimiter here. break; }, @@ -1048,7 +1051,7 @@ fn nextToken(self: *Assembler, start_offset: u32) !Token { .string_end => switch (c) { ' ', '\t', '\r', '\n', '=', '|' => break, else => { - try self.addError(offset, "unexpected character after string literal", .{}); + try ass.addError(offset, "unexpected character after string literal", .{}); // The token is still unmistakibly a string. break; }, @@ -1066,13 +1069,13 @@ fn nextToken(self: *Assembler, start_offset: u32) !Token { switch (state) { .string, .escape => { - try self.addError(token_start, "unterminated string", .{}); + try ass.addError(token_start, "unterminated string", .{}); }, .result_id => if (offset - token_start == 1) { - try self.addError(token_start, "result-id must have at least one name character", .{}); + try ass.addError(token_start, "result-id must have at least one name character", .{}); }, .value => { - const text = self.tokenText(tok); + const text = ass.tokenText(tok); const prefix = "Op"; const looks_like_opcode = text.len > prefix.len and std.mem.startsWith(u8, text, prefix) and diff --git a/src/codegen/spirv/CodeGen.zig b/src/codegen/spirv/CodeGen.zig index 81c0e7da5c..fa52c226bd 100644 --- a/src/codegen/spirv/CodeGen.zig +++ b/src/codegen/spirv/CodeGen.zig @@ -144,36 +144,28 @@ const ControlFlow = union(enum) { pt: Zcu.PerThread, air: Air, -/// Note: If the declaration is not a function, this value will be undefined! liveness: Air.Liveness, owner_nav: InternPool.Nav.Index, module: *Module, control_flow: ControlFlow, base_line: u32, block_label: Id = .none, -/// The base offset of the current decl, which is what `dbg_stmt` is relative to. -/// An array of function argument result-ids. Each index corresponds with the -/// function argument of the same index. -args: std.ArrayListUnmanaged(Id) = .empty, -/// A counter to keep track of how many `arg` instructions we've seen yet. next_arg_index: u32 = 0, -/// A map keeping track of which instruction generated which result-id. +args: std.ArrayListUnmanaged(Id) = .empty, inst_results: std.AutoHashMapUnmanaged(Air.Inst.Index, Id) = .empty, -file_path_id: Id = .none, +id_scratch: std.ArrayListUnmanaged(Id) = .empty, prologue: Section = .{}, body: Section = .{}, -decl_deps: std.AutoArrayHashMapUnmanaged(Decl.Index, void) = .empty, error_msg: ?*Zcu.ErrorMsg = null, -/// Free resources owned by the CodeGen. pub fn deinit(cg: *CodeGen) void { const gpa = cg.module.gpa; + cg.control_flow.deinit(gpa); cg.args.deinit(gpa); cg.inst_results.deinit(gpa); - cg.control_flow.deinit(gpa); + cg.id_scratch.deinit(gpa); cg.prologue.deinit(gpa); cg.body.deinit(gpa); - cg.decl_deps.deinit(gpa); } const Error = error{ CodegenFail, OutOfMemory }; @@ -191,9 +183,11 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { if (!do_codegen and !ty.hasRuntimeBits(zcu)) return; const spv_decl_index = try cg.module.resolveNav(ip, cg.owner_nav); - const result_id = cg.module.declPtr(spv_decl_index).result_id; + const decl = cg.module.declPtr(spv_decl_index); + const result_id = decl.result_id; + decl.begin_dep = cg.module.decl_deps.items.len; - switch (cg.module.declPtr(spv_decl_index).kind) { + switch (decl.kind) { .func => { const fn_info = zcu.typeToFunc(ty).?; const return_ty_id = try cg.resolveFnReturnType(.fromInterned(fn_info.return_type)); @@ -201,7 +195,7 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { const func_result_id = if (is_test) cg.module.allocId() else result_id; const prototype_ty_id = try cg.resolveType(ty, .direct); - try cg.prologue.emit(cg.module.gpa, .OpFunction, .{ + try cg.prologue.emit(gpa, .OpFunction, .{ .id_result_type = return_ty_id, .id_result = func_result_id, .function_type = prototype_ty_id, @@ -218,7 +212,7 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { const param_type_id = try cg.resolveType(param_ty, .direct); const arg_result_id = cg.module.allocId(); - try cg.prologue.emit(cg.module.gpa, .OpFunctionParameter, .{ + try cg.prologue.emit(gpa, .OpFunctionParameter, .{ .id_result_type = param_type_id, .id_result = arg_result_id, }); @@ -230,7 +224,7 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { // The root block of a function declaration should appear before OpVariable instructions, // so it is generated into the function's prologue. - try cg.prologue.emit(cg.module.gpa, .OpLabel, .{ + try cg.prologue.emit(gpa, .OpLabel, .{ .id_result = root_block_id, }); cg.block_label = root_block_id; @@ -241,23 +235,22 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { _ = try cg.genStructuredBody(.selection, main_body); // We always expect paths to here to end, but we still need the block // to act as a dummy merge block. - try cg.body.emit(cg.module.gpa, .OpUnreachable, {}); + try cg.body.emit(gpa, .OpUnreachable, {}); }, .unstructured => { try cg.genBody(main_body); }, } - try cg.body.emit(cg.module.gpa, .OpFunctionEnd, {}); + try cg.body.emit(gpa, .OpFunctionEnd, {}); // Append the actual code into the functions section. - try cg.module.sections.functions.append(cg.module.gpa, cg.prologue); - try cg.module.sections.functions.append(cg.module.gpa, cg.body); + try cg.module.sections.functions.append(gpa, cg.prologue); + try cg.module.sections.functions.append(gpa, cg.body); // Temporarily generate a test kernel declaration if this is a test function. if (is_test) { try cg.generateTestEntryPoint(nav.fqn.toSlice(ip), spv_decl_index, func_result_id); } - try cg.module.declareDeclDeps(spv_decl_index, cg.decl_deps.keys()); try cg.module.debugName(func_result_id, nav.fqn.toSlice(ip)); }, .global => { @@ -275,7 +268,7 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { const ty_id = try cg.resolveType(ty, .indirect); const ptr_ty_id = try cg.module.ptrType(ty_id, storage_class); - try cg.module.sections.globals.emit(cg.module.gpa, .OpVariable, .{ + try cg.module.sections.globals.emit(gpa, .OpVariable, .{ .id_result_type = ptr_ty_id, .id_result = result_id, .storage_class = storage_class, @@ -307,7 +300,6 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { } try cg.module.debugName(result_id, nav.fqn.toSlice(ip)); - try cg.module.declareDeclDeps(spv_decl_index, &.{}); }, .invocation_global => { const maybe_init_val: ?Value = switch (ip.indexToKey(val.toIntern())) { @@ -317,8 +309,6 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { else => val, }; - try cg.module.declareDeclDeps(spv_decl_index, &.{}); - const ty_id = try cg.resolveType(ty, .indirect); const ptr_ty_id = try cg.module.ptrType(ty_id, .function); @@ -328,7 +318,7 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { const initializer_proto_ty_id = try cg.module.functionType(void_ty_id, &.{}); const initializer_id = cg.module.allocId(); - try cg.prologue.emit(cg.module.gpa, .OpFunction, .{ + try cg.prologue.emit(gpa, .OpFunction, .{ .id_result_type = try cg.resolveType(.void, .direct), .id_result = initializer_id, .function_control = .{}, @@ -336,26 +326,25 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { }); const root_block_id = cg.module.allocId(); - try cg.prologue.emit(cg.module.gpa, .OpLabel, .{ + try cg.prologue.emit(gpa, .OpLabel, .{ .id_result = root_block_id, }); cg.block_label = root_block_id; const val_id = try cg.constant(ty, init_val, .indirect); - try cg.body.emit(cg.module.gpa, .OpStore, .{ + try cg.body.emit(gpa, .OpStore, .{ .pointer = result_id, .object = val_id, }); - try cg.body.emit(cg.module.gpa, .OpReturn, {}); - try cg.body.emit(cg.module.gpa, .OpFunctionEnd, {}); - try cg.module.sections.functions.append(cg.module.gpa, cg.prologue); - try cg.module.sections.functions.append(cg.module.gpa, cg.body); - try cg.module.declareDeclDeps(spv_decl_index, cg.decl_deps.keys()); + try cg.body.emit(gpa, .OpReturn, {}); + try cg.body.emit(gpa, .OpFunctionEnd, {}); + try cg.module.sections.functions.append(gpa, cg.prologue); + try cg.module.sections.functions.append(gpa, cg.body); try cg.module.debugNameFmt(initializer_id, "initializer of {f}", .{nav.fqn.fmt(ip)}); - try cg.module.sections.globals.emit(cg.module.gpa, .OpExtInst, .{ + try cg.module.sections.globals.emit(gpa, .OpExtInst, .{ .id_result_type = ptr_ty_id, .id_result = result_id, .set = try cg.module.importInstructionSet(.zig), @@ -363,7 +352,7 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { .id_ref_4 = &.{initializer_id}, }); } else { - try cg.module.sections.globals.emit(cg.module.gpa, .OpExtInst, .{ + try cg.module.sections.globals.emit(gpa, .OpExtInst, .{ .id_result_type = ptr_ty_id, .id_result = result_id, .set = try cg.module.importInstructionSet(.zig), @@ -373,6 +362,8 @@ pub fn genNav(cg: *CodeGen, do_codegen: bool) Error!void { } }, } + + cg.module.declPtr(spv_decl_index).end_dep = cg.module.decl_deps.items.len; } pub fn fail(cg: *CodeGen, comptime format: []const u8, args: anytype) Error { @@ -413,7 +404,7 @@ fn resolve(cg: *CodeGen, inst: Air.Inst.Ref) !Id { else => unreachable, }; const spv_decl_index = try cg.module.resolveNav(ip, fn_nav); - try cg.decl_deps.put(cg.module.gpa, spv_decl_index, {}); + try cg.module.decl_deps.append(cg.module.gpa, spv_decl_index); return cg.module.declPtr(spv_decl_index).result_id; } @@ -433,7 +424,7 @@ fn resolveUav(cg: *CodeGen, val: InternPool.Index) !Id { const ty_id = try cg.resolveType(ty, .indirect); const spv_decl_index = blk: { - const entry = try cg.module.uav_link.getOrPut(cg.module.gpa, .{ val, .function }); + const entry = try cg.module.uav_link.getOrPut(gpa, .{ val, .function }); if (entry.found_existing) { try cg.addFunctionDep(entry.value_ptr.*, .function); return cg.module.declPtr(entry.value_ptr.*).result_id; @@ -458,57 +449,52 @@ fn resolveUav(cg: *CodeGen, val: InternPool.Index) !Id { // TODO: This should probably be made a little more robust. const func_prologue = cg.prologue; const func_body = cg.body; - const func_deps = cg.decl_deps; const block_label = cg.block_label; defer { cg.prologue = func_prologue; cg.body = func_body; - cg.decl_deps = func_deps; cg.block_label = block_label; } cg.prologue = .{}; cg.body = .{}; - cg.decl_deps = .{}; defer { cg.prologue.deinit(gpa); cg.body.deinit(gpa); - cg.decl_deps.deinit(gpa); } const void_ty_id = try cg.resolveType(.void, .direct); const initializer_proto_ty_id = try cg.module.functionType(void_ty_id, &.{}); const initializer_id = cg.module.allocId(); - try cg.prologue.emit(cg.module.gpa, .OpFunction, .{ + try cg.prologue.emit(gpa, .OpFunction, .{ .id_result_type = try cg.resolveType(.void, .direct), .id_result = initializer_id, .function_control = .{}, .function_type = initializer_proto_ty_id, }); const root_block_id = cg.module.allocId(); - try cg.prologue.emit(cg.module.gpa, .OpLabel, .{ + try cg.prologue.emit(gpa, .OpLabel, .{ .id_result = root_block_id, }); cg.block_label = root_block_id; const val_id = try cg.constant(ty, .fromInterned(val), .indirect); - try cg.body.emit(cg.module.gpa, .OpStore, .{ + try cg.body.emit(gpa, .OpStore, .{ .pointer = result_id, .object = val_id, }); - try cg.body.emit(cg.module.gpa, .OpReturn, {}); - try cg.body.emit(cg.module.gpa, .OpFunctionEnd, {}); + try cg.body.emit(gpa, .OpReturn, {}); + try cg.body.emit(gpa, .OpFunctionEnd, {}); - try cg.module.sections.functions.append(cg.module.gpa, cg.prologue); - try cg.module.sections.functions.append(cg.module.gpa, cg.body); - try cg.module.declareDeclDeps(spv_decl_index, cg.decl_deps.keys()); + try cg.module.sections.functions.append(gpa, cg.prologue); + try cg.module.sections.functions.append(gpa, cg.body); try cg.module.debugNameFmt(initializer_id, "initializer of __anon_{d}", .{@intFromEnum(val)}); const fn_decl_ptr_ty_id = try cg.module.ptrType(ty_id, .function); - try cg.module.sections.globals.emit(cg.module.gpa, .OpExtInst, .{ + try cg.module.sections.globals.emit(gpa, .OpExtInst, .{ .id_result_type = fn_decl_ptr_ty_id, .id_result = result_id, .set = try cg.module.importInstructionSet(.zig), @@ -521,13 +507,14 @@ fn resolveUav(cg: *CodeGen, val: InternPool.Index) !Id { } fn addFunctionDep(cg: *CodeGen, decl_index: Module.Decl.Index, storage_class: StorageClass) !void { + const gpa = cg.module.gpa; const target = cg.module.zcu.getTarget(); if (target.cpu.has(.spirv, .v1_4)) { - try cg.decl_deps.put(cg.module.gpa, decl_index, {}); + try cg.module.decl_deps.append(gpa, decl_index); } else { // Before version 1.4, the interface’s storage classes are limited to the Input and Output if (storage_class == .input or storage_class == .output) { - try cg.decl_deps.put(cg.module.gpa, decl_index, {}); + try cg.module.decl_deps.append(gpa, decl_index); } } } @@ -752,8 +739,10 @@ fn constructCompositeSplat(cg: *CodeGen, ty: Type, constituent: Id) !Id { const zcu = cg.module.zcu; const n: usize = @intCast(ty.arrayLen(zcu)); - const constituents = try gpa.alloc(Id, n); - defer gpa.free(constituents); + const scratch_top = cg.id_scratch.items.len; + defer cg.id_scratch.shrinkRetainingCapacity(scratch_top); + + const constituents = try cg.id_scratch.addManyAsSlice(gpa, n); @memset(constituents, constituent); const result_ty_id = try cg.resolveType(ty, .direct); @@ -928,8 +917,9 @@ fn constant(cg: *CodeGen, ty: Type, val: Value, repr: Repr) Error!Id { inline .array_type, .vector_type => |array_type, tag| { const elem_ty: Type = .fromInterned(array_type.child); - const constituents = try gpa.alloc(Id, @intCast(ty.arrayLenIncludingSentinel(zcu))); - defer gpa.free(constituents); + const scratch_top = cg.id_scratch.items.len; + defer cg.id_scratch.shrinkRetainingCapacity(scratch_top); + const constituents = try cg.id_scratch.addManyAsSlice(gpa, @intCast(ty.arrayLenIncludingSentinel(zcu))); const child_repr: Repr = switch (tag) { .array_type => .indirect, @@ -1044,6 +1034,7 @@ fn constantPtr(cg: *CodeGen, ptr_val: Value) !Id { } fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id { + const gpa = cg.module.gpa; const pt = cg.pt; const zcu = cg.module.zcu; switch (derivation) { @@ -1055,7 +1046,7 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id { // as a runtime operation. const result_ptr_id = cg.module.allocId(); const value_id = try cg.constInt(.usize, int.addr); - try cg.body.emit(cg.module.gpa, .OpConvertUToPtr, .{ + try cg.body.emit(gpa, .OpConvertUToPtr, .{ .id_result_type = result_ty_id, .id_result = result_ptr_id, .integer_value = value_id, @@ -1103,7 +1094,7 @@ fn derivePtr(cg: *CodeGen, derivation: Value.PointerDeriveStep) !Id { // Allow changing the pointer type child only to restructure arrays. // e.g. [3][2]T to T is fine, as is [2]T -> [2][1]T. const result_ptr_id = cg.module.allocId(); - try cg.body.emit(cg.module.gpa, .OpBitcast, .{ + try cg.body.emit(gpa, .OpBitcast, .{ .id_result_type = result_ty_id, .id_result = result_ptr_id, .operand = parent_ptr_id, @@ -1191,6 +1182,7 @@ fn constantNavRef(cg: *CodeGen, ty: Type, nav_index: InternPool.Nav.Index) !Id { const spv_decl_index = try cg.module.resolveNav(ip, nav_index); const spv_decl = cg.module.declPtr(spv_decl_index); + const spv_decl_result_id = spv_decl.result_id; assert(spv_decl.kind != .func); const storage_class = cg.module.storageClass(nav.getAddrspace()); @@ -1205,12 +1197,12 @@ fn constantNavRef(cg: *CodeGen, ty: Type, nav_index: InternPool.Nav.Index) !Id { try cg.body.emit(cg.module.gpa, .OpBitcast, .{ .id_result_type = ty_id, .id_result = casted_ptr_id, - .operand = spv_decl.result_id, + .operand = spv_decl_result_id, }); return casted_ptr_id; } - return spv_decl.result_id; + return spv_decl_result_id; } // Turn a Zig type's name into a cache reference. @@ -1430,8 +1422,11 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { } const return_ty_id = try cg.resolveFnReturnType(.fromInterned(fn_info.return_type)); - const param_ty_ids = try gpa.alloc(Id, fn_info.param_types.len); - defer gpa.free(param_ty_ids); + + const scratch_top = cg.id_scratch.items.len; + defer cg.id_scratch.shrinkRetainingCapacity(scratch_top); + const param_ty_ids = try cg.id_scratch.addManyAsSlice(gpa, fn_info.param_types.len); + var param_index: usize = 0; for (fn_info.param_types.get(ip)) |param_ty_index| { const param_ty: Type = .fromInterned(param_ty_index); @@ -1472,8 +1467,9 @@ fn resolveType(cg: *CodeGen, ty: Type, repr: Repr) Error!Id { .@"struct" => { const struct_type = switch (ip.indexToKey(ty.toIntern())) { .tuple_type => |tuple| { - const member_types = try gpa.alloc(Id, tuple.values.len); - defer gpa.free(member_types); + const scratch_top = cg.id_scratch.items.len; + defer cg.id_scratch.shrinkRetainingCapacity(scratch_top); + const member_types = try cg.id_scratch.addManyAsSlice(gpa, tuple.values.len); var member_index: usize = 0; for (tuple.types.get(ip), tuple.values.get(ip)) |field_ty, field_val| { @@ -1755,11 +1751,14 @@ const Temporary = struct { .exploded_vector => |range| { assert(temp.ty.isVector(zcu)); assert(temp.ty.vectorLen(zcu) == range.len); - const constituents = try gpa.alloc(Id, range.len); - defer gpa.free(constituents); + + const scratch_top = cg.id_scratch.items.len; + defer cg.id_scratch.shrinkRetainingCapacity(scratch_top); + const constituents = try cg.id_scratch.addManyAsSlice(gpa, range.len); for (constituents, 0..range.len) |*id, i| { id.* = range.at(i); } + const result_ty_id = try cg.resolveType(temp.ty, .direct); return cg.constructComposite(result_ty_id, constituents); }, @@ -2039,14 +2038,12 @@ fn buildFma(cg: *CodeGen, a: Temporary, b: Temporary, c: Temporary) !Temporary { const op_c = try v.prepare(cg, c); const set = try cg.importExtendedSet(); - - // TODO: Put these numbers in some definition - const instruction: u32 = switch (target.os.tag) { - .opencl => 26, // fma + const opcode: u32 = switch (target.os.tag) { + .opencl => @intFromEnum(spec.OpenClOpcode.fma), // NOTE: Vulkan's FMA instruction does *NOT* produce the right values! - // its precision guarantees do NOT match zigs and it does NOT match OpenCLs! - // it needs to be emulated! - .vulkan, .opengl => return cg.todo("implement fma operation for {s} os", .{@tagName(target.os.tag)}), + // its precision guarantees do NOT match zigs and it does NOT match OpenCLs! + // it needs to be emulated! + .vulkan, .opengl => @intFromEnum(spec.GlslOpcode.Fma), else => unreachable, }; @@ -2055,7 +2052,7 @@ fn buildFma(cg: *CodeGen, a: Temporary, b: Temporary, c: Temporary) !Temporary { .id_result_type = op_result_ty_id, .id_result = results.at(i), .set = set, - .instruction = .{ .inst = instruction }, + .instruction = .{ .inst = opcode }, .id_ref_4 = &.{ op_a.at(i), op_b.at(i), op_c.at(i) }, }); } @@ -2138,6 +2135,44 @@ const UnaryOp = enum { log, log2, log10, + + pub fn extInstOpcode(op: UnaryOp, target: *const std.Target) ?u32 { + return switch (target.os.tag) { + .opencl => @intFromEnum(@as(spec.OpenClOpcode, switch (op) { + .i_abs => .s_abs, + .f_abs => .fabs, + .clz => .clz, + .ctz => .ctz, + .floor => .floor, + .ceil => .ceil, + .trunc => .trunc, + .round => .round, + .sqrt => .sqrt, + .sin => .sin, + .cos => .cos, + .tan => .tan, + .exp => .exp, + .exp2 => .exp2, + .log => .log, + .log2 => .log2, + .log10 => .log10, + else => return null, + })), + // Note: We'll need to check these for floating point accuracy + // Vulkan does not put tight requirements on these, for correction + // we might want to emulate them at some point. + .vulkan, .opengl => @intFromEnum(@as(spec.GlslOpcode, switch (op) { + .i_abs => .SAbs, + .f_abs => .FAbs, + .floor => .Floor, + .ceil => .Ceil, + .trunc => .Trunc, + .round => .Round, + else => return null, + })), + else => unreachable, + }; + } }; fn buildUnary(cg: *CodeGen, op: UnaryOp, operand: Temporary) !Temporary { @@ -2149,84 +2184,36 @@ fn buildUnary(cg: *CodeGen, op: UnaryOp, operand: Temporary) !Temporary { const op_result_ty = operand.ty.scalarType(zcu); const op_result_ty_id = try cg.resolveType(op_result_ty, .direct); const result_ty = try v.resultType(cg, operand.ty); - const op_operand = try v.prepare(cg, operand); - if (switch (op) { - .l_not => .OpLogicalNot, - .bit_not => .OpNot, - .i_neg => .OpSNegate, - .f_neg => .OpFNegate, - else => @as(?Opcode, null), - }) |opcode| { - for (0..ops) |i| { - try cg.body.emitRaw(cg.module.gpa, opcode, 3); - cg.body.writeOperand(Id, op_result_ty_id); - cg.body.writeOperand(Id, results.at(i)); - cg.body.writeOperand(Id, op_operand.at(i)); - } - } else { + if (op.extInstOpcode(target)) |opcode| { const set = try cg.importExtendedSet(); - const extinst: u32 = switch (target.os.tag) { - .opencl => switch (op) { - .i_abs => 141, // s_abs - .f_abs => 23, // fabs - .clz => 151, // clz - .ctz => 152, // ctz - .floor => 25, // floor - .ceil => 12, // ceil - .trunc => 66, // trunc - .round => 55, // round - .sqrt => 61, // sqrt - .sin => 57, // sin - .cos => 14, // cos - .tan => 62, // tan - .exp => 19, // exp - .exp2 => 20, // exp2 - .log => 37, // log - .log2 => 38, // log2 - .log10 => 39, // log10 - else => unreachable, - }, - // Note: We'll need to check these for floating point accuracy - // Vulkan does not put tight requirements on these, for correction - // we might want to emulate them at some point. - .vulkan, .opengl => switch (op) { - .i_abs => 5, // SAbs - .f_abs => 4, // FAbs - .floor => 8, // Floor - .ceil => 9, // Ceil - .trunc => 3, // Trunc - .round => 1, // Round - .clz, - .ctz, - .sqrt, - .sin, - .cos, - .tan, - .exp, - .exp2, - .log, - .log2, - .log10, - => return cg.todo( - "implement unary operation '{s}' for {s} os", - .{ @tagName(op), @tagName(target.os.tag) }, - ), - else => unreachable, - }, - else => unreachable, - }; - for (0..ops) |i| { try cg.body.emit(cg.module.gpa, .OpExtInst, .{ .id_result_type = op_result_ty_id, .id_result = results.at(i), .set = set, - .instruction = .{ .inst = extinst }, + .instruction = .{ .inst = opcode }, .id_ref_4 = &.{op_operand.at(i)}, }); } + } else { + const opcode: Opcode = switch (op) { + .l_not => .OpLogicalNot, + .bit_not => .OpNot, + .i_neg => .OpSNegate, + .f_neg => .OpFNegate, + else => return cg.todo( + "implement unary operation '{s}' for {s} os", + .{ @tagName(op), @tagName(target.os.tag) }, + ), + }; + for (0..ops) |i| { + try cg.body.emitRaw(cg.module.gpa, opcode, 3); + cg.body.writeOperand(Id, op_result_ty_id); + cg.body.writeOperand(Id, results.at(i)); + cg.body.writeOperand(Id, op_operand.at(i)); + } } return v.finalize(result_ty, results); @@ -2288,9 +2275,9 @@ fn buildWideMul( // OpUMulExtended. For these we will use the OpenCL s_mul_hi to compute the high-order bits // instead. const set = try cg.importExtendedSet(); - const overflow_inst: u32 = switch (signedness) { - .signed => 160, // s_mul_hi - .unsigned => 203, // u_mul_hi + const overflow_inst: spec.OpenClOpcode = switch (signedness) { + .signed => .s_mul_hi, + .unsigned => .u_mul_hi, }; for (0..ops) |i| { @@ -2305,7 +2292,7 @@ fn buildWideMul( .id_result_type = arith_op_ty_id, .id_result = overflow_results.at(i), .set = set, - .instruction = .{ .inst = overflow_inst }, + .instruction = .{ .inst = @intFromEnum(overflow_inst) }, .id_ref_4 = &.{ lhs_op.at(i), rhs_op.at(i) }, }); } @@ -2428,7 +2415,7 @@ fn generateTestEntryPoint( .vulkan, .opengl => { if (cg.module.error_buffer == null) { const spv_err_decl_index = try cg.module.allocDecl(.global); - try cg.module.declareDeclDeps(spv_err_decl_index, &.{}); + const err_buf_result_id = cg.module.declPtr(spv_err_decl_index).result_id; const buffer_struct_ty_id = try cg.module.structType( &.{anyerror_ty_id}, @@ -2446,14 +2433,13 @@ fn generateTestEntryPoint( .type = buffer_struct_ty_id, }); - const buffer_struct_id = cg.module.declPtr(spv_err_decl_index).result_id; try cg.module.sections.globals.emit(gpa, .OpVariable, .{ .id_result_type = ptr_buffer_struct_ty_id, - .id_result = buffer_struct_id, + .id_result = err_buf_result_id, .storage_class = cg.module.storageClass(.global), }); - try cg.module.decorate(buffer_struct_id, .{ .descriptor_set = .{ .descriptor_set = 0 } }); - try cg.module.decorate(buffer_struct_id, .{ .binding = .{ .binding_point = 0 } }); + try cg.module.decorate(err_buf_result_id, .{ .descriptor_set = .{ .descriptor_set = 0 } }); + try cg.module.decorate(err_buf_result_id, .{ .binding = .{ .binding_point = 0 } }); cg.module.error_buffer = spv_err_decl_index; } @@ -2481,7 +2467,7 @@ fn generateTestEntryPoint( const spv_err_decl_index = cg.module.error_buffer.?; const buffer_id = cg.module.declPtr(spv_err_decl_index).result_id; - try cg.decl_deps.put(gpa, spv_err_decl_index, {}); + try cg.module.decl_deps.append(gpa, spv_err_decl_index); const zero_id = try cg.constInt(.u32, 0); try section.emit(gpa, .OpInBoundsAccessChain, .{ @@ -2867,7 +2853,54 @@ fn airShift(cg: *CodeGen, inst: Air.Inst.Index, unsigned: Opcode, signed: Opcode return try result.materialize(cg); } -const MinMax = enum { min, max }; +const MinMax = enum { + min, + max, + + pub fn extInstOpcode( + op: MinMax, + target: *const std.Target, + info: ArithmeticTypeInfo, + ) u32 { + return switch (target.os.tag) { + .opencl => @intFromEnum(@as(spec.OpenClOpcode, switch (info.class) { + .float => switch (op) { + .min => .fmin, + .max => .fmax, + }, + .integer, .strange_integer, .composite_integer => switch (info.signedness) { + .signed => switch (op) { + .min => .s_min, + .max => .s_max, + }, + .unsigned => switch (op) { + .min => .u_min, + .max => .u_max, + }, + }, + .bool => unreachable, + })), + .vulkan, .opengl => @intFromEnum(@as(spec.GlslOpcode, switch (info.class) { + .float => switch (op) { + .min => .FMin, + .max => .FMax, + }, + .integer, .strange_integer, .composite_integer => switch (info.signedness) { + .signed => switch (op) { + .min => .SMin, + .max => .SMax, + }, + .unsigned => switch (op) { + .min => .UMin, + .max => .UMax, + }, + }, + .bool => unreachable, + })), + else => unreachable, + }; + } +}; fn airMinMax(cg: *CodeGen, inst: Air.Inst.Index, op: MinMax) !?Id { const bin_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; @@ -2895,57 +2928,14 @@ fn minMax(cg: *CodeGen, lhs: Temporary, rhs: Temporary, op: MinMax) !Temporary { const op_lhs = try v.prepare(cg, lhs); const op_rhs = try v.prepare(cg, rhs); - const ext_inst: u32 = switch (target.os.tag) { - .opencl => switch (info.class) { - .float => switch (op) { - .min => 28, // fmin - .max => 27, // fmax - }, - .integer, - .strange_integer, - .composite_integer, - => switch (info.signedness) { - .signed => switch (op) { - .min => 158, // s_min - .max => 156, // s_max - }, - .unsigned => switch (op) { - .min => 159, // u_min - .max => 157, // u_max - }, - }, - .bool => unreachable, - }, - .vulkan, .opengl => switch (info.class) { - .float => switch (op) { - .min => 37, // FMin - .max => 40, // FMax - }, - .integer, - .strange_integer, - .composite_integer, - => switch (info.signedness) { - .signed => switch (op) { - .min => 39, // SMin - .max => 42, // SMax - }, - .unsigned => switch (op) { - .min => 38, // UMin - .max => 41, // UMax - }, - }, - .bool => unreachable, - }, - else => unreachable, - }; - const set = try cg.importExtendedSet(); + const opcode = op.extInstOpcode(target, info); for (0..ops) |i| { try cg.body.emit(cg.module.gpa, .OpExtInst, .{ .id_result_type = op_result_ty_id, .id_result = results.at(i), .set = set, - .instruction = .{ .inst = ext_inst }, + .instruction = .{ .inst = opcode }, .id_ref_4 = &.{ op_lhs.at(i), op_rhs.at(i) }, }); } @@ -3562,8 +3552,9 @@ fn airShuffleOne(cg: *CodeGen, inst: Air.Inst.Index) !?Id { const elem_ty = result_ty.childType(zcu); const operand = try cg.resolve(unwrapped.operand); - const constituents = try gpa.alloc(Id, mask.len); - defer gpa.free(constituents); + const scratch_top = cg.id_scratch.items.len; + defer cg.id_scratch.shrinkRetainingCapacity(scratch_top); + const constituents = try cg.id_scratch.addManyAsSlice(gpa, mask.len); for (constituents, mask) |*id, mask_elem| { id.* = switch (mask_elem.unwrap()) { @@ -3588,8 +3579,9 @@ fn airShuffleTwo(cg: *CodeGen, inst: Air.Inst.Index) !?Id { const operand_a = try cg.resolve(unwrapped.operand_a); const operand_b = try cg.resolve(unwrapped.operand_b); - const constituents = try gpa.alloc(Id, mask.len); - defer gpa.free(constituents); + const scratch_top = cg.id_scratch.items.len; + defer cg.id_scratch.shrinkRetainingCapacity(scratch_top); + const constituents = try cg.id_scratch.addManyAsSlice(gpa, mask.len); for (constituents, mask) |*id, mask_elem| { id.* = switch (mask_elem.unwrap()) { @@ -3603,17 +3595,6 @@ fn airShuffleTwo(cg: *CodeGen, inst: Air.Inst.Index) !?Id { return try cg.constructComposite(result_ty_id, constituents); } -fn indicesToIds(cg: *CodeGen, indices: []const u32) ![]Id { - const gpa = cg.module.gpa; - const ids = try gpa.alloc(Id, indices.len); - errdefer gpa.free(ids); - for (indices, ids) |index, *id| { - id.* = try cg.constInt(.u32, index); - } - - return ids; -} - fn accessChainId( cg: *CodeGen, result_ty_id: Id, @@ -3641,8 +3622,12 @@ fn accessChain( indices: []const u32, ) !Id { const gpa = cg.module.gpa; - const ids = try cg.indicesToIds(indices); - defer gpa.free(ids); + const scratch_top = cg.id_scratch.items.len; + defer cg.id_scratch.shrinkRetainingCapacity(scratch_top); + const ids = try cg.id_scratch.addManyAsSlice(gpa, indices.len); + for (indices, ids) |index, *id| { + id.* = try cg.constInt(.u32, index); + } return try cg.accessChainId(result_ty_id, base, ids); } @@ -3655,13 +3640,18 @@ fn ptrAccessChain( ) !Id { const gpa = cg.module.gpa; const target = cg.module.zcu.getTarget(); - const ids = try cg.indicesToIds(indices); - defer gpa.free(ids); + + const scratch_top = cg.id_scratch.items.len; + defer cg.id_scratch.shrinkRetainingCapacity(scratch_top); + const ids = try cg.id_scratch.addManyAsSlice(gpa, indices.len); + for (indices, ids) |index, *id| { + id.* = try cg.constInt(.u32, index); + } const result_id = cg.module.allocId(); switch (target.os.tag) { .opencl, .amdhsa => { - try cg.body.emit(cg.module.gpa, .OpInBoundsPtrAccessChain, .{ + try cg.body.emit(gpa, .OpInBoundsPtrAccessChain, .{ .id_result_type = result_ty_id, .id_result = result_id, .base = base, @@ -3669,8 +3659,8 @@ fn ptrAccessChain( .indexes = ids, }); }, - else => { - try cg.body.emit(cg.module.gpa, .OpPtrAccessChain, .{ + .vulkan, .opengl => { + try cg.body.emit(gpa, .OpPtrAccessChain, .{ .id_result_type = result_ty_id, .id_result = result_id, .base = base, @@ -3678,6 +3668,7 @@ fn ptrAccessChain( .indexes = ids, }); }, + else => unreachable, } return result_id; } @@ -3739,6 +3730,7 @@ fn cmp( lhs: Temporary, rhs: Temporary, ) !Temporary { + const gpa = cg.module.gpa; const pt = cg.pt; const zcu = cg.module.zcu; const ip = &zcu.intern_pool; @@ -3771,14 +3763,14 @@ fn cmp( const usize_ty_id = try cg.resolveType(.usize, .direct); const lhs_int_id = cg.module.allocId(); - try cg.body.emit(cg.module.gpa, .OpConvertPtrToU, .{ + try cg.body.emit(gpa, .OpConvertPtrToU, .{ .id_result_type = usize_ty_id, .id_result = lhs_int_id, .pointer = try lhs.materialize(cg), }); const rhs_int_id = cg.module.allocId(); - try cg.body.emit(cg.module.gpa, .OpConvertPtrToU, .{ + try cg.body.emit(gpa, .OpConvertPtrToU, .{ .id_result_type = usize_ty_id, .id_result = rhs_int_id, .pointer = try rhs.materialize(cg), @@ -3937,6 +3929,7 @@ fn bitCast( src_ty: Type, src_id: Id, ) !Id { + const gpa = cg.module.gpa; const zcu = cg.module.zcu; const src_ty_id = try cg.resolveType(src_ty, .direct); const dst_ty_id = try cg.resolveType(dst_ty, .direct); @@ -3949,7 +3942,7 @@ fn bitCast( if (src_ty.zigTypeTag(zcu) == .int and dst_ty.isPtrAtRuntime(zcu)) { const result_id = cg.module.allocId(); - try cg.body.emit(cg.module.gpa, .OpConvertUToPtr, .{ + try cg.body.emit(gpa, .OpConvertUToPtr, .{ .id_result_type = dst_ty_id, .id_result = result_id, .integer_value = src_id, @@ -3963,7 +3956,7 @@ fn bitCast( const can_bitcast = (src_ty.isNumeric(zcu) and dst_ty.isNumeric(zcu)) or (src_ty.isPtrAtRuntime(zcu) and dst_ty.isPtrAtRuntime(zcu)); if (can_bitcast) { const result_id = cg.module.allocId(); - try cg.body.emit(cg.module.gpa, .OpBitcast, .{ + try cg.body.emit(gpa, .OpBitcast, .{ .id_result_type = dst_ty_id, .id_result = result_id, .operand = src_id, @@ -3977,7 +3970,7 @@ fn bitCast( const tmp_id = try cg.alloc(src_ty, .{ .storage_class = .function }); try cg.store(src_ty, tmp_id, src_id, .{}); const casted_ptr_id = cg.module.allocId(); - try cg.body.emit(cg.module.gpa, .OpBitcast, .{ + try cg.body.emit(gpa, .OpBitcast, .{ .id_result_type = dst_ptr_ty_id, .id_result = casted_ptr_id, .operand = tmp_id, @@ -4057,16 +4050,17 @@ fn airFloatFromInt(cg: *CodeGen, inst: Air.Inst.Index) !?Id { } fn floatFromInt(cg: *CodeGen, result_ty: Type, operand_ty: Type, operand_id: Id) !Id { + const gpa = cg.module.gpa; const operand_info = cg.arithmeticTypeInfo(operand_ty); const result_id = cg.module.allocId(); const result_ty_id = try cg.resolveType(result_ty, .direct); switch (operand_info.signedness) { - .signed => try cg.body.emit(cg.module.gpa, .OpConvertSToF, .{ + .signed => try cg.body.emit(gpa, .OpConvertSToF, .{ .id_result_type = result_ty_id, .id_result = result_id, .signed_value = operand_id, }), - .unsigned => try cg.body.emit(cg.module.gpa, .OpConvertUToF, .{ + .unsigned => try cg.body.emit(gpa, .OpConvertUToF, .{ .id_result_type = result_ty_id, .id_result = result_id, .unsigned_value = operand_id, @@ -4083,16 +4077,17 @@ fn airIntFromFloat(cg: *CodeGen, inst: Air.Inst.Index) !?Id { } fn intFromFloat(cg: *CodeGen, result_ty: Type, operand_id: Id) !Id { + const gpa = cg.module.gpa; const result_info = cg.arithmeticTypeInfo(result_ty); const result_ty_id = try cg.resolveType(result_ty, .direct); const result_id = cg.module.allocId(); switch (result_info.signedness) { - .signed => try cg.body.emit(cg.module.gpa, .OpConvertFToS, .{ + .signed => try cg.body.emit(gpa, .OpConvertFToS, .{ .id_result_type = result_ty_id, .id_result = result_id, .float_value = operand_id, }), - .unsigned => try cg.body.emit(cg.module.gpa, .OpConvertFToU, .{ + .unsigned => try cg.body.emit(gpa, .OpConvertFToU, .{ .id_result_type = result_ty_id, .id_result = result_id, .float_value = operand_id, @@ -4214,10 +4209,13 @@ fn airAggregateInit(cg: *CodeGen, inst: Air.Inst.Index) !?Id { return running_int_id; } + const scratch_top = cg.id_scratch.items.len; + defer cg.id_scratch.shrinkRetainingCapacity(scratch_top); + const constituents = try cg.id_scratch.addManyAsSlice(gpa, elements.len); + const types = try gpa.alloc(Type, elements.len); defer gpa.free(types); - const constituents = try gpa.alloc(Id, elements.len); - defer gpa.free(constituents); + var index: usize = 0; switch (ip.indexToKey(result_ty.toIntern())) { @@ -4255,8 +4253,9 @@ fn airAggregateInit(cg: *CodeGen, inst: Air.Inst.Index) !?Id { }, .vector => { const n_elems = result_ty.vectorLen(zcu); - const elem_ids = try gpa.alloc(Id, n_elems); - defer gpa.free(elem_ids); + const scratch_top = cg.id_scratch.items.len; + defer cg.id_scratch.shrinkRetainingCapacity(scratch_top); + const elem_ids = try cg.id_scratch.addManyAsSlice(gpa, n_elems); for (elements, 0..) |element, i| { elem_ids[i] = try cg.resolve(element); @@ -4268,8 +4267,9 @@ fn airAggregateInit(cg: *CodeGen, inst: Air.Inst.Index) !?Id { .array => { const array_info = result_ty.arrayInfo(zcu); const n_elems: usize = @intCast(result_ty.arrayLenIncludingSentinel(zcu)); - const elem_ids = try gpa.alloc(Id, n_elems); - defer gpa.free(elem_ids); + const scratch_top = cg.id_scratch.items.len; + defer cg.id_scratch.shrinkRetainingCapacity(scratch_top); + const elem_ids = try cg.id_scratch.addManyAsSlice(gpa, n_elems); for (elements, 0..) |element, i| { const id = try cg.resolve(element); @@ -4407,6 +4407,7 @@ fn airPtrElemPtr(cg: *CodeGen, inst: Air.Inst.Index) !?Id { } fn airArrayElemVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id { + const gpa = cg.module.gpa; const zcu = cg.module.zcu; const bin_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; const array_ty = cg.typeOf(bin_op.lhs); @@ -4427,13 +4428,13 @@ fn airArrayElemVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id { const ptr_elem_ty_id = try cg.module.ptrType(elem_ty_id, .function); const tmp_id = cg.module.allocId(); - try cg.prologue.emit(cg.module.gpa, .OpVariable, .{ + try cg.prologue.emit(gpa, .OpVariable, .{ .id_result_type = ptr_array_ty_id, .id_result = tmp_id, .storage_class = .function, }); - try cg.body.emit(cg.module.gpa, .OpStore, .{ + try cg.body.emit(gpa, .OpStore, .{ .pointer = tmp_id, .object = array_id, }); @@ -4441,7 +4442,7 @@ fn airArrayElemVal(cg: *CodeGen, inst: Air.Inst.Index) !?Id { const elem_ptr_id = try cg.accessChainId(ptr_elem_ty_id, tmp_id, &.{index_id}); const result_id = cg.module.allocId(); - try cg.body.emit(cg.module.gpa, .OpLoad, .{ + try cg.body.emit(gpa, .OpLoad, .{ .id_result_type = try cg.resolveType(elem_ty, elem_repr), .id_result = result_id, .pointer = elem_ptr_id, @@ -4914,7 +4915,7 @@ fn structuredBreak(cg: *CodeGen, target_block: Id) !void { .loop => unreachable, }; - try cg.body.emitBranch(cg.module.gpa, merge_block); + try cg.body.emit(gpa, .OpBranch, .{ .target_label = merge_block }); } /// Generate a body in a way that exits the body using only structured constructs. @@ -4997,7 +4998,8 @@ fn genStructuredBody( while (i > 0) { i -= 1; const step = merge_stack[i]; - try cg.body.emitBranch(cg.module.gpa, step.merge_block); + + try cg.body.emit(gpa, .OpBranch, .{ .target_label = step.merge_block }); try cg.beginSpvBlock(step.merge_block); const next_block = try cg.structuredNextBlock(&.{ incoming, step.incoming }); incoming = .{ @@ -5010,7 +5012,8 @@ fn genStructuredBody( }, .loop => |merge| { // Close the loop by jumping to the continue label - try cg.body.emitBranch(cg.module.gpa, block_merge_type.loop.continue_label); + + try cg.body.emit(gpa, .OpBranch, .{ .target_label = block_merge_type.loop.continue_label }); // For blocks we must simple merge all the incoming blocks to get the next block. try cg.beginSpvBlock(merge.merge_block); return try cg.structuredNextBlock(merge.merges.items); @@ -5064,7 +5067,7 @@ fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index) const result_type_id = try cg.resolveType(ty, .direct); try cg.body.emitRaw( - cg.module.gpa, + gpa, .OpPhi, // result type + result + variable/parent... 2 + @as(u16, @intCast(block.incoming_blocks.items.len * 2)), @@ -5100,7 +5103,7 @@ fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index) const this_block = try cg.constInt(.u32, @intFromEnum(inst)); const jump_to_this_block_id = cg.module.allocId(); const bool_ty_id = try cg.resolveType(.bool, .direct); - try cg.body.emit(cg.module.gpa, .OpIEqual, .{ + try cg.body.emit(gpa, .OpIEqual, .{ .id_result_type = bool_ty_id, .id_result = jump_to_this_block_id, .operand_1 = next_block, @@ -5120,11 +5123,11 @@ fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index) // generate a conditional branch to there and to the instructions following this block. const merge_label = cg.module.allocId(); const then_label = cg.module.allocId(); - try cg.body.emit(cg.module.gpa, .OpSelectionMerge, .{ + try cg.body.emit(gpa, .OpSelectionMerge, .{ .merge_block = merge_label, .selection_control = .{}, }); - try cg.body.emit(cg.module.gpa, .OpBranchConditional, .{ + try cg.body.emit(gpa, .OpBranchConditional, .{ .condition = jump_to_this_block_id, .true_label = then_label, .false_label = merge_label, @@ -5143,7 +5146,7 @@ fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index) // To jump out of a loop block, generate a conditional that exits the block // to the loop merge if the target ID is not the one of this block. const continue_label = cg.module.allocId(); - try cg.body.emit(cg.module.gpa, .OpBranchConditional, .{ + try cg.body.emit(gpa, .OpBranchConditional, .{ .condition = jump_to_this_block_id, .true_label = continue_label, .false_label = merge.merge_block, @@ -5197,12 +5200,13 @@ fn airBr(cg: *CodeGen, inst: Air.Inst.Index) !void { block.label = cg.module.allocId(); } - try cg.body.emitBranch(cg.module.gpa, block.label.?); + try cg.body.emit(gpa, .OpBranch, .{ .target_label = block.label.? }); }, } } fn airCondBr(cg: *CodeGen, inst: Air.Inst.Index) !void { + const gpa = cg.module.gpa; const pl_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; const cond_br = cg.air.extraData(Air.CondBr, pl_op.payload); const then_body: []const Air.Inst.Index = @ptrCast(cg.air.extra.items[cond_br.end..][0..cond_br.data.then_body_len]); @@ -5216,11 +5220,11 @@ fn airCondBr(cg: *CodeGen, inst: Air.Inst.Index) !void { .structured => { const merge_label = cg.module.allocId(); - try cg.body.emit(cg.module.gpa, .OpSelectionMerge, .{ + try cg.body.emit(gpa, .OpSelectionMerge, .{ .merge_block = merge_label, .selection_control = .{}, }); - try cg.body.emit(cg.module.gpa, .OpBranchConditional, .{ + try cg.body.emit(gpa, .OpBranchConditional, .{ .condition = condition_id, .true_label = then_label, .false_label = else_label, @@ -5232,7 +5236,8 @@ fn airCondBr(cg: *CodeGen, inst: Air.Inst.Index) !void { .src_label = cg.block_label, .next_block = then_next, }; - try cg.body.emitBranch(cg.module.gpa, merge_label); + + try cg.body.emit(gpa, .OpBranch, .{ .target_label = merge_label }); try cg.beginSpvBlock(else_label); const else_next = try cg.genStructuredBody(.selection, else_body); @@ -5240,7 +5245,8 @@ fn airCondBr(cg: *CodeGen, inst: Air.Inst.Index) !void { .src_label = cg.block_label, .next_block = else_next, }; - try cg.body.emitBranch(cg.module.gpa, merge_label); + + try cg.body.emit(gpa, .OpBranch, .{ .target_label = merge_label }); try cg.beginSpvBlock(merge_label); const next_block = try cg.structuredNextBlock(&.{ then_incoming, else_incoming }); @@ -5248,7 +5254,7 @@ fn airCondBr(cg: *CodeGen, inst: Air.Inst.Index) !void { try cg.structuredBreak(next_block); }, .unstructured => { - try cg.body.emit(cg.module.gpa, .OpBranchConditional, .{ + try cg.body.emit(gpa, .OpBranchConditional, .{ .condition = condition_id, .true_label = then_label, .false_label = else_label, @@ -5263,6 +5269,7 @@ fn airCondBr(cg: *CodeGen, inst: Air.Inst.Index) !void { } fn airLoop(cg: *CodeGen, inst: Air.Inst.Index) !void { + const gpa = cg.module.gpa; const ty_pl = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl; const loop = cg.air.extraData(Air.Block, ty_pl.payload); const body: []const Air.Inst.Index = @ptrCast(cg.air.extra.items[loop.end..][0..loop.data.body_len]); @@ -5278,16 +5285,18 @@ fn airLoop(cg: *CodeGen, inst: Air.Inst.Index) !void { // The back-edge must point to the loop header, so generate a separate block for the // loop header so that we don't accidentally include some instructions from there // in the loop. - try cg.body.emitBranch(cg.module.gpa, header_label); + + try cg.body.emit(gpa, .OpBranch, .{ .target_label = header_label }); try cg.beginSpvBlock(header_label); // Emit loop header and jump to loop body - try cg.body.emit(cg.module.gpa, .OpLoopMerge, .{ + try cg.body.emit(gpa, .OpLoopMerge, .{ .merge_block = merge_label, .continue_target = continue_label, .loop_control = .{}, }); - try cg.body.emitBranch(cg.module.gpa, body_label); + + try cg.body.emit(gpa, .OpBranch, .{ .target_label = body_label }); try cg.beginSpvBlock(body_label); @@ -5298,13 +5307,15 @@ fn airLoop(cg: *CodeGen, inst: Air.Inst.Index) !void { try cg.structuredBreak(next_block); try cg.beginSpvBlock(continue_label); - try cg.body.emitBranch(cg.module.gpa, header_label); + + try cg.body.emit(gpa, .OpBranch, .{ .target_label = header_label }); }, .unstructured => { - try cg.body.emitBranch(cg.module.gpa, body_label); + try cg.body.emit(gpa, .OpBranch, .{ .target_label = body_label }); try cg.beginSpvBlock(body_label); try cg.genBody(body); - try cg.body.emitBranch(cg.module.gpa, body_label); + + try cg.body.emit(gpa, .OpBranch, .{ .target_label = body_label }); }, } } @@ -5332,6 +5343,7 @@ fn airStore(cg: *CodeGen, inst: Air.Inst.Index) !void { } fn airRet(cg: *CodeGen, inst: Air.Inst.Index) !void { + const gpa = cg.module.gpa; const zcu = cg.module.zcu; const operand = cg.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const ret_ty = cg.typeOf(operand); @@ -5342,17 +5354,18 @@ fn airRet(cg: *CodeGen, inst: Air.Inst.Index) !void { // return type and return zero so they can be function pointers coerced // to functions that return anyerror. const no_err_id = try cg.constInt(.anyerror, 0); - return try cg.body.emit(cg.module.gpa, .OpReturnValue, .{ .value = no_err_id }); + return try cg.body.emit(gpa, .OpReturnValue, .{ .value = no_err_id }); } else { - return try cg.body.emit(cg.module.gpa, .OpReturn, {}); + return try cg.body.emit(gpa, .OpReturn, {}); } } const operand_id = try cg.resolve(operand); - try cg.body.emit(cg.module.gpa, .OpReturnValue, .{ .value = operand_id }); + try cg.body.emit(gpa, .OpReturnValue, .{ .value = operand_id }); } fn airRetLoad(cg: *CodeGen, inst: Air.Inst.Index) !void { + const gpa = cg.module.gpa; const zcu = cg.module.zcu; const un_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].un_op; const ptr_ty = cg.typeOf(un_op); @@ -5365,20 +5378,21 @@ fn airRetLoad(cg: *CodeGen, inst: Air.Inst.Index) !void { // return type and return zero so they can be function pointers coerced // to functions that return anyerror. const no_err_id = try cg.constInt(.anyerror, 0); - return try cg.body.emit(cg.module.gpa, .OpReturnValue, .{ .value = no_err_id }); + return try cg.body.emit(gpa, .OpReturnValue, .{ .value = no_err_id }); } else { - return try cg.body.emit(cg.module.gpa, .OpReturn, {}); + return try cg.body.emit(gpa, .OpReturn, {}); } } const ptr = try cg.resolve(un_op); const value = try cg.load(ret_ty, ptr, .{ .is_volatile = ptr_ty.isVolatilePtr(zcu) }); - try cg.body.emit(cg.module.gpa, .OpReturnValue, .{ + try cg.body.emit(gpa, .OpReturnValue, .{ .value = value, }); } fn airTry(cg: *CodeGen, inst: Air.Inst.Index) !?Id { + const gpa = cg.module.gpa; const zcu = cg.module.zcu; const pl_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].pl_op; const err_union_id = try cg.resolve(pl_op.operand); @@ -5400,7 +5414,7 @@ fn airTry(cg: *CodeGen, inst: Air.Inst.Index) !?Id { const zero_id = try cg.constInt(.anyerror, 0); const is_err_id = cg.module.allocId(); - try cg.body.emit(cg.module.gpa, .OpINotEqual, .{ + try cg.body.emit(gpa, .OpINotEqual, .{ .id_result_type = bool_ty_id, .id_result = is_err_id, .operand_1 = err_id, @@ -5420,7 +5434,7 @@ fn airTry(cg: *CodeGen, inst: Air.Inst.Index) !?Id { // to not break and end in a return instruction. Thus, // for structured control flow, we can just naively use // the ok block as the merge block here. - try cg.body.emit(cg.module.gpa, .OpSelectionMerge, .{ + try cg.body.emit(gpa, .OpSelectionMerge, .{ .merge_block = ok_block, .selection_control = .{}, }); @@ -5428,7 +5442,7 @@ fn airTry(cg: *CodeGen, inst: Air.Inst.Index) !?Id { .unstructured => {}, } - try cg.body.emit(cg.module.gpa, .OpBranchConditional, .{ + try cg.body.emit(gpa, .OpBranchConditional, .{ .condition = is_err_id, .true_label = err_block, .false_label = ok_block, @@ -5768,14 +5782,14 @@ fn airSwitchBr(cg: *CodeGen, inst: Air.Inst.Index) !void { }; if (cg.control_flow == .structured) { - try cg.body.emit(cg.module.gpa, .OpSelectionMerge, .{ + try cg.body.emit(gpa, .OpSelectionMerge, .{ .merge_block = merge_label.?, .selection_control = .{}, }); } // Emit the instruction before generating the blocks. - try cg.body.emitRaw(cg.module.gpa, .OpSwitch, 2 + (cond_words + 1) * num_conditions); + try cg.body.emitRaw(gpa, .OpSwitch, 2 + (cond_words + 1) * num_conditions); cg.body.writeOperand(Id, cond_indirect); cg.body.writeOperand(Id, default); @@ -5830,7 +5844,8 @@ fn airSwitchBr(cg: *CodeGen, inst: Air.Inst.Index) !void { .src_label = cg.block_label, .next_block = next_block, }); - try cg.body.emitBranch(cg.module.gpa, merge_label.?); + + try cg.body.emit(gpa, .OpBranch, .{ .target_label = merge_label.? }); }, .unstructured => { try cg.genBody(case.body); @@ -5848,14 +5863,15 @@ fn airSwitchBr(cg: *CodeGen, inst: Air.Inst.Index) !void { .src_label = cg.block_label, .next_block = next_block, }); - try cg.body.emitBranch(cg.module.gpa, merge_label.?); + + try cg.body.emit(gpa, .OpBranch, .{ .target_label = merge_label.? }); }, .unstructured => { try cg.genBody(else_body); }, } } else { - try cg.body.emit(cg.module.gpa, .OpUnreachable, {}); + try cg.body.emit(gpa, .OpUnreachable, {}); } if (cg.control_flow == .structured) { @@ -5921,8 +5937,8 @@ fn airAssembly(cg: *CodeGen, inst: Air.Inst.Index) !?Id { return cg.todo("implement inline asm with more than 1 output", .{}); } - var as: Assembler = .{ .cg = cg }; - defer as.deinit(); + var ass: Assembler = .{ .cg = cg }; + defer ass.deinit(); var output_extra_i = extra_i; for (outputs) |output| { @@ -5974,8 +5990,8 @@ fn airAssembly(cg: *CodeGen, inst: Air.Inst.Index) !?Id { .undef => return cg.fail("assembly input with 'c' constraint cannot be undefined", .{}), - .int => try as.value_map.put(gpa, name, .{ .constant = @intCast(val.toUnsignedInt(zcu)) }), - .enum_literal => |str| try as.value_map.put(gpa, name, .{ .string = str.toSlice(ip) }), + .int => try ass.value_map.put(gpa, name, .{ .constant = @intCast(val.toUnsignedInt(zcu)) }), + .enum_literal => |str| try ass.value_map.put(gpa, name, .{ .string = str.toSlice(ip) }), else => unreachable, // TODO } @@ -5986,10 +6002,10 @@ fn airAssembly(cg: *CodeGen, inst: Air.Inst.Index) !?Id { // That's fine for now, just make sure to resolve it as such. const val = (try cg.air.value(input, cg.pt)).?; const ty_id = try cg.resolveType(val.toType(), .direct); - try as.value_map.put(gpa, name, .{ .ty = ty_id }); + try ass.value_map.put(gpa, name, .{ .ty = ty_id }); } else { const ty_id = try cg.resolveType(input_ty, .direct); - try as.value_map.put(gpa, name, .{ .ty = ty_id }); + try ass.value_map.put(gpa, name, .{ .ty = ty_id }); } } else { if (input_ty.zigTypeTag(zcu) == .type) { @@ -5997,7 +6013,7 @@ fn airAssembly(cg: *CodeGen, inst: Air.Inst.Index) !?Id { } const val_id = try cg.resolve(input); - try as.value_map.put(gpa, name, .{ .value = val_id }); + try ass.value_map.put(gpa, name, .{ .value = val_id }); } } @@ -6006,17 +6022,17 @@ fn airAssembly(cg: *CodeGen, inst: Air.Inst.Index) !?Id { const asm_source = std.mem.sliceAsBytes(cg.air.extra.items[extra_i..])[0..extra.data.source_len]; - as.assemble(asm_source) catch |err| switch (err) { + ass.assemble(asm_source) catch |err| switch (err) { error.AssembleFail => { // TODO: For now the compiler only supports a single error message per decl, // so to translate the possible multiple errors from the assembler, emit // them as notes here. // TODO: Translate proper error locations. - assert(as.errors.items.len != 0); + assert(ass.errors.items.len != 0); assert(cg.error_msg == null); const src_loc = zcu.navSrcLoc(cg.owner_nav); cg.error_msg = try Zcu.ErrorMsg.create(zcu.gpa, src_loc, "failed to assemble SPIR-V inline assembly", .{}); - const notes = try zcu.gpa.alloc(Zcu.ErrorMsg, as.errors.items.len); + const notes = try zcu.gpa.alloc(Zcu.ErrorMsg, ass.errors.items.len); // Sub-scope to prevent `return error.CodegenFail` from running the errdefers. { @@ -6026,8 +6042,8 @@ fn airAssembly(cg: *CodeGen, inst: Air.Inst.Index) !?Id { note.deinit(zcu.gpa); }; - while (i < as.errors.items.len) : (i += 1) { - notes[i] = try Zcu.ErrorMsg.init(zcu.gpa, src_loc, "{s}", .{as.errors.items[i].msg}); + while (i < ass.errors.items.len) : (i += 1) { + notes[i] = try Zcu.ErrorMsg.init(zcu.gpa, src_loc, "{s}", .{ass.errors.items[i].msg}); } } cg.error_msg.?.notes = notes; @@ -6043,7 +6059,7 @@ fn airAssembly(cg: *CodeGen, inst: Air.Inst.Index) !?Id { const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0); output_extra_i += (constraint.len + name.len + (2 + 3)) / 4; - const result = as.value_map.get(name) orelse return { + const result = ass.value_map.get(name) orelse return { return cg.fail("invalid asm output '{s}'", .{name}); }; @@ -6083,8 +6099,11 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie const callee_id = try cg.resolve(pl_op.operand); comptime assert(zig_call_abi_ver == 3); - const params = try gpa.alloc(Id, args.len); - defer gpa.free(params); + + const scratch_top = cg.id_scratch.items.len; + defer cg.id_scratch.shrinkRetainingCapacity(scratch_top); + const params = try cg.id_scratch.addManyAsSlice(gpa, args.len); + var n_params: usize = 0; for (args) |arg| { // Note: resolve() might emit instructions, so we need to call it @@ -6098,7 +6117,7 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie n_params += 1; } - try cg.body.emit(cg.module.gpa, .OpFunctionCall, .{ + try cg.body.emit(gpa, .OpFunctionCall, .{ .id_result_type = result_type_id, .id_result = result_id, .function = callee_id, @@ -6119,15 +6138,16 @@ fn builtin3D( dimension: u32, out_of_range_value: anytype, ) !Id { + const gpa = cg.module.gpa; if (dimension >= 3) return try cg.constInt(result_ty, out_of_range_value); const u32_ty_id = try cg.module.intType(.unsigned, 32); const vec_ty_id = try cg.module.vectorType(3, u32_ty_id); const ptr_ty_id = try cg.module.ptrType(vec_ty_id, .input); const spv_decl_index = try cg.module.builtin(ptr_ty_id, builtin, .input); - try cg.decl_deps.put(cg.module.gpa, spv_decl_index, {}); + try cg.module.decl_deps.append(gpa, spv_decl_index); const ptr_id = cg.module.declPtr(spv_decl_index).result_id; const vec_id = cg.module.allocId(); - try cg.body.emit(cg.module.gpa, .OpLoad, .{ + try cg.body.emit(gpa, .OpLoad, .{ .id_result_type = vec_ty_id, .id_result = vec_id, .pointer = ptr_id, diff --git a/src/codegen/spirv/Module.zig b/src/codegen/spirv/Module.zig index acdbf376da..8daac06222 100644 --- a/src/codegen/spirv/Module.zig +++ b/src/codegen/spirv/Module.zig @@ -125,9 +125,9 @@ pub const Decl = struct { /// - For `invocation_global`, this is the result-id of the associated InvocationGlobal instruction. result_id: Id, /// The offset of the first dependency of this decl in the `decl_deps` array. - begin_dep: u32, + begin_dep: usize = 0, /// The past-end offset of the dependencies of this decl in the `decl_deps` array. - end_dep: u32, + end_dep: usize = 0, }; /// This models a kernel entry point. @@ -258,7 +258,6 @@ pub fn resolveNav(module: *Module, ip: *InternPool, nav_index: InternPool.Nav.In .generic => .invocation_global, else => .global, }; - entry.value_ptr.* = try module.allocDecl(kind); } @@ -782,15 +781,15 @@ pub fn builtin( const gop = try module.cache.builtins.getOrPut(module.gpa, .{ spirv_builtin, storage_class }); if (!gop.found_existing) { const decl_index = try module.allocDecl(.global); - const result_id = module.declPtr(decl_index).result_id; + const decl = module.declPtr(decl_index); + gop.value_ptr.* = decl_index; try module.sections.globals.emit(module.gpa, .OpVariable, .{ .id_result_type = result_ty_id, - .id_result = result_id, + .id_result = decl.result_id, .storage_class = storage_class, }); - try module.decorate(result_id, .{ .built_in = .{ .built_in = spirv_builtin } }); - try module.declareDeclDeps(decl_index, &.{}); + try module.decorate(decl.result_id, .{ .built_in = .{ .built_in = spirv_builtin } }); } return gop.value_ptr.*; } @@ -847,8 +846,6 @@ pub fn allocDecl(module: *Module, kind: Decl.Kind) !Decl.Index { try module.decls.append(module.gpa, .{ .kind = kind, .result_id = module.allocId(), - .begin_dep = undefined, - .end_dep = undefined, }); return @as(Decl.Index, @enumFromInt(@as(u32, @intCast(module.decls.items.len - 1)))); @@ -858,17 +855,6 @@ pub fn declPtr(module: *Module, index: Decl.Index) *Decl { return &module.decls.items[@intFromEnum(index)]; } -/// Declare ALL dependencies for a decl. -pub fn declareDeclDeps(module: *Module, decl_index: Decl.Index, deps: []const Decl.Index) !void { - const begin_dep: u32 = @intCast(module.decl_deps.items.len); - try module.decl_deps.appendSlice(module.gpa, deps); - const end_dep: u32 = @intCast(module.decl_deps.items.len); - - const decl = module.declPtr(decl_index); - decl.begin_dep = begin_dep; - decl.end_dep = end_dep; -} - /// Declare a SPIR-V function as an entry point. This causes an extra wrapper /// function to be generated, which is then exported as the real entry point. The purpose of this /// wrapper is to allocate and initialize the structure holding the instance globals. diff --git a/src/codegen/spirv/Section.zig b/src/codegen/spirv/Section.zig index b5851c3b7c..d5748afa39 100644 --- a/src/codegen/spirv/Section.zig +++ b/src/codegen/spirv/Section.zig @@ -21,7 +21,7 @@ pub fn deinit(section: *Section, allocator: Allocator) void { } pub fn reset(section: *Section) void { - section.instructions.items.len = 0; + section.instructions.clearRetainingCapacity(); } pub fn toWords(section: Section) []Word { @@ -86,16 +86,6 @@ pub fn emit( section.writeOperands(opcode.Operands(), operands); } -pub fn emitBranch( - section: *Section, - allocator: Allocator, - target_label: spec.Id, -) !void { - try section.emit(allocator, .OpBranch, .{ - .target_label = target_label, - }); -} - pub fn writeWord(section: *Section, word: Word) void { section.instructions.appendAssumeCapacity(word); } diff --git a/src/codegen/spirv/spec.zig b/src/codegen/spirv/spec.zig index 92f37d33c5..9f91320fdc 100644 --- a/src/codegen/spirv/spec.zig +++ b/src/codegen/spirv/spec.zig @@ -191,25 +191,6 @@ pub const OperandKind = enum { pair_id_ref_literal_integer, pair_id_ref_id_ref, tensor_operands, - debug_info_debug_info_flags, - debug_info_debug_base_type_attribute_encoding, - debug_info_debug_composite_type, - debug_info_debug_type_qualifier, - debug_info_debug_operation, - open_cl_debug_info_100_debug_info_flags, - open_cl_debug_info_100_debug_base_type_attribute_encoding, - open_cl_debug_info_100_debug_composite_type, - open_cl_debug_info_100_debug_type_qualifier, - open_cl_debug_info_100_debug_operation, - open_cl_debug_info_100_debug_imported_entity, - non_semantic_clspv_reflection_6_kernel_property_flags, - non_semantic_shader_debug_info_100_debug_info_flags, - non_semantic_shader_debug_info_100_build_identifier_flags, - non_semantic_shader_debug_info_100_debug_base_type_attribute_encoding, - non_semantic_shader_debug_info_100_debug_composite_type, - non_semantic_shader_debug_info_100_debug_type_qualifier, - non_semantic_shader_debug_info_100_debug_operation, - non_semantic_shader_debug_info_100_debug_imported_entity, pub fn category(self: OperandKind) OperandCategory { return switch (self) { @@ -285,25 +266,6 @@ pub const OperandKind = enum { .pair_id_ref_literal_integer => .composite, .pair_id_ref_id_ref => .composite, .tensor_operands => .bit_enum, - .debug_info_debug_info_flags => .bit_enum, - .debug_info_debug_base_type_attribute_encoding => .value_enum, - .debug_info_debug_composite_type => .value_enum, - .debug_info_debug_type_qualifier => .value_enum, - .debug_info_debug_operation => .value_enum, - .open_cl_debug_info_100_debug_info_flags => .bit_enum, - .open_cl_debug_info_100_debug_base_type_attribute_encoding => .value_enum, - .open_cl_debug_info_100_debug_composite_type => .value_enum, - .open_cl_debug_info_100_debug_type_qualifier => .value_enum, - .open_cl_debug_info_100_debug_operation => .value_enum, - .open_cl_debug_info_100_debug_imported_entity => .value_enum, - .non_semantic_clspv_reflection_6_kernel_property_flags => .bit_enum, - .non_semantic_shader_debug_info_100_debug_info_flags => .bit_enum, - .non_semantic_shader_debug_info_100_build_identifier_flags => .bit_enum, - .non_semantic_shader_debug_info_100_debug_base_type_attribute_encoding => .value_enum, - .non_semantic_shader_debug_info_100_debug_composite_type => .value_enum, - .non_semantic_shader_debug_info_100_debug_type_qualifier => .value_enum, - .non_semantic_shader_debug_info_100_debug_operation => .value_enum, - .non_semantic_shader_debug_info_100_debug_imported_entity => .value_enum, }; } pub fn enumerants(self: OperandKind) []const Enumerant { @@ -1475,178 +1437,10 @@ pub const OperandKind = enum { .{ .name = "MakeElementVisibleARM", .value = 0x0008, .parameters = &.{.id_ref} }, .{ .name = "NonPrivateElementARM", .value = 0x0010, .parameters = &.{} }, }, - .debug_info_debug_info_flags => &.{ - .{ .name = "FlagIsProtected", .value = 0x01, .parameters = &.{} }, - .{ .name = "FlagIsPrivate", .value = 0x02, .parameters = &.{} }, - .{ .name = "FlagIsPublic", .value = 0x03, .parameters = &.{} }, - .{ .name = "FlagIsLocal", .value = 0x04, .parameters = &.{} }, - .{ .name = "FlagIsDefinition", .value = 0x08, .parameters = &.{} }, - .{ .name = "FlagFwdDecl", .value = 0x10, .parameters = &.{} }, - .{ .name = "FlagArtificial", .value = 0x20, .parameters = &.{} }, - .{ .name = "FlagExplicit", .value = 0x40, .parameters = &.{} }, - .{ .name = "FlagPrototyped", .value = 0x80, .parameters = &.{} }, - .{ .name = "FlagObjectPointer", .value = 0x100, .parameters = &.{} }, - .{ .name = "FlagStaticMember", .value = 0x200, .parameters = &.{} }, - .{ .name = "FlagIndirectVariable", .value = 0x400, .parameters = &.{} }, - .{ .name = "FlagLValueReference", .value = 0x800, .parameters = &.{} }, - .{ .name = "FlagRValueReference", .value = 0x1000, .parameters = &.{} }, - .{ .name = "FlagIsOptimized", .value = 0x2000, .parameters = &.{} }, - }, - .debug_info_debug_base_type_attribute_encoding => &.{ - .{ .name = "Unspecified", .value = 0, .parameters = &.{} }, - .{ .name = "Address", .value = 1, .parameters = &.{} }, - .{ .name = "Boolean", .value = 2, .parameters = &.{} }, - .{ .name = "Float", .value = 4, .parameters = &.{} }, - .{ .name = "Signed", .value = 5, .parameters = &.{} }, - .{ .name = "SignedChar", .value = 6, .parameters = &.{} }, - .{ .name = "Unsigned", .value = 7, .parameters = &.{} }, - .{ .name = "UnsignedChar", .value = 8, .parameters = &.{} }, - }, - .debug_info_debug_composite_type => &.{ - .{ .name = "Class", .value = 0, .parameters = &.{} }, - .{ .name = "Structure", .value = 1, .parameters = &.{} }, - .{ .name = "Union", .value = 2, .parameters = &.{} }, - }, - .debug_info_debug_type_qualifier => &.{ - .{ .name = "ConstType", .value = 0, .parameters = &.{} }, - .{ .name = "VolatileType", .value = 1, .parameters = &.{} }, - .{ .name = "RestrictType", .value = 2, .parameters = &.{} }, - }, - .debug_info_debug_operation => &.{ - .{ .name = "Deref", .value = 0, .parameters = &.{} }, - .{ .name = "Plus", .value = 1, .parameters = &.{} }, - .{ .name = "Minus", .value = 2, .parameters = &.{} }, - .{ .name = "PlusUconst", .value = 3, .parameters = &.{.literal_integer} }, - .{ .name = "BitPiece", .value = 4, .parameters = &.{ .literal_integer, .literal_integer } }, - .{ .name = "Swap", .value = 5, .parameters = &.{} }, - .{ .name = "Xderef", .value = 6, .parameters = &.{} }, - .{ .name = "StackValue", .value = 7, .parameters = &.{} }, - .{ .name = "Constu", .value = 8, .parameters = &.{.literal_integer} }, - }, - .open_cl_debug_info_100_debug_info_flags => &.{ - .{ .name = "FlagIsProtected", .value = 0x01, .parameters = &.{} }, - .{ .name = "FlagIsPrivate", .value = 0x02, .parameters = &.{} }, - .{ .name = "FlagIsPublic", .value = 0x03, .parameters = &.{} }, - .{ .name = "FlagIsLocal", .value = 0x04, .parameters = &.{} }, - .{ .name = "FlagIsDefinition", .value = 0x08, .parameters = &.{} }, - .{ .name = "FlagFwdDecl", .value = 0x10, .parameters = &.{} }, - .{ .name = "FlagArtificial", .value = 0x20, .parameters = &.{} }, - .{ .name = "FlagExplicit", .value = 0x40, .parameters = &.{} }, - .{ .name = "FlagPrototyped", .value = 0x80, .parameters = &.{} }, - .{ .name = "FlagObjectPointer", .value = 0x100, .parameters = &.{} }, - .{ .name = "FlagStaticMember", .value = 0x200, .parameters = &.{} }, - .{ .name = "FlagIndirectVariable", .value = 0x400, .parameters = &.{} }, - .{ .name = "FlagLValueReference", .value = 0x800, .parameters = &.{} }, - .{ .name = "FlagRValueReference", .value = 0x1000, .parameters = &.{} }, - .{ .name = "FlagIsOptimized", .value = 0x2000, .parameters = &.{} }, - .{ .name = "FlagIsEnumClass", .value = 0x4000, .parameters = &.{} }, - .{ .name = "FlagTypePassByValue", .value = 0x8000, .parameters = &.{} }, - .{ .name = "FlagTypePassByReference", .value = 0x10000, .parameters = &.{} }, - }, - .open_cl_debug_info_100_debug_base_type_attribute_encoding => &.{ - .{ .name = "Unspecified", .value = 0, .parameters = &.{} }, - .{ .name = "Address", .value = 1, .parameters = &.{} }, - .{ .name = "Boolean", .value = 2, .parameters = &.{} }, - .{ .name = "Float", .value = 3, .parameters = &.{} }, - .{ .name = "Signed", .value = 4, .parameters = &.{} }, - .{ .name = "SignedChar", .value = 5, .parameters = &.{} }, - .{ .name = "Unsigned", .value = 6, .parameters = &.{} }, - .{ .name = "UnsignedChar", .value = 7, .parameters = &.{} }, - }, - .open_cl_debug_info_100_debug_composite_type => &.{ - .{ .name = "Class", .value = 0, .parameters = &.{} }, - .{ .name = "Structure", .value = 1, .parameters = &.{} }, - .{ .name = "Union", .value = 2, .parameters = &.{} }, - }, - .open_cl_debug_info_100_debug_type_qualifier => &.{ - .{ .name = "ConstType", .value = 0, .parameters = &.{} }, - .{ .name = "VolatileType", .value = 1, .parameters = &.{} }, - .{ .name = "RestrictType", .value = 2, .parameters = &.{} }, - .{ .name = "AtomicType", .value = 3, .parameters = &.{} }, - }, - .open_cl_debug_info_100_debug_operation => &.{ - .{ .name = "Deref", .value = 0, .parameters = &.{} }, - .{ .name = "Plus", .value = 1, .parameters = &.{} }, - .{ .name = "Minus", .value = 2, .parameters = &.{} }, - .{ .name = "PlusUconst", .value = 3, .parameters = &.{.literal_integer} }, - .{ .name = "BitPiece", .value = 4, .parameters = &.{ .literal_integer, .literal_integer } }, - .{ .name = "Swap", .value = 5, .parameters = &.{} }, - .{ .name = "Xderef", .value = 6, .parameters = &.{} }, - .{ .name = "StackValue", .value = 7, .parameters = &.{} }, - .{ .name = "Constu", .value = 8, .parameters = &.{.literal_integer} }, - .{ .name = "Fragment", .value = 9, .parameters = &.{ .literal_integer, .literal_integer } }, - }, - .open_cl_debug_info_100_debug_imported_entity => &.{ - .{ .name = "ImportedModule", .value = 0, .parameters = &.{} }, - .{ .name = "ImportedDeclaration", .value = 1, .parameters = &.{} }, - }, - .non_semantic_clspv_reflection_6_kernel_property_flags => &.{ - .{ .name = "MayUsePrintf", .value = 0x1, .parameters = &.{} }, - }, - .non_semantic_shader_debug_info_100_debug_info_flags => &.{ - .{ .name = "FlagIsProtected", .value = 0x01, .parameters = &.{} }, - .{ .name = "FlagIsPrivate", .value = 0x02, .parameters = &.{} }, - .{ .name = "FlagIsPublic", .value = 0x03, .parameters = &.{} }, - .{ .name = "FlagIsLocal", .value = 0x04, .parameters = &.{} }, - .{ .name = "FlagIsDefinition", .value = 0x08, .parameters = &.{} }, - .{ .name = "FlagFwdDecl", .value = 0x10, .parameters = &.{} }, - .{ .name = "FlagArtificial", .value = 0x20, .parameters = &.{} }, - .{ .name = "FlagExplicit", .value = 0x40, .parameters = &.{} }, - .{ .name = "FlagPrototyped", .value = 0x80, .parameters = &.{} }, - .{ .name = "FlagObjectPointer", .value = 0x100, .parameters = &.{} }, - .{ .name = "FlagStaticMember", .value = 0x200, .parameters = &.{} }, - .{ .name = "FlagIndirectVariable", .value = 0x400, .parameters = &.{} }, - .{ .name = "FlagLValueReference", .value = 0x800, .parameters = &.{} }, - .{ .name = "FlagRValueReference", .value = 0x1000, .parameters = &.{} }, - .{ .name = "FlagIsOptimized", .value = 0x2000, .parameters = &.{} }, - .{ .name = "FlagIsEnumClass", .value = 0x4000, .parameters = &.{} }, - .{ .name = "FlagTypePassByValue", .value = 0x8000, .parameters = &.{} }, - .{ .name = "FlagTypePassByReference", .value = 0x10000, .parameters = &.{} }, - .{ .name = "FlagUnknownPhysicalLayout", .value = 0x20000, .parameters = &.{} }, - }, - .non_semantic_shader_debug_info_100_build_identifier_flags => &.{ - .{ .name = "IdentifierPossibleDuplicates", .value = 0x01, .parameters = &.{} }, - }, - .non_semantic_shader_debug_info_100_debug_base_type_attribute_encoding => &.{ - .{ .name = "Unspecified", .value = 0, .parameters = &.{} }, - .{ .name = "Address", .value = 1, .parameters = &.{} }, - .{ .name = "Boolean", .value = 2, .parameters = &.{} }, - .{ .name = "Float", .value = 3, .parameters = &.{} }, - .{ .name = "Signed", .value = 4, .parameters = &.{} }, - .{ .name = "SignedChar", .value = 5, .parameters = &.{} }, - .{ .name = "Unsigned", .value = 6, .parameters = &.{} }, - .{ .name = "UnsignedChar", .value = 7, .parameters = &.{} }, - }, - .non_semantic_shader_debug_info_100_debug_composite_type => &.{ - .{ .name = "Class", .value = 0, .parameters = &.{} }, - .{ .name = "Structure", .value = 1, .parameters = &.{} }, - .{ .name = "Union", .value = 2, .parameters = &.{} }, - }, - .non_semantic_shader_debug_info_100_debug_type_qualifier => &.{ - .{ .name = "ConstType", .value = 0, .parameters = &.{} }, - .{ .name = "VolatileType", .value = 1, .parameters = &.{} }, - .{ .name = "RestrictType", .value = 2, .parameters = &.{} }, - .{ .name = "AtomicType", .value = 3, .parameters = &.{} }, - }, - .non_semantic_shader_debug_info_100_debug_operation => &.{ - .{ .name = "Deref", .value = 0, .parameters = &.{} }, - .{ .name = "Plus", .value = 1, .parameters = &.{} }, - .{ .name = "Minus", .value = 2, .parameters = &.{} }, - .{ .name = "PlusUconst", .value = 3, .parameters = &.{.id_ref} }, - .{ .name = "BitPiece", .value = 4, .parameters = &.{ .id_ref, .id_ref } }, - .{ .name = "Swap", .value = 5, .parameters = &.{} }, - .{ .name = "Xderef", .value = 6, .parameters = &.{} }, - .{ .name = "StackValue", .value = 7, .parameters = &.{} }, - .{ .name = "Constu", .value = 8, .parameters = &.{.id_ref} }, - .{ .name = "Fragment", .value = 9, .parameters = &.{ .id_ref, .id_ref } }, - }, - .non_semantic_shader_debug_info_100_debug_imported_entity => &.{ - .{ .name = "ImportedModule", .value = 0, .parameters = &.{} }, - .{ .name = "ImportedDeclaration", .value = 1, .parameters = &.{} }, - }, }; } }; + pub const Opcode = enum(u16) { OpNop = 0, OpUndef = 1, @@ -3533,6 +3327,259 @@ pub const Opcode = enum(u16) { }; } }; + +pub const GlslOpcode = enum(u16) { + Round = 1, + RoundEven = 2, + Trunc = 3, + FAbs = 4, + SAbs = 5, + FSign = 6, + SSign = 7, + Floor = 8, + Ceil = 9, + Fract = 10, + Radians = 11, + Degrees = 12, + Sin = 13, + Cos = 14, + Tan = 15, + Asin = 16, + Acos = 17, + Atan = 18, + Sinh = 19, + Cosh = 20, + Tanh = 21, + Asinh = 22, + Acosh = 23, + Atanh = 24, + Atan2 = 25, + Pow = 26, + Exp = 27, + Log = 28, + Exp2 = 29, + Log2 = 30, + Sqrt = 31, + InverseSqrt = 32, + Determinant = 33, + MatrixInverse = 34, + Modf = 35, + ModfStruct = 36, + FMin = 37, + UMin = 38, + SMin = 39, + FMax = 40, + UMax = 41, + SMax = 42, + FClamp = 43, + UClamp = 44, + SClamp = 45, + FMix = 46, + IMix = 47, + Step = 48, + SmoothStep = 49, + Fma = 50, + Frexp = 51, + FrexpStruct = 52, + Ldexp = 53, + PackSnorm4x8 = 54, + PackUnorm4x8 = 55, + PackSnorm2x16 = 56, + PackUnorm2x16 = 57, + PackHalf2x16 = 58, + PackDouble2x32 = 59, + UnpackSnorm2x16 = 60, + UnpackUnorm2x16 = 61, + UnpackHalf2x16 = 62, + UnpackSnorm4x8 = 63, + UnpackUnorm4x8 = 64, + UnpackDouble2x32 = 65, + Length = 66, + Distance = 67, + Cross = 68, + Normalize = 69, + FaceForward = 70, + Reflect = 71, + Refract = 72, + FindILsb = 73, + FindSMsb = 74, + FindUMsb = 75, + InterpolateAtCentroid = 76, + InterpolateAtSample = 77, + InterpolateAtOffset = 78, + NMin = 79, + NMax = 80, + NClamp = 81, +}; + +pub const OpenClOpcode = enum(u16) { + acos = 0, + acosh = 1, + acospi = 2, + asin = 3, + asinh = 4, + asinpi = 5, + atan = 6, + atan2 = 7, + atanh = 8, + atanpi = 9, + atan2pi = 10, + cbrt = 11, + ceil = 12, + copysign = 13, + cos = 14, + cosh = 15, + cospi = 16, + erfc = 17, + erf = 18, + exp = 19, + exp2 = 20, + exp10 = 21, + expm1 = 22, + fabs = 23, + fdim = 24, + floor = 25, + fma = 26, + fmax = 27, + fmin = 28, + fmod = 29, + fract = 30, + frexp = 31, + hypot = 32, + ilogb = 33, + ldexp = 34, + lgamma = 35, + lgamma_r = 36, + log = 37, + log2 = 38, + log10 = 39, + log1p = 40, + logb = 41, + mad = 42, + maxmag = 43, + minmag = 44, + modf = 45, + nan = 46, + nextafter = 47, + pow = 48, + pown = 49, + powr = 50, + remainder = 51, + remquo = 52, + rint = 53, + rootn = 54, + round = 55, + rsqrt = 56, + sin = 57, + sincos = 58, + sinh = 59, + sinpi = 60, + sqrt = 61, + tan = 62, + tanh = 63, + tanpi = 64, + tgamma = 65, + trunc = 66, + half_cos = 67, + half_divide = 68, + half_exp = 69, + half_exp2 = 70, + half_exp10 = 71, + half_log = 72, + half_log2 = 73, + half_log10 = 74, + half_powr = 75, + half_recip = 76, + half_rsqrt = 77, + half_sin = 78, + half_sqrt = 79, + half_tan = 80, + native_cos = 81, + native_divide = 82, + native_exp = 83, + native_exp2 = 84, + native_exp10 = 85, + native_log = 86, + native_log2 = 87, + native_log10 = 88, + native_powr = 89, + native_recip = 90, + native_rsqrt = 91, + native_sin = 92, + native_sqrt = 93, + native_tan = 94, + fclamp = 95, + degrees = 96, + fmax_common = 97, + fmin_common = 98, + mix = 99, + radians = 100, + step = 101, + smoothstep = 102, + sign = 103, + cross = 104, + distance = 105, + length = 106, + normalize = 107, + fast_distance = 108, + fast_length = 109, + fast_normalize = 110, + s_abs = 141, + s_abs_diff = 142, + s_add_sat = 143, + u_add_sat = 144, + s_hadd = 145, + u_hadd = 146, + s_rhadd = 147, + u_rhadd = 148, + s_clamp = 149, + u_clamp = 150, + clz = 151, + ctz = 152, + s_mad_hi = 153, + u_mad_sat = 154, + s_mad_sat = 155, + s_max = 156, + u_max = 157, + s_min = 158, + u_min = 159, + s_mul_hi = 160, + rotate = 161, + s_sub_sat = 162, + u_sub_sat = 163, + u_upsample = 164, + s_upsample = 165, + popcount = 166, + s_mad24 = 167, + u_mad24 = 168, + s_mul24 = 169, + u_mul24 = 170, + vloadn = 171, + vstoren = 172, + vload_half = 173, + vload_halfn = 174, + vstore_half = 175, + vstore_half_r = 176, + vstore_halfn = 177, + vstore_halfn_r = 178, + vloada_halfn = 179, + vstorea_halfn = 180, + vstorea_halfn_r = 181, + shuffle = 182, + shuffle2 = 183, + printf = 184, + prefetch = 185, + bitselect = 186, + select = 187, + u_abs = 201, + u_abs_diff = 202, + u_mul_hi = 203, + u_mad_hi = 204, +}; + +pub const Zig = enum(u16) { + InvocationGlobal = 0, +}; pub const ImageOperands = packed struct { bias: bool = false, lod: bool = false, @@ -5494,335 +5541,10 @@ pub const TensorOperands = packed struct { _reserved_bit_31: bool = false, }; }; -pub const @"DebugInfo.DebugInfoFlags" = packed struct { - flag_is_protected: bool = false, - flag_is_private: bool = false, - flag_is_local: bool = false, - flag_is_definition: bool = false, - flag_fwd_decl: bool = false, - flag_artificial: bool = false, - flag_explicit: bool = false, - flag_prototyped: bool = false, - flag_object_pointer: bool = false, - flag_static_member: bool = false, - flag_indirect_variable: bool = false, - flag_l_value_reference: bool = false, - flag_r_value_reference: bool = false, - flag_is_optimized: bool = false, - _reserved_bit_14: bool = false, - _reserved_bit_15: bool = false, - _reserved_bit_16: bool = false, - _reserved_bit_17: bool = false, - _reserved_bit_18: bool = false, - _reserved_bit_19: bool = false, - _reserved_bit_20: bool = false, - _reserved_bit_21: bool = false, - _reserved_bit_22: bool = false, - _reserved_bit_23: bool = false, - _reserved_bit_24: bool = false, - _reserved_bit_25: bool = false, - _reserved_bit_26: bool = false, - _reserved_bit_27: bool = false, - _reserved_bit_28: bool = false, - _reserved_bit_29: bool = false, - _reserved_bit_30: bool = false, - _reserved_bit_31: bool = false, -}; -pub const @"DebugInfo.DebugBaseTypeAttributeEncoding" = enum(u32) { - unspecified = 0, - address = 1, - boolean = 2, - float = 4, - signed = 5, - signed_char = 6, - unsigned = 7, - unsigned_char = 8, -}; -pub const @"DebugInfo.DebugCompositeType" = enum(u32) { - class = 0, - structure = 1, - @"union" = 2, -}; -pub const @"DebugInfo.DebugTypeQualifier" = enum(u32) { - const_type = 0, - volatile_type = 1, - restrict_type = 2, -}; -pub const @"DebugInfo.DebugOperation" = enum(u32) { - deref = 0, - plus = 1, - minus = 2, - plus_uconst = 3, - bit_piece = 4, - swap = 5, - xderef = 6, - stack_value = 7, - constu = 8, - - pub const Extended = union(@"DebugInfo.DebugOperation") { - deref, - plus, - minus, - plus_uconst: struct { literal_integer: LiteralInteger }, - bit_piece: struct { literal_integer_0: LiteralInteger, literal_integer_1: LiteralInteger }, - swap, - xderef, - stack_value, - constu: struct { literal_integer: LiteralInteger }, - }; -}; -pub const @"OpenCL.DebugInfo.100.DebugInfoFlags" = packed struct { - flag_is_protected: bool = false, - flag_is_private: bool = false, - flag_is_local: bool = false, - flag_is_definition: bool = false, - flag_fwd_decl: bool = false, - flag_artificial: bool = false, - flag_explicit: bool = false, - flag_prototyped: bool = false, - flag_object_pointer: bool = false, - flag_static_member: bool = false, - flag_indirect_variable: bool = false, - flag_l_value_reference: bool = false, - flag_r_value_reference: bool = false, - flag_is_optimized: bool = false, - flag_is_enum_class: bool = false, - flag_type_pass_by_value: bool = false, - flag_type_pass_by_reference: bool = false, - _reserved_bit_17: bool = false, - _reserved_bit_18: bool = false, - _reserved_bit_19: bool = false, - _reserved_bit_20: bool = false, - _reserved_bit_21: bool = false, - _reserved_bit_22: bool = false, - _reserved_bit_23: bool = false, - _reserved_bit_24: bool = false, - _reserved_bit_25: bool = false, - _reserved_bit_26: bool = false, - _reserved_bit_27: bool = false, - _reserved_bit_28: bool = false, - _reserved_bit_29: bool = false, - _reserved_bit_30: bool = false, - _reserved_bit_31: bool = false, -}; -pub const @"OpenCL.DebugInfo.100.DebugBaseTypeAttributeEncoding" = enum(u32) { - unspecified = 0, - address = 1, - boolean = 2, - float = 3, - signed = 4, - signed_char = 5, - unsigned = 6, - unsigned_char = 7, -}; -pub const @"OpenCL.DebugInfo.100.DebugCompositeType" = enum(u32) { - class = 0, - structure = 1, - @"union" = 2, -}; -pub const @"OpenCL.DebugInfo.100.DebugTypeQualifier" = enum(u32) { - const_type = 0, - volatile_type = 1, - restrict_type = 2, - atomic_type = 3, -}; -pub const @"OpenCL.DebugInfo.100.DebugOperation" = enum(u32) { - deref = 0, - plus = 1, - minus = 2, - plus_uconst = 3, - bit_piece = 4, - swap = 5, - xderef = 6, - stack_value = 7, - constu = 8, - fragment = 9, - - pub const Extended = union(@"OpenCL.DebugInfo.100.DebugOperation") { - deref, - plus, - minus, - plus_uconst: struct { literal_integer: LiteralInteger }, - bit_piece: struct { literal_integer_0: LiteralInteger, literal_integer_1: LiteralInteger }, - swap, - xderef, - stack_value, - constu: struct { literal_integer: LiteralInteger }, - fragment: struct { literal_integer_0: LiteralInteger, literal_integer_1: LiteralInteger }, - }; -}; -pub const @"OpenCL.DebugInfo.100.DebugImportedEntity" = enum(u32) { - imported_module = 0, - imported_declaration = 1, -}; -pub const @"NonSemantic.ClspvReflection.6.KernelPropertyFlags" = packed struct { - may_use_printf: bool = false, - _reserved_bit_1: bool = false, - _reserved_bit_2: bool = false, - _reserved_bit_3: bool = false, - _reserved_bit_4: bool = false, - _reserved_bit_5: bool = false, - _reserved_bit_6: bool = false, - _reserved_bit_7: bool = false, - _reserved_bit_8: bool = false, - _reserved_bit_9: bool = false, - _reserved_bit_10: bool = false, - _reserved_bit_11: bool = false, - _reserved_bit_12: bool = false, - _reserved_bit_13: bool = false, - _reserved_bit_14: bool = false, - _reserved_bit_15: bool = false, - _reserved_bit_16: bool = false, - _reserved_bit_17: bool = false, - _reserved_bit_18: bool = false, - _reserved_bit_19: bool = false, - _reserved_bit_20: bool = false, - _reserved_bit_21: bool = false, - _reserved_bit_22: bool = false, - _reserved_bit_23: bool = false, - _reserved_bit_24: bool = false, - _reserved_bit_25: bool = false, - _reserved_bit_26: bool = false, - _reserved_bit_27: bool = false, - _reserved_bit_28: bool = false, - _reserved_bit_29: bool = false, - _reserved_bit_30: bool = false, - _reserved_bit_31: bool = false, -}; -pub const @"NonSemantic.Shader.DebugInfo.100.DebugInfoFlags" = packed struct { - flag_is_protected: bool = false, - flag_is_private: bool = false, - flag_is_local: bool = false, - flag_is_definition: bool = false, - flag_fwd_decl: bool = false, - flag_artificial: bool = false, - flag_explicit: bool = false, - flag_prototyped: bool = false, - flag_object_pointer: bool = false, - flag_static_member: bool = false, - flag_indirect_variable: bool = false, - flag_l_value_reference: bool = false, - flag_r_value_reference: bool = false, - flag_is_optimized: bool = false, - flag_is_enum_class: bool = false, - flag_type_pass_by_value: bool = false, - flag_type_pass_by_reference: bool = false, - flag_unknown_physical_layout: bool = false, - _reserved_bit_18: bool = false, - _reserved_bit_19: bool = false, - _reserved_bit_20: bool = false, - _reserved_bit_21: bool = false, - _reserved_bit_22: bool = false, - _reserved_bit_23: bool = false, - _reserved_bit_24: bool = false, - _reserved_bit_25: bool = false, - _reserved_bit_26: bool = false, - _reserved_bit_27: bool = false, - _reserved_bit_28: bool = false, - _reserved_bit_29: bool = false, - _reserved_bit_30: bool = false, - _reserved_bit_31: bool = false, -}; -pub const @"NonSemantic.Shader.DebugInfo.100.BuildIdentifierFlags" = packed struct { - identifier_possible_duplicates: bool = false, - _reserved_bit_1: bool = false, - _reserved_bit_2: bool = false, - _reserved_bit_3: bool = false, - _reserved_bit_4: bool = false, - _reserved_bit_5: bool = false, - _reserved_bit_6: bool = false, - _reserved_bit_7: bool = false, - _reserved_bit_8: bool = false, - _reserved_bit_9: bool = false, - _reserved_bit_10: bool = false, - _reserved_bit_11: bool = false, - _reserved_bit_12: bool = false, - _reserved_bit_13: bool = false, - _reserved_bit_14: bool = false, - _reserved_bit_15: bool = false, - _reserved_bit_16: bool = false, - _reserved_bit_17: bool = false, - _reserved_bit_18: bool = false, - _reserved_bit_19: bool = false, - _reserved_bit_20: bool = false, - _reserved_bit_21: bool = false, - _reserved_bit_22: bool = false, - _reserved_bit_23: bool = false, - _reserved_bit_24: bool = false, - _reserved_bit_25: bool = false, - _reserved_bit_26: bool = false, - _reserved_bit_27: bool = false, - _reserved_bit_28: bool = false, - _reserved_bit_29: bool = false, - _reserved_bit_30: bool = false, - _reserved_bit_31: bool = false, -}; -pub const @"NonSemantic.Shader.DebugInfo.100.DebugBaseTypeAttributeEncoding" = enum(u32) { - unspecified = 0, - address = 1, - boolean = 2, - float = 3, - signed = 4, - signed_char = 5, - unsigned = 6, - unsigned_char = 7, -}; -pub const @"NonSemantic.Shader.DebugInfo.100.DebugCompositeType" = enum(u32) { - class = 0, - structure = 1, - @"union" = 2, -}; -pub const @"NonSemantic.Shader.DebugInfo.100.DebugTypeQualifier" = enum(u32) { - const_type = 0, - volatile_type = 1, - restrict_type = 2, - atomic_type = 3, -}; -pub const @"NonSemantic.Shader.DebugInfo.100.DebugOperation" = enum(u32) { - deref = 0, - plus = 1, - minus = 2, - plus_uconst = 3, - bit_piece = 4, - swap = 5, - xderef = 6, - stack_value = 7, - constu = 8, - fragment = 9, - - pub const Extended = union(@"NonSemantic.Shader.DebugInfo.100.DebugOperation") { - deref, - plus, - minus, - plus_uconst: struct { id_ref: Id }, - bit_piece: struct { id_ref_0: Id, id_ref_1: Id }, - swap, - xderef, - stack_value, - constu: struct { id_ref: Id }, - fragment: struct { id_ref_0: Id, id_ref_1: Id }, - }; -}; -pub const @"NonSemantic.Shader.DebugInfo.100.DebugImportedEntity" = enum(u32) { - imported_module = 0, - imported_declaration = 1, -}; pub const InstructionSet = enum { core, - SPV_AMD_shader_trinary_minmax, - SPV_EXT_INST_TYPE_TOSA_001000_1, - @"NonSemantic.VkspReflection", - SPV_AMD_shader_explicit_vertex_parameter, - DebugInfo, - @"NonSemantic.DebugBreak", - @"OpenCL.DebugInfo.100", - @"NonSemantic.ClspvReflection.6", @"GLSL.std.450", - SPV_AMD_shader_ballot, - @"NonSemantic.DebugPrintf", - SPV_AMD_gcn_shader, @"OpenCL.std", - @"NonSemantic.Shader.DebugInfo.100", zig, pub fn instructions(self: InstructionSet) []const Instruction { @@ -14088,1972 +13810,6 @@ pub const InstructionSet = enum { }, }, }, - .SPV_AMD_shader_trinary_minmax => &.{ - .{ - .name = "FMin3AMD", - .opcode = 1, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "UMin3AMD", - .opcode = 2, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "SMin3AMD", - .opcode = 3, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "FMax3AMD", - .opcode = 4, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "UMax3AMD", - .opcode = 5, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "SMax3AMD", - .opcode = 6, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "FMid3AMD", - .opcode = 7, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "UMid3AMD", - .opcode = 8, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "SMid3AMD", - .opcode = 9, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - }, - .SPV_EXT_INST_TYPE_TOSA_001000_1 => &.{ - .{ - .name = "ARGMAX", - .opcode = 0, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "AVG_POOL2D", - .opcode = 1, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "CONV2D", - .opcode = 2, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "CONV3D", - .opcode = 3, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DEPTHWISE_CONV2D", - .opcode = 4, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "FFT2D", - .opcode = 5, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "MATMUL", - .opcode = 6, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "MAX_POOL2D", - .opcode = 7, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "RFFT2D", - .opcode = 8, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "TRANSPOSE_CONV2D", - .opcode = 9, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "CLAMP", - .opcode = 10, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "ERF", - .opcode = 11, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "SIGMOID", - .opcode = 12, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "TANH", - .opcode = 13, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "ADD", - .opcode = 14, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "ARITHMETIC_RIGHT_SHIFT", - .opcode = 15, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "BITWISE_AND", - .opcode = 16, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "BITWISE_OR", - .opcode = 17, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "BITWISE_XOR", - .opcode = 18, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "INTDIV", - .opcode = 19, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "LOGICAL_AND", - .opcode = 20, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "LOGICAL_LEFT_SHIFT", - .opcode = 21, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "LOGICAL_RIGHT_SHIFT", - .opcode = 22, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "LOGICAL_OR", - .opcode = 23, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "LOGICAL_XOR", - .opcode = 24, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "MAXIMUM", - .opcode = 25, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "MINIMUM", - .opcode = 26, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "MUL", - .opcode = 27, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "POW", - .opcode = 28, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "SUB", - .opcode = 29, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "TABLE", - .opcode = 30, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "ABS", - .opcode = 31, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "BITWISE_NOT", - .opcode = 32, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "CEIL", - .opcode = 33, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "CLZ", - .opcode = 34, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "COS", - .opcode = 35, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "EXP", - .opcode = 36, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "FLOOR", - .opcode = 37, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "LOG", - .opcode = 38, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "LOGICAL_NOT", - .opcode = 39, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "NEGATE", - .opcode = 40, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "RECIPROCAL", - .opcode = 41, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "RSQRT", - .opcode = 42, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "SIN", - .opcode = 43, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "SELECT", - .opcode = 44, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "EQUAL", - .opcode = 45, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "GREATER", - .opcode = 46, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "GREATER_EQUAL", - .opcode = 47, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "REDUCE_ALL", - .opcode = 48, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "REDUCE_ANY", - .opcode = 49, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "REDUCE_MAX", - .opcode = 50, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "REDUCE_MIN", - .opcode = 51, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "REDUCE_PRODUCT", - .opcode = 52, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "REDUCE_SUM", - .opcode = 53, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "CONCAT", - .opcode = 54, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .variadic }, - }, - }, - .{ - .name = "PAD", - .opcode = 55, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "RESHAPE", - .opcode = 56, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "REVERSE", - .opcode = 57, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "SLICE", - .opcode = 58, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "TILE", - .opcode = 59, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "TRANSPOSE", - .opcode = 60, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "GATHER", - .opcode = 61, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "SCATTER", - .opcode = 62, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "RESIZE", - .opcode = 63, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "CAST", - .opcode = 64, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "RESCALE", - .opcode = 65, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - }, - .@"NonSemantic.VkspReflection" => &.{ - .{ - .name = "Configuration", - .opcode = 1, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "StartCounter", - .opcode = 2, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "StopCounter", - .opcode = 3, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "PushConstants", - .opcode = 4, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "SpecializationMapEntry", - .opcode = 5, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DescriptorSetBuffer", - .opcode = 6, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DescriptorSetImage", - .opcode = 7, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DescriptorSetSampler", - .opcode = 8, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - }, - .SPV_AMD_shader_explicit_vertex_parameter => &.{ - .{ - .name = "InterpolateAtVertexAMD", - .opcode = 1, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - }, - .DebugInfo => &.{ - .{ - .name = "DebugInfoNone", - .opcode = 0, - .operands = &.{}, - }, - .{ - .name = "DebugCompilationUnit", - .opcode = 1, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - }, - }, - .{ - .name = "DebugTypeBasic", - .opcode = 2, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .debug_info_debug_base_type_attribute_encoding, .quantifier = .required }, - }, - }, - .{ - .name = "DebugTypePointer", - .opcode = 3, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .storage_class, .quantifier = .required }, - .{ .kind = .debug_info_debug_info_flags, .quantifier = .required }, - }, - }, - .{ - .name = "DebugTypeQualifier", - .opcode = 4, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .debug_info_debug_type_qualifier, .quantifier = .required }, - }, - }, - .{ - .name = "DebugTypeArray", - .opcode = 5, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .variadic }, - }, - }, - .{ - .name = "DebugTypeVector", - .opcode = 6, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - }, - }, - .{ - .name = "DebugTypedef", - .opcode = 7, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugTypeFunction", - .opcode = 8, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .variadic }, - }, - }, - .{ - .name = "DebugTypeEnum", - .opcode = 9, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .debug_info_debug_info_flags, .quantifier = .required }, - .{ .kind = .pair_id_ref_id_ref, .quantifier = .variadic }, - }, - }, - .{ - .name = "DebugTypeComposite", - .opcode = 10, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .debug_info_debug_composite_type, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .debug_info_debug_info_flags, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .variadic }, - }, - }, - .{ - .name = "DebugTypeMember", - .opcode = 11, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .debug_info_debug_info_flags, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "DebugTypeInheritance", - .opcode = 12, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .debug_info_debug_info_flags, .quantifier = .required }, - }, - }, - .{ - .name = "DebugTypePtrToMember", - .opcode = 13, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugTypeTemplate", - .opcode = 14, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .variadic }, - }, - }, - .{ - .name = "DebugTypeTemplateParameter", - .opcode = 15, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - }, - }, - .{ - .name = "DebugTypeTemplateTemplateParameter", - .opcode = 16, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - }, - }, - .{ - .name = "DebugTypeTemplateParameterPack", - .opcode = 17, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .variadic }, - }, - }, - .{ - .name = "DebugGlobalVariable", - .opcode = 18, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .debug_info_debug_info_flags, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "DebugFunctionDeclaration", - .opcode = 19, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .debug_info_debug_info_flags, .quantifier = .required }, - }, - }, - .{ - .name = "DebugFunction", - .opcode = 20, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .debug_info_debug_info_flags, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "DebugLexicalBlock", - .opcode = 21, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "DebugLexicalBlockDiscriminator", - .opcode = 22, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugScope", - .opcode = 23, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "DebugNoScope", - .opcode = 24, - .operands = &.{}, - }, - .{ - .name = "DebugInlinedAt", - .opcode = 25, - .operands = &.{ - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "DebugLocalVariable", - .opcode = 26, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .optional }, - }, - }, - .{ - .name = "DebugInlinedVariable", - .opcode = 27, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugDeclare", - .opcode = 28, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugValue", - .opcode = 29, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .variadic }, - }, - }, - .{ - .name = "DebugOperation", - .opcode = 30, - .operands = &.{ - .{ .kind = .debug_info_debug_operation, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .variadic }, - }, - }, - .{ - .name = "DebugExpression", - .opcode = 31, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .variadic }, - }, - }, - .{ - .name = "DebugMacroDef", - .opcode = 32, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "DebugMacroUndef", - .opcode = 33, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - }, - .@"NonSemantic.DebugBreak" => &.{ - .{ - .name = "DebugBreak", - .opcode = 1, - .operands = &.{}, - }, - }, - .@"OpenCL.DebugInfo.100" => &.{ - .{ - .name = "DebugInfoNone", - .opcode = 0, - .operands = &.{}, - }, - .{ - .name = "DebugCompilationUnit", - .opcode = 1, - .operands = &.{ - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .source_language, .quantifier = .required }, - }, - }, - .{ - .name = "DebugTypeBasic", - .opcode = 2, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .open_cl_debug_info_100_debug_base_type_attribute_encoding, .quantifier = .required }, - }, - }, - .{ - .name = "DebugTypePointer", - .opcode = 3, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .storage_class, .quantifier = .required }, - .{ .kind = .open_cl_debug_info_100_debug_info_flags, .quantifier = .required }, - }, - }, - .{ - .name = "DebugTypeQualifier", - .opcode = 4, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .open_cl_debug_info_100_debug_type_qualifier, .quantifier = .required }, - }, - }, - .{ - .name = "DebugTypeArray", - .opcode = 5, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .variadic }, - }, - }, - .{ - .name = "DebugTypeVector", - .opcode = 6, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - }, - }, - .{ - .name = "DebugTypedef", - .opcode = 7, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugTypeFunction", - .opcode = 8, - .operands = &.{ - .{ .kind = .open_cl_debug_info_100_debug_info_flags, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .variadic }, - }, - }, - .{ - .name = "DebugTypeEnum", - .opcode = 9, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .open_cl_debug_info_100_debug_info_flags, .quantifier = .required }, - .{ .kind = .pair_id_ref_id_ref, .quantifier = .variadic }, - }, - }, - .{ - .name = "DebugTypeComposite", - .opcode = 10, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .open_cl_debug_info_100_debug_composite_type, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .open_cl_debug_info_100_debug_info_flags, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .variadic }, - }, - }, - .{ - .name = "DebugTypeMember", - .opcode = 11, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .open_cl_debug_info_100_debug_info_flags, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "DebugTypeInheritance", - .opcode = 12, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .open_cl_debug_info_100_debug_info_flags, .quantifier = .required }, - }, - }, - .{ - .name = "DebugTypePtrToMember", - .opcode = 13, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugTypeTemplate", - .opcode = 14, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .variadic }, - }, - }, - .{ - .name = "DebugTypeTemplateParameter", - .opcode = 15, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - }, - }, - .{ - .name = "DebugTypeTemplateTemplateParameter", - .opcode = 16, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - }, - }, - .{ - .name = "DebugTypeTemplateParameterPack", - .opcode = 17, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .variadic }, - }, - }, - .{ - .name = "DebugGlobalVariable", - .opcode = 18, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .open_cl_debug_info_100_debug_info_flags, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "DebugFunctionDeclaration", - .opcode = 19, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .open_cl_debug_info_100_debug_info_flags, .quantifier = .required }, - }, - }, - .{ - .name = "DebugFunction", - .opcode = 20, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .open_cl_debug_info_100_debug_info_flags, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "DebugLexicalBlock", - .opcode = 21, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "DebugLexicalBlockDiscriminator", - .opcode = 22, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugScope", - .opcode = 23, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "DebugNoScope", - .opcode = 24, - .operands = &.{}, - }, - .{ - .name = "DebugInlinedAt", - .opcode = 25, - .operands = &.{ - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "DebugLocalVariable", - .opcode = 26, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .open_cl_debug_info_100_debug_info_flags, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .optional }, - }, - }, - .{ - .name = "DebugInlinedVariable", - .opcode = 27, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugDeclare", - .opcode = 28, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugValue", - .opcode = 29, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .variadic }, - }, - }, - .{ - .name = "DebugOperation", - .opcode = 30, - .operands = &.{ - .{ .kind = .open_cl_debug_info_100_debug_operation, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .variadic }, - }, - }, - .{ - .name = "DebugExpression", - .opcode = 31, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .variadic }, - }, - }, - .{ - .name = "DebugMacroDef", - .opcode = 32, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "DebugMacroUndef", - .opcode = 33, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugImportedEntity", - .opcode = 34, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .open_cl_debug_info_100_debug_imported_entity, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugSource", - .opcode = 35, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "DebugModuleINTEL", - .opcode = 36, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .literal_integer, .quantifier = .required }, - }, - }, - }, - .@"NonSemantic.ClspvReflection.6" => &.{ - .{ - .name = "Kernel", - .opcode = 1, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - .{ .kind = .id_ref, .quantifier = .optional }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "ArgumentInfo", - .opcode = 2, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - .{ .kind = .id_ref, .quantifier = .optional }, - .{ .kind = .id_ref, .quantifier = .optional }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "ArgumentStorageBuffer", - .opcode = 3, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "ArgumentUniform", - .opcode = 4, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "ArgumentPodStorageBuffer", - .opcode = 5, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "ArgumentPodUniform", - .opcode = 6, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "ArgumentPodPushConstant", - .opcode = 7, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "ArgumentSampledImage", - .opcode = 8, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "ArgumentStorageImage", - .opcode = 9, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "ArgumentSampler", - .opcode = 10, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "ArgumentWorkgroup", - .opcode = 11, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "SpecConstantWorkgroupSize", - .opcode = 12, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "SpecConstantGlobalOffset", - .opcode = 13, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "SpecConstantWorkDim", - .opcode = 14, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "PushConstantGlobalOffset", - .opcode = 15, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "PushConstantEnqueuedLocalSize", - .opcode = 16, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "PushConstantGlobalSize", - .opcode = 17, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "PushConstantRegionOffset", - .opcode = 18, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "PushConstantNumWorkgroups", - .opcode = 19, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "PushConstantRegionGroupOffset", - .opcode = 20, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "ConstantDataStorageBuffer", - .opcode = 21, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "ConstantDataUniform", - .opcode = 22, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "LiteralSampler", - .opcode = 23, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "PropertyRequiredWorkgroupSize", - .opcode = 24, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "SpecConstantSubgroupMaxSize", - .opcode = 25, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "ArgumentPointerPushConstant", - .opcode = 26, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "ArgumentPointerUniform", - .opcode = 27, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "ProgramScopeVariablesStorageBuffer", - .opcode = 28, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "ProgramScopeVariablePointerRelocation", - .opcode = 29, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "ImageArgumentInfoChannelOrderPushConstant", - .opcode = 30, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "ImageArgumentInfoChannelDataTypePushConstant", - .opcode = 31, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "ImageArgumentInfoChannelOrderUniform", - .opcode = 32, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "ImageArgumentInfoChannelDataTypeUniform", - .opcode = 33, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "ArgumentStorageTexelBuffer", - .opcode = 34, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "ArgumentUniformTexelBuffer", - .opcode = 35, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "ConstantDataPointerPushConstant", - .opcode = 36, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "ProgramScopeVariablePointerPushConstant", - .opcode = 37, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "PrintfInfo", - .opcode = 38, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .variadic }, - }, - }, - .{ - .name = "PrintfBufferStorageBuffer", - .opcode = 39, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "PrintfBufferPointerPushConstant", - .opcode = 40, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "NormalizedSamplerMaskPushConstant", - .opcode = 41, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "WorkgroupVariableSize", - .opcode = 42, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - }, .@"GLSL.std.450" => &.{ .{ .name = "Round", @@ -16662,71 +14418,6 @@ pub const InstructionSet = enum { }, }, }, - .SPV_AMD_shader_ballot => &.{ - .{ - .name = "SwizzleInvocationsAMD", - .opcode = 1, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "SwizzleInvocationsMaskedAMD", - .opcode = 2, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "WriteInvocationAMD", - .opcode = 3, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "MbcntAMD", - .opcode = 4, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - }, - .@"NonSemantic.DebugPrintf" => &.{ - .{ - .name = "DebugPrintf", - .opcode = 1, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .variadic }, - }, - }, - }, - .SPV_AMD_gcn_shader => &.{ - .{ - .name = "CubeFaceIndexAMD", - .opcode = 1, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "CubeFaceCoordAMD", - .opcode = 2, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "TimeAMD", - .opcode = 3, - .operands = &.{}, - }, - }, .@"OpenCL.std" => &.{ .{ .name = "acos", @@ -17977,443 +15668,6 @@ pub const InstructionSet = enum { }, }, }, - .@"NonSemantic.Shader.DebugInfo.100" => &.{ - .{ - .name = "DebugInfoNone", - .opcode = 0, - .operands = &.{}, - }, - .{ - .name = "DebugCompilationUnit", - .opcode = 1, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugTypeBasic", - .opcode = 2, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugTypePointer", - .opcode = 3, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugTypeQualifier", - .opcode = 4, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugTypeArray", - .opcode = 5, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .variadic }, - }, - }, - .{ - .name = "DebugTypeVector", - .opcode = 6, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugTypedef", - .opcode = 7, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugTypeFunction", - .opcode = 8, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .variadic }, - }, - }, - .{ - .name = "DebugTypeEnum", - .opcode = 9, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .pair_id_ref_id_ref, .quantifier = .variadic }, - }, - }, - .{ - .name = "DebugTypeComposite", - .opcode = 10, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .variadic }, - }, - }, - .{ - .name = "DebugTypeMember", - .opcode = 11, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "DebugTypeInheritance", - .opcode = 12, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugTypePtrToMember", - .opcode = 13, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugTypeTemplate", - .opcode = 14, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .variadic }, - }, - }, - .{ - .name = "DebugTypeTemplateParameter", - .opcode = 15, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugTypeTemplateTemplateParameter", - .opcode = 16, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugTypeTemplateParameterPack", - .opcode = 17, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .variadic }, - }, - }, - .{ - .name = "DebugGlobalVariable", - .opcode = 18, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "DebugFunctionDeclaration", - .opcode = 19, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugFunction", - .opcode = 20, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "DebugLexicalBlock", - .opcode = 21, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "DebugLexicalBlockDiscriminator", - .opcode = 22, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugScope", - .opcode = 23, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "DebugNoScope", - .opcode = 24, - .operands = &.{}, - }, - .{ - .name = "DebugInlinedAt", - .opcode = 25, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "DebugLocalVariable", - .opcode = 26, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "DebugInlinedVariable", - .opcode = 27, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugDeclare", - .opcode = 28, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .variadic }, - }, - }, - .{ - .name = "DebugValue", - .opcode = 29, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .variadic }, - }, - }, - .{ - .name = "DebugOperation", - .opcode = 30, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .variadic }, - }, - }, - .{ - .name = "DebugExpression", - .opcode = 31, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .variadic }, - }, - }, - .{ - .name = "DebugMacroDef", - .opcode = 32, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "DebugMacroUndef", - .opcode = 33, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugImportedEntity", - .opcode = 34, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugSource", - .opcode = 35, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .optional }, - }, - }, - .{ - .name = "DebugFunctionDefinition", - .opcode = 101, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugSourceContinued", - .opcode = 102, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugLine", - .opcode = 103, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugNoLine", - .opcode = 104, - .operands = &.{}, - }, - .{ - .name = "DebugBuildIdentifier", - .opcode = 105, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugStoragePath", - .opcode = 106, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugEntryPoint", - .opcode = 107, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - .{ - .name = "DebugTypeMatrix", - .opcode = 108, - .operands = &.{ - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - .{ .kind = .id_ref, .quantifier = .required }, - }, - }, - }, .zig => &.{ .{ .name = "InvocationGlobal", diff --git a/src/link/SpirV.zig b/src/link/SpirV.zig index 3f13883649..8c42d75954 100644 --- a/src/link/SpirV.zig +++ b/src/link/SpirV.zig @@ -23,6 +23,7 @@ const Linker = @This(); base: link.File, module: Module, +cg: CodeGen, pub fn createEmpty( arena: Allocator, @@ -63,6 +64,16 @@ pub fn createEmpty( .arena = arena, .zcu = comp.zcu.?, }, + .cg = .{ + // These fields are populated in generate() + .pt = undefined, + .air = undefined, + .liveness = undefined, + .owner_nav = undefined, + .module = undefined, + .control_flow = .{ .structured = .{} }, + .base_line = undefined, + }, }; errdefer linker.deinit(); @@ -84,6 +95,7 @@ pub fn open( } pub fn deinit(linker: *Linker) void { + linker.cg.deinit(); linker.module.deinit(); } @@ -99,29 +111,41 @@ fn generate( const gpa = zcu.gpa; const structured_cfg = zcu.navFileScope(nav_index).mod.?.structured_cfg; - var cg: CodeGen = .{ + linker.cg.control_flow.deinit(gpa); + linker.cg.args.clearRetainingCapacity(); + linker.cg.inst_results.clearRetainingCapacity(); + linker.cg.id_scratch.clearRetainingCapacity(); + linker.cg.prologue.reset(); + linker.cg.body.reset(); + + linker.cg = .{ .pt = pt, - .module = &linker.module, - .owner_nav = nav_index, .air = air, .liveness = liveness, + .owner_nav = nav_index, + .module = &linker.module, .control_flow = switch (structured_cfg) { true => .{ .structured = .{} }, false => .{ .unstructured = .{} }, }, .base_line = zcu.navSrcLine(nav_index), - }; - defer cg.deinit(); - cg.genNav(do_codegen) catch |err| switch (err) { - error.CodegenFail => switch (zcu.codegenFailMsg(nav_index, cg.error_msg.?)) { + .args = linker.cg.args, + .inst_results = linker.cg.inst_results, + .id_scratch = linker.cg.id_scratch, + .prologue = linker.cg.prologue, + .body = linker.cg.body, + }; + + linker.cg.genNav(do_codegen) catch |err| switch (err) { + error.CodegenFail => switch (zcu.codegenFailMsg(nav_index, linker.cg.error_msg.?)) { error.CodegenFail => {}, error.OutOfMemory => |e| return e, }, else => |other| { // There might be an error that happened *after* linker.error_msg // was already allocated, so be sure to free it. - if (cg.error_msg) |error_msg| { + if (linker.cg.error_msg) |error_msg| { error_msg.deinit(gpa); } diff --git a/tools/gen_spirv_spec.zig b/tools/gen_spirv_spec.zig index b181bd4084..912c4e4de1 100644 --- a/tools/gen_spirv_spec.zig +++ b/tools/gen_spirv_spec.zig @@ -12,6 +12,7 @@ const ExtendedStructSet = std.StringHashMap(void); const Extension = struct { name: []const u8, + opcode_name: []const u8, spec: ExtensionRegistry, }; @@ -44,23 +45,11 @@ const OperandKindMap = std.ArrayHashMap(StringPair, OperandKind, StringPairConte /// Khronos made it so that these names are not defined explicitly, so /// we need to hardcode it (like they did). -/// See https://github.com/KhronosGroup/SPIRV-Registry/ -const set_names = std.StaticStringMap([]const u8).initComptime(.{ - .{ "opencl.std.100", "OpenCL.std" }, - .{ "glsl.std.450", "GLSL.std.450" }, - .{ "opencl.debuginfo.100", "OpenCL.DebugInfo.100" }, - .{ "spv-amd-shader-ballot", "SPV_AMD_shader_ballot" }, - .{ "nonsemantic.shader.debuginfo.100", "NonSemantic.Shader.DebugInfo.100" }, - .{ "nonsemantic.vkspreflection", "NonSemantic.VkspReflection" }, - .{ "nonsemantic.clspvreflection", "NonSemantic.ClspvReflection.6" }, // This version needs to be handled manually - .{ "spv-amd-gcn-shader", "SPV_AMD_gcn_shader" }, - .{ "spv-amd-shader-trinary-minmax", "SPV_AMD_shader_trinary_minmax" }, - .{ "debuginfo", "DebugInfo" }, - .{ "nonsemantic.debugprintf", "NonSemantic.DebugPrintf" }, - .{ "spv-amd-shader-explicit-vertex-parameter", "SPV_AMD_shader_explicit_vertex_parameter" }, - .{ "nonsemantic.debugbreak", "NonSemantic.DebugBreak" }, - .{ "tosa.001000.1", "SPV_EXT_INST_TYPE_TOSA_001000_1" }, - .{ "zig", "zig" }, +/// See https://github.com/KhronosGroup/SPIRV-Registry +const set_names = std.StaticStringMap(struct { []const u8, []const u8 }).initComptime(.{ + .{ "opencl.std.100", .{ "OpenCL.std", "OpenClOpcode" } }, + .{ "glsl.std.450", .{ "GLSL.std.450", "GlslOpcode" } }, + .{ "zig", .{ "zig", "Zig" } }, }); var arena = std.heap.ArenaAllocator.init(std.heap.smp_allocator); @@ -78,7 +67,7 @@ pub fn main() !void { const dir = try std.fs.cwd().openDir(json_path, .{ .iterate = true }); const core_spec = try readRegistry(CoreRegistry, dir, "spirv.core.grammar.json"); - std.sort.block(Instruction, core_spec.instructions, CmpInst{}, CmpInst.lt); + std.mem.sortUnstable(Instruction, core_spec.instructions, CmpInst{}, CmpInst.lt); var exts = std.ArrayList(Extension).init(allocator); @@ -134,14 +123,24 @@ fn readExtRegistry(exts: *std.ArrayList(Extension), dir: std.fs.Dir, sub_path: [ const name = filename["extinst.".len .. filename.len - ".grammar.json".len]; const spec = try readRegistry(ExtensionRegistry, dir, sub_path); + const set_name = set_names.get(name) orelse { + std.log.info("ignored instruction set '{s}'", .{name}); + return; + }; + std.sort.block(Instruction, spec.instructions, CmpInst{}, CmpInst.lt); - try exts.append(.{ .name = set_names.get(name).?, .spec = spec }); + try exts.append(.{ + .name = set_name.@"0", + .opcode_name = set_name.@"1", + .spec = spec, + }); } fn readRegistry(comptime RegistryType: type, dir: std.fs.Dir, path: []const u8) !RegistryType { const spec = try dir.readFileAlloc(allocator, path, std.math.maxInt(usize)); // Required for json parsing. + // TODO: ALI @setEvalBranchQuota(10000); var scanner = std.json.Scanner.initCompleteInput(allocator, spec); @@ -191,7 +190,11 @@ fn tagPriorityScore(tag: []const u8) usize { } } -fn render(writer: *std.io.Writer, registry: CoreRegistry, extensions: []const Extension) !void { +fn render( + writer: *std.io.Writer, + registry: CoreRegistry, + extensions: []const Extension, +) !void { try writer.writeAll( \\//! This file is auto-generated by tools/gen_spirv_spec.zig. \\ @@ -317,13 +320,18 @@ fn render(writer: *std.io.Writer, registry: CoreRegistry, extensions: []const Ex // Note: extensions don't seem to have class. try renderClass(writer, registry.instructions); try renderOperandKind(writer, all_operand_kinds.values()); - try renderOpcodes(writer, registry.instructions, extended_structs); + + try renderOpcodes(writer, "Opcode", true, registry.instructions, extended_structs); + for (extensions) |ext| { + try renderOpcodes(writer, ext.opcode_name, false, ext.spec.instructions, extended_structs); + } + try renderOperandKinds(writer, all_operand_kinds.values(), extended_structs); try renderInstructionSet(writer, registry, extensions, all_operand_kinds); } fn renderInstructionSet( - writer: anytype, + writer: *std.io.Writer, core: CoreRegistry, extensions: []const Extension, all_operand_kinds: OperandKindMap, @@ -358,7 +366,7 @@ fn renderInstructionSet( } fn renderInstructionsCase( - writer: anytype, + writer: *std.io.Writer, set_name: []const u8, instructions: []const Instruction, all_operand_kinds: OperandKindMap, @@ -405,7 +413,7 @@ fn renderInstructionsCase( ); } -fn renderClass(writer: anytype, instructions: []const Instruction) !void { +fn renderClass(writer: *std.io.Writer, instructions: []const Instruction) !void { var class_map = std.StringArrayHashMap(void).init(allocator); for (instructions) |inst| { @@ -454,7 +462,7 @@ fn formatId(identifier: []const u8) std.fmt.Alt(Formatter, Formatter.format) { return .{ .data = .{ .data = identifier } }; } -fn renderOperandKind(writer: anytype, operands: []const OperandKind) !void { +fn renderOperandKind(writer: *std.io.Writer, operands: []const OperandKind) !void { try writer.writeAll( \\pub const OperandKind = enum { \\ opcode, @@ -510,7 +518,7 @@ fn renderOperandKind(writer: anytype, operands: []const OperandKind) !void { try writer.writeAll("};\n}\n};\n"); } -fn renderEnumerant(writer: anytype, enumerant: Enumerant) !void { +fn renderEnumerant(writer: *std.io.Writer, enumerant: Enumerant) !void { try writer.print(".{{.name = \"{s}\", .value = ", .{enumerant.enumerant}); switch (enumerant.value) { .bitflag => |flag| try writer.writeAll(flag), @@ -527,7 +535,9 @@ fn renderEnumerant(writer: anytype, enumerant: Enumerant) !void { } fn renderOpcodes( - writer: anytype, + writer: *std.io.Writer, + opcode_type_name: []const u8, + want_operands: bool, instructions: []const Instruction, extended_structs: ExtendedStructSet, ) !void { @@ -538,7 +548,9 @@ fn renderOpcodes( try aliases.ensureTotalCapacity(instructions.len); for (instructions, 0..) |inst, i| { - if (std.mem.eql(u8, inst.class.?, "@exclude")) continue; + if (inst.class) |class| { + if (std.mem.eql(u8, class, "@exclude")) continue; + } const result = inst_map.getOrPutAssumeCapacity(inst.opcode); if (!result.found_existing) { @@ -562,58 +574,67 @@ fn renderOpcodes( const instructions_indices = inst_map.values(); - try writer.writeAll("pub const Opcode = enum(u16) {\n"); + try writer.print("\npub const {f} = enum(u16) {{\n", .{std.zig.fmtId(opcode_type_name)}); for (instructions_indices) |i| { const inst = instructions[i]; try writer.print("{f} = {},\n", .{ std.zig.fmtId(inst.opname), inst.opcode }); } - try writer.writeAll( - \\ - ); + try writer.writeAll("\n"); for (aliases.items) |alias| { - try writer.print("pub const {f} = Opcode.{f};\n", .{ + try writer.print("pub const {f} = {f}.{f};\n", .{ formatId(instructions[alias.inst].opname), + std.zig.fmtId(opcode_type_name), formatId(instructions[alias.alias].opname), }); } - try writer.writeAll( - \\ - \\pub fn Operands(comptime self: Opcode) type { - \\ return switch (self) { - \\ - ); + if (want_operands) { + try writer.print( + \\ + \\pub fn Operands(comptime self: {f}) type {{ + \\ return switch (self) {{ + \\ + , .{std.zig.fmtId(opcode_type_name)}); - for (instructions_indices) |i| { - const inst = instructions[i]; - try renderOperand(writer, .instruction, inst.opname, inst.operands, extended_structs, false); + for (instructions_indices) |i| { + const inst = instructions[i]; + try renderOperand(writer, .instruction, inst.opname, inst.operands, extended_structs, false); + } + + try writer.writeAll( + \\ }; + \\} + \\ + ); + + try writer.print( + \\pub fn class(self: {f}) Class {{ + \\ return switch (self) {{ + \\ + , .{std.zig.fmtId(opcode_type_name)}); + + for (instructions_indices) |i| { + const inst = instructions[i]; + try writer.print(".{f} => .{f},\n", .{ std.zig.fmtId(inst.opname), formatId(inst.class.?) }); + } + + try writer.writeAll( + \\ }; + \\} + \\ + ); } try writer.writeAll( - \\ }; - \\} - \\pub fn class(self: Opcode) Class { - \\ return switch (self) { - \\ - ); - - for (instructions_indices) |i| { - const inst = instructions[i]; - try writer.print(".{f} => .{f},\n", .{ std.zig.fmtId(inst.opname), formatId(inst.class.?) }); - } - - try writer.writeAll( - \\ }; - \\} \\}; \\ ); } fn renderOperandKinds( - writer: anytype, + writer: *std.io.Writer, kinds: []const OperandKind, extended_structs: ExtendedStructSet, ) !void { @@ -627,7 +648,7 @@ fn renderOperandKinds( } fn renderValueEnum( - writer: anytype, + writer: *std.io.Writer, enumeration: OperandKind, extended_structs: ExtendedStructSet, ) !void { @@ -705,7 +726,7 @@ fn renderValueEnum( } fn renderBitEnum( - writer: anytype, + writer: *std.io.Writer, enumeration: OperandKind, extended_structs: ExtendedStructSet, ) !void { @@ -788,7 +809,7 @@ fn renderBitEnum( } fn renderOperand( - writer: anytype, + writer: *std.io.Writer, kind: enum { @"union", instruction, @@ -872,7 +893,7 @@ fn renderOperand( try writer.writeAll(",\n"); } -fn renderFieldName(writer: anytype, operands: []const Operand, field_index: usize) !void { +fn renderFieldName(writer: *std.io.Writer, operands: []const Operand, field_index: usize) !void { const operand = operands[field_index]; derive_from_kind: {