mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-04-26 13:01:34 +03:00
CLI: use zon format for clang options
- plain old data ftw - 177K -> 151K - data bypasses Sema This change is not really important but it was nice to explore best practices for data like this. When I measured building the compiler, I found no statistically significant difference in compilation time.
This commit is contained in:
+28
-101
@@ -13,6 +13,8 @@ const std = @import("std");
|
||||
const Io = std.Io;
|
||||
const assert = std.debug.assert;
|
||||
const json = std.json;
|
||||
const fatal = std.process.fatal;
|
||||
const ClangCliParam = std.zig.ClangCliParam;
|
||||
|
||||
const KnownOpt = struct {
|
||||
name: []const u8,
|
||||
@@ -682,13 +684,9 @@ pub fn main(init: std.process.Init) !void {
|
||||
|
||||
const json_text = switch (child_result.term) {
|
||||
.exited => |code| if (code == 0) child_result.stdout else {
|
||||
std.debug.print("llvm-tblgen exited with code {d}\n", .{code});
|
||||
std.process.exit(1);
|
||||
},
|
||||
else => {
|
||||
std.debug.print("llvm-tblgen crashed\n", .{});
|
||||
std.process.exit(1);
|
||||
fatal("llvm-tblgen exited with code {d}", .{code});
|
||||
},
|
||||
else => fatal("llvm-tblgen crashed", .{}),
|
||||
};
|
||||
|
||||
const parsed = try json.parseFromSlice(json.Value, arena, json_text, .{});
|
||||
@@ -718,18 +716,13 @@ pub fn main(init: std.process.Init) !void {
|
||||
try stdout.writeAll(
|
||||
\\// This file is generated by tools/update_clang_options.zig.
|
||||
\\// zig fmt: off
|
||||
\\const clang_options = @import("clang_options.zig");
|
||||
\\const CliArg = clang_options.CliArg;
|
||||
\\const flagpd1 = clang_options.flagpd1;
|
||||
\\const flagpsl = clang_options.flagpsl;
|
||||
\\const joinpd1 = clang_options.joinpd1;
|
||||
\\const jspd1 = clang_options.jspd1;
|
||||
\\const sepd1 = clang_options.sepd1;
|
||||
\\const m = clang_options.m;
|
||||
\\pub const data = blk: { @setEvalBranchQuota(6000); break :blk &[_]CliArg{
|
||||
\\
|
||||
);
|
||||
|
||||
var serializer: std.zon.Serializer = .{ .writer = stdout };
|
||||
var top = try serializer.beginTuple(.{});
|
||||
serializer.indent_level = 0;
|
||||
|
||||
for (all_objects.items) |obj| {
|
||||
const name = obj.get("Name").?.string;
|
||||
var pd1 = false;
|
||||
@@ -744,113 +737,48 @@ pub fn main(init: std.process.Init) !void {
|
||||
} else if (std.mem.eql(u8, prefix, "/")) {
|
||||
pslash = true;
|
||||
} else {
|
||||
std.debug.print("{s} has unrecognized prefix '{s}'\n", .{ name, prefix });
|
||||
std.process.exit(1);
|
||||
fatal("{s} has unrecognized prefix '{s}'", .{ name, prefix });
|
||||
}
|
||||
}
|
||||
const syntax = objSyntax(obj) orelse continue;
|
||||
|
||||
var element: ClangCliParam = .{
|
||||
.name = name,
|
||||
.syntax = syntax,
|
||||
.pd1 = pd1,
|
||||
.pd2 = pd2,
|
||||
.psl = pslash,
|
||||
};
|
||||
|
||||
if (std.mem.eql(u8, name, "MT") and syntax == .flag) {
|
||||
// `-MT foo` is ambiguous because there is also an -MT flag
|
||||
// The canonical way to specify the flag is with `/MT` and so we make this
|
||||
// the only way.
|
||||
try stdout.print("flagpsl(\"{s}\"),\n", .{name});
|
||||
element.psl = true;
|
||||
element.pd1 = false;
|
||||
element.pd2 = false;
|
||||
} else if (knownOption(name)) |ident| {
|
||||
|
||||
// Workaround the fact that in 'Options.td' -Ofast is listed as 'joined'
|
||||
const final_syntax = if (std.mem.eql(u8, name, "Ofast")) .flag else syntax;
|
||||
|
||||
try stdout.print(
|
||||
\\.{{
|
||||
\\ .name = "{s}",
|
||||
\\ .syntax = {f},
|
||||
\\ .zig_equivalent = .{s},
|
||||
\\ .pd1 = {},
|
||||
\\ .pd2 = {},
|
||||
\\ .psl = {},
|
||||
\\}},
|
||||
\\
|
||||
, .{ name, final_syntax, ident, pd1, pd2, pslash });
|
||||
if (std.mem.eql(u8, name, "Ofast")) element.syntax = .flag;
|
||||
element.ze = std.meta.stringToEnum(ClangCliParam.ZigEquivalent, ident) orelse fatal("unknown known option: {s}", .{ident});
|
||||
} else if (pd1 and !pd2 and !pslash and syntax == .flag) {
|
||||
if ((std.mem.startsWith(u8, name, "mno-") and
|
||||
llvm_to_zig_cpu_features.contains(name["mno-".len..])) or
|
||||
(std.mem.startsWith(u8, name, "m") and
|
||||
llvm_to_zig_cpu_features.contains(name["m".len..])))
|
||||
{
|
||||
try stdout.print("m(\"{s}\"),\n", .{name});
|
||||
} else {
|
||||
try stdout.print("flagpd1(\"{s}\"),\n", .{name});
|
||||
element.ze = .m;
|
||||
}
|
||||
} else if (!pd1 and !pd2 and pslash and syntax == .flag) {
|
||||
try stdout.print("flagpsl(\"{s}\"),\n", .{name});
|
||||
} else if (pd1 and !pd2 and !pslash and syntax == .joined) {
|
||||
try stdout.print("joinpd1(\"{s}\"),\n", .{name});
|
||||
} else if (pd1 and !pd2 and !pslash and syntax == .joined_or_separate) {
|
||||
try stdout.print("jspd1(\"{s}\"),\n", .{name});
|
||||
} else if (pd1 and !pd2 and !pslash and syntax == .separate) {
|
||||
try stdout.print("sepd1(\"{s}\"),\n", .{name});
|
||||
} else {
|
||||
try stdout.print(
|
||||
\\.{{
|
||||
\\ .name = "{s}",
|
||||
\\ .syntax = {f},
|
||||
\\ .zig_equivalent = .other,
|
||||
\\ .pd1 = {},
|
||||
\\ .pd2 = {},
|
||||
\\ .psl = {},
|
||||
\\}},
|
||||
\\
|
||||
, .{ name, syntax, pd1, pd2, pslash });
|
||||
}
|
||||
try top.field(element, .{ .emit_default_optional_fields = false });
|
||||
}
|
||||
|
||||
try stdout.writeAll(
|
||||
\\};};
|
||||
\\
|
||||
);
|
||||
try top.end();
|
||||
|
||||
try stdout.flush();
|
||||
}
|
||||
|
||||
// TODO we should be able to import clang_options.zig but currently this is problematic because it will
|
||||
// import stage2.zig and that causes a bunch of stuff to get exported
|
||||
const Syntax = union(enum) {
|
||||
/// A flag with no values.
|
||||
flag,
|
||||
|
||||
/// An option which prefixes its (single) value.
|
||||
joined,
|
||||
|
||||
/// An option which is followed by its value.
|
||||
separate,
|
||||
|
||||
/// An option which is either joined to its (non-empty) value, or followed by its value.
|
||||
joined_or_separate,
|
||||
|
||||
/// An option which is both joined to its (first) value, and followed by its (second) value.
|
||||
joined_and_separate,
|
||||
|
||||
/// An option followed by its values, which are separated by commas.
|
||||
comma_joined,
|
||||
|
||||
/// An option which consumes an optional joined argument and any other remaining arguments.
|
||||
remaining_args_joined,
|
||||
|
||||
/// An option which is which takes multiple (separate) arguments.
|
||||
multi_arg: u8,
|
||||
|
||||
pub fn format(
|
||||
self: Syntax,
|
||||
out_stream: *std.Io.Writer,
|
||||
) std.Io.Writer.Error!void {
|
||||
switch (self) {
|
||||
.multi_arg => |n| return out_stream.print(".{{.{t}={d}}}", .{ self, n }),
|
||||
else => return out_stream.print(".{s}", .{@tagName(self)}),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fn objSyntax(obj: *json.ObjectMap) ?Syntax {
|
||||
fn objSyntax(obj: *json.ObjectMap) ?ClangCliParam.Syntax {
|
||||
const num_args = @as(u8, @intCast(obj.get("NumArgs").?.integer));
|
||||
for (obj.get("!superclasses").?.array.items) |superclass_json| {
|
||||
const superclass = superclass_json.string;
|
||||
@@ -911,7 +839,7 @@ fn objSyntax(obj: *json.ObjectMap) ?Syntax {
|
||||
return null;
|
||||
}
|
||||
|
||||
fn syntaxMatchesWithEql(syntax: Syntax) bool {
|
||||
fn syntaxMatchesWithEql(syntax: ClangCliParam.Syntax) bool {
|
||||
return switch (syntax) {
|
||||
.flag,
|
||||
.separate,
|
||||
@@ -966,9 +894,8 @@ fn printUsageAndExit(arg0: []const u8) noreturn {
|
||||
fn printUsage(w: *std.Io.Writer, arg0: []const u8) std.Io.Writer.Error!void {
|
||||
try w.print(
|
||||
\\Usage: {s} /path/to/llvm-tblgen /path/to/git/llvm/llvm-project
|
||||
\\Alternative Usage: zig run /path/to/git/zig/tools/update_clang_options.zig -- /path/to/llvm-tblgen /path/to/git/llvm/llvm-project
|
||||
\\
|
||||
\\Prints to stdout Zig code which you can use to replace the file src/clang_options_data.zig.
|
||||
\\Prints to stdout Zig code which you can use to replace the file src/clang_options.zon.
|
||||
\\
|
||||
, .{arg0});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user