Skip to content

Commit 1db8cad

Browse files
authored
Merge pull request #21920 from alexrp/nobuiltin
compiler: Improve handling of `-fno-builtin` and compiler-rt options
2 parents bbbc95a + c9052ef commit 1db8cad

14 files changed

+156
-124
lines changed

lib/c.zig

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,14 @@ const native_os = builtin.os.tag;
1111
const native_arch = builtin.cpu.arch;
1212
const native_abi = builtin.abi;
1313

14+
const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .internal else .strong;
15+
1416
const is_wasm = switch (native_arch) {
1517
.wasm32, .wasm64 => true,
1618
else => false,
1719
};
18-
const is_msvc = switch (native_abi) {
19-
.msvc => true,
20-
else => false,
21-
};
2220
const is_freestanding = switch (native_os) {
23-
.freestanding => true,
21+
.freestanding, .other => true,
2422
else => false,
2523
};
2624

@@ -30,14 +28,14 @@ comptime {
3028
}
3129

3230
if (builtin.link_libc) {
33-
@export(&strcmp, .{ .name = "strcmp", .linkage = .strong });
34-
@export(&strncmp, .{ .name = "strncmp", .linkage = .strong });
35-
@export(&strerror, .{ .name = "strerror", .linkage = .strong });
36-
@export(&strlen, .{ .name = "strlen", .linkage = .strong });
37-
@export(&strcpy, .{ .name = "strcpy", .linkage = .strong });
38-
@export(&strncpy, .{ .name = "strncpy", .linkage = .strong });
39-
@export(&strcat, .{ .name = "strcat", .linkage = .strong });
40-
@export(&strncat, .{ .name = "strncat", .linkage = .strong });
31+
@export(&strcmp, .{ .name = "strcmp", .linkage = linkage });
32+
@export(&strncmp, .{ .name = "strncmp", .linkage = linkage });
33+
@export(&strerror, .{ .name = "strerror", .linkage = linkage });
34+
@export(&strlen, .{ .name = "strlen", .linkage = linkage });
35+
@export(&strcpy, .{ .name = "strcpy", .linkage = linkage });
36+
@export(&strncpy, .{ .name = "strncpy", .linkage = linkage });
37+
@export(&strcat, .{ .name = "strcat", .linkage = linkage });
38+
@export(&strncat, .{ .name = "strncat", .linkage = linkage });
4139
}
4240
}
4341

lib/std/Target.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1076,7 +1076,7 @@ pub fn toElfMachine(target: Target) std.elf.EM {
10761076
pub fn toCoffMachine(target: Target) std.coff.MachineType {
10771077
return switch (target.cpu.arch) {
10781078
.arm => .ARM,
1079-
.thumb => .THUMB,
1079+
.thumb => .ARMNT,
10801080
.aarch64 => .ARM64,
10811081
.loongarch32 => .LOONGARCH32,
10821082
.loongarch64 => .LOONGARCH64,

src/Compilation.zig

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ windows_libs: std.StringArrayHashMapUnmanaged(void),
8989
version: ?std.SemanticVersion,
9090
libc_installation: ?*const LibCInstallation,
9191
skip_linker_dependencies: bool,
92-
no_builtin: bool,
9392
function_sections: bool,
9493
data_sections: bool,
9594
link_eh_frame_hdr: bool,
@@ -852,6 +851,7 @@ pub const cache_helpers = struct {
852851
hh.add(mod.fuzz);
853852
hh.add(mod.unwind_tables);
854853
hh.add(mod.structured_cfg);
854+
hh.add(mod.no_builtin);
855855
hh.addListOfBytes(mod.cc_argv);
856856
}
857857

@@ -1057,7 +1057,6 @@ pub const CreateOptions = struct {
10571057
want_lto: ?bool = null,
10581058
function_sections: bool = false,
10591059
data_sections: bool = false,
1060-
no_builtin: bool = false,
10611060
time_report: bool = false,
10621061
stack_report: bool = false,
10631062
link_eh_frame_hdr: bool = false,
@@ -1299,7 +1298,11 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
12991298
},
13001299
.fully_qualified_name = "compiler_rt",
13011300
.cc_argv = &.{},
1302-
.inherited = .{},
1301+
.inherited = .{
1302+
.stack_check = false,
1303+
.stack_protector = 0,
1304+
.no_builtin = true,
1305+
},
13031306
.global = options.config,
13041307
.parent = options.root_mod,
13051308
.builtin_mod = options.root_mod.getBuiltinDependency(),
@@ -1353,7 +1356,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
13531356
cache.hash.add(options.config.link_mode);
13541357
cache.hash.add(options.function_sections);
13551358
cache.hash.add(options.data_sections);
1356-
cache.hash.add(options.no_builtin);
13571359
cache.hash.add(link_libc);
13581360
cache.hash.add(options.config.link_libcpp);
13591361
cache.hash.add(options.config.link_libunwind);
@@ -1490,7 +1492,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
14901492
.framework_dirs = options.framework_dirs,
14911493
.llvm_opt_bisect_limit = options.llvm_opt_bisect_limit,
14921494
.skip_linker_dependencies = options.skip_linker_dependencies,
1493-
.no_builtin = options.no_builtin,
14941495
.job_queued_update_builtin_zig = have_zcu,
14951496
.function_sections = options.function_sections,
14961497
.data_sections = options.data_sections,
@@ -5261,7 +5262,7 @@ pub fn addCCArgs(
52615262
try argv.append("-fdata-sections");
52625263
}
52635264

5264-
if (comp.no_builtin) {
5265+
if (mod.no_builtin) {
52655266
try argv.append("-fno-builtin");
52665267
}
52675268

@@ -6154,7 +6155,6 @@ fn buildOutputFromZig(
61546155

61556156
assert(output_mode != .Exe);
61566157

6157-
const unwind_tables = comp.link_eh_frame_hdr;
61586158
const strip = comp.compilerRtStrip();
61596159
const optimize_mode = comp.compilerRtOptMode();
61606160

@@ -6168,7 +6168,6 @@ fn buildOutputFromZig(
61686168
.root_optimize_mode = optimize_mode,
61696169
.root_strip = strip,
61706170
.link_libc = comp.config.link_libc,
6171-
.any_unwind_tables = unwind_tables,
61726171
});
61736172

61746173
const root_mod = try Package.Module.create(arena, .{
@@ -6185,10 +6184,11 @@ fn buildOutputFromZig(
61856184
.stack_protector = 0,
61866185
.red_zone = comp.root_mod.red_zone,
61876186
.omit_frame_pointer = comp.root_mod.omit_frame_pointer,
6188-
.unwind_tables = unwind_tables,
6187+
.unwind_tables = comp.root_mod.unwind_tables,
61896188
.pic = comp.root_mod.pic,
61906189
.optimize_mode = optimize_mode,
61916190
.structured_cfg = comp.root_mod.structured_cfg,
6191+
.no_builtin = true,
61926192
.code_model = comp.root_mod.code_model,
61936193
},
61946194
.global = config,
@@ -6237,7 +6237,6 @@ fn buildOutputFromZig(
62376237
},
62386238
.function_sections = true,
62396239
.data_sections = true,
6240-
.no_builtin = true,
62416240
.emit_h = null,
62426241
.verbose_cc = comp.verbose_cc,
62436242
.verbose_link = comp.verbose_link,
@@ -6262,16 +6261,24 @@ fn buildOutputFromZig(
62626261
comp.queueLinkTaskMode(crt_file.full_object_path, output_mode);
62636262
}
62646263

6264+
pub const CrtFileOptions = struct {
6265+
function_sections: ?bool = null,
6266+
data_sections: ?bool = null,
6267+
omit_frame_pointer: ?bool = null,
6268+
pic: ?bool = null,
6269+
no_builtin: ?bool = null,
6270+
};
6271+
62656272
pub fn build_crt_file(
62666273
comp: *Compilation,
62676274
root_name: []const u8,
62686275
output_mode: std.builtin.OutputMode,
6269-
pic: ?bool,
62706276
misc_task_tag: MiscTask,
62716277
prog_node: std.Progress.Node,
62726278
/// These elements have to get mutated to add the owner module after it is
62736279
/// created within this function.
62746280
c_source_files: []CSourceFile,
6281+
options: CrtFileOptions,
62756282
) !void {
62766283
const tracy_trace = trace(@src());
62776284
defer tracy_trace.end();
@@ -6316,13 +6323,16 @@ pub fn build_crt_file(
63166323
.sanitize_c = false,
63176324
.sanitize_thread = false,
63186325
.red_zone = comp.root_mod.red_zone,
6319-
.omit_frame_pointer = comp.root_mod.omit_frame_pointer,
6326+
// Some libcs (e.g. musl) are opinionated about -fomit-frame-pointer.
6327+
.omit_frame_pointer = options.omit_frame_pointer orelse comp.root_mod.omit_frame_pointer,
63206328
.valgrind = false,
63216329
.unwind_tables = false,
6322-
// Some CRT objects (rcrt1.o, Scrt1.o) are opinionated about PIC.
6323-
.pic = pic orelse comp.root_mod.pic,
6330+
// Some CRT objects (e.g. musl's rcrt1.o and Scrt1.o) are opinionated about PIC.
6331+
.pic = options.pic orelse comp.root_mod.pic,
63246332
.optimize_mode = comp.compilerRtOptMode(),
63256333
.structured_cfg = comp.root_mod.structured_cfg,
6334+
// Some libcs (e.g. musl) are opinionated about -fno-builtin.
6335+
.no_builtin = options.no_builtin orelse comp.root_mod.no_builtin,
63266336
},
63276337
.global = config,
63286338
.cc_argv = &.{},
@@ -6350,6 +6360,8 @@ pub fn build_crt_file(
63506360
.directory = null, // Put it in the cache directory.
63516361
.basename = basename,
63526362
},
6363+
.function_sections = options.function_sections orelse false,
6364+
.data_sections = options.data_sections orelse false,
63536365
.emit_h = null,
63546366
.c_source_files = c_source_files,
63556367
.verbose_cc = comp.verbose_cc,

src/Package/Module.zig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ unwind_tables: bool,
3131
cc_argv: []const []const u8,
3232
/// (SPIR-V) whether to generate a structured control flow graph or not
3333
structured_cfg: bool,
34+
no_builtin: bool,
3435

3536
/// If the module is an `@import("builtin")` module, this is the `File` that
3637
/// is preallocated for it. Otherwise this field is null.
@@ -95,6 +96,7 @@ pub const CreateOptions = struct {
9596
sanitize_thread: ?bool = null,
9697
fuzz: ?bool = null,
9798
structured_cfg: ?bool = null,
99+
no_builtin: ?bool = null,
98100
};
99101
};
100102

@@ -298,6 +300,13 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
298300
};
299301
};
300302

303+
const no_builtin = b: {
304+
if (options.inherited.no_builtin) |x| break :b x;
305+
if (options.parent) |p| break :b p.no_builtin;
306+
307+
break :b target.cpu.arch.isBpf();
308+
};
309+
301310
const llvm_cpu_features: ?[*:0]const u8 = b: {
302311
if (resolved_target.llvm_cpu_features) |x| break :b x;
303312
if (!options.global.use_llvm) break :b null;
@@ -350,6 +359,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
350359
.unwind_tables = unwind_tables,
351360
.cc_argv = options.cc_argv,
352361
.structured_cfg = structured_cfg,
362+
.no_builtin = no_builtin,
353363
.builtin_file = null,
354364
};
355365

@@ -442,6 +452,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module {
442452
.unwind_tables = unwind_tables,
443453
.cc_argv = &.{},
444454
.structured_cfg = structured_cfg,
455+
.no_builtin = no_builtin,
445456
.builtin_file = new_file,
446457
};
447458
new_file.* = .{
@@ -502,6 +513,7 @@ pub fn createLimited(gpa: Allocator, options: LimitedOptions) Allocator.Error!*P
502513
.unwind_tables = undefined,
503514
.cc_argv = undefined,
504515
.structured_cfg = undefined,
516+
.no_builtin = undefined,
505517
.builtin_file = null,
506518
};
507519
return mod;

src/codegen/llvm.zig

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3222,8 +3222,6 @@ pub const Object = struct {
32223222
owner_mod: *Package.Module,
32233223
omit_frame_pointer: bool,
32243224
) Allocator.Error!void {
3225-
const comp = o.pt.zcu.comp;
3226-
32273225
if (!owner_mod.red_zone) {
32283226
try attributes.addFnAttr(.noredzone, &o.builder);
32293227
}
@@ -3242,8 +3240,7 @@ pub const Object = struct {
32423240
if (owner_mod.unwind_tables) {
32433241
try attributes.addFnAttr(.{ .uwtable = Builder.Attribute.UwTable.default }, &o.builder);
32443242
}
3245-
const target = owner_mod.resolved_target.result;
3246-
if (comp.skip_linker_dependencies or comp.no_builtin or target.cpu.arch.isBpf()) {
3243+
if (owner_mod.no_builtin) {
32473244
// The intent here is for compiler-rt and libc functions to not generate
32483245
// infinite recursion. For example, if we are compiling the memcpy function,
32493246
// and llvm detects that the body is equivalent to memcpy, it may replace the
@@ -3258,6 +3255,7 @@ pub const Object = struct {
32583255
try attributes.addFnAttr(.minsize, &o.builder);
32593256
try attributes.addFnAttr(.optsize, &o.builder);
32603257
}
3258+
const target = owner_mod.resolved_target.result;
32613259
if (target.cpu.model.llvm_name) |s| {
32623260
try attributes.addFnAttr(.{ .string = .{
32633261
.kind = try o.builder.string("target-cpu"),
@@ -5578,6 +5576,10 @@ pub const FuncGen = struct {
55785576
var attributes: Builder.FunctionAttributes.Wip = .{};
55795577
defer attributes.deinit(&o.builder);
55805578

5579+
if (self.ng.ownerModule().no_builtin) {
5580+
try attributes.addFnAttr(.nobuiltin, &o.builder);
5581+
}
5582+
55815583
switch (modifier) {
55825584
.auto, .never_tail, .always_tail => {},
55835585
.never_inline => try attributes.addFnAttr(.@"noinline", &o.builder),
@@ -12728,6 +12730,8 @@ fn backendSupportsF16(target: std.Target) bool {
1272812730
.mips64,
1272912731
.mips64el,
1273012732
.s390x,
12733+
.sparc,
12734+
.sparc64,
1273112735
=> false,
1273212736
.arm,
1273312737
.armeb,

src/glibc.zig

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
221221
.owner = comp.root_mod,
222222
},
223223
};
224-
return comp.build_crt_file("crti", .Obj, null, .@"glibc crti.o", prog_node, &files);
224+
return comp.build_crt_file("crti", .Obj, .@"glibc crti.o", prog_node, &files, .{});
225225
},
226226
.crtn_o => {
227227
var args = std.ArrayList([]const u8).init(arena);
@@ -242,7 +242,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
242242
.owner = undefined,
243243
},
244244
};
245-
return comp.build_crt_file("crtn", .Obj, null, .@"glibc crtn.o", prog_node, &files);
245+
return comp.build_crt_file("crtn", .Obj, .@"glibc crtn.o", prog_node, &files, .{});
246246
},
247247
.scrt1_o => {
248248
const start_o: Compilation.CSourceFile = blk: {
@@ -295,7 +295,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
295295
};
296296
var files = [_]Compilation.CSourceFile{ start_o, abi_note_o, init_o };
297297
const basename = if (comp.config.output_mode == .Exe and !comp.config.pie) "crt1" else "Scrt1";
298-
return comp.build_crt_file(basename, .Obj, null, .@"glibc Scrt1.o", prog_node, &files);
298+
return comp.build_crt_file(basename, .Obj, .@"glibc Scrt1.o", prog_node, &files, .{});
299299
},
300300
.libc_nonshared_a => {
301301
const s = path.sep_str;
@@ -373,7 +373,6 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
373373
"-fmerge-all-constants",
374374
"-frounding-math",
375375
"-Wno-unsupported-floating-point-opt", // For targets that don't support -frounding-math.
376-
"-fno-stack-protector",
377376
"-fno-common",
378377
"-fmath-errno",
379378
"-ftls-model=initial-exec",
@@ -413,7 +412,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
413412
files_index += 1;
414413
}
415414
const files = files_buf[0..files_index];
416-
return comp.build_crt_file("c_nonshared", .Lib, null, .@"glibc libc_nonshared.a", prog_node, files);
415+
return comp.build_crt_file("c_nonshared", .Lib, .@"glibc libc_nonshared.a", prog_node, files, .{});
417416
},
418417
}
419418
}

src/libcxx.zig

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ pub fn buildLibCXX(comp: *Compilation, prog_node: std.Progress.Node) BuildError!
195195
.valgrind = false,
196196
.optimize_mode = optimize_mode,
197197
.structured_cfg = comp.root_mod.structured_cfg,
198-
.pic = comp.root_mod.pic,
198+
.pic = if (target_util.supports_fpic(target)) true else null,
199199
},
200200
.global = config,
201201
.cc_argv = &.{},
@@ -278,9 +278,6 @@ pub fn buildLibCXX(comp: *Compilation, prog_node: std.Progress.Node) BuildError!
278278
try cflags.append("-faligned-allocation");
279279
}
280280

281-
if (target_util.supports_fpic(target)) {
282-
try cflags.append("-fPIC");
283-
}
284281
try cflags.append("-nostdinc++");
285282
try cflags.append("-std=c++23");
286283
try cflags.append("-Wno-user-defined-literals");

0 commit comments

Comments
 (0)