spirv: define and use extended instruction set opcodes

This commit is contained in:
Ali Cheraghi
2025-08-03 17:02:51 +03:30
parent 246e1de554
commit cd4b03c5ed
7 changed files with 977 additions and 3679 deletions
+291 -288
View File
@@ -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 interfaces 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 => "<end of input>",
.result_id => "<result-id>",
.result_id_assign => "<assigned result-id>",
@@ -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
+310 -290
View File
@@ -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 interfaces 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,
+6 -20
View File
@@ -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.
+1 -11
View File
@@ -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);
}
+254 -3000
View File
@@ -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",
+32 -8
View File
@@ -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);
}
+83 -62
View File
@@ -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: {