2020-03-21 14:12:28 +00:00
|
|
|
//! To get started, run this tool with no args and read the help message.
|
|
|
|
//!
|
|
|
|
//! Clang has a file "options.td" which describes all of its command line parameter options.
|
|
|
|
//! When using `zig cc`, Zig acts as a proxy between the user and Clang. It does not need
|
|
|
|
//! to understand all the parameters, but it does need to understand some of them, such as
|
|
|
|
//! the target. This means that Zig must understand when a C command line parameter expects
|
|
|
|
//! to "consume" the next parameter on the command line.
|
|
|
|
//!
|
|
|
|
//! For example, `-z -target` would mean to pass `-target` to the linker, whereas `-E -target`
|
|
|
|
//! would mean that the next parameter specifies the target.
|
|
|
|
|
|
|
|
const std = @import("std");
|
|
|
|
const fs = std.fs;
|
|
|
|
const assert = std.debug.assert;
|
|
|
|
const json = std.json;
|
|
|
|
|
|
|
|
const KnownOpt = struct {
|
|
|
|
name: []const u8,
|
|
|
|
|
|
|
|
/// Corresponds to stage.zig ClangArgIterator.Kind
|
|
|
|
ident: []const u8,
|
|
|
|
};
|
|
|
|
|
|
|
|
const known_options = [_]KnownOpt{
|
|
|
|
.{
|
|
|
|
.name = "target",
|
|
|
|
.ident = "target",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "o",
|
|
|
|
.ident = "o",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "c",
|
|
|
|
.ident = "c",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "l",
|
|
|
|
.ident = "l",
|
|
|
|
},
|
2020-03-21 19:29:52 +00:00
|
|
|
.{
|
|
|
|
.name = "pipe",
|
|
|
|
.ident = "ignore",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "help",
|
2020-03-21 20:38:58 +00:00
|
|
|
.ident = "driver_punt",
|
2020-03-21 19:29:52 +00:00
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "fPIC",
|
|
|
|
.ident = "pic",
|
|
|
|
},
|
2021-06-11 23:56:14 +01:00
|
|
|
.{
|
|
|
|
.name = "fpic",
|
|
|
|
.ident = "pic",
|
|
|
|
},
|
2020-03-21 19:29:52 +00:00
|
|
|
.{
|
|
|
|
.name = "fno-PIC",
|
|
|
|
.ident = "no_pic",
|
|
|
|
},
|
2021-06-11 23:56:14 +01:00
|
|
|
.{
|
|
|
|
.name = "fno-pic",
|
|
|
|
.ident = "no_pic",
|
|
|
|
},
|
2020-11-23 00:28:11 +00:00
|
|
|
.{
|
|
|
|
.name = "fPIE",
|
|
|
|
.ident = "pie",
|
|
|
|
},
|
2021-06-11 23:56:14 +01:00
|
|
|
.{
|
|
|
|
.name = "fpie",
|
|
|
|
.ident = "pie",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "pie",
|
|
|
|
.ident = "pie",
|
|
|
|
},
|
2020-11-23 00:28:11 +00:00
|
|
|
.{
|
|
|
|
.name = "fno-PIE",
|
|
|
|
.ident = "no_pie",
|
|
|
|
},
|
2021-06-11 23:56:14 +01:00
|
|
|
.{
|
|
|
|
.name = "fno-pie",
|
|
|
|
.ident = "no_pie",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "no-pie",
|
|
|
|
.ident = "no_pie",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "nopie",
|
|
|
|
.ident = "no_pie",
|
|
|
|
},
|
2021-01-23 06:36:30 +00:00
|
|
|
.{
|
|
|
|
.name = "flto",
|
|
|
|
.ident = "lto",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "fno-lto",
|
|
|
|
.ident = "no_lto",
|
|
|
|
},
|
2021-06-10 19:25:33 +01:00
|
|
|
.{
|
|
|
|
.name = "funwind-tables",
|
|
|
|
.ident = "unwind_tables",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "fno-unwind-tables",
|
|
|
|
.ident = "no_unwind_tables",
|
|
|
|
},
|
2020-04-04 19:58:24 +01:00
|
|
|
.{
|
|
|
|
.name = "nolibc",
|
|
|
|
.ident = "nostdlib",
|
|
|
|
},
|
2020-03-21 19:29:52 +00:00
|
|
|
.{
|
|
|
|
.name = "nostdlib",
|
|
|
|
.ident = "nostdlib",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "no-standard-libraries",
|
|
|
|
.ident = "nostdlib",
|
|
|
|
},
|
2020-03-27 02:48:37 +00:00
|
|
|
.{
|
|
|
|
.name = "nostdlib++",
|
|
|
|
.ident = "nostdlib_cpp",
|
|
|
|
},
|
2020-04-04 19:58:24 +01:00
|
|
|
.{
|
|
|
|
.name = "nostdinc++",
|
|
|
|
.ident = "nostdlib_cpp",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "nostdlibinc",
|
|
|
|
.ident = "nostdlibinc",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "nostdinc",
|
|
|
|
.ident = "nostdlibinc",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "no-standard-includes",
|
|
|
|
.ident = "nostdlibinc",
|
|
|
|
},
|
2020-03-21 19:29:52 +00:00
|
|
|
.{
|
|
|
|
.name = "shared",
|
|
|
|
.ident = "shared",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "rdynamic",
|
|
|
|
.ident = "rdynamic",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "Wl,",
|
|
|
|
.ident = "wl",
|
|
|
|
},
|
2020-03-28 06:23:56 +00:00
|
|
|
.{
|
|
|
|
.name = "Xlinker",
|
|
|
|
.ident = "for_linker",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "for-linker",
|
|
|
|
.ident = "for_linker",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "for-linker=",
|
|
|
|
.ident = "for_linker",
|
|
|
|
},
|
2020-03-28 07:35:54 +00:00
|
|
|
.{
|
|
|
|
.name = "z",
|
|
|
|
.ident = "linker_input_z",
|
|
|
|
},
|
2020-03-21 20:38:58 +00:00
|
|
|
.{
|
|
|
|
.name = "E",
|
2020-09-26 04:52:02 +01:00
|
|
|
.ident = "preprocess_only",
|
2020-03-22 00:32:48 +00:00
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "preprocess",
|
2020-09-26 04:52:02 +01:00
|
|
|
.ident = "preprocess_only",
|
2020-03-21 20:38:58 +00:00
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "S",
|
2020-09-26 04:52:02 +01:00
|
|
|
.ident = "asm_only",
|
2020-03-21 20:38:58 +00:00
|
|
|
},
|
2020-03-22 00:32:48 +00:00
|
|
|
.{
|
|
|
|
.name = "assemble",
|
2020-09-26 04:52:02 +01:00
|
|
|
.ident = "asm_only",
|
2020-03-22 00:32:48 +00:00
|
|
|
},
|
2020-10-07 19:27:35 +01:00
|
|
|
.{
|
|
|
|
.name = "O0",
|
|
|
|
.ident = "optimize",
|
|
|
|
},
|
2020-03-22 02:30:46 +00:00
|
|
|
.{
|
|
|
|
.name = "O1",
|
|
|
|
.ident = "optimize",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "O2",
|
|
|
|
.ident = "optimize",
|
|
|
|
},
|
2020-10-07 19:27:35 +01:00
|
|
|
// O3 is only detected from the joined "-O" option
|
|
|
|
.{
|
|
|
|
.name = "O4",
|
|
|
|
.ident = "optimize",
|
|
|
|
},
|
2020-03-22 02:30:46 +00:00
|
|
|
.{
|
|
|
|
.name = "Og",
|
|
|
|
.ident = "optimize",
|
|
|
|
},
|
2020-10-07 19:27:35 +01:00
|
|
|
.{
|
|
|
|
.name = "Os",
|
|
|
|
.ident = "optimize",
|
|
|
|
},
|
|
|
|
// Oz is only detected from the joined "-O" option
|
2020-03-22 02:30:46 +00:00
|
|
|
.{
|
|
|
|
.name = "O",
|
|
|
|
.ident = "optimize",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "Ofast",
|
|
|
|
.ident = "optimize",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "optimize",
|
|
|
|
.ident = "optimize",
|
|
|
|
},
|
2020-10-07 19:27:35 +01:00
|
|
|
.{
|
|
|
|
.name = "g1",
|
|
|
|
.ident = "debug",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "gline-tables-only",
|
|
|
|
.ident = "debug",
|
|
|
|
},
|
2020-03-22 02:30:46 +00:00
|
|
|
.{
|
|
|
|
.name = "g",
|
|
|
|
.ident = "debug",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "debug",
|
|
|
|
.ident = "debug",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "g-dwarf",
|
|
|
|
.ident = "debug",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "g-dwarf-2",
|
|
|
|
.ident = "debug",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "g-dwarf-3",
|
|
|
|
.ident = "debug",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "g-dwarf-4",
|
|
|
|
.ident = "debug",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "g-dwarf-5",
|
|
|
|
.ident = "debug",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "fsanitize",
|
|
|
|
.ident = "sanitize",
|
|
|
|
},
|
2020-03-25 16:05:33 +00:00
|
|
|
.{
|
|
|
|
.name = "T",
|
|
|
|
.ident = "linker_script",
|
|
|
|
},
|
2020-03-25 23:32:12 +00:00
|
|
|
.{
|
|
|
|
.name = "###",
|
2020-11-19 22:30:16 +00:00
|
|
|
.ident = "dry_run",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "v",
|
|
|
|
.ident = "verbose",
|
2020-03-25 23:32:12 +00:00
|
|
|
},
|
2020-04-01 10:22:19 +01:00
|
|
|
.{
|
|
|
|
.name = "L",
|
2020-04-01 23:05:06 +01:00
|
|
|
.ident = "lib_dir",
|
2020-04-01 10:22:19 +01:00
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "library-directory",
|
2020-04-01 23:05:06 +01:00
|
|
|
.ident = "lib_dir",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "mcpu",
|
|
|
|
.ident = "mcpu",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "march",
|
|
|
|
.ident = "mcpu",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "mtune",
|
|
|
|
.ident = "mcpu",
|
2020-04-01 10:22:19 +01:00
|
|
|
},
|
2021-01-12 05:01:16 +00:00
|
|
|
.{
|
|
|
|
.name = "mred-zone",
|
|
|
|
.ident = "red_zone",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "mno-red-zone",
|
|
|
|
.ident = "no_red_zone",
|
|
|
|
},
|
2021-09-30 19:49:13 +01:00
|
|
|
.{
|
|
|
|
.name = "fomit-frame-pointer",
|
|
|
|
.ident = "omit_frame_pointer",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "fno-omit-frame-pointer",
|
|
|
|
.ident = "no_omit_frame_pointer",
|
|
|
|
},
|
2021-11-22 00:00:41 +00:00
|
|
|
.{
|
|
|
|
.name = "ffunction-sections",
|
|
|
|
.ident = "function_sections",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "fno-function-sections",
|
|
|
|
.ident = "no_function_sections",
|
|
|
|
},
|
2021-11-22 00:07:18 +00:00
|
|
|
.{
|
|
|
|
.name = "fcolor-diagnostics",
|
|
|
|
.ident = "color_diagnostics",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "fno-color-diagnostics",
|
|
|
|
.ident = "no_color_diagnostics",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "fcaret-diagnostics",
|
|
|
|
.ident = "color_diagnostics",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "fno-caret-diagnostics",
|
|
|
|
.ident = "no_color_diagnostics",
|
|
|
|
},
|
2020-04-02 20:47:27 +01:00
|
|
|
.{
|
|
|
|
.name = "MD",
|
|
|
|
.ident = "dep_file",
|
|
|
|
},
|
2021-03-05 01:14:00 +00:00
|
|
|
.{
|
|
|
|
.name = "write-dependencies",
|
|
|
|
.ident = "dep_file",
|
|
|
|
},
|
2020-04-02 20:47:27 +01:00
|
|
|
.{
|
|
|
|
.name = "MV",
|
|
|
|
.ident = "dep_file",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "MF",
|
|
|
|
.ident = "dep_file",
|
|
|
|
},
|
2020-04-03 02:15:36 +01:00
|
|
|
.{
|
|
|
|
.name = "MT",
|
|
|
|
.ident = "dep_file",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "MG",
|
|
|
|
.ident = "dep_file",
|
|
|
|
},
|
2021-03-05 01:14:00 +00:00
|
|
|
.{
|
|
|
|
.name = "print-missing-file-dependencies",
|
|
|
|
.ident = "dep_file",
|
|
|
|
},
|
2020-04-03 02:15:36 +01:00
|
|
|
.{
|
|
|
|
.name = "MJ",
|
|
|
|
.ident = "dep_file",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "MM",
|
2021-03-05 01:14:00 +00:00
|
|
|
.ident = "dep_file_mm",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "user-dependencies",
|
|
|
|
.ident = "dep_file_mm",
|
2020-04-03 02:15:36 +01:00
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "MMD",
|
|
|
|
.ident = "dep_file",
|
|
|
|
},
|
2021-03-05 01:14:00 +00:00
|
|
|
.{
|
|
|
|
.name = "write-user-dependencies",
|
|
|
|
.ident = "dep_file",
|
|
|
|
},
|
2020-04-03 02:15:36 +01:00
|
|
|
.{
|
|
|
|
.name = "MP",
|
|
|
|
.ident = "dep_file",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "MQ",
|
|
|
|
.ident = "dep_file",
|
|
|
|
},
|
2020-04-02 20:59:48 +01:00
|
|
|
.{
|
|
|
|
.name = "F",
|
|
|
|
.ident = "framework_dir",
|
|
|
|
},
|
|
|
|
.{
|
|
|
|
.name = "framework",
|
|
|
|
.ident = "framework",
|
|
|
|
},
|
2021-02-07 21:51:27 +00:00
|
|
|
.{
|
|
|
|
.name = "s",
|
|
|
|
.ident = "strip",
|
|
|
|
},
|
2021-03-14 14:52:35 +00:00
|
|
|
.{
|
|
|
|
.name = "dynamiclib",
|
|
|
|
.ident = "shared",
|
|
|
|
},
|
2021-06-09 09:07:06 +01:00
|
|
|
.{
|
|
|
|
.name = "mexec-model",
|
|
|
|
.ident = "exec_model",
|
2021-06-11 04:13:43 +01:00
|
|
|
},
|
2021-09-17 00:37:21 +01:00
|
|
|
.{
|
|
|
|
.name = "emit-llvm",
|
|
|
|
.ident = "emit_llvm",
|
|
|
|
},
|
2020-03-21 14:12:28 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
const blacklisted_options = [_][]const u8{};
|
|
|
|
|
|
|
|
fn knownOption(name: []const u8) ?[]const u8 {
|
|
|
|
const chopped_name = if (std.mem.endsWith(u8, name, "=")) name[0 .. name.len - 1] else name;
|
|
|
|
for (known_options) |item| {
|
|
|
|
if (std.mem.eql(u8, chopped_name, item.name)) {
|
|
|
|
return item.ident;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2021-11-27 02:59:33 +00:00
|
|
|
const cpu_targets = struct {
|
|
|
|
pub const aarch64 = std.Target.aarch64;
|
|
|
|
pub const arc = std.Target.arc;
|
|
|
|
pub const amdgpu = std.Target.amdgpu;
|
|
|
|
pub const arm = std.Target.arm;
|
|
|
|
pub const avr = std.Target.avr;
|
|
|
|
pub const bpf = std.Target.bpf;
|
|
|
|
pub const hexagon = std.Target.hexagon;
|
|
|
|
pub const mips = std.Target.mips;
|
|
|
|
pub const msp430 = std.Target.msp430;
|
|
|
|
pub const nvptx = std.Target.nvptx;
|
|
|
|
pub const powerpc = std.Target.powerpc;
|
|
|
|
pub const riscv = std.Target.riscv;
|
|
|
|
pub const sparc = std.Target.sparc;
|
|
|
|
pub const spirv = std.Target.spirv;
|
|
|
|
pub const systemz = std.Target.systemz;
|
|
|
|
pub const ve = std.Target.ve;
|
|
|
|
pub const wasm = std.Target.wasm;
|
|
|
|
pub const x86 = std.Target.x86;
|
|
|
|
};
|
|
|
|
|
2020-03-21 14:12:28 +00:00
|
|
|
pub fn main() anyerror!void {
|
|
|
|
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
|
|
|
defer arena.deinit();
|
2021-10-29 02:03:15 +01:00
|
|
|
<<<<<<< HEAD
|
2020-03-21 14:12:28 +00:00
|
|
|
const allocator = &arena.allocator;
|
2021-11-27 02:59:33 +00:00
|
|
|
|
2021-10-29 02:03:15 +01:00
|
|
|
=======
|
|
|
|
|
|
|
|
const allocator = arena.getAllocator();
|
|
|
|
>>>>>>> 11157e318 (allocgate: stage 1 and 2 building)
|
2020-03-21 14:12:28 +00:00
|
|
|
const args = try std.process.argsAlloc(allocator);
|
|
|
|
|
|
|
|
if (args.len <= 1) {
|
|
|
|
usageAndExit(std.io.getStdErr(), args[0], 1);
|
|
|
|
}
|
|
|
|
if (std.mem.eql(u8, args[1], "--help")) {
|
|
|
|
usageAndExit(std.io.getStdOut(), args[0], 0);
|
|
|
|
}
|
|
|
|
if (args.len < 3) {
|
|
|
|
usageAndExit(std.io.getStdErr(), args[0], 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
const llvm_tblgen_exe = args[1];
|
|
|
|
if (std.mem.startsWith(u8, llvm_tblgen_exe, "-")) {
|
|
|
|
usageAndExit(std.io.getStdErr(), args[0], 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
const llvm_src_root = args[2];
|
|
|
|
if (std.mem.startsWith(u8, llvm_src_root, "-")) {
|
|
|
|
usageAndExit(std.io.getStdErr(), args[0], 1);
|
|
|
|
}
|
|
|
|
|
2021-11-27 02:59:33 +00:00
|
|
|
var llvm_to_zig_cpu_features = std.StringHashMap([]const u8).init(allocator);
|
|
|
|
|
|
|
|
inline for (@typeInfo(cpu_targets).Struct.decls) |decl| {
|
|
|
|
const Feature = @field(cpu_targets, decl.name).Feature;
|
|
|
|
const all_features = @field(cpu_targets, decl.name).all_features;
|
|
|
|
|
|
|
|
for (all_features) |feat, i| {
|
|
|
|
const llvm_name = feat.llvm_name orelse continue;
|
|
|
|
const zig_feat = @intToEnum(Feature, i);
|
|
|
|
const zig_name = @tagName(zig_feat);
|
|
|
|
try llvm_to_zig_cpu_features.put(llvm_name, zig_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-21 14:12:28 +00:00
|
|
|
const child_args = [_][]const u8{
|
|
|
|
llvm_tblgen_exe,
|
|
|
|
"--dump-json",
|
2021-01-12 05:01:16 +00:00
|
|
|
try std.fmt.allocPrint(allocator, "{s}/clang/include/clang/Driver/Options.td", .{llvm_src_root}),
|
|
|
|
try std.fmt.allocPrint(allocator, "-I={s}/llvm/include", .{llvm_src_root}),
|
|
|
|
try std.fmt.allocPrint(allocator, "-I={s}/clang/include/clang/Driver", .{llvm_src_root}),
|
2020-03-21 14:12:28 +00:00
|
|
|
};
|
|
|
|
|
2020-03-30 19:23:22 +01:00
|
|
|
const child_result = try std.ChildProcess.exec(.{
|
2020-03-21 14:12:28 +00:00
|
|
|
.allocator = allocator,
|
|
|
|
.argv = &child_args,
|
|
|
|
.max_output_bytes = 100 * 1024 * 1024,
|
|
|
|
});
|
|
|
|
|
2021-11-27 02:59:33 +00:00
|
|
|
std.debug.print("{s}\n", .{child_result.stderr});
|
2020-03-21 14:12:28 +00:00
|
|
|
|
|
|
|
const json_text = switch (child_result.term) {
|
|
|
|
.Exited => |code| if (code == 0) child_result.stdout else {
|
2021-11-27 02:59:33 +00:00
|
|
|
std.debug.print("llvm-tblgen exited with code {d}\n", .{code});
|
2020-03-21 14:12:28 +00:00
|
|
|
std.process.exit(1);
|
|
|
|
},
|
|
|
|
else => {
|
2021-11-27 02:59:33 +00:00
|
|
|
std.debug.print("llvm-tblgen crashed\n", .{});
|
2020-03-21 14:12:28 +00:00
|
|
|
std.process.exit(1);
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
var parser = json.Parser.init(allocator, false);
|
|
|
|
const tree = try parser.parse(json_text);
|
|
|
|
const root_map = &tree.root.Object;
|
|
|
|
|
2020-03-21 19:29:52 +00:00
|
|
|
var all_objects = std.ArrayList(*json.ObjectMap).init(allocator);
|
2020-03-21 14:12:28 +00:00
|
|
|
{
|
|
|
|
var it = root_map.iterator();
|
|
|
|
it_map: while (it.next()) |kv| {
|
2021-06-07 02:24:49 +01:00
|
|
|
if (kv.key_ptr.len == 0) continue;
|
|
|
|
if (kv.key_ptr.*[0] == '!') continue;
|
|
|
|
if (kv.value_ptr.* != .Object) continue;
|
|
|
|
if (!kv.value_ptr.Object.contains("NumArgs")) continue;
|
|
|
|
if (!kv.value_ptr.Object.contains("Name")) continue;
|
2020-03-21 14:12:28 +00:00
|
|
|
for (blacklisted_options) |blacklisted_key| {
|
2021-06-07 02:24:49 +01:00
|
|
|
if (std.mem.eql(u8, blacklisted_key, kv.key_ptr.*)) continue :it_map;
|
2020-03-21 14:12:28 +00:00
|
|
|
}
|
2021-06-07 02:24:49 +01:00
|
|
|
if (kv.value_ptr.Object.get("Name").?.String.len == 0) continue;
|
|
|
|
try all_objects.append(&kv.value_ptr.Object);
|
2020-03-21 14:12:28 +00:00
|
|
|
}
|
|
|
|
}
|
2020-03-21 19:29:52 +00:00
|
|
|
// Some options have multiple matches. As an example, "-Wl,foo" matches both
|
|
|
|
// "W" and "Wl,". So we sort this list in order of descending priority.
|
2020-11-06 18:54:08 +00:00
|
|
|
std.sort.sort(*json.ObjectMap, all_objects.items, {}, objectLessThan);
|
2020-03-21 14:12:28 +00:00
|
|
|
|
2021-01-06 01:57:18 +00:00
|
|
|
var buffered_stdout = std.io.bufferedWriter(std.io.getStdOut().writer());
|
|
|
|
const stdout = buffered_stdout.writer();
|
2020-03-21 14:12:28 +00:00
|
|
|
try stdout.writeAll(
|
|
|
|
\\// This file is generated by tools/update_clang_options.zig.
|
|
|
|
\\// zig fmt: off
|
2021-08-31 02:47:00 +01:00
|
|
|
\\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;
|
2021-11-27 02:59:33 +00:00
|
|
|
\\const m = clang_options.m;
|
2020-03-21 14:12:28 +00:00
|
|
|
\\pub const data = blk: { @setEvalBranchQuota(6000); break :blk &[_]CliArg{
|
|
|
|
\\
|
|
|
|
);
|
|
|
|
|
2020-11-06 18:54:08 +00:00
|
|
|
for (all_objects.items) |obj| {
|
2020-09-26 04:52:02 +01:00
|
|
|
const name = obj.get("Name").?.String;
|
2020-03-21 14:12:28 +00:00
|
|
|
var pd1 = false;
|
|
|
|
var pd2 = false;
|
|
|
|
var pslash = false;
|
2020-11-06 18:54:08 +00:00
|
|
|
for (obj.get("Prefixes").?.Array.items) |prefix_json| {
|
2020-03-21 14:12:28 +00:00
|
|
|
const prefix = prefix_json.String;
|
|
|
|
if (std.mem.eql(u8, prefix, "-")) {
|
|
|
|
pd1 = true;
|
|
|
|
} else if (std.mem.eql(u8, prefix, "--")) {
|
|
|
|
pd2 = true;
|
|
|
|
} else if (std.mem.eql(u8, prefix, "/")) {
|
|
|
|
pslash = true;
|
|
|
|
} else {
|
2021-11-27 02:59:33 +00:00
|
|
|
std.debug.print("{s} has unrecognized prefix '{s}'\n", .{ name, prefix });
|
2020-03-21 14:12:28 +00:00
|
|
|
std.process.exit(1);
|
|
|
|
}
|
|
|
|
}
|
2020-03-21 19:29:52 +00:00
|
|
|
const syntax = objSyntax(obj);
|
|
|
|
|
2020-04-03 02:15:36 +01:00
|
|
|
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.
|
2021-01-12 05:01:16 +00:00
|
|
|
try stdout.print("flagpsl(\"{s}\"),\n", .{name});
|
2020-04-03 02:15:36 +01:00
|
|
|
} else if (knownOption(name)) |ident| {
|
2020-10-07 19:27:35 +01:00
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
2020-03-21 14:12:28 +00:00
|
|
|
try stdout.print(
|
|
|
|
\\.{{
|
2021-01-12 05:01:16 +00:00
|
|
|
\\ .name = "{s}",
|
|
|
|
\\ .syntax = {s},
|
|
|
|
\\ .zig_equivalent = .{s},
|
|
|
|
\\ .pd1 = {s},
|
|
|
|
\\ .pd2 = {s},
|
|
|
|
\\ .psl = {s},
|
2020-03-21 14:12:28 +00:00
|
|
|
\\}},
|
|
|
|
\\
|
2020-10-07 19:27:35 +01:00
|
|
|
, .{ name, final_syntax, ident, pd1, pd2, pslash });
|
2020-03-21 19:29:52 +00:00
|
|
|
} else if (pd1 and !pd2 and !pslash and syntax == .flag) {
|
2021-11-27 02:59:33 +00:00
|
|
|
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});
|
|
|
|
}
|
2020-04-03 02:15:36 +01:00
|
|
|
} else if (!pd1 and !pd2 and pslash and syntax == .flag) {
|
2021-01-12 05:01:16 +00:00
|
|
|
try stdout.print("flagpsl(\"{s}\"),\n", .{name});
|
2020-03-21 19:29:52 +00:00
|
|
|
} else if (pd1 and !pd2 and !pslash and syntax == .joined) {
|
2021-01-12 05:01:16 +00:00
|
|
|
try stdout.print("joinpd1(\"{s}\"),\n", .{name});
|
2020-03-21 19:29:52 +00:00
|
|
|
} else if (pd1 and !pd2 and !pslash and syntax == .joined_or_separate) {
|
2021-01-12 05:01:16 +00:00
|
|
|
try stdout.print("jspd1(\"{s}\"),\n", .{name});
|
2020-03-21 19:29:52 +00:00
|
|
|
} else if (pd1 and !pd2 and !pslash and syntax == .separate) {
|
2021-01-12 05:01:16 +00:00
|
|
|
try stdout.print("sepd1(\"{s}\"),\n", .{name});
|
2020-03-21 14:12:28 +00:00
|
|
|
} else {
|
|
|
|
try stdout.print(
|
|
|
|
\\.{{
|
2021-01-12 05:01:16 +00:00
|
|
|
\\ .name = "{s}",
|
|
|
|
\\ .syntax = {s},
|
2020-03-21 14:12:28 +00:00
|
|
|
\\ .zig_equivalent = .other,
|
2021-01-12 05:01:16 +00:00
|
|
|
\\ .pd1 = {s},
|
|
|
|
\\ .pd2 = {s},
|
|
|
|
\\ .psl = {s},
|
2020-03-21 14:12:28 +00:00
|
|
|
\\}},
|
|
|
|
\\
|
2020-03-21 19:29:52 +00:00
|
|
|
, .{ name, syntax, pd1, pd2, pslash });
|
2020-03-21 14:12:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
try stdout.writeAll(
|
|
|
|
\\};};
|
|
|
|
\\
|
|
|
|
);
|
|
|
|
|
2021-01-06 01:57:18 +00:00
|
|
|
try buffered_stdout.flush();
|
2020-03-21 14:12:28 +00:00
|
|
|
}
|
|
|
|
|
2020-03-21 19:29:52 +00:00
|
|
|
// 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,
|
|
|
|
comptime fmt: []const u8,
|
|
|
|
options: std.fmt.FormatOptions,
|
2020-09-26 04:52:02 +01:00
|
|
|
out_stream: anytype,
|
2020-03-21 19:29:52 +00:00
|
|
|
) !void {
|
2021-06-20 02:10:22 +01:00
|
|
|
_ = fmt;
|
|
|
|
_ = options;
|
2020-03-21 19:29:52 +00:00
|
|
|
switch (self) {
|
2021-01-12 05:01:16 +00:00
|
|
|
.multi_arg => |n| return out_stream.print(".{{.{s}={}}}", .{ @tagName(self), n }),
|
|
|
|
else => return out_stream.print(".{s}", .{@tagName(self)}),
|
2020-03-21 19:29:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
fn objSyntax(obj: *json.ObjectMap) Syntax {
|
2020-09-26 04:52:02 +01:00
|
|
|
const num_args = @intCast(u8, obj.get("NumArgs").?.Integer);
|
2020-11-06 18:54:08 +00:00
|
|
|
for (obj.get("!superclasses").?.Array.items) |superclass_json| {
|
2020-03-21 19:29:52 +00:00
|
|
|
const superclass = superclass_json.String;
|
|
|
|
if (std.mem.eql(u8, superclass, "Joined")) {
|
|
|
|
return .joined;
|
|
|
|
} else if (std.mem.eql(u8, superclass, "CLJoined")) {
|
|
|
|
return .joined;
|
|
|
|
} else if (std.mem.eql(u8, superclass, "CLIgnoredJoined")) {
|
|
|
|
return .joined;
|
|
|
|
} else if (std.mem.eql(u8, superclass, "CLCompileJoined")) {
|
|
|
|
return .joined;
|
|
|
|
} else if (std.mem.eql(u8, superclass, "JoinedOrSeparate")) {
|
|
|
|
return .joined_or_separate;
|
|
|
|
} else if (std.mem.eql(u8, superclass, "CLJoinedOrSeparate")) {
|
|
|
|
return .joined_or_separate;
|
|
|
|
} else if (std.mem.eql(u8, superclass, "CLCompileJoinedOrSeparate")) {
|
|
|
|
return .joined_or_separate;
|
|
|
|
} else if (std.mem.eql(u8, superclass, "Flag")) {
|
|
|
|
return .flag;
|
|
|
|
} else if (std.mem.eql(u8, superclass, "CLFlag")) {
|
|
|
|
return .flag;
|
|
|
|
} else if (std.mem.eql(u8, superclass, "CLIgnoredFlag")) {
|
|
|
|
return .flag;
|
|
|
|
} else if (std.mem.eql(u8, superclass, "Separate")) {
|
|
|
|
return .separate;
|
|
|
|
} else if (std.mem.eql(u8, superclass, "JoinedAndSeparate")) {
|
|
|
|
return .joined_and_separate;
|
|
|
|
} else if (std.mem.eql(u8, superclass, "CommaJoined")) {
|
|
|
|
return .comma_joined;
|
|
|
|
} else if (std.mem.eql(u8, superclass, "CLRemainingArgsJoined")) {
|
|
|
|
return .remaining_args_joined;
|
|
|
|
} else if (std.mem.eql(u8, superclass, "MultiArg")) {
|
|
|
|
return .{ .multi_arg = num_args };
|
|
|
|
}
|
|
|
|
}
|
2020-09-26 04:52:02 +01:00
|
|
|
const name = obj.get("Name").?.String;
|
2020-03-21 19:29:52 +00:00
|
|
|
if (std.mem.eql(u8, name, "<input>")) {
|
|
|
|
return .flag;
|
|
|
|
} else if (std.mem.eql(u8, name, "<unknown>")) {
|
|
|
|
return .flag;
|
|
|
|
}
|
2020-09-26 04:52:02 +01:00
|
|
|
const kind_def = obj.get("Kind").?.Object.get("def").?.String;
|
2020-03-21 19:29:52 +00:00
|
|
|
if (std.mem.eql(u8, kind_def, "KIND_FLAG")) {
|
|
|
|
return .flag;
|
|
|
|
}
|
2020-09-26 04:52:02 +01:00
|
|
|
const key = obj.get("!name").?.String;
|
2021-11-27 02:59:33 +00:00
|
|
|
std.debug.print("{s} (key {s}) has unrecognized superclasses:\n", .{ name, key });
|
2020-11-06 18:54:08 +00:00
|
|
|
for (obj.get("!superclasses").?.Array.items) |superclass_json| {
|
2021-11-27 02:59:33 +00:00
|
|
|
std.debug.print(" {s}\n", .{superclass_json.String});
|
2020-03-21 19:29:52 +00:00
|
|
|
}
|
|
|
|
std.process.exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn syntaxMatchesWithEql(syntax: Syntax) bool {
|
|
|
|
return switch (syntax) {
|
|
|
|
.flag,
|
|
|
|
.separate,
|
|
|
|
.multi_arg,
|
|
|
|
=> true,
|
|
|
|
|
|
|
|
.joined,
|
|
|
|
.joined_or_separate,
|
|
|
|
.joined_and_separate,
|
|
|
|
.comma_joined,
|
|
|
|
.remaining_args_joined,
|
|
|
|
=> false,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-06-12 15:32:02 +01:00
|
|
|
fn objectLessThan(context: void, a: *json.ObjectMap, b: *json.ObjectMap) bool {
|
2021-06-20 02:10:22 +01:00
|
|
|
_ = context;
|
2020-03-21 19:29:52 +00:00
|
|
|
// Priority is determined by exact matches first, followed by prefix matches in descending
|
|
|
|
// length, with key as a final tiebreaker.
|
|
|
|
const a_syntax = objSyntax(a);
|
|
|
|
const b_syntax = objSyntax(b);
|
|
|
|
|
|
|
|
const a_match_with_eql = syntaxMatchesWithEql(a_syntax);
|
|
|
|
const b_match_with_eql = syntaxMatchesWithEql(b_syntax);
|
|
|
|
|
|
|
|
if (a_match_with_eql and !b_match_with_eql) {
|
|
|
|
return true;
|
|
|
|
} else if (!a_match_with_eql and b_match_with_eql) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!a_match_with_eql and !b_match_with_eql) {
|
2020-09-26 04:52:02 +01:00
|
|
|
const a_name = a.get("Name").?.String;
|
|
|
|
const b_name = b.get("Name").?.String;
|
2020-03-21 19:29:52 +00:00
|
|
|
if (a_name.len != b_name.len) {
|
|
|
|
return a_name.len > b_name.len;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-26 04:52:02 +01:00
|
|
|
const a_key = a.get("!name").?.String;
|
|
|
|
const b_key = b.get("!name").?.String;
|
2020-03-21 19:29:52 +00:00
|
|
|
return std.mem.lessThan(u8, a_key, b_key);
|
2020-03-21 14:12:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn usageAndExit(file: fs.File, arg0: []const u8, code: u8) noreturn {
|
2021-01-06 01:57:18 +00:00
|
|
|
file.writer().print(
|
2021-01-12 05:01:16 +00:00
|
|
|
\\Usage: {s} /path/to/llvm-tblgen /path/to/git/llvm/llvm-project
|
2020-10-10 04:09:36 +01:00
|
|
|
\\Alternative Usage: zig run /path/to/git/zig/tools/update_clang_options.zig -- /path/to/llvm-tblgen /path/to/git/llvm/llvm-project
|
2020-03-21 14:12:28 +00:00
|
|
|
\\
|
2020-10-10 04:09:36 +01:00
|
|
|
\\Prints to stdout Zig code which you can use to replace the file src/clang_options_data.zig.
|
2020-03-21 14:12:28 +00:00
|
|
|
\\
|
|
|
|
, .{arg0}) catch std.process.exit(1);
|
|
|
|
std.process.exit(code);
|
|
|
|
}
|