Commit 7c25390c95
Changed files (11)
src/link/Elf.zig
@@ -1289,6 +1289,10 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
// TODO: remove when stage2 can build compiler_rt.zig
if (!build_options.is_stage1) break :blk null;
+ // In the case of build-obj we include the compiler-rt symbols directly alongside
+ // the symbols of the root source file, in the same compilation unit.
+ if (is_obj) break :blk null;
+
if (is_exe_or_dyn_lib) {
break :blk comp.compiler_rt_static_lib.?.full_object_path;
} else {
src/link/Wasm.zig
@@ -645,7 +645,9 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
break :blk full_obj_path;
} else null;
- const compiler_rt_path: ?[]const u8 = if (self.base.options.include_compiler_rt)
+ const is_obj = self.base.options.output_mode == .Obj;
+
+ const compiler_rt_path: ?[]const u8 = if (self.base.options.include_compiler_rt and !is_obj)
comp.compiler_rt_static_lib.?.full_object_path
else
null;
src/stage1/all_types.hpp
@@ -2150,6 +2150,7 @@ struct CodeGen {
bool have_stack_probing;
bool red_zone;
bool function_sections;
+ bool include_compiler_rt;
bool test_is_evented;
bool valgrind_enabled;
bool tsan_enabled;
src/stage1/codegen.cpp
@@ -9542,6 +9542,22 @@ static void gen_root_source(CodeGen *g) {
g->panic_fn = panic_fn_val->data.x_ptr.data.fn.fn_entry;
assert(g->panic_fn != nullptr);
+ if (g->include_compiler_rt) {
+ Buf *import_target_path;
+ Buf full_path = BUF_INIT;
+ ZigType *compiler_rt_import;
+ if ((err = analyze_import(g, std_import, buf_create_from_str("./special/compiler_rt.zig"),
+ &compiler_rt_import, &import_target_path, &full_path)))
+ {
+ if (err == ErrorFileNotFound) {
+ fprintf(stderr, "unable to find '%s'", buf_ptr(import_target_path));
+ } else {
+ fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(&full_path), err_str(err));
+ }
+ exit(1);
+ }
+ }
+
if (!g->error_during_imports) {
semantic_analyze(g);
}
src/stage1/stage1.cpp
@@ -101,6 +101,7 @@ void zig_stage1_build_object(struct ZigStage1 *stage1) {
g->link_libc = stage1->link_libc;
g->link_libcpp = stage1->link_libcpp;
g->function_sections = stage1->function_sections;
+ g->include_compiler_rt = stage1->include_compiler_rt;
g->subsystem = stage1->subsystem;
src/stage1/stage1.h
@@ -196,6 +196,7 @@ struct ZigStage1 {
bool valgrind_enabled;
bool tsan_enabled;
bool function_sections;
+ bool include_compiler_rt;
bool enable_stack_probing;
bool red_zone;
bool enable_time_report;
src/stage1/zig0.cpp
@@ -39,6 +39,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
" --color [auto|off|on] enable or disable colored error messages\n"
" --name [name] override output name\n"
" -femit-bin=[path] Output machine code\n"
+ " -fcompiler-rt Always include compiler-rt symbols in output\n"
" --pkg-begin [name] [path] make pkg available to import and push current pkg\n"
" --pkg-end pop current pkg\n"
" -ODebug build with optimizations off and safety on\n"
@@ -266,6 +267,7 @@ int main(int argc, char **argv) {
const char *mcpu = nullptr;
bool single_threaded = false;
bool is_test_build = false;
+ bool include_compiler_rt = false;
for (int i = 1; i < argc; i += 1) {
char *arg = argv[i];
@@ -334,6 +336,8 @@ int main(int argc, char **argv) {
mcpu = arg + strlen("-mcpu=");
} else if (str_starts_with(arg, "-femit-bin=")) {
emit_bin_path = arg + strlen("-femit-bin=");
+ } else if (strcmp(arg, "-fcompiler-rt") == 0) {
+ include_compiler_rt = true;
} else if (i + 1 >= argc) {
fprintf(stderr, "Expected another argument after %s\n", arg);
return print_error_usage(arg0);
@@ -468,6 +472,7 @@ int main(int argc, char **argv) {
stage1->subsystem = subsystem;
stage1->pic = true;
stage1->is_single_threaded = single_threaded;
+ stage1->include_compiler_rt = include_compiler_rt;
zig_stage1_build_object(stage1);
src/Compilation.zig
@@ -826,6 +826,9 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
const ofmt = options.object_format orelse options.target.getObjectFormat();
const use_stage1 = options.use_stage1 orelse blk: {
+ // Even though we may have no Zig code to compile (depending on `options.root_pkg`),
+ // we may need to use stage1 for building compiler-rt and other dependencies.
+
if (build_options.omit_stage2)
break :blk true;
if (options.use_llvm) |use_llvm| {
@@ -833,9 +836,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
break :blk false;
}
}
- // If we have no zig code to compile, no need for stage1 backend.
- if (options.root_pkg == null)
- break :blk false;
break :blk build_options.is_stage1;
};
@@ -878,9 +878,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
if (options.emit_llvm_ir != null or options.emit_llvm_bc != null) {
return error.EmittingLlvmModuleRequiresUsingLlvmBackend;
}
- if (use_stage1) {
- return error.@"stage1 only supports LLVM backend";
- }
}
const tsan = options.want_tsan orelse false;
@@ -1542,24 +1539,19 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
}
// The `use_stage1` condition is here only because stage2 cannot yet build compiler-rt.
- // Once it is capable this condition should be removed.
+ // Once it is capable this condition should be removed. When removing this condition,
+ // also test the use case of `build-obj -fcompiler-rt` with the self-hosted compiler
+ // and make sure the compiler-rt symbols are emitted. Currently this is hooked up for
+ // stage1 but not stage2.
if (comp.bin_file.options.use_stage1) {
if (comp.bin_file.options.include_compiler_rt) {
if (is_exe_or_dyn_lib) {
try comp.work_queue.writeItem(.{ .compiler_rt_lib = {} });
- } else {
+ } else if (options.output_mode != .Obj) {
+ // If build-obj with -fcompiler-rt is requested, that is handled specially
+ // elsewhere. In this case we are making a static library, so we ask
+ // for a compiler-rt object to put in it.
try comp.work_queue.writeItem(.{ .compiler_rt_obj = {} });
- if (comp.bin_file.options.object_format != .elf and
- comp.bin_file.options.output_mode == .Obj)
- {
- // For ELF we can rely on using -r to link multiple objects together into one,
- // but to truly support `build-obj -fcompiler-rt` will require virtually
- // injecting `_ = @import("compiler_rt.zig")` into the root source file of
- // the compilation.
- fatal("Embedding compiler-rt into {s} objects is not yet implemented.", .{
- @tagName(comp.bin_file.options.object_format),
- });
- }
}
}
if (needs_c_symbols) {
@@ -4002,6 +3994,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
man.hash.add(target.os.getVersionRange());
man.hash.add(comp.bin_file.options.dll_export_fns);
man.hash.add(comp.bin_file.options.function_sections);
+ man.hash.add(comp.bin_file.options.include_compiler_rt);
man.hash.add(comp.bin_file.options.is_test);
man.hash.add(comp.bin_file.options.emit != null);
man.hash.add(mod.emit_h != null);
@@ -4182,6 +4175,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
.valgrind_enabled = comp.bin_file.options.valgrind,
.tsan_enabled = comp.bin_file.options.tsan,
.function_sections = comp.bin_file.options.function_sections,
+ .include_compiler_rt = comp.bin_file.options.include_compiler_rt,
.enable_stack_probing = comp.bin_file.options.stack_check,
.red_zone = comp.bin_file.options.red_zone,
.enable_time_report = comp.time_report,
src/main.zig
@@ -385,8 +385,8 @@ const usage_build_generic =
\\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so)
\\ --sysroot [path] Set the system root directory (usually /)
\\ --version [ver] Dynamic library semver
- \\ -fsoname[=name] (Linux) Override the default SONAME value
- \\ -fno-soname (Linux) Disable emitting a SONAME
+ \\ -fsoname[=name] Override the default SONAME value
+ \\ -fno-soname Disable emitting a SONAME
\\ -fLLD Force using LLD as the linker
\\ -fno-LLD Prevent using LLD as the linker
\\ -fcompiler-rt Always include compiler-rt symbols in output
src/stage1.zig
@@ -21,7 +21,6 @@ comptime {
assert(build_options.is_stage1);
assert(build_options.have_llvm);
if (!builtin.is_test) {
- _ = @import("compiler_rt");
@export(main, .{ .name = "main" });
}
}
@@ -126,6 +125,7 @@ pub const Module = extern struct {
valgrind_enabled: bool,
tsan_enabled: bool,
function_sections: bool,
+ include_compiler_rt: bool,
enable_stack_probing: bool,
red_zone: bool,
enable_time_report: bool,
CMakeLists.txt
@@ -796,6 +796,7 @@ set(BUILD_ZIG1_ARGS
--name zig1
--zig-lib-dir "${CMAKE_SOURCE_DIR}/lib"
"-femit-bin=${ZIG1_OBJECT}"
+ -fcompiler-rt
"${ZIG1_RELEASE_ARG}"
"${ZIG1_SINGLE_THREADED_ARG}"
-lc