mirror of
https://github.com/ziglang/zig.git
synced 2025-12-25 15:43:06 +00:00
The idea here is that instead of the linker calling into codegen, instead codegen should run before we touch the linker, and after MIR is produced, it is sent to the linker. Aside from simplifying the call graph (by preventing N linkers from each calling into M codegen backends!), this has the huge benefit that it is possible to parallellize codegen separately from linking. The threading model can look like this: * 1 semantic analysis thread, which generates AIR * N codegen threads, which process AIR into MIR * 1 linker thread, which emits MIR to the binary The codegen threads are also responsible for `Air.Legalize` and `Air.Liveness`; it's more efficient to do this work here instead of blocking the main thread for this trivially parallel task. I have repurposed the `Zcu.Feature.separate_thread` backend feature to indicate support for this 1:N:1 threading pattern. This commit makes the C backend support this feature, since it was relatively easy to divorce from `link.C`: it just required eliminating some shared buffers. Other backends don't currently support this feature. In fact, they don't even compile -- the next few commits will fix them back up.
297 lines
8.7 KiB
Zig
297 lines
8.7 KiB
Zig
pub const Env = enum {
|
|
/// zig1 features
|
|
/// - `-ofmt=c` only
|
|
/// - `-OReleaseFast` or `-OReleaseSmall` only
|
|
/// - no `@setRuntimeSafety(true)`
|
|
bootstrap,
|
|
|
|
/// zig2 features
|
|
core,
|
|
|
|
/// stage3 features
|
|
full,
|
|
|
|
/// - `zig cc`
|
|
/// - `zig c++`
|
|
/// - `zig translate-c`
|
|
c_source,
|
|
|
|
/// - `zig ast-check`
|
|
/// - `zig changelist`
|
|
/// - `zig dump-zir`
|
|
ast_gen,
|
|
|
|
/// - ast_gen
|
|
/// - `zig build-* -fno-emit-bin`
|
|
sema,
|
|
|
|
/// - `zig build-* -ofmt=c`
|
|
cbe,
|
|
|
|
/// - sema
|
|
/// - `zig build-* -fincremental -fno-llvm -fno-lld -target x86_64-linux --listen=-`
|
|
@"x86_64-linux",
|
|
|
|
/// - sema
|
|
/// - `zig build-* -fincremental -fno-llvm -fno-lld -target powerpc(64)(le)-linux --listen=-`
|
|
@"powerpc-linux",
|
|
|
|
/// - sema
|
|
/// - `zig build-* -fno-llvm -fno-lld -target riscv64-linux`
|
|
@"riscv64-linux",
|
|
|
|
/// - sema
|
|
/// - `zig build-* -fno-llvm -fno-lld -target wasm32-* --listen=-`
|
|
wasm,
|
|
|
|
pub inline fn supports(comptime dev_env: Env, comptime feature: Feature) bool {
|
|
return switch (dev_env) {
|
|
.full => true,
|
|
.bootstrap => switch (feature) {
|
|
.build_exe_command,
|
|
.build_obj_command,
|
|
.ast_gen,
|
|
.sema,
|
|
.c_backend,
|
|
.c_linker,
|
|
=> true,
|
|
else => false,
|
|
},
|
|
.core => switch (feature) {
|
|
.build_exe_command,
|
|
.build_lib_command,
|
|
.build_obj_command,
|
|
.test_command,
|
|
.run_command,
|
|
.ar_command,
|
|
.build_command,
|
|
.clang_command,
|
|
.stdio_listen,
|
|
.build_import_lib,
|
|
.make_executable,
|
|
.make_writable,
|
|
.incremental,
|
|
.ast_gen,
|
|
.sema,
|
|
.legalize,
|
|
.llvm_backend,
|
|
.c_backend,
|
|
.wasm_backend,
|
|
.arm_backend,
|
|
.x86_64_backend,
|
|
.aarch64_backend,
|
|
.x86_backend,
|
|
.powerpc_backend,
|
|
.riscv64_backend,
|
|
.sparc64_backend,
|
|
.spirv64_backend,
|
|
.lld_linker,
|
|
.coff_linker,
|
|
.elf_linker,
|
|
.macho_linker,
|
|
.c_linker,
|
|
.wasm_linker,
|
|
.spirv_linker,
|
|
.plan9_linker,
|
|
.goff_linker,
|
|
.xcoff_linker,
|
|
=> true,
|
|
.cc_command,
|
|
.translate_c_command,
|
|
.fmt_command,
|
|
.jit_command,
|
|
.fetch_command,
|
|
.init_command,
|
|
.targets_command,
|
|
.version_command,
|
|
.env_command,
|
|
.zen_command,
|
|
.help_command,
|
|
.ast_check_command,
|
|
.detect_cpu_command,
|
|
.changelist_command,
|
|
.dump_zir_command,
|
|
.llvm_ints_command,
|
|
.docs_emit,
|
|
// Avoid dragging networking into zig2.c because it adds dependencies on some
|
|
// linker symbols that are annoying to satisfy while bootstrapping.
|
|
.network_listen,
|
|
.win32_resource,
|
|
=> false,
|
|
},
|
|
.c_source => switch (feature) {
|
|
.clang_command,
|
|
.cc_command,
|
|
.translate_c_command,
|
|
=> true,
|
|
else => false,
|
|
},
|
|
.ast_gen => switch (feature) {
|
|
.ast_check_command,
|
|
.changelist_command,
|
|
.dump_zir_command,
|
|
.make_executable,
|
|
.make_writable,
|
|
.incremental,
|
|
.ast_gen,
|
|
=> true,
|
|
else => false,
|
|
},
|
|
.sema => switch (feature) {
|
|
.build_exe_command,
|
|
.build_lib_command,
|
|
.build_obj_command,
|
|
.test_command,
|
|
.run_command,
|
|
.sema,
|
|
=> true,
|
|
else => Env.ast_gen.supports(feature),
|
|
},
|
|
.cbe => switch (feature) {
|
|
.c_backend,
|
|
.c_linker,
|
|
=> true,
|
|
else => Env.sema.supports(feature),
|
|
},
|
|
.@"x86_64-linux" => switch (feature) {
|
|
.build_command,
|
|
.stdio_listen,
|
|
.incremental,
|
|
.legalize,
|
|
.x86_64_backend,
|
|
.elf_linker,
|
|
=> true,
|
|
else => Env.sema.supports(feature),
|
|
},
|
|
.@"powerpc-linux" => switch (feature) {
|
|
.build_command,
|
|
.stdio_listen,
|
|
.incremental,
|
|
.x86_64_backend,
|
|
.elf_linker,
|
|
=> true,
|
|
else => Env.sema.supports(feature),
|
|
},
|
|
.@"riscv64-linux" => switch (feature) {
|
|
.riscv64_backend,
|
|
.elf_linker,
|
|
=> true,
|
|
else => Env.sema.supports(feature),
|
|
},
|
|
.wasm => switch (feature) {
|
|
.stdio_listen,
|
|
.incremental,
|
|
.wasm_backend,
|
|
.wasm_linker,
|
|
=> true,
|
|
else => Env.sema.supports(feature),
|
|
},
|
|
};
|
|
}
|
|
|
|
pub inline fn supportsAny(comptime dev_env: Env, comptime features: []const Feature) bool {
|
|
inline for (features) |feature| if (dev_env.supports(feature)) return true;
|
|
return false;
|
|
}
|
|
|
|
pub inline fn supportsAll(comptime dev_env: Env, comptime features: []const Feature) bool {
|
|
inline for (features) |feature| if (!dev_env.supports(feature)) return false;
|
|
return true;
|
|
}
|
|
};
|
|
|
|
pub const Feature = enum {
|
|
build_exe_command,
|
|
build_lib_command,
|
|
build_obj_command,
|
|
test_command,
|
|
run_command,
|
|
ar_command,
|
|
build_command,
|
|
clang_command,
|
|
cc_command,
|
|
translate_c_command,
|
|
fmt_command,
|
|
jit_command,
|
|
fetch_command,
|
|
init_command,
|
|
targets_command,
|
|
version_command,
|
|
env_command,
|
|
zen_command,
|
|
help_command,
|
|
ast_check_command,
|
|
detect_cpu_command,
|
|
changelist_command,
|
|
dump_zir_command,
|
|
llvm_ints_command,
|
|
|
|
docs_emit,
|
|
stdio_listen,
|
|
network_listen,
|
|
build_import_lib,
|
|
win32_resource,
|
|
make_executable,
|
|
make_writable,
|
|
incremental,
|
|
ast_gen,
|
|
sema,
|
|
legalize,
|
|
|
|
llvm_backend,
|
|
c_backend,
|
|
wasm_backend,
|
|
arm_backend,
|
|
x86_64_backend,
|
|
aarch64_backend,
|
|
x86_backend,
|
|
powerpc_backend,
|
|
riscv64_backend,
|
|
sparc64_backend,
|
|
spirv64_backend,
|
|
|
|
lld_linker,
|
|
coff_linker,
|
|
elf_linker,
|
|
macho_linker,
|
|
c_linker,
|
|
wasm_linker,
|
|
spirv_linker,
|
|
plan9_linker,
|
|
goff_linker,
|
|
xcoff_linker,
|
|
};
|
|
|
|
/// Makes the code following the call to this function unreachable if `feature` is disabled.
|
|
pub fn check(comptime feature: Feature) if (env.supports(feature)) void else noreturn {
|
|
if (env.supports(feature)) return;
|
|
@panic("development environment " ++ @tagName(env) ++ " does not support feature " ++ @tagName(feature));
|
|
}
|
|
|
|
/// Makes the code following the call to this function unreachable if all of `features` are disabled.
|
|
pub fn checkAny(comptime features: []const Feature) if (env.supportsAny(features)) void else noreturn {
|
|
if (env.supportsAny(features)) return;
|
|
comptime var feature_tags: []const u8 = "";
|
|
inline for (features[0 .. features.len - 1]) |feature| feature_tags = feature_tags ++ @tagName(feature) ++ ", ";
|
|
feature_tags = feature_tags ++ "or " ++ @tagName(features[features.len - 1]);
|
|
@panic("development environment " ++ @tagName(env) ++ " does not support feature " ++ feature_tags);
|
|
}
|
|
|
|
/// Makes the code following the call to this function unreachable if any of `features` are disabled.
|
|
pub fn checkAll(comptime features: []const Feature) if (env.supportsAll(features)) void else noreturn {
|
|
if (env.supportsAll(features)) return;
|
|
inline for (features) |feature| if (!env.supports(feature))
|
|
@panic("development environment " ++ @tagName(env) ++ " does not support feature " ++ @tagName(feature));
|
|
}
|
|
|
|
const build_options = @import("build_options");
|
|
|
|
pub const env: Env = if (@hasDecl(build_options, "dev"))
|
|
@field(Env, @tagName(build_options.dev))
|
|
else if (@hasDecl(build_options, "only_c") and build_options.only_c)
|
|
.bootstrap
|
|
else if (@hasDecl(build_options, "only_core_functionality") and build_options.only_core_functionality)
|
|
.core
|
|
else
|
|
.full;
|