update_cpu_features: Handle targets that don't have LLVM data.

This commit is contained in:
Alex Rønne Petersen 2024-12-17 15:23:50 +01:00
parent b541a7af11
commit 5248f0a909
No known key found for this signature in database

View file

@ -34,10 +34,12 @@ const Feature = struct {
flatten: bool = false,
};
const LlvmTarget = struct {
const ArchTarget = struct {
zig_name: []const u8,
llvm_name: []const u8,
td_name: []const u8,
llvm: ?struct {
name: []const u8,
td_name: []const u8,
},
feature_overrides: []const FeatureOverride = &.{},
extra_cpus: []const Cpu = &.{},
extra_features: []const Feature = &.{},
@ -45,11 +47,13 @@ const LlvmTarget = struct {
branch_quota: ?usize = null,
};
const llvm_targets = [_]LlvmTarget{
const targets = [_]ArchTarget{
.{
.zig_name = "aarch64",
.llvm_name = "AArch64",
.td_name = "AArch64.td",
.llvm = .{
.name = "AArch64",
.td_name = "AArch64",
},
.branch_quota = 2000,
.feature_overrides = &.{
.{
@ -391,8 +395,10 @@ const llvm_targets = [_]LlvmTarget{
},
.{
.zig_name = "amdgcn",
.llvm_name = "AMDGPU",
.td_name = "AMDGPU.td",
.llvm = .{
.name = "AMDGPU",
.td_name = "AMDGPU",
},
.feature_overrides = &.{
.{
.llvm_name = "DumpCode",
@ -418,13 +424,17 @@ const llvm_targets = [_]LlvmTarget{
},
.{
.zig_name = "arc",
.llvm_name = "ARC",
.td_name = "ARC.td",
.llvm = .{
.name = "ARC",
.td_name = "ARC",
},
},
.{
.zig_name = "arm",
.llvm_name = "ARM",
.td_name = "ARM.td",
.llvm = .{
.name = "ARM",
.td_name = "ARM",
},
.branch_quota = 10000,
.feature_overrides = &.{
.{
@ -928,66 +938,90 @@ const llvm_targets = [_]LlvmTarget{
},
.{
.zig_name = "avr",
.llvm_name = "AVR",
.td_name = "AVR.td",
.llvm = .{
.name = "AVR",
.td_name = "AVR",
},
},
.{
.zig_name = "bpf",
.llvm_name = "BPF",
.td_name = "BPF.td",
.llvm = .{
.name = "BPF",
.td_name = "BPF",
},
},
.{
.zig_name = "csky",
.llvm_name = "CSKY",
.td_name = "CSKY.td",
.llvm = .{
.name = "CSKY",
.td_name = "CSKY",
},
},
.{
.zig_name = "hexagon",
.llvm_name = "Hexagon",
.td_name = "Hexagon.td",
.llvm = .{
.name = "Hexagon",
.td_name = "Hexagon",
},
},
.{
.zig_name = "lanai",
.llvm_name = "Lanai",
.td_name = "Lanai.td",
.llvm = .{
.name = "Lanai",
.td_name = "Lanai",
},
},
.{
.zig_name = "loongarch",
.llvm_name = "LoongArch",
.td_name = "LoongArch.td",
.llvm = .{
.name = "LoongArch",
.td_name = "LoongArch",
},
},
.{
.zig_name = "m68k",
.llvm_name = "M68k",
.td_name = "M68k.td",
.llvm = .{
.name = "M68k",
.td_name = "M68k",
},
},
.{
.zig_name = "msp430",
.llvm_name = "MSP430",
.td_name = "MSP430.td",
.llvm = .{
.name = "MSP430",
.td_name = "MSP430",
},
},
.{
.zig_name = "mips",
.llvm_name = "Mips",
.td_name = "Mips.td",
.llvm = .{
.name = "Mips",
.td_name = "Mips",
},
},
.{
.zig_name = "nvptx",
.llvm_name = "NVPTX",
.td_name = "NVPTX.td",
.llvm = .{
.name = "NVPTX",
.td_name = "NVPTX",
},
},
.{
.zig_name = "powerpc",
.llvm_name = "PowerPC",
.td_name = "PPC.td",
.llvm = .{
.name = "PowerPC",
.td_name = "PPC",
},
.omit_cpus = &.{
"ppc32",
},
},
.{
.zig_name = "riscv",
.llvm_name = "RISCV",
.td_name = "RISCV.td",
.llvm = .{
.name = "RISCV",
.td_name = "RISCV",
},
.branch_quota = 2000,
.feature_overrides = &.{
.{
@ -1010,29 +1044,38 @@ const llvm_targets = [_]LlvmTarget{
},
.{
.zig_name = "sparc",
.llvm_name = "Sparc",
.td_name = "Sparc.td",
.llvm = .{
.name = "Sparc",
.td_name = "Sparc",
},
},
// TODO: merge tools/update_spirv_features.zig into this script
//.{
// .zig_name = "spirv",
// .llvm_name = "SPIRV",
// .td_name = "SPIRV.td",
// .llvm = .{
// .name = "SPIRV",
// },
//},
.{
.zig_name = "s390x",
.llvm_name = "SystemZ",
.td_name = "SystemZ.td",
.llvm = .{
.name = "SystemZ",
.td_name = "SystemZ",
},
},
.{
.zig_name = "ve",
.llvm_name = "VE",
.td_name = "VE.td",
.llvm = .{
.name = "VE",
.td_name = "VE",
},
},
.{
.zig_name = "wasm",
.llvm_name = "WebAssembly",
.td_name = "WebAssembly.td",
.llvm = .{
.name = "WebAssembly",
.td_name = "WebAssembly",
},
.extra_features = &.{
.{
.zig_name = "nontrapping_bulk_memory_len0",
@ -1057,8 +1100,10 @@ const llvm_targets = [_]LlvmTarget{
},
.{
.zig_name = "x86",
.llvm_name = "X86",
.td_name = "X86.td",
.llvm = .{
.name = "X86",
.td_name = "X86",
},
.feature_overrides = &.{
.{
.llvm_name = "64bit-mode",
@ -1362,13 +1407,17 @@ const llvm_targets = [_]LlvmTarget{
},
.{
.zig_name = "xcore",
.llvm_name = "XCore",
.td_name = "XCore.td",
.llvm = .{
.name = "XCore",
.td_name = "XCore",
},
},
.{
.zig_name = "xtensa",
.llvm_name = "Xtensa",
.td_name = "Xtensa.td",
.llvm = .{
.name = "Xtensa",
.td_name = "Xtensa",
},
},
};
@ -1413,33 +1462,33 @@ pub fn main() anyerror!void {
var zig_src_dir = try fs.cwd().openDir(zig_src_root, .{});
defer zig_src_dir.close();
const root_progress = std.Progress.start(.{ .estimated_total_items = llvm_targets.len });
const root_progress = std.Progress.start(.{ .estimated_total_items = targets.len });
defer root_progress.end();
if (builtin.single_threaded) {
for (llvm_targets) |llvm_target| {
if (filter) |zig_name| if (!std.mem.eql(u8, llvm_target.zig_name, zig_name)) continue;
for (targets) |target| {
if (filter) |zig_name| if (!std.mem.eql(u8, target.zig_name, zig_name)) continue;
try processOneTarget(.{
.llvm_tblgen_exe = llvm_tblgen_exe,
.llvm_src_root = llvm_src_root,
.zig_src_dir = zig_src_dir,
.root_progress = root_progress,
.llvm_target = llvm_target,
.target = target,
});
}
} else {
var pool: std.Thread.Pool = undefined;
try pool.init(.{ .allocator = arena, .n_jobs = llvm_targets.len });
try pool.init(.{ .allocator = arena, .n_jobs = targets.len });
defer pool.deinit();
for (llvm_targets) |llvm_target| {
if (filter) |zig_name| if (!std.mem.eql(u8, llvm_target.zig_name, zig_name)) continue;
for (targets) |target| {
if (filter) |zig_name| if (!std.mem.eql(u8, target.zig_name, zig_name)) continue;
const job = Job{
.llvm_tblgen_exe = llvm_tblgen_exe,
.llvm_src_root = llvm_src_root,
.zig_src_dir = zig_src_dir,
.root_progress = root_progress,
.llvm_target = llvm_target,
.target = target,
};
try pool.spawn(processOneTarget, .{job});
}
@ -1451,162 +1500,147 @@ const Job = struct {
llvm_src_root: []const u8,
zig_src_dir: std.fs.Dir,
root_progress: std.Progress.Node,
llvm_target: LlvmTarget,
target: ArchTarget,
};
fn processOneTarget(job: Job) void {
errdefer |err| std.debug.panic("panic: {s}", .{@errorName(err)});
const llvm_target = job.llvm_target;
const target = job.target;
var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator);
defer arena_state.deinit();
const arena = arena_state.allocator();
const progress_node = job.root_progress.start(llvm_target.zig_name, 3);
const progress_node = job.root_progress.start(target.zig_name, 3);
defer progress_node.end();
const tblgen_progress = progress_node.start("running llvm-tblgen", 0);
const child_args = [_][]const u8{
job.llvm_tblgen_exe,
"--dump-json",
try std.fmt.allocPrint(arena, "{s}/llvm/lib/Target/{s}/{s}", .{
job.llvm_src_root,
llvm_target.llvm_name,
llvm_target.td_name,
}),
try std.fmt.allocPrint(arena, "-I={s}/llvm/include", .{job.llvm_src_root}),
try std.fmt.allocPrint(arena, "-I={s}/llvm/lib/Target/{s}", .{
job.llvm_src_root, llvm_target.llvm_name,
}),
};
const child_result = try std.process.Child.run(.{
.allocator = arena,
.argv = &child_args,
.max_output_bytes = 500 * 1024 * 1024,
});
tblgen_progress.end();
if (child_result.stderr.len != 0) {
std.debug.print("{s}\n", .{child_result.stderr});
}
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);
},
};
const json_parse_progress = progress_node.start("parsing JSON", 0);
const parsed = try json.parseFromSlice(json.Value, arena, json_text, .{});
defer parsed.deinit();
const root_map = &parsed.value.object;
json_parse_progress.end();
const render_progress = progress_node.start("rendering Zig code", 0);
// So far, LLVM only has a few aliases for the same CPU.
var cpu_aliases = std.StringHashMap(std.SegmentedList(struct {
llvm: []const u8,
zig: []const u8,
}, 4)).init(arena);
{
var it = root_map.iterator();
while (it.next()) |kv| {
if (kv.key_ptr.len == 0) continue;
if (kv.key_ptr.*[0] == '!') continue;
if (kv.value_ptr.* != .object) continue;
if (hasSuperclass(&kv.value_ptr.object, "ProcessorAlias")) {
// Note that `Name` is actually the alias, while `Alias` is the name that will have
// a full `Processor` object defined.
const llvm_alias = kv.value_ptr.object.get("Name").?.string;
const llvm_name = kv.value_ptr.object.get("Alias").?.string;
const gop = try cpu_aliases.getOrPut(try llvmNameToZigName(arena, llvm_name));
if (!gop.found_existing) gop.value_ptr.* = .{};
try gop.value_ptr.append(arena, .{
.llvm = llvm_alias,
.zig = try llvmNameToZigName(arena, llvm_alias),
});
}
}
}
var features_table = std.StringHashMap(Feature).init(arena);
var all_features = std.ArrayList(Feature).init(arena);
var all_cpus = std.ArrayList(Cpu).init(arena);
{
var it = root_map.iterator();
while (it.next()) |kv| {
if (kv.key_ptr.len == 0) continue;
if (kv.key_ptr.*[0] == '!') continue;
if (kv.value_ptr.* != .object) continue;
if (hasSuperclass(&kv.value_ptr.object, "SubtargetFeature")) {
const llvm_name = kv.value_ptr.object.get("Name").?.string;
if (llvm_name.len == 0) continue;
var zig_name = try llvmNameToZigName(arena, llvm_name);
var desc = kv.value_ptr.object.get("Desc").?.string;
var deps = std.ArrayList([]const u8).init(arena);
var omit = false;
var flatten = false;
var omit_deps: []const []const u8 = &.{};
var extra_deps: []const []const u8 = &.{};
for (llvm_target.feature_overrides) |feature_override| {
if (mem.eql(u8, llvm_name, feature_override.llvm_name)) {
if (feature_override.omit) {
// Still put the feature into the table so that we can
// expand dependencies for the feature overrides marked `flatten`.
omit = true;
}
if (feature_override.flatten) {
flatten = true;
}
if (feature_override.zig_name) |override_name| {
zig_name = override_name;
}
if (feature_override.desc) |override_desc| {
desc = override_desc;
}
omit_deps = feature_override.omit_deps;
extra_deps = feature_override.extra_deps;
break;
}
if (target.llvm) |llvm| {
const tblgen_progress = progress_node.start("running llvm-tblgen", 0);
const child_args = [_][]const u8{
job.llvm_tblgen_exe,
"--dump-json",
try std.fmt.allocPrint(arena, "{s}/llvm/lib/Target/{s}/{s}.td", .{
job.llvm_src_root,
llvm.name,
llvm.td_name,
}),
try std.fmt.allocPrint(arena, "-I={s}/llvm/include", .{job.llvm_src_root}),
try std.fmt.allocPrint(arena, "-I={s}/llvm/lib/Target/{s}", .{
job.llvm_src_root, llvm.name,
}),
};
const child_result = try std.process.Child.run(.{
.allocator = arena,
.argv = &child_args,
.max_output_bytes = 500 * 1024 * 1024,
});
tblgen_progress.end();
if (child_result.stderr.len != 0) {
std.debug.print("{s}\n", .{child_result.stderr});
}
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);
},
};
const json_parse_progress = progress_node.start("parsing JSON", 0);
const parsed = try json.parseFromSlice(json.Value, arena, json_text, .{});
defer parsed.deinit();
const root_map = &parsed.value.object;
json_parse_progress.end();
const collate_progress = progress_node.start("collating LLVM data", 0);
// So far, LLVM only has a few aliases for the same CPU.
var cpu_aliases = std.StringHashMap(std.SegmentedList(struct {
llvm: []const u8,
zig: []const u8,
}, 4)).init(arena);
{
var it = root_map.iterator();
while (it.next()) |kv| {
if (kv.key_ptr.len == 0) continue;
if (kv.key_ptr.*[0] == '!') continue;
if (kv.value_ptr.* != .object) continue;
if (hasSuperclass(&kv.value_ptr.object, "ProcessorAlias")) {
// Note that `Name` is actually the alias, while `Alias` is the name that will have
// a full `Processor` object defined.
const llvm_alias = kv.value_ptr.object.get("Name").?.string;
const llvm_name = kv.value_ptr.object.get("Alias").?.string;
const gop = try cpu_aliases.getOrPut(try llvmNameToZigName(arena, llvm_name));
if (!gop.found_existing) gop.value_ptr.* = .{};
try gop.value_ptr.append(arena, .{
.llvm = llvm_alias,
.zig = try llvmNameToZigName(arena, llvm_alias),
});
}
const implies = kv.value_ptr.object.get("Implies").?.array;
for (implies.items) |imply| {
const other_key = imply.object.get("def").?.string;
const other_obj = root_map.get(other_key).?.object;
const other_llvm_name = other_obj.get("Name").?.string;
const other_zig_name = (try llvmFeatureNameToZigNameOmit(
arena,
llvm_target,
other_llvm_name,
)) orelse continue;
for (omit_deps) |omit_dep| {
if (mem.eql(u8, other_zig_name, omit_dep)) break;
} else {
try deps.append(other_zig_name);
}
}
{
var it = root_map.iterator();
while (it.next()) |kv| {
if (kv.key_ptr.len == 0) continue;
if (kv.key_ptr.*[0] == '!') continue;
if (kv.value_ptr.* != .object) continue;
if (hasSuperclass(&kv.value_ptr.object, "SubtargetFeature")) {
const llvm_name = kv.value_ptr.object.get("Name").?.string;
if (llvm_name.len == 0) continue;
var zig_name = try llvmNameToZigName(arena, llvm_name);
var desc = kv.value_ptr.object.get("Desc").?.string;
var deps = std.ArrayList([]const u8).init(arena);
var omit = false;
var flatten = false;
var omit_deps: []const []const u8 = &.{};
var extra_deps: []const []const u8 = &.{};
for (target.feature_overrides) |feature_override| {
if (mem.eql(u8, llvm_name, feature_override.llvm_name)) {
if (feature_override.omit) {
// Still put the feature into the table so that we can
// expand dependencies for the feature overrides marked `flatten`.
omit = true;
}
if (feature_override.flatten) {
flatten = true;
}
if (feature_override.zig_name) |override_name| {
zig_name = override_name;
}
if (feature_override.desc) |override_desc| {
desc = override_desc;
}
omit_deps = feature_override.omit_deps;
extra_deps = feature_override.extra_deps;
break;
}
}
}
// This is used by AArch64.
if (kv.value_ptr.object.get("DefaultExts")) |exts_val| {
for (exts_val.array.items) |ext| {
const other_key = ext.object.get("def").?.string;
const implies = kv.value_ptr.object.get("Implies").?.array;
for (implies.items) |imply| {
const other_key = imply.object.get("def").?.string;
const other_obj = root_map.get(other_key).?.object;
const other_llvm_name = other_obj.get("Name").?.string;
const other_zig_name = (try llvmFeatureNameToZigNameOmit(
arena,
llvm_target,
target,
other_llvm_name,
)) orelse continue;
for (omit_deps) |omit_dep| {
@ -1615,118 +1649,141 @@ fn processOneTarget(job: Job) void {
try deps.append(other_zig_name);
}
}
}
for (extra_deps) |extra_dep| {
try deps.append(extra_dep);
}
const feature: Feature = .{
.llvm_name = llvm_name,
.zig_name = zig_name,
.desc = desc,
.deps = deps.items,
.flatten = flatten,
};
try features_table.put(zig_name, feature);
if (!omit and !flatten) {
try all_features.append(feature);
}
}
if (hasSuperclass(&kv.value_ptr.object, "Processor")) {
const llvm_name = kv.value_ptr.object.get("Name").?.string;
if (llvm_name.len == 0) continue;
const omitted = for (llvm_target.omit_cpus) |omit_cpu_name| {
if (mem.eql(u8, omit_cpu_name, llvm_name)) break true;
} else false;
if (omitted) continue;
var zig_name = try llvmNameToZigName(arena, llvm_name);
var deps = std.ArrayList([]const u8).init(arena);
var omit_deps: []const []const u8 = &.{};
var extra_deps: []const []const u8 = &.{};
for (llvm_target.feature_overrides) |feature_override| {
if (mem.eql(u8, llvm_name, feature_override.llvm_name)) {
if (feature_override.omit) {
continue;
// This is used by AArch64.
if (kv.value_ptr.object.get("DefaultExts")) |exts_val| {
for (exts_val.array.items) |ext| {
const other_key = ext.object.get("def").?.string;
const other_obj = root_map.get(other_key).?.object;
const other_llvm_name = other_obj.get("Name").?.string;
const other_zig_name = (try llvmFeatureNameToZigNameOmit(
arena,
target,
other_llvm_name,
)) orelse continue;
for (omit_deps) |omit_dep| {
if (mem.eql(u8, other_zig_name, omit_dep)) break;
} else {
try deps.append(other_zig_name);
}
}
if (feature_override.zig_name) |override_name| {
zig_name = override_name;
}
omit_deps = feature_override.omit_deps;
extra_deps = feature_override.extra_deps;
break;
}
for (extra_deps) |extra_dep| {
try deps.append(extra_dep);
}
const feature: Feature = .{
.llvm_name = llvm_name,
.zig_name = zig_name,
.desc = desc,
.deps = deps.items,
.flatten = flatten,
};
try features_table.put(zig_name, feature);
if (!omit and !flatten) {
try all_features.append(feature);
}
}
const features = kv.value_ptr.object.get("Features").?.array;
for (features.items) |feature| {
const feature_key = feature.object.get("def").?.string;
const feature_obj = root_map.get(feature_key).?.object;
const feature_llvm_name = feature_obj.get("Name").?.string;
if (feature_llvm_name.len == 0) continue;
const feature_zig_name = (try llvmFeatureNameToZigNameOmit(
arena,
llvm_target,
feature_llvm_name,
)) orelse continue;
for (omit_deps) |omit_dep| {
if (mem.eql(u8, feature_zig_name, omit_dep)) break;
} else {
if (hasSuperclass(&kv.value_ptr.object, "Processor")) {
const llvm_name = kv.value_ptr.object.get("Name").?.string;
if (llvm_name.len == 0) continue;
const omitted = for (target.omit_cpus) |omit_cpu_name| {
if (mem.eql(u8, omit_cpu_name, llvm_name)) break true;
} else false;
if (omitted) continue;
var zig_name = try llvmNameToZigName(arena, llvm_name);
var deps = std.ArrayList([]const u8).init(arena);
var omit_deps: []const []const u8 = &.{};
var extra_deps: []const []const u8 = &.{};
for (target.feature_overrides) |feature_override| {
if (mem.eql(u8, llvm_name, feature_override.llvm_name)) {
if (feature_override.omit) {
continue;
}
if (feature_override.zig_name) |override_name| {
zig_name = override_name;
}
omit_deps = feature_override.omit_deps;
extra_deps = feature_override.extra_deps;
break;
}
}
const features = kv.value_ptr.object.get("Features").?.array;
for (features.items) |feature| {
const feature_key = feature.object.get("def").?.string;
const feature_obj = root_map.get(feature_key).?.object;
const feature_llvm_name = feature_obj.get("Name").?.string;
if (feature_llvm_name.len == 0) continue;
const feature_zig_name = (try llvmFeatureNameToZigNameOmit(
arena,
target,
feature_llvm_name,
)) orelse continue;
for (omit_deps) |omit_dep| {
if (mem.eql(u8, feature_zig_name, omit_dep)) break;
} else {
try deps.append(feature_zig_name);
}
}
for (extra_deps) |extra_dep| {
try deps.append(extra_dep);
}
const tune_features = kv.value_ptr.object.get("TuneFeatures").?.array;
for (tune_features.items) |feature| {
const feature_key = feature.object.get("def").?.string;
const feature_obj = root_map.get(feature_key).?.object;
const feature_llvm_name = feature_obj.get("Name").?.string;
if (feature_llvm_name.len == 0) continue;
const feature_zig_name = (try llvmFeatureNameToZigNameOmit(
arena,
target,
feature_llvm_name,
)) orelse continue;
try deps.append(feature_zig_name);
}
}
for (extra_deps) |extra_dep| {
try deps.append(extra_dep);
}
const tune_features = kv.value_ptr.object.get("TuneFeatures").?.array;
for (tune_features.items) |feature| {
const feature_key = feature.object.get("def").?.string;
const feature_obj = root_map.get(feature_key).?.object;
const feature_llvm_name = feature_obj.get("Name").?.string;
if (feature_llvm_name.len == 0) continue;
const feature_zig_name = (try llvmFeatureNameToZigNameOmit(
arena,
llvm_target,
feature_llvm_name,
)) orelse continue;
try deps.append(feature_zig_name);
}
try all_cpus.append(.{
.llvm_name = llvm_name,
.zig_name = zig_name,
.features = deps.items,
});
try all_cpus.append(.{
.llvm_name = llvm_name,
.zig_name = zig_name,
.features = deps.items,
});
if (cpu_aliases.get(zig_name)) |aliases| {
var alias_it = aliases.constIterator(0);
if (cpu_aliases.get(zig_name)) |aliases| {
var alias_it = aliases.constIterator(0);
alias_it: while (alias_it.next()) |alias| {
for (llvm_target.omit_cpus) |omit_cpu_name| {
if (mem.eql(u8, omit_cpu_name, alias.llvm)) continue :alias_it;
alias_it: while (alias_it.next()) |alias| {
for (target.omit_cpus) |omit_cpu_name| {
if (mem.eql(u8, omit_cpu_name, alias.llvm)) continue :alias_it;
}
try all_cpus.append(.{
.llvm_name = alias.llvm,
.zig_name = alias.zig,
.features = deps.items,
});
}
try all_cpus.append(.{
.llvm_name = alias.llvm,
.zig_name = alias.zig,
.features = deps.items,
});
}
}
}
}
collate_progress.end();
}
for (llvm_target.extra_features) |extra_feature| {
for (target.extra_features) |extra_feature| {
try features_table.put(extra_feature.zig_name, extra_feature);
try all_features.append(extra_feature);
}
for (llvm_target.extra_cpus) |extra_cpu| {
for (target.extra_cpus) |extra_cpu| {
try all_cpus.append(extra_cpu);
}
mem.sort(Feature, all_features.items, {}, featureLessThan);
mem.sort(Cpu, all_cpus.items, {}, cpuLessThan);
const render_progress = progress_node.start("rendering Zig code", 0);
var target_dir = try job.zig_src_dir.openDir("lib/std/Target", .{});
defer target_dir.close();
const zig_code_basename = try std.fmt.allocPrint(arena, "{s}.zig", .{llvm_target.zig_name});
const zig_code_basename = try std.fmt.allocPrint(arena, "{s}.zig", .{target.zig_name});
var zig_code_file = try target_dir.createFile(zig_code_basename, .{});
defer zig_code_file.close();
@ -1760,7 +1817,7 @@ fn processOneTarget(job: Job) void {
\\pub const all_features = blk: {
\\
);
if (llvm_target.branch_quota) |branch_quota| {
if (target.branch_quota) |branch_quota| {
try w.print(" @setEvalBranchQuota({d});\n", .{branch_quota});
}
try w.writeAll(
@ -1941,10 +1998,10 @@ fn llvmNameToZigName(arena: mem.Allocator, llvm_name: []const u8) ![]const u8 {
fn llvmFeatureNameToZigNameOmit(
arena: mem.Allocator,
llvm_target: LlvmTarget,
target: ArchTarget,
llvm_name: []const u8,
) !?[]const u8 {
for (llvm_target.feature_overrides) |feature_override| {
for (target.feature_overrides) |feature_override| {
if (mem.eql(u8, feature_override.llvm_name, llvm_name)) {
if (feature_override.omit) return null;
return feature_override.zig_name orelse break;