mirror of
https://github.com/ziglang/zig.git
synced 2024-11-25 05:40:16 +00:00
3d5721da23
For module parsing and assembling, we will also need to know all of the SPIR-V extensions and their instructions. This commit updates the generator to generate those. Because there are multiple instruction sets that each have a separate list of Opcodes, no separate enum is generated for these opcodes. Additionally, the previous mechanism for runtime instruction information, `Opcode`'s `fn operands()`, has been removed in favor for `InstructionSet.core.instructions()`. Any mapping from operand to instruction is to be done at runtime. Using a runtime populated hashmap should also be more efficient than the previous mechanism using `stringToEnum`.
110 lines
3.2 KiB
Zig
110 lines
3.2 KiB
Zig
//! See https://www.khronos.org/registry/spir-v/specs/unified1/MachineReadableGrammar.html
|
|
//! and the files in https://github.com/KhronosGroup/SPIRV-Headers/blob/master/include/spirv/unified1/
|
|
//! Note: Non-canonical casing in these structs used to match SPIR-V spec json.
|
|
|
|
const std = @import("std");
|
|
|
|
pub const Registry = union(enum) {
|
|
core: CoreRegistry,
|
|
extension: ExtensionRegistry,
|
|
};
|
|
|
|
pub const CoreRegistry = struct {
|
|
copyright: [][]const u8,
|
|
/// Hexadecimal representation of the magic number
|
|
magic_number: []const u8,
|
|
major_version: u32,
|
|
minor_version: u32,
|
|
revision: u32,
|
|
instruction_printing_class: []InstructionPrintingClass,
|
|
instructions: []Instruction,
|
|
operand_kinds: []OperandKind,
|
|
};
|
|
|
|
pub const ExtensionRegistry = struct {
|
|
copyright: ?[][]const u8 = null,
|
|
version: ?u32 = null,
|
|
revision: u32,
|
|
instructions: []Instruction,
|
|
operand_kinds: []OperandKind = &[_]OperandKind{},
|
|
};
|
|
|
|
pub const InstructionPrintingClass = struct {
|
|
tag: []const u8,
|
|
heading: ?[]const u8 = null,
|
|
};
|
|
|
|
pub const Instruction = struct {
|
|
opname: []const u8,
|
|
class: ?[]const u8 = null, // Note: Only available in the core registry.
|
|
opcode: u32,
|
|
operands: []Operand = &[_]Operand{},
|
|
capabilities: [][]const u8 = &[_][]const u8{},
|
|
// DebugModuleINTEL has this...
|
|
capability: ?[]const u8 = null,
|
|
extensions: [][]const u8 = &[_][]const u8{},
|
|
version: ?[]const u8 = null,
|
|
|
|
lastVersion: ?[]const u8 = null,
|
|
};
|
|
|
|
pub const Operand = struct {
|
|
kind: []const u8,
|
|
/// If this field is 'null', the operand is only expected once.
|
|
quantifier: ?Quantifier = null,
|
|
name: []const u8 = "",
|
|
};
|
|
|
|
pub const Quantifier = enum {
|
|
/// zero or once
|
|
@"?",
|
|
/// zero or more
|
|
@"*",
|
|
};
|
|
|
|
pub const OperandCategory = enum {
|
|
BitEnum,
|
|
ValueEnum,
|
|
Id,
|
|
Literal,
|
|
Composite,
|
|
};
|
|
|
|
pub const OperandKind = struct {
|
|
category: OperandCategory,
|
|
/// The name
|
|
kind: []const u8,
|
|
doc: ?[]const u8 = null,
|
|
enumerants: ?[]Enumerant = null,
|
|
bases: ?[]const []const u8 = null,
|
|
};
|
|
|
|
pub const Enumerant = struct {
|
|
enumerant: []const u8,
|
|
value: union(enum) {
|
|
bitflag: []const u8, // Hexadecimal representation of the value
|
|
int: u31,
|
|
|
|
pub fn jsonParse(
|
|
allocator: std.mem.Allocator,
|
|
source: anytype,
|
|
options: std.json.ParseOptions,
|
|
) std.json.ParseError(@TypeOf(source.*))!@This() {
|
|
_ = options;
|
|
switch (try source.nextAlloc(allocator, .alloc_if_needed)) {
|
|
inline .string, .allocated_string => |s| return @This(){ .bitflag = s },
|
|
inline .number, .allocated_number => |s| return @This(){ .int = try std.fmt.parseInt(u31, s, 10) },
|
|
else => return error.UnexpectedToken,
|
|
}
|
|
}
|
|
pub const jsonStringify = @compileError("not supported");
|
|
},
|
|
capabilities: [][]const u8 = &[_][]const u8{},
|
|
/// Valid for .ValueEnum and .BitEnum
|
|
extensions: [][]const u8 = &[_][]const u8{},
|
|
/// `quantifier` will always be `null`.
|
|
parameters: []Operand = &[_]Operand{},
|
|
version: ?[]const u8 = null,
|
|
lastVersion: ?[]const u8 = null,
|
|
};
|