From c761d8e63582d035666389ba60c7d936f7fca606 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Wed, 12 Aug 2020 02:20:07 +0200 Subject: [PATCH] Make SPIR-V registry parse-able by std.json.parse --- generator/index.zig | 1 + generator/spirv/generator.zig | 14 ++++++ generator/spirv/registry.zig | 89 +++++++++++++++++++---------------- 3 files changed, 63 insertions(+), 41 deletions(-) create mode 100644 generator/spirv/generator.zig diff --git a/generator/index.zig b/generator/index.zig index fba7350..ceb2a6b 100644 --- a/generator/index.zig +++ b/generator/index.zig @@ -1,5 +1,6 @@ pub const generateVk = @import("vulkan/generator.zig").generate; pub const VkGenerateStep = @import("vulkan/build_integration.zig").GenerateStep; +pub const generateSpirv = @import("spirv/generator.zig").generate; pub const ShaderCompileStep = @import("build_integration.zig").ShaderCompileStep; test "main" { diff --git a/generator/spirv/generator.zig b/generator/spirv/generator.zig new file mode 100644 index 0000000..70b454a --- /dev/null +++ b/generator/spirv/generator.zig @@ -0,0 +1,14 @@ +const std = @import("std"); +const reg = @import("registry.zig"); +const Allocator = std.mem.Allocator; + +pub fn generate(allocator: *Allocator, spec_jsons: []const []const u8, writer: anytype) !void { + var arena = std.heap.ArenaAllocator.init(allocator); + defer arena.deinit(); + + const registries = try arena.allocator.alloc(reg.Registry, spec_jsons.len); + for (registries) |*registry, i| { + var tokens = std.json.TokenStream.init(spec_jsons[i]); + registry.* = try std.json.parse(reg.Registry, &tokens, .{.allocator = &arena.allocator}); + } +} diff --git a/generator/spirv/registry.zig b/generator/spirv/registry.zig index 0016fe4..60a1be7 100644 --- a/generator/spirv/registry.zig +++ b/generator/spirv/registry.zig @@ -1,65 +1,72 @@ // See https://www.khronos.org/registry/spir-v/specs/unified1/MachineReadableGrammar.html -pub const Registry = struct { - copyright: []const u8, - registry_type: RegistryType, - instruction: []Instruction, +pub const Registry = union(enum) { + core: CoreRegistry, + extension: ExtensionRegistry, +}; + +pub const CoreRegistry = struct { + copyright: [][]const u8, + magic_number: []const u8, // Hexadecimal representation of the magic number + major_version: u32, + minor_version: u32, + revision: u32, + instructions: []Instruction, operand_kinds: []OperandKind, }; -pub const RegistryType = union(enum) { - core: struct { - magic_number: u32, - major_version: u32, - minor_version: u32, - revision: u32, - }, - extension: struct { - version: u32, - revision: u32, - }, +pub const ExtensionRegistry = struct { + copyright: [][]const u8, + version: u32, + minor_version: u32, + revision: u32, + instructions: []Instruction, + operand_kinds: []OperandKind, }; pub const Instruction = struct { opname: []const u8, opcode: u32, - operands: []Operand, - capabilities: [][]const u8, + operands: []Operand = &[_]Operand{}, + capabilities: [][]const u8 = &[_][]const u8{}, + extensions: [][]const u8 = &[_][]const u8{}, }; pub const Operand = struct { kind: []const u8, - quantifier: Quantifier, - name: []const u8, + + /// Either + /// - null: exactly once. + /// - "?": zero or once. + /// - "*": zero or more. + quantifier: ?[]const u8 = null, + name: []const u8 = "", }; -pub const Quantifier = enum { - one, - zero_or_one, - zero_or_more, -}; - -pub const OperandCategory = union(enum) { - bit_enum: []Enumerant, - value_enum: []Enumerant, - id, - literal, - composite: Composite, +pub const OperandCategory = enum { + // Note: non-canonical casing to match Spir-V JSON spec/ + BitEnum, + ValueEnum, + Id, + Literal, + Composite, }; pub const OperandKind = struct { category: OperandCategory, - name: []const u8, - doc: []const u8, + kind: []const u8, + doc: []const u8 = "", + enumerants: ?[]Enumerant = null, + bases: ?[]const []const u8 = null, }; pub const Enumerant = struct { - name: []const u8, - value: u32, // A power of 2 for `.bit_enum`. - capabilities: [][]const u8, - parameters: []Operand, // `quantifier` will always be `.one`. -}; - -pub const Composite = struct { - bases: [][]const u8, + enumerant: []const u8, + value: union(enum) { + bitflag: []const u8, // Hexadecimal representation of the value + int: u31, + }, + capabilities: [][]const u8 = &[_][]const u8{}, + extensions: [][]const u8 = &[_][]const u8{}, // Valid for .ValueEnum + parameters: []Operand = &[_]Operand{}, // `quantifier` will always be `null`. };