diff --git a/src/Compilation.zig b/src/Compilation.zig index 51877d7973..24ee899610 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -89,7 +89,6 @@ windows_libs: std.StringArrayHashMapUnmanaged(void), version: ?std.SemanticVersion, libc_installation: ?*const LibCInstallation, skip_linker_dependencies: bool, -no_builtin: bool, function_sections: bool, data_sections: bool, link_eh_frame_hdr: bool, @@ -852,6 +851,7 @@ pub const cache_helpers = struct { hh.add(mod.fuzz); hh.add(mod.unwind_tables); hh.add(mod.structured_cfg); + hh.add(mod.no_builtin); hh.addListOfBytes(mod.cc_argv); } @@ -1057,7 +1057,6 @@ pub const CreateOptions = struct { want_lto: ?bool = null, function_sections: bool = false, data_sections: bool = false, - no_builtin: bool = false, time_report: bool = false, stack_report: bool = false, link_eh_frame_hdr: bool = false, @@ -1353,7 +1352,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil cache.hash.add(options.config.link_mode); cache.hash.add(options.function_sections); cache.hash.add(options.data_sections); - cache.hash.add(options.no_builtin); cache.hash.add(link_libc); cache.hash.add(options.config.link_libcpp); cache.hash.add(options.config.link_libunwind); @@ -1490,7 +1488,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil .framework_dirs = options.framework_dirs, .llvm_opt_bisect_limit = options.llvm_opt_bisect_limit, .skip_linker_dependencies = options.skip_linker_dependencies, - .no_builtin = options.no_builtin, .job_queued_update_builtin_zig = have_zcu, .function_sections = options.function_sections, .data_sections = options.data_sections, @@ -5261,7 +5258,7 @@ pub fn addCCArgs( try argv.append("-fdata-sections"); } - if (comp.no_builtin) { + if (mod.no_builtin) { try argv.append("-fno-builtin"); } @@ -6189,6 +6186,7 @@ fn buildOutputFromZig( .pic = comp.root_mod.pic, .optimize_mode = optimize_mode, .structured_cfg = comp.root_mod.structured_cfg, + .no_builtin = true, .code_model = comp.root_mod.code_model, }, .global = config, @@ -6237,7 +6235,6 @@ fn buildOutputFromZig( }, .function_sections = true, .data_sections = true, - .no_builtin = true, .emit_h = null, .verbose_cc = comp.verbose_cc, .verbose_link = comp.verbose_link, @@ -6262,16 +6259,21 @@ fn buildOutputFromZig( comp.queueLinkTaskMode(crt_file.full_object_path, output_mode); } +pub const CrtFileOptions = struct { + pic: ?bool = null, + no_builtin: ?bool = null, +}; + pub fn build_crt_file( comp: *Compilation, root_name: []const u8, output_mode: std.builtin.OutputMode, - pic: ?bool, misc_task_tag: MiscTask, prog_node: std.Progress.Node, /// These elements have to get mutated to add the owner module after it is /// created within this function. c_source_files: []CSourceFile, + options: CrtFileOptions, ) !void { const tracy_trace = trace(@src()); defer tracy_trace.end(); @@ -6319,10 +6321,12 @@ pub fn build_crt_file( .omit_frame_pointer = comp.root_mod.omit_frame_pointer, .valgrind = false, .unwind_tables = false, - // Some CRT objects (rcrt1.o, Scrt1.o) are opinionated about PIC. - .pic = pic orelse comp.root_mod.pic, + // Some CRT objects (e.g. musl's rcrt1.o and Scrt1.o) are opinionated about PIC. + .pic = options.pic orelse comp.root_mod.pic, .optimize_mode = comp.compilerRtOptMode(), .structured_cfg = comp.root_mod.structured_cfg, + // Some libcs (e.g. musl) are opinionated about -fno-builtin. + .no_builtin = options.no_builtin orelse comp.root_mod.no_builtin, }, .global = config, .cc_argv = &.{}, diff --git a/src/Package/Module.zig b/src/Package/Module.zig index 0a3d754e7a..0e777145d9 100644 --- a/src/Package/Module.zig +++ b/src/Package/Module.zig @@ -31,6 +31,7 @@ unwind_tables: bool, cc_argv: []const []const u8, /// (SPIR-V) whether to generate a structured control flow graph or not structured_cfg: bool, +no_builtin: bool, /// If the module is an `@import("builtin")` module, this is the `File` that /// is preallocated for it. Otherwise this field is null. @@ -95,6 +96,7 @@ pub const CreateOptions = struct { sanitize_thread: ?bool = null, fuzz: ?bool = null, structured_cfg: ?bool = null, + no_builtin: ?bool = null, }; }; @@ -298,6 +300,13 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { }; }; + const no_builtin = b: { + if (options.inherited.no_builtin) |x| break :b x; + if (options.parent) |p| break :b p.no_builtin; + + break :b target.cpu.arch.isBpf(); + }; + const llvm_cpu_features: ?[*:0]const u8 = b: { if (resolved_target.llvm_cpu_features) |x| break :b x; if (!options.global.use_llvm) break :b null; @@ -350,6 +359,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { .unwind_tables = unwind_tables, .cc_argv = options.cc_argv, .structured_cfg = structured_cfg, + .no_builtin = no_builtin, .builtin_file = null, }; @@ -442,6 +452,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { .unwind_tables = unwind_tables, .cc_argv = &.{}, .structured_cfg = structured_cfg, + .no_builtin = no_builtin, .builtin_file = new_file, }; new_file.* = .{ @@ -502,6 +513,7 @@ pub fn createLimited(gpa: Allocator, options: LimitedOptions) Allocator.Error!*P .unwind_tables = undefined, .cc_argv = undefined, .structured_cfg = undefined, + .no_builtin = undefined, .builtin_file = null, }; return mod; diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 3a8fde75da..1b90453d49 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -3222,8 +3222,6 @@ pub const Object = struct { owner_mod: *Package.Module, omit_frame_pointer: bool, ) Allocator.Error!void { - const comp = o.pt.zcu.comp; - if (!owner_mod.red_zone) { try attributes.addFnAttr(.noredzone, &o.builder); } @@ -3242,8 +3240,7 @@ pub const Object = struct { if (owner_mod.unwind_tables) { try attributes.addFnAttr(.{ .uwtable = Builder.Attribute.UwTable.default }, &o.builder); } - const target = owner_mod.resolved_target.result; - if (comp.skip_linker_dependencies or comp.no_builtin or target.cpu.arch.isBpf()) { + if (owner_mod.no_builtin) { // The intent here is for compiler-rt and libc functions to not generate // infinite recursion. For example, if we are compiling the memcpy function, // and llvm detects that the body is equivalent to memcpy, it may replace the @@ -3258,6 +3255,7 @@ pub const Object = struct { try attributes.addFnAttr(.minsize, &o.builder); try attributes.addFnAttr(.optsize, &o.builder); } + const target = owner_mod.resolved_target.result; if (target.cpu.model.llvm_name) |s| { try attributes.addFnAttr(.{ .string = .{ .kind = try o.builder.string("target-cpu"), diff --git a/src/glibc.zig b/src/glibc.zig index 65161cec4e..c7f84a797c 100644 --- a/src/glibc.zig +++ b/src/glibc.zig @@ -221,7 +221,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre .owner = comp.root_mod, }, }; - return comp.build_crt_file("crti", .Obj, null, .@"glibc crti.o", prog_node, &files); + return comp.build_crt_file("crti", .Obj, .@"glibc crti.o", prog_node, &files, .{}); }, .crtn_o => { var args = std.ArrayList([]const u8).init(arena); @@ -242,7 +242,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre .owner = undefined, }, }; - return comp.build_crt_file("crtn", .Obj, null, .@"glibc crtn.o", prog_node, &files); + return comp.build_crt_file("crtn", .Obj, .@"glibc crtn.o", prog_node, &files, .{}); }, .scrt1_o => { const start_o: Compilation.CSourceFile = blk: { @@ -295,7 +295,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre }; var files = [_]Compilation.CSourceFile{ start_o, abi_note_o, init_o }; const basename = if (comp.config.output_mode == .Exe and !comp.config.pie) "crt1" else "Scrt1"; - return comp.build_crt_file(basename, .Obj, null, .@"glibc Scrt1.o", prog_node, &files); + return comp.build_crt_file(basename, .Obj, .@"glibc Scrt1.o", prog_node, &files, .{}); }, .libc_nonshared_a => { const s = path.sep_str; @@ -413,7 +413,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre files_index += 1; } const files = files_buf[0..files_index]; - return comp.build_crt_file("c_nonshared", .Lib, null, .@"glibc libc_nonshared.a", prog_node, files); + return comp.build_crt_file("c_nonshared", .Lib, .@"glibc libc_nonshared.a", prog_node, files, .{}); }, } } diff --git a/src/main.zig b/src/main.zig index 24fc0aa60c..e77effd443 100644 --- a/src/main.zig +++ b/src/main.zig @@ -810,7 +810,6 @@ fn buildOutputType( var compatibility_version: ?std.SemanticVersion = null; var function_sections = false; var data_sections = false; - var no_builtin = false; var listen: Listen = .none; var debug_compile_errors = false; var verbose_link = (native_os != .wasi or builtin.link_libc) and @@ -1550,9 +1549,9 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "-fno-data-sections")) { data_sections = false; } else if (mem.eql(u8, arg, "-fbuiltin")) { - no_builtin = false; + mod_opts.no_builtin = false; } else if (mem.eql(u8, arg, "-fno-builtin")) { - no_builtin = true; + mod_opts.no_builtin = true; } else if (mem.startsWith(u8, arg, "-fopt-bisect-limit=")) { const next_arg = arg["-fopt-bisect-limit=".len..]; llvm_opt_bisect_limit = std.fmt.parseInt(c_int, next_arg, 0) catch |err| @@ -1963,8 +1962,8 @@ fn buildOutputType( .no_function_sections => function_sections = false, .data_sections => data_sections = true, .no_data_sections => data_sections = false, - .builtin => no_builtin = false, - .no_builtin => no_builtin = true, + .builtin => mod_opts.no_builtin = false, + .no_builtin => mod_opts.no_builtin = true, .color_diagnostics => color = .on, .no_color_diagnostics => color = .off, .stack_check => mod_opts.stack_check = true, @@ -3468,7 +3467,6 @@ fn buildOutputType( .image_base = image_base, .function_sections = function_sections, .data_sections = data_sections, - .no_builtin = no_builtin, .clang_passthrough_mode = clang_passthrough_mode, .clang_preprocessor_mode = clang_preprocessor_mode, .version = optional_version, diff --git a/src/mingw.zig b/src/mingw.zig index d4ef1ac5a7..cdee9acb07 100644 --- a/src/mingw.zig +++ b/src/mingw.zig @@ -41,7 +41,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre .owner = undefined, }, }; - return comp.build_crt_file("crt2", .Obj, null, .@"mingw-w64 crt2.o", prog_node, &files); + return comp.build_crt_file("crt2", .Obj, .@"mingw-w64 crt2.o", prog_node, &files, .{}); }, .dllcrt2_o => { @@ -56,7 +56,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre .owner = undefined, }, }; - return comp.build_crt_file("dllcrt2", .Obj, null, .@"mingw-w64 dllcrt2.o", prog_node, &files); + return comp.build_crt_file("dllcrt2", .Obj, .@"mingw-w64 dllcrt2.o", prog_node, &files, .{}); }, .mingw32_lib => { @@ -118,7 +118,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre } else { @panic("unsupported arch"); } - return comp.build_crt_file("mingw32", .Lib, null, .@"mingw-w64 mingw32.lib", prog_node, c_source_files.items); + return comp.build_crt_file("mingw32", .Lib, .@"mingw-w64 mingw32.lib", prog_node, c_source_files.items, .{}); }, } } diff --git a/src/musl.zig b/src/musl.zig index 3a0aeb9417..eb83bcf901 100644 --- a/src/musl.zig +++ b/src/musl.zig @@ -38,7 +38,9 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro .owner = undefined, }, }; - return comp.build_crt_file("crti", .Obj, null, .@"musl crti.o", prog_node, &files); + return comp.build_crt_file("crti", .Obj, .@"musl crti.o", prog_node, &files, .{ + .no_builtin = true, + }); }, .crtn_o => { var args = std.ArrayList([]const u8).init(arena); @@ -50,7 +52,9 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro .owner = undefined, }, }; - return comp.build_crt_file("crtn", .Obj, null, .@"musl crtn.o", prog_node, &files); + return comp.build_crt_file("crtn", .Obj, .@"musl crtn.o", prog_node, &files, .{ + .no_builtin = true, + }); }, .crt1_o => { var args = std.ArrayList([]const u8).init(arena); @@ -68,7 +72,9 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro .owner = undefined, }, }; - return comp.build_crt_file("crt1", .Obj, null, .@"musl crt1.o", prog_node, &files); + return comp.build_crt_file("crt1", .Obj, .@"musl crt1.o", prog_node, &files, .{ + .no_builtin = true, + }); }, .rcrt1_o => { var args = std.ArrayList([]const u8).init(arena); @@ -86,7 +92,10 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro .owner = undefined, }, }; - return comp.build_crt_file("rcrt1", .Obj, true, .@"musl rcrt1.o", prog_node, &files); + return comp.build_crt_file("rcrt1", .Obj, .@"musl rcrt1.o", prog_node, &files, .{ + .pic = true, + .no_builtin = true, + }); }, .scrt1_o => { var args = std.ArrayList([]const u8).init(arena); @@ -104,7 +113,10 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro .owner = undefined, }, }; - return comp.build_crt_file("Scrt1", .Obj, true, .@"musl Scrt1.o", prog_node, &files); + return comp.build_crt_file("Scrt1", .Obj, .@"musl Scrt1.o", prog_node, &files, .{ + .pic = true, + .no_builtin = true, + }); }, .libc_a => { // When there is a src//foo.* then it should substitute for src/foo.* @@ -197,7 +209,9 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro .owner = undefined, }; } - return comp.build_crt_file("c", .Lib, null, .@"musl libc.a", prog_node, c_source_files.items); + return comp.build_crt_file("c", .Lib, .@"musl libc.a", prog_node, c_source_files.items, .{ + .no_builtin = true, + }); }, .libc_so => { const optimize_mode = comp.compilerRtOptMode(); @@ -410,7 +424,6 @@ fn addCcArgs( try args.appendSlice(&[_][]const u8{ "-std=c99", "-ffreestanding", - "-fno-builtin", "-fexcess-precision=standard", "-frounding-math", "-ffp-contract=off", diff --git a/src/wasi_libc.zig b/src/wasi_libc.zig index 3b9d9c5446..c9fbbc6e7c 100644 --- a/src/wasi_libc.zig +++ b/src/wasi_libc.zig @@ -81,7 +81,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre .owner = undefined, }, }; - return comp.build_crt_file("crt1-reactor", .Obj, null, .@"wasi crt1-reactor.o", prog_node, &files); + return comp.build_crt_file("crt1-reactor", .Obj, .@"wasi crt1-reactor.o", prog_node, &files, .{}); }, .crt1_command_o => { var args = std.ArrayList([]const u8).init(arena); @@ -96,7 +96,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre .owner = undefined, }, }; - return comp.build_crt_file("crt1-command", .Obj, null, .@"wasi crt1-command.o", prog_node, &files); + return comp.build_crt_file("crt1-command", .Obj, .@"wasi crt1-command.o", prog_node, &files, .{}); }, .libc_a => { var libc_sources = std.ArrayList(Compilation.CSourceFile).init(arena); @@ -150,7 +150,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre } } - try comp.build_crt_file("c", .Lib, null, .@"wasi libc.a", prog_node, libc_sources.items); + try comp.build_crt_file("c", .Lib, .@"wasi libc.a", prog_node, libc_sources.items, .{}); }, .libwasi_emulated_process_clocks_a => { var args = std.ArrayList([]const u8).init(arena); @@ -167,7 +167,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre .owner = undefined, }); } - try comp.build_crt_file("wasi-emulated-process-clocks", .Lib, null, .@"libwasi-emulated-process-clocks.a", prog_node, emu_clocks_sources.items); + try comp.build_crt_file("wasi-emulated-process-clocks", .Lib, .@"libwasi-emulated-process-clocks.a", prog_node, emu_clocks_sources.items, .{}); }, .libwasi_emulated_getpid_a => { var args = std.ArrayList([]const u8).init(arena); @@ -184,7 +184,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre .owner = undefined, }); } - try comp.build_crt_file("wasi-emulated-getpid", .Lib, null, .@"libwasi-emulated-getpid.a", prog_node, emu_getpid_sources.items); + try comp.build_crt_file("wasi-emulated-getpid", .Lib, .@"libwasi-emulated-getpid.a", prog_node, emu_getpid_sources.items, .{}); }, .libwasi_emulated_mman_a => { var args = std.ArrayList([]const u8).init(arena); @@ -201,7 +201,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre .owner = undefined, }); } - try comp.build_crt_file("wasi-emulated-mman", .Lib, null, .@"libwasi-emulated-mman.a", prog_node, emu_mman_sources.items); + try comp.build_crt_file("wasi-emulated-mman", .Lib, .@"libwasi-emulated-mman.a", prog_node, emu_mman_sources.items, .{}); }, .libwasi_emulated_signal_a => { var emu_signal_sources = std.ArrayList(Compilation.CSourceFile).init(arena); @@ -238,7 +238,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre } } - try comp.build_crt_file("wasi-emulated-signal", .Lib, null, .@"libwasi-emulated-signal.a", prog_node, emu_signal_sources.items); + try comp.build_crt_file("wasi-emulated-signal", .Lib, .@"libwasi-emulated-signal.a", prog_node, emu_signal_sources.items, .{}); }, } }