| ... | @@ -48,16 +48,13 @@ pub fn main() !void { | ... | @@ -48,16 +48,13 @@ pub fn main() !void { |
| 48 | const a = arena.allocator(); | 48 | const a = arena.allocator(); |
| 49 | | 49 | |
| 50 | const args = try std.process.argsAlloc(a); | 50 | const args = try std.process.argsAlloc(a); |
| 51 | if (args.len != 2) { | 51 | if (args.len != 3) { |
| 52 | usageAndExit(args[0], 1); | 52 | usageAndExit(args[0], 1); |
| 53 | } | 53 | } |
| 54 | | 54 | |
| 55 | const json_path = try std.fs.path.join(a, &.{ args[1], "include/spirv/unified1/" }); | 55 | const json_path = try std.fs.path.join(a, &.{ args[1], "include/spirv/unified1/" }); |
| 56 | const dir = try std.fs.cwd().openDir(json_path, .{ .iterate = true }); | 56 | const dir = try std.fs.cwd().openDir(json_path, .{ .iterate = true }); |
| 57 | | 57 | |
| 58 | // const spec_path = try std.fs.path.join(a, &.{spirv_headers_dir_path, "spirv.core.grammar.json"}); | | |
| 59 | // const core_spec = try std.fs.cwd().readFileAlloc(a, spec_path, std.math.maxInt(usize)); | | |
| 60 | | | |
| 61 | const core_spec = try readRegistry(CoreRegistry, a, dir, "spirv.core.grammar.json"); | 58 | const core_spec = try readRegistry(CoreRegistry, a, dir, "spirv.core.grammar.json"); |
| 62 | std.sort.block(Instruction, core_spec.instructions, CmpInst{}, CmpInst.lt); | 59 | std.sort.block(Instruction, core_spec.instructions, CmpInst{}, CmpInst.lt); |
| 63 | | 60 | |
| ... | @@ -65,24 +62,35 @@ pub fn main() !void { | ... | @@ -65,24 +62,35 @@ pub fn main() !void { |
| 65 | | 62 | |
| 66 | var it = dir.iterate(); | 63 | var it = dir.iterate(); |
| 67 | while (try it.next()) |entry| { | 64 | while (try it.next()) |entry| { |
| 68 | if (entry.kind != .file or !std.mem.startsWith(u8, entry.name, "extinst.")) { | 65 | if (entry.kind != .file) { |
| 69 | continue; | 66 | continue; |
| 70 | } | 67 | } |
| 71 | | 68 | |
| 72 | std.debug.assert(std.mem.endsWith(u8, entry.name, ".grammar.json")); | 69 | try readExtRegistry(&exts, a, dir, entry.name); |
| 73 | const name = entry.name["extinst.".len .. entry.name.len - ".grammar.json".len]; | | |
| 74 | const spec = try readRegistry(ExtensionRegistry, a, dir, entry.name); | | |
| 75 | | | |
| 76 | std.sort.block(Instruction, spec.instructions, CmpInst{}, CmpInst.lt); | | |
| 77 | | | |
| 78 | try exts.append(.{ .name = try a.dupe(u8, name), .spec = spec }); | | |
| 79 | } | 70 | } |
| 80 | | 71 | |
| | 72 | try readExtRegistry(&exts, a, std.fs.cwd(), args[2]); |
| | 73 | |
| 81 | var bw = std.io.bufferedWriter(std.io.getStdOut().writer()); | 74 | var bw = std.io.bufferedWriter(std.io.getStdOut().writer()); |
| 82 | try render(bw.writer(), a, core_spec, exts.items); | 75 | try render(bw.writer(), a, core_spec, exts.items); |
| 83 | try bw.flush(); | 76 | try bw.flush(); |
| 84 | } | 77 | } |
| 85 | | 78 | |
| | 79 | fn readExtRegistry(exts: *std.ArrayList(Extension), a: Allocator, dir: std.fs.Dir, sub_path: []const u8) !void { |
| | 80 | const filename = std.fs.path.basename(sub_path); |
| | 81 | if (!std.mem.startsWith(u8, filename, "extinst.")) { |
| | 82 | return; |
| | 83 | } |
| | 84 | |
| | 85 | std.debug.assert(std.mem.endsWith(u8, filename, ".grammar.json")); |
| | 86 | const name = filename["extinst.".len .. filename.len - ".grammar.json".len]; |
| | 87 | const spec = try readRegistry(ExtensionRegistry, a, dir, sub_path); |
| | 88 | |
| | 89 | std.sort.block(Instruction, spec.instructions, CmpInst{}, CmpInst.lt); |
| | 90 | |
| | 91 | try exts.append(.{ .name = try a.dupe(u8, name), .spec = spec }); |
| | 92 | } |
| | 93 | |
| 86 | fn readRegistry(comptime RegistryType: type, a: Allocator, dir: std.fs.Dir, path: []const u8) !RegistryType { | 94 | fn readRegistry(comptime RegistryType: type, a: Allocator, dir: std.fs.Dir, path: []const u8) !RegistryType { |
| 87 | const spec = try dir.readFileAlloc(a, path, std.math.maxInt(usize)); | 95 | const spec = try dir.readFileAlloc(a, path, std.math.maxInt(usize)); |
| 88 | // Required for json parsing. | 96 | // Required for json parsing. |
| ... | @@ -374,14 +382,19 @@ fn renderInstructionClass(writer: anytype, class: []const u8) !void { | ... | @@ -374,14 +382,19 @@ fn renderInstructionClass(writer: anytype, class: []const u8) !void { |
| 374 | } | 382 | } |
| 375 | | 383 | |
| 376 | fn renderOperandKind(writer: anytype, operands: []const OperandKind) !void { | 384 | fn renderOperandKind(writer: anytype, operands: []const OperandKind) !void { |
| 377 | try writer.writeAll("pub const OperandKind = enum {\n"); | 385 | try writer.writeAll( |
| | 386 | \\pub const OperandKind = enum { |
| | 387 | \\ Opcode, |
| | 388 | \\ |
| | 389 | ); |
| 378 | for (operands) |operand| { | 390 | for (operands) |operand| { |
| 379 | try writer.print("{},\n", .{std.zig.fmtId(operand.kind)}); | 391 | try writer.print("{},\n", .{std.zig.fmtId(operand.kind)}); |
| 380 | } | 392 | } |
| 381 | try writer.writeAll( | 393 | try writer.writeAll( |
| 382 | \\ | 394 | \\ |
| 383 | \\pub fn category(self: OperandKind) OperandCategory { | 395 | \\pub fn category(self: OperandKind) OperandCategory { |
| 384 | \\return switch (self) { | 396 | \\ return switch (self) { |
| | 397 | \\ .Opcode => .literal, |
| 385 | \\ | 398 | \\ |
| 386 | ); | 399 | ); |
| 387 | for (operands) |operand| { | 400 | for (operands) |operand| { |
| ... | @@ -395,10 +408,11 @@ fn renderOperandKind(writer: anytype, operands: []const OperandKind) !void { | ... | @@ -395,10 +408,11 @@ fn renderOperandKind(writer: anytype, operands: []const OperandKind) !void { |
| 395 | try writer.print(".{} => .{s},\n", .{ std.zig.fmtId(operand.kind), cat }); | 408 | try writer.print(".{} => .{s},\n", .{ std.zig.fmtId(operand.kind), cat }); |
| 396 | } | 409 | } |
| 397 | try writer.writeAll( | 410 | try writer.writeAll( |
| 398 | \\}; | 411 | \\ }; |
| 399 | \\} | 412 | \\} |
| 400 | \\pub fn enumerants(self: OperandKind) []const Enumerant { | 413 | \\pub fn enumerants(self: OperandKind) []const Enumerant { |
| 401 | \\return switch (self) { | 414 | \\ return switch (self) { |
| | 415 | \\ .Opcode => unreachable, |
| 402 | \\ | 416 | \\ |
| 403 | ); | 417 | ); |
| 404 | for (operands) |operand| { | 418 | for (operands) |operand| { |
| ... | @@ -483,7 +497,9 @@ fn renderOpcodes( | ... | @@ -483,7 +497,9 @@ fn renderOpcodes( |
| 483 | try writer.print("{} = {},\n", .{ std.zig.fmtId(inst.opname), inst.opcode }); | 497 | try writer.print("{} = {},\n", .{ std.zig.fmtId(inst.opname), inst.opcode }); |
| 484 | } | 498 | } |
| 485 | | 499 | |
| 486 | try writer.writeByte('\n'); | 500 | try writer.writeAll( |
| | 501 | \\ |
| | 502 | ); |
| 487 | | 503 | |
| 488 | for (aliases.items) |alias| { | 504 | for (aliases.items) |alias| { |
| 489 | try writer.print("pub const {} = Opcode.{};\n", .{ | 505 | try writer.print("pub const {} = Opcode.{};\n", .{ |
| ... | @@ -495,7 +511,7 @@ fn renderOpcodes( | ... | @@ -495,7 +511,7 @@ fn renderOpcodes( |
| 495 | try writer.writeAll( | 511 | try writer.writeAll( |
| 496 | \\ | 512 | \\ |
| 497 | \\pub fn Operands(comptime self: Opcode) type { | 513 | \\pub fn Operands(comptime self: Opcode) type { |
| 498 | \\return switch (self) { | 514 | \\ return switch (self) { |
| 499 | \\ | 515 | \\ |
| 500 | ); | 516 | ); |
| 501 | | 517 | |
| ... | @@ -505,10 +521,10 @@ fn renderOpcodes( | ... | @@ -505,10 +521,10 @@ fn renderOpcodes( |
| 505 | } | 521 | } |
| 506 | | 522 | |
| 507 | try writer.writeAll( | 523 | try writer.writeAll( |
| 508 | \\}; | 524 | \\ }; |
| 509 | \\} | 525 | \\} |
| 510 | \\pub fn class(self: Opcode) Class { | 526 | \\pub fn class(self: Opcode) Class { |
| 511 | \\return switch (self) { | 527 | \\ return switch (self) { |
| 512 | \\ | 528 | \\ |
| 513 | ); | 529 | ); |
| 514 | | 530 | |
| ... | @@ -519,7 +535,12 @@ fn renderOpcodes( | ... | @@ -519,7 +535,12 @@ fn renderOpcodes( |
| 519 | try writer.writeAll(",\n"); | 535 | try writer.writeAll(",\n"); |
| 520 | } | 536 | } |
| 521 | | 537 | |
| 522 | try writer.writeAll("};\n}\n};\n"); | 538 | try writer.writeAll( |
| | 539 | \\ }; |
| | 540 | \\} |
| | 541 | \\}; |
| | 542 | \\ |
| | 543 | ); |
| 523 | } | 544 | } |
| 524 | | 545 | |
| 525 | fn renderOperandKinds( | 546 | fn renderOperandKinds( |
| ... | @@ -844,7 +865,7 @@ fn parseHexInt(text: []const u8) !u31 { | ... | @@ -844,7 +865,7 @@ fn parseHexInt(text: []const u8) !u31 { |
| 844 | | 865 | |
| 845 | fn usageAndExit(arg0: []const u8, code: u8) noreturn { | 866 | fn usageAndExit(arg0: []const u8, code: u8) noreturn { |
| 846 | std.io.getStdErr().writer().print( | 867 | std.io.getStdErr().writer().print( |
| 847 | \\Usage: {s} <SPIRV-Headers repository path> | 868 | \\Usage: {s} <SPIRV-Headers repository path> <path/to/zig/src/codegen/spirv/extinst.zig.grammar.json> |
| 848 | \\ | 869 | \\ |
| 849 | \\Generates Zig bindings for SPIR-V specifications found in the SPIRV-Headers | 870 | \\Generates Zig bindings for SPIR-V specifications found in the SPIRV-Headers |
| 850 | \\repository. The result, printed to stdout, should be used to update | 871 | \\repository. The result, printed to stdout, should be used to update |