From f49a54745ba67a4226cbe706727fb6817b64b1aa Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 17 Jul 2025 22:51:23 -0700 Subject: compiler: update aro and translate-c to latest; delete clang translate-c --- src/Compilation.zig | 161 ++-------------------------------------------------- 1 file changed, 4 insertions(+), 157 deletions(-) (limited to 'src/Compilation.zig') diff --git a/src/Compilation.zig b/src/Compilation.zig index bf7246b8d8..6e27d339f8 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -5657,149 +5657,10 @@ pub const CImportResult = struct { /// Caller owns returned memory. pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module) !CImportResult { dev.check(.translate_c_command); - - const tracy_trace = trace(@src()); - defer tracy_trace.end(); - - const cimport_zig_basename = "cimport.zig"; - - var man = comp.obtainCObjectCacheManifest(owner_mod); - defer man.deinit(); - - man.hash.add(@as(u16, 0xb945)); // Random number to distinguish translate-c from compiling C objects - man.hash.addBytes(c_src); - man.hash.add(comp.config.c_frontend); - - // If the previous invocation resulted in clang errors, we will see a hit - // here with 0 files in the manifest, in which case it is actually a miss. - // We need to "unhit" in this case, to keep the digests matching. - const prev_hash_state = man.hash.peekBin(); - const actual_hit = hit: { - _ = try man.hit(); - if (man.files.entries.len == 0) { - man.unhit(prev_hash_state, 0); - break :hit false; - } - break :hit true; - }; - const digest = if (!actual_hit) digest: { - var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa); - defer arena_allocator.deinit(); - const arena = arena_allocator.allocator(); - - const tmp_digest = man.hash.peek(); - const tmp_dir_sub_path = try fs.path.join(arena, &[_][]const u8{ "o", &tmp_digest }); - var zig_cache_tmp_dir = try comp.dirs.local_cache.handle.makeOpenPath(tmp_dir_sub_path, .{}); - defer zig_cache_tmp_dir.close(); - const cimport_basename = "cimport.h"; - const out_h_path = try comp.dirs.local_cache.join(arena, &[_][]const u8{ - tmp_dir_sub_path, cimport_basename, - }); - const out_dep_path = try std.fmt.allocPrint(arena, "{s}.d", .{out_h_path}); - - try zig_cache_tmp_dir.writeFile(.{ .sub_path = cimport_basename, .data = c_src }); - if (comp.verbose_cimport) { - log.info("C import source: {s}", .{out_h_path}); - } - - var argv = std.array_list.Managed([]const u8).init(comp.gpa); - defer argv.deinit(); - - try argv.append(@tagName(comp.config.c_frontend)); // argv[0] is program name, actual args start at [1] - try comp.addTranslateCCArgs(arena, &argv, .c, out_dep_path, owner_mod); - - try argv.append(out_h_path); - - if (comp.verbose_cc) { - dump_argv(argv.items); - } - var tree = switch (comp.config.c_frontend) { - .aro => tree: { - if (true) @panic("TODO"); - break :tree undefined; - }, - .clang => tree: { - if (!build_options.have_llvm) unreachable; - const translate_c = @import("translate_c.zig"); - - // Convert to null terminated args. - const new_argv_with_sentinel = try arena.alloc(?[*:0]const u8, argv.items.len + 1); - new_argv_with_sentinel[argv.items.len] = null; - const new_argv = new_argv_with_sentinel[0..argv.items.len :null]; - for (argv.items, 0..) |arg, i| { - new_argv[i] = try arena.dupeZ(u8, arg); - } - - const c_headers_dir_path_z = try comp.dirs.zig_lib.joinZ(arena, &.{"include"}); - var errors = std.zig.ErrorBundle.empty; - errdefer errors.deinit(comp.gpa); - break :tree translate_c.translate( - comp.gpa, - new_argv.ptr, - new_argv.ptr + new_argv.len, - &errors, - c_headers_dir_path_z, - ) catch |err| switch (err) { - error.OutOfMemory => return error.OutOfMemory, - error.SemanticAnalyzeFail => { - return CImportResult{ - .digest = undefined, - .cache_hit = actual_hit, - .errors = errors, - }; - }, - }; - }, - }; - defer tree.deinit(comp.gpa); - - if (comp.verbose_cimport) { - log.info("C import .d file: {s}", .{out_dep_path}); - } - - const dep_basename = fs.path.basename(out_dep_path); - try man.addDepFilePost(zig_cache_tmp_dir, dep_basename); - switch (comp.cache_use) { - .whole => |whole| if (whole.cache_manifest) |whole_cache_manifest| { - whole.cache_manifest_mutex.lock(); - defer whole.cache_manifest_mutex.unlock(); - try whole_cache_manifest.addDepFilePost(zig_cache_tmp_dir, dep_basename); - }, - .incremental, .none => {}, - } - - const bin_digest = man.finalBin(); - const hex_digest = Cache.binToHex(bin_digest); - const o_sub_path = "o" ++ fs.path.sep_str ++ hex_digest; - var o_dir = try comp.dirs.local_cache.handle.makeOpenPath(o_sub_path, .{}); - defer o_dir.close(); - - var out_zig_file = try o_dir.createFile(cimport_zig_basename, .{}); - defer out_zig_file.close(); - - const formatted = try tree.renderAlloc(comp.gpa); - defer comp.gpa.free(formatted); - - try out_zig_file.writeAll(formatted); - - break :digest bin_digest; - } else man.finalBin(); - - if (man.have_exclusive_lock) { - // Write the updated manifest. This is a no-op if the manifest is not dirty. Note that it is - // possible we had a hit and the manifest is dirty, for example if the file mtime changed but - // the contents were the same, we hit the cache but the manifest is dirty and we need to update - // it to prevent doing a full file content comparison the next time around. - man.writeManifest() catch |err| { - log.warn("failed to write cache manifest for C import: {s}", .{@errorName(err)}); - }; - } - - return CImportResult{ - .digest = digest, - .cache_hit = actual_hit, - .errors = std.zig.ErrorBundle.empty, - }; + _ = comp; + _ = c_src; + _ = owner_mod; + @panic("TODO execute 'zig translate-c' as a sub process and use the results"); } fn workerUpdateCObject( @@ -6739,20 +6600,6 @@ pub fn tmpFilePath(comp: Compilation, ally: Allocator, suffix: []const u8) error } } -pub fn addTranslateCCArgs( - comp: *Compilation, - arena: Allocator, - argv: *std.array_list.Managed([]const u8), - ext: FileExt, - out_dep_path: ?[]const u8, - owner_mod: *Package.Module, -) !void { - try argv.appendSlice(&.{ "-x", "c" }); - try comp.addCCArgs(arena, argv, ext, out_dep_path, owner_mod); - // This gives us access to preprocessing entities, presumably at the cost of performance. - try argv.appendSlice(&.{ "-Xclang", "-detailed-preprocessing-record" }); -} - /// Add common C compiler args between translate-c and C object compilation. pub fn addCCArgs( comp: *const Compilation, -- cgit v1.2.3 From 01d993b2305961100d2e898270b7a6be832d0fa7 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 18 Jul 2025 14:26:41 -0700 Subject: add translate-c CLI args --- src/Compilation.zig | 14 ++++++++++++++ src/main.zig | 43 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 51 insertions(+), 6 deletions(-) (limited to 'src/Compilation.zig') diff --git a/src/Compilation.zig b/src/Compilation.zig index 6e27d339f8..cf911bd348 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -6600,6 +6600,20 @@ pub fn tmpFilePath(comp: Compilation, ally: Allocator, suffix: []const u8) error } } +pub fn addTranslateCCArgs( + comp: *Compilation, + arena: Allocator, + argv: *std.ArrayList([]const u8), + ext: FileExt, + out_dep_path: ?[]const u8, + owner_mod: *Package.Module, +) !void { + try argv.appendSlice(&.{ "-x", "c" }); + try comp.addCCArgs(arena, argv, ext, out_dep_path, owner_mod); + // This gives us access to preprocessing entities, presumably at the cost of performance. + try argv.appendSlice(&.{ "-Xclang", "-detailed-preprocessing-record" }); +} + /// Add common C compiler args between translate-c and C object compilation. pub fn addCCArgs( comp: *const Compilation, diff --git a/src/main.zig b/src/main.zig index 4441734cbe..f95ea7300e 100644 --- a/src/main.zig +++ b/src/main.zig @@ -4542,9 +4542,22 @@ fn cmdTranslateC( assert(comp.c_source_files.len == 1); const c_source_file = comp.c_source_files[0]; - var argv: std.ArrayListUnmanaged([]const u8) = .empty; - try argv.append(arena, c_source_file.src_path); + var zig_cache_tmp_dir = try comp.dirs.local_cache.handle.makeOpenPath("tmp", .{}); + defer zig_cache_tmp_dir.close(); + + const ext = Compilation.classifyFileExt(c_source_file.src_path); + const out_dep_path: ?[]const u8 = blk: { + if (comp.disable_c_depfile) break :blk null; + const c_src_basename = fs.path.basename(c_source_file.src_path); + const dep_basename = try std.fmt.allocPrint(arena, "{s}.d", .{c_src_basename}); + const out_dep_path = try comp.tmpFilePath(arena, dep_basename); + break :blk out_dep_path; + }; + var argv = std.ArrayList([]const u8).init(arena); + try argv.append("arocc"); + try comp.addTranslateCCArgs(arena, &argv, ext, out_dep_path, comp.root_mod); + try argv.append(c_source_file.src_path); if (comp.verbose_cc) Compilation.dump_argv(argv.items); try jitCmd(comp.gpa, arena, argv.items, .{ @@ -4553,6 +4566,23 @@ fn cmdTranslateC( .depend_on_aro = true, .progress_node = prog_node, }); + + if (out_dep_path) |dep_file_path| { + const dep_basename = fs.path.basename(dep_file_path); + // Add the files depended on to the cache system. + //man.addDepFilePost(zig_cache_tmp_dir, dep_basename) catch |err| switch (err) { + // error.FileNotFound => { + // // Clang didn't emit the dep file; nothing to add to the manifest. + // break :add_deps; + // }, + // else => |e| return e, + //}; + // Just to save disk space, we delete the file because it is never needed again. + zig_cache_tmp_dir.deleteFile(dep_basename) catch |err| { + warn("failed to delete '{s}': {t}", .{ dep_file_path, err }); + }; + } + return cleanExit(); } @@ -5512,12 +5542,13 @@ fn jitCmd( child_argv.appendSliceAssumeCapacity(args); if (process.can_execv and options.capture == null) { + if (EnvVar.ZIG_DEBUG_CMD.isSet()) { + const cmd = try std.mem.join(arena, " ", child_argv.items); + std.debug.print("{s}\n", .{cmd}); + } const err = process.execv(gpa, child_argv.items); const cmd = try std.mem.join(arena, " ", child_argv.items); - fatal("the following command failed to execve with '{s}':\n{s}", .{ - @errorName(err), - cmd, - }); + fatal("the following command failed to execve with '{t}':\n{s}", .{ err, cmd }); } if (!process.can_spawn) { -- cgit v1.2.3 From 21f5f06f1f66c9f849ae39d868c2d4548078231f Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Tue, 29 Jul 2025 23:49:19 +0300 Subject: Compilation: avoid passing Clang specific options to Aro --- src/Compilation.zig | 488 +++++++++++++++++++++++++++++----------------------- src/main.zig | 1 - 2 files changed, 275 insertions(+), 214 deletions(-) (limited to 'src/Compilation.zig') diff --git a/src/Compilation.zig b/src/Compilation.zig index cf911bd348..26eebab98d 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -6608,14 +6608,43 @@ pub fn addTranslateCCArgs( out_dep_path: ?[]const u8, owner_mod: *Package.Module, ) !void { + const target = &owner_mod.resolved_target.result; + try argv.appendSlice(&.{ "-x", "c" }); - try comp.addCCArgs(arena, argv, ext, out_dep_path, owner_mod); - // This gives us access to preprocessing entities, presumably at the cost of performance. - try argv.appendSlice(&.{ "-Xclang", "-detailed-preprocessing-record" }); + + const resource_path = try comp.dirs.zig_lib.join(arena, &.{"compiler/aro/include"}); + try argv.appendSlice(&.{ "-isystem", resource_path }); + + try comp.addCommonCCArgs(arena, argv, ext, out_dep_path, owner_mod); + + try argv.appendSlice(&[_][]const u8{ "-target", try target.zigTriple(arena) }); + + const mcpu = mcpu: { + var buf: std.ArrayListUnmanaged(u8) = .empty; + defer buf.deinit(comp.gpa); + + try buf.print(comp.gpa, "-mcpu={s}", .{target.cpu.model.name}); + + // TODO better serialization https://github.com/ziglang/zig/issues/4584 + const all_features_list = target.cpu.arch.allFeaturesList(); + try argv.ensureUnusedCapacity(all_features_list.len * 4); + for (all_features_list, 0..) |feature, index_usize| { + const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize)); + const is_enabled = target.cpu.features.isEnabled(index); + + const plus_or_minus = "-+"[@intFromBool(is_enabled)]; + try buf.print(comp.gpa, "{c}{s}", .{ plus_or_minus, feature.name }); + } + break :mcpu try buf.toOwnedSlice(arena); + }; + try argv.append(mcpu); + + try argv.appendSlice(comp.global_cc_argv); + try argv.appendSlice(owner_mod.cc_argv); } /// Add common C compiler args between translate-c and C object compilation. -pub fn addCCArgs( +fn addCommonCCArgs( comp: *const Compilation, arena: Allocator, argv: *std.array_list.Managed([]const u8), @@ -6625,32 +6654,13 @@ pub fn addCCArgs( ) !void { const target = &mod.resolved_target.result; - // As of Clang 16.x, it will by default read extra flags from /etc/clang. - // I'm sure the person who implemented this means well, but they have a lot - // to learn about abstractions and where the appropriate boundaries between - // them are. The road to hell is paved with good intentions. Fortunately it - // can be disabled. - try argv.append("--no-default-config"); - - // We don't ever put `-fcolor-diagnostics` or `-fno-color-diagnostics` because in passthrough mode - // we want Clang to infer it, and in normal mode we always want it off, which will be true since - // clang will detect stderr as a pipe rather than a terminal. - if (!comp.clang_passthrough_mode and ext.clangSupportsDiagnostics()) { - // Make stderr more easily parseable. - try argv.append("-fno-caret-diagnostics"); - } - - // We never want clang to invoke the system assembler for anything. So we would want - // this option always enabled. However, it only matters for some targets. To avoid - // "unused parameter" warnings, and to keep CLI spam to a minimum, we only put this - // flag on the command line if it is necessary. - if (target_util.clangMightShellOutForAssembly(target)) { - try argv.append("-integrated-as"); + if (target_util.supports_fpic(target)) { + // PIE needs to go before PIC because Clang interprets `-fno-PIE` to imply `-fno-PIC`, which + // we don't necessarily want. + try argv.append(if (comp.config.pie) "-fPIE" else "-fno-PIE"); + try argv.append(if (mod.pic) "-fPIC" else "-fno-PIC"); } - const llvm_triple = try @import("codegen/llvm.zig").targetTriple(arena, target); - try argv.appendSlice(&[_][]const u8{ "-target", llvm_triple }); - switch (target.os.tag) { .ios, .macos, .tvos, .watchos => |os| { try argv.ensureUnusedCapacity(2); @@ -6676,78 +6686,6 @@ pub fn addCCArgs( else => {}, } - const xclang_flag = switch (ext) { - .assembly, .assembly_with_cpp => "-Xclangas", - else => "-Xclang", - }; - - if (target_util.clangSupportsTargetCpuArg(target)) { - if (target.cpu.model.llvm_name) |llvm_name| { - try argv.appendSlice(&[_][]const u8{ - xclang_flag, "-target-cpu", xclang_flag, llvm_name, - }); - } - } - - // It would be really nice if there was a more compact way to communicate this info to Clang. - const all_features_list = target.cpu.arch.allFeaturesList(); - try argv.ensureUnusedCapacity(all_features_list.len * 4); - for (all_features_list, 0..) |feature, index_usize| { - const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize)); - const is_enabled = target.cpu.features.isEnabled(index); - - if (feature.llvm_name) |llvm_name| { - // We communicate float ABI to Clang through the dedicated options. - if (std.mem.startsWith(u8, llvm_name, "soft-float") or - std.mem.startsWith(u8, llvm_name, "hard-float")) - continue; - - // Ignore these until we figure out how to handle the concept of omitting features. - // See https://github.com/ziglang/zig/issues/23539 - if (target_util.isDynamicAMDGCNFeature(target, feature)) continue; - - argv.appendSliceAssumeCapacity(&[_][]const u8{ xclang_flag, "-target-feature", xclang_flag }); - const plus_or_minus = "-+"[@intFromBool(is_enabled)]; - const arg = try std.fmt.allocPrint(arena, "{c}{s}", .{ plus_or_minus, llvm_name }); - argv.appendAssumeCapacity(arg); - } - } - - if (target.cpu.arch.isThumb()) { - try argv.append(switch (ext) { - .assembly, .assembly_with_cpp => "-Wa,-mthumb", - else => "-mthumb", - }); - } - - if (target_util.llvmMachineAbi(target)) |mabi| { - // Clang's integrated Arm assembler doesn't support `-mabi` yet... - // Clang's FreeBSD driver doesn't support `-mabi` on PPC64 (ELFv2 is used anyway). - if (!(target.cpu.arch.isArm() and (ext == .assembly or ext == .assembly_with_cpp)) and - !(target.cpu.arch.isPowerPC64() and target.os.tag == .freebsd)) - { - try argv.append(try std.fmt.allocPrint(arena, "-mabi={s}", .{mabi})); - } - } - - // We might want to support -mfloat-abi=softfp for Arm and CSKY here in the future. - if (target_util.clangSupportsFloatAbiArg(target)) { - const fabi = @tagName(target.abi.float()); - - try argv.append(switch (target.cpu.arch) { - // For whatever reason, Clang doesn't support `-mfloat-abi` for s390x. - .s390x => try std.fmt.allocPrint(arena, "-m{s}-float", .{fabi}), - else => try std.fmt.allocPrint(arena, "-mfloat-abi={s}", .{fabi}), - }); - } - - if (target_util.supports_fpic(target)) { - // PIE needs to go before PIC because Clang interprets `-fno-PIE` to imply `-fno-PIC`, which - // we don't necessarily want. - try argv.append(if (comp.config.pie) "-fPIE" else "-fno-PIE"); - try argv.append(if (mod.pic) "-fPIC" else "-fno-PIC"); - } - if (comp.mingw_unicode_entry_point) { try argv.append("-municode"); } @@ -6784,45 +6722,6 @@ pub fn addCCArgs( if (ext != .assembly) { try argv.append(if (target.os.tag == .freestanding) "-ffreestanding" else "-fhosted"); - if (target_util.clangSupportsNoImplicitFloatArg(target) and target.abi.float() == .soft) { - try argv.append("-mno-implicit-float"); - } - - if (target_util.hasRedZone(target)) { - try argv.append(if (mod.red_zone) "-mred-zone" else "-mno-red-zone"); - } - - try argv.append(if (mod.omit_frame_pointer) "-fomit-frame-pointer" else "-fno-omit-frame-pointer"); - - const ssp_buf_size = mod.stack_protector; - if (ssp_buf_size != 0) { - try argv.appendSlice(&[_][]const u8{ - "-fstack-protector-strong", - "--param", - try std.fmt.allocPrint(arena, "ssp-buffer-size={d}", .{ssp_buf_size}), - }); - } else { - try argv.append("-fno-stack-protector"); - } - - try argv.append(if (mod.no_builtin) "-fno-builtin" else "-fbuiltin"); - - try argv.append(if (comp.function_sections) "-ffunction-sections" else "-fno-function-sections"); - try argv.append(if (comp.data_sections) "-fdata-sections" else "-fno-data-sections"); - - switch (mod.unwind_tables) { - .none => { - try argv.append("-fno-unwind-tables"); - try argv.append("-fno-asynchronous-unwind-tables"); - }, - .sync => { - // Need to override Clang's convoluted default logic. - try argv.append("-fno-asynchronous-unwind-tables"); - try argv.append("-funwind-tables"); - }, - .async => try argv.append("-fasynchronous-unwind-tables"), - } - try argv.append("-nostdinc"); if (ext == .cpp or ext == .hpp) { @@ -6961,80 +6860,6 @@ pub fn addCCArgs( else => {}, } - // Only assembly files support these flags. - switch (ext) { - .assembly, - .assembly_with_cpp, - => { - // The Clang assembler does not accept the list of CPU features like the - // compiler frontend does. Therefore we must hard-code the -m flags for - // all CPU features here. - switch (target.cpu.arch) { - .riscv32, .riscv32be, .riscv64, .riscv64be => { - const RvArchFeat = struct { char: u8, feat: std.Target.riscv.Feature }; - const letters = [_]RvArchFeat{ - .{ .char = 'm', .feat = .m }, - .{ .char = 'a', .feat = .a }, - .{ .char = 'f', .feat = .f }, - .{ .char = 'd', .feat = .d }, - .{ .char = 'c', .feat = .c }, - }; - const prefix: []const u8 = if (target.cpu.arch == .riscv64) "rv64" else "rv32"; - const prefix_len = 4; - assert(prefix.len == prefix_len); - var march_buf: [prefix_len + letters.len + 1]u8 = undefined; - var march_index: usize = prefix_len; - @memcpy(march_buf[0..prefix.len], prefix); - - if (target.cpu.has(.riscv, .e)) { - march_buf[march_index] = 'e'; - } else { - march_buf[march_index] = 'i'; - } - march_index += 1; - - for (letters) |letter| { - if (target.cpu.has(.riscv, letter.feat)) { - march_buf[march_index] = letter.char; - march_index += 1; - } - } - - const march_arg = try std.fmt.allocPrint(arena, "-march={s}", .{ - march_buf[0..march_index], - }); - try argv.append(march_arg); - - if (target.cpu.has(.riscv, .relax)) { - try argv.append("-mrelax"); - } else { - try argv.append("-mno-relax"); - } - if (target.cpu.has(.riscv, .save_restore)) { - try argv.append("-msave-restore"); - } else { - try argv.append("-mno-save-restore"); - } - }, - .mips, .mipsel, .mips64, .mips64el => { - if (target.cpu.model.llvm_name) |llvm_name| { - try argv.append(try std.fmt.allocPrint(arena, "-march={s}", .{llvm_name})); - } - }, - else => { - // TODO - }, - } - - if (target_util.clangAssemblerSupportsMcpuArg(target)) { - if (target.cpu.model.llvm_name) |llvm_name| { - try argv.append(try std.fmt.allocPrint(arena, "-mcpu={s}", .{llvm_name})); - } - } - }, - else => {}, - } - // Only compiled files support these flags. switch (ext) { .c, @@ -7133,6 +6958,243 @@ pub fn addCCArgs( }, else => {}, } +} + +/// Add common C compiler args and Clang specific args. +pub fn addCCArgs( + comp: *const Compilation, + arena: Allocator, + argv: *std.ArrayList([]const u8), + ext: FileExt, + out_dep_path: ?[]const u8, + mod: *Package.Module, +) !void { + const target = &mod.resolved_target.result; + + // As of Clang 16.x, it will by default read extra flags from /etc/clang. + // I'm sure the person who implemented this means well, but they have a lot + // to learn about abstractions and where the appropriate boundaries between + // them are. The road to hell is paved with good intentions. Fortunately it + // can be disabled. + try argv.append("--no-default-config"); + + // We don't ever put `-fcolor-diagnostics` or `-fno-color-diagnostics` because in passthrough mode + // we want Clang to infer it, and in normal mode we always want it off, which will be true since + // clang will detect stderr as a pipe rather than a terminal. + if (!comp.clang_passthrough_mode and ext.clangSupportsDiagnostics()) { + // Make stderr more easily parseable. + try argv.append("-fno-caret-diagnostics"); + } + + // We never want clang to invoke the system assembler for anything. So we would want + // this option always enabled. However, it only matters for some targets. To avoid + // "unused parameter" warnings, and to keep CLI spam to a minimum, we only put this + // flag on the command line if it is necessary. + if (target_util.clangMightShellOutForAssembly(target)) { + try argv.append("-integrated-as"); + } + + const llvm_triple = try @import("codegen/llvm.zig").targetTriple(arena, target); + try argv.appendSlice(&[_][]const u8{ "-target", llvm_triple }); + + if (target.cpu.arch.isThumb()) { + try argv.append(switch (ext) { + .assembly, .assembly_with_cpp => "-Wa,-mthumb", + else => "-mthumb", + }); + } + + if (target_util.llvmMachineAbi(target)) |mabi| { + // Clang's integrated Arm assembler doesn't support `-mabi` yet... + // Clang's FreeBSD driver doesn't support `-mabi` on PPC64 (ELFv2 is used anyway). + if (!(target.cpu.arch.isArm() and (ext == .assembly or ext == .assembly_with_cpp)) and + !(target.cpu.arch.isPowerPC64() and target.os.tag == .freebsd)) + { + try argv.append(try std.fmt.allocPrint(arena, "-mabi={s}", .{mabi})); + } + } + + // We might want to support -mfloat-abi=softfp for Arm and CSKY here in the future. + if (target_util.clangSupportsFloatAbiArg(target)) { + const fabi = @tagName(target.abi.float()); + + try argv.append(switch (target.cpu.arch) { + // For whatever reason, Clang doesn't support `-mfloat-abi` for s390x. + .s390x => try std.fmt.allocPrint(arena, "-m{s}-float", .{fabi}), + else => try std.fmt.allocPrint(arena, "-mfloat-abi={s}", .{fabi}), + }); + } + + try comp.addCommonCCArgs(arena, argv, ext, out_dep_path, mod); + + // Only assembly files support these flags. + switch (ext) { + .assembly, + .assembly_with_cpp, + => { + // The Clang assembler does not accept the list of CPU features like the + // compiler frontend does. Therefore we must hard-code the -m flags for + // all CPU features here. + switch (target.cpu.arch) { + .riscv32, .riscv32be, .riscv64, .riscv64be => { + const RvArchFeat = struct { char: u8, feat: std.Target.riscv.Feature }; + const letters = [_]RvArchFeat{ + .{ .char = 'm', .feat = .m }, + .{ .char = 'a', .feat = .a }, + .{ .char = 'f', .feat = .f }, + .{ .char = 'd', .feat = .d }, + .{ .char = 'c', .feat = .c }, + }; + const prefix: []const u8 = if (target.cpu.arch == .riscv64) "rv64" else "rv32"; + const prefix_len = 4; + assert(prefix.len == prefix_len); + var march_buf: [prefix_len + letters.len + 1]u8 = undefined; + var march_index: usize = prefix_len; + @memcpy(march_buf[0..prefix.len], prefix); + + if (target.cpu.has(.riscv, .e)) { + march_buf[march_index] = 'e'; + } else { + march_buf[march_index] = 'i'; + } + march_index += 1; + + for (letters) |letter| { + if (target.cpu.has(.riscv, letter.feat)) { + march_buf[march_index] = letter.char; + march_index += 1; + } + } + + const march_arg = try std.fmt.allocPrint(arena, "-march={s}", .{ + march_buf[0..march_index], + }); + try argv.append(march_arg); + + if (target.cpu.has(.riscv, .relax)) { + try argv.append("-mrelax"); + } else { + try argv.append("-mno-relax"); + } + if (target.cpu.has(.riscv, .save_restore)) { + try argv.append("-msave-restore"); + } else { + try argv.append("-mno-save-restore"); + } + }, + .mips, .mipsel, .mips64, .mips64el => { + if (target.cpu.model.llvm_name) |llvm_name| { + try argv.append(try std.fmt.allocPrint(arena, "-march={s}", .{llvm_name})); + } + }, + else => { + // TODO + }, + } + + if (target_util.clangAssemblerSupportsMcpuArg(target)) { + if (target.cpu.model.llvm_name) |llvm_name| { + try argv.append(try std.fmt.allocPrint(arena, "-mcpu={s}", .{llvm_name})); + } + } + }, + else => {}, + } + + // Non-preprocessed assembly files don't support these flags. + if (ext != .assembly) { + if (target_util.clangSupportsNoImplicitFloatArg(target) and target.abi.float() == .soft) { + try argv.append("-mno-implicit-float"); + } + + if (target_util.hasRedZone(target)) { + try argv.append(if (mod.red_zone) "-mred-zone" else "-mno-red-zone"); + } + + try argv.append(if (mod.omit_frame_pointer) "-fomit-frame-pointer" else "-fno-omit-frame-pointer"); + + const ssp_buf_size = mod.stack_protector; + if (ssp_buf_size != 0) { + try argv.appendSlice(&[_][]const u8{ + "-fstack-protector-strong", + "--param", + try std.fmt.allocPrint(arena, "ssp-buffer-size={d}", .{ssp_buf_size}), + }); + } else { + try argv.append("-fno-stack-protector"); + } + + try argv.append(if (mod.no_builtin) "-fno-builtin" else "-fbuiltin"); + + try argv.append(if (comp.function_sections) "-ffunction-sections" else "-fno-function-sections"); + try argv.append(if (comp.data_sections) "-fdata-sections" else "-fno-data-sections"); + + switch (mod.unwind_tables) { + .none => { + try argv.append("-fno-unwind-tables"); + try argv.append("-fno-asynchronous-unwind-tables"); + }, + .sync => { + // Need to override Clang's convoluted default logic. + try argv.append("-fno-asynchronous-unwind-tables"); + try argv.append("-funwind-tables"); + }, + .async => try argv.append("-fasynchronous-unwind-tables"), + } + } + + // Only compiled files support these flags. + switch (ext) { + .c, + .h, + .cpp, + .hpp, + .m, + .hm, + .mm, + .hmm, + .ll, + .bc, + => { + const xclang_flag = switch (ext) { + .assembly, .assembly_with_cpp => "-Xclangas", + else => "-Xclang", + }; + + if (target_util.clangSupportsTargetCpuArg(target)) { + if (target.cpu.model.llvm_name) |llvm_name| { + try argv.appendSlice(&[_][]const u8{ + xclang_flag, "-target-cpu", xclang_flag, llvm_name, + }); + } + } + + // It would be really nice if there was a more compact way to communicate this info to Clang. + const all_features_list = target.cpu.arch.allFeaturesList(); + try argv.ensureUnusedCapacity(all_features_list.len * 4); + for (all_features_list, 0..) |feature, index_usize| { + const index = @as(std.Target.Cpu.Feature.Set.Index, @intCast(index_usize)); + const is_enabled = target.cpu.features.isEnabled(index); + + if (feature.llvm_name) |llvm_name| { + // We communicate float ABI to Clang through the dedicated options. + if (std.mem.startsWith(u8, llvm_name, "soft-float") or + std.mem.startsWith(u8, llvm_name, "hard-float")) + continue; + + // Ignore these until we figure out how to handle the concept of omitting features. + // See https://github.com/ziglang/zig/issues/23539 + if (target_util.isDynamicAMDGCNFeature(target, feature)) continue; + + argv.appendSliceAssumeCapacity(&[_][]const u8{ xclang_flag, "-target-feature", xclang_flag }); + const plus_or_minus = "-+"[@intFromBool(is_enabled)]; + const arg = try std.fmt.allocPrint(arena, "{c}{s}", .{ plus_or_minus, llvm_name }); + argv.appendAssumeCapacity(arg); + } + } + }, + else => {}, + } try argv.appendSlice(comp.global_cc_argv); try argv.appendSlice(mod.cc_argv); diff --git a/src/main.zig b/src/main.zig index f95ea7300e..de1c112c85 100644 --- a/src/main.zig +++ b/src/main.zig @@ -4555,7 +4555,6 @@ fn cmdTranslateC( }; var argv = std.ArrayList([]const u8).init(arena); - try argv.append("arocc"); try comp.addTranslateCCArgs(arena, &argv, ext, out_dep_path, comp.root_mod); try argv.append(c_source_file.src_path); if (comp.verbose_cc) Compilation.dump_argv(argv.items); -- cgit v1.2.3 From e5f4dbdf8aab9e5b17d2401b55493300235ab15b Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 11 Aug 2025 16:20:57 -0700 Subject: fix rebase conflicts --- lib/compiler/aro/aro/Parser.zig | 2 +- lib/compiler/aro/aro/Preprocessor.zig | 2 +- src/Compilation.zig | 2 +- src/main.zig | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/Compilation.zig') diff --git a/lib/compiler/aro/aro/Parser.zig b/lib/compiler/aro/aro/Parser.zig index e7a60eb76c..8cc088942b 100644 --- a/lib/compiler/aro/aro/Parser.zig +++ b/lib/compiler/aro/aro/Parser.zig @@ -32,7 +32,7 @@ const Type = TypeStore.Type; const QualType = TypeStore.QualType; const Value = @import("Value.zig"); -const NodeList = std.ArrayList(Node.Index); +const NodeList = std.array_list.Managed(Node.Index); const Switch = struct { default: ?TokenIndex = null, ranges: std.array_list.Managed(Range), diff --git a/lib/compiler/aro/aro/Preprocessor.zig b/lib/compiler/aro/aro/Preprocessor.zig index 45d40af3c6..680e01ebf8 100644 --- a/lib/compiler/aro/aro/Preprocessor.zig +++ b/lib/compiler/aro/aro/Preprocessor.zig @@ -814,7 +814,7 @@ fn fatalNotFound(pp: *Preprocessor, tok: TokenWithExpansionLocs, filename: []con defer pp.diagnostics.state.fatal_errors = old; var sf = std.heap.stackFallback(1024, pp.gpa); - var buf = std.ArrayList(u8).init(sf.get()); + var buf = std.array_list.Managed(u8).init(sf.get()); defer buf.deinit(); try buf.print("'{s}' not found", .{filename}); diff --git a/src/Compilation.zig b/src/Compilation.zig index 26eebab98d..74ec79b35f 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -6603,7 +6603,7 @@ pub fn tmpFilePath(comp: Compilation, ally: Allocator, suffix: []const u8) error pub fn addTranslateCCArgs( comp: *Compilation, arena: Allocator, - argv: *std.ArrayList([]const u8), + argv: *std.array_list.Managed([]const u8), ext: FileExt, out_dep_path: ?[]const u8, owner_mod: *Package.Module, diff --git a/src/main.zig b/src/main.zig index de1c112c85..94120f0a1c 100644 --- a/src/main.zig +++ b/src/main.zig @@ -4554,7 +4554,7 @@ fn cmdTranslateC( break :blk out_dep_path; }; - var argv = std.ArrayList([]const u8).init(arena); + var argv = std.array_list.Managed([]const u8).init(arena); try comp.addTranslateCCArgs(arena, &argv, ext, out_dep_path, comp.root_mod); try argv.append(c_source_file.src_path); if (comp.verbose_cc) Compilation.dump_argv(argv.items); -- cgit v1.2.3 From 9e979e5a9dbee39d45ac7dc4fbedb63ddcae8e99 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 11 Aug 2025 19:44:29 -0700 Subject: Compilation: re-implement cImport --- src/Compilation.zig | 89 +++++++++++++++++++++++++++++++++++++++++++++++++---- src/Sema.zig | 11 +++---- src/main.zig | 23 ++++++++++---- 3 files changed, 105 insertions(+), 18 deletions(-) (limited to 'src/Compilation.zig') diff --git a/src/Compilation.zig b/src/Compilation.zig index 74ec79b35f..d0f33f123d 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -5655,12 +5655,89 @@ pub const CImportResult = struct { }; /// Caller owns returned memory. -pub fn cImport(comp: *Compilation, c_src: []const u8, owner_mod: *Package.Module) !CImportResult { +pub fn cImport( + comp: *Compilation, + c_src: []const u8, + owner_mod: *Package.Module, + prog_node: std.Progress.Node, +) !CImportResult { dev.check(.translate_c_command); - _ = comp; - _ = c_src; - _ = owner_mod; - @panic("TODO execute 'zig translate-c' as a sub process and use the results"); + + const cimport_basename = "cimport.h"; + const translated_basename = "cimport.zig"; + + var man = comp.obtainCObjectCacheManifest(owner_mod); + defer man.deinit(); + + man.hash.add(@as(u16, 0x7dd9)); // Random number to distinguish translate-c from compiling C objects + man.hash.addBytes(c_src); + + const digest, const is_hit = if (try man.hit()) .{ man.finalBin(), true } else digest: { + var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa); + defer arena_allocator.deinit(); + const arena = arena_allocator.allocator(); + + const tmp_basename = std.fmt.hex(std.crypto.random.int(u64)); + const tmp_sub_path = "tmp" ++ fs.path.sep_str ++ tmp_basename; + const cache_dir = comp.dirs.local_cache.handle; + const out_h_sub_path = tmp_sub_path ++ fs.path.sep_str ++ cimport_basename; + + try cache_dir.makePath(tmp_sub_path); + + const out_h_path = try comp.dirs.local_cache.join(arena, &.{out_h_sub_path}); + const translated_path = try comp.dirs.local_cache.join(arena, &.{ tmp_sub_path, translated_basename }); + const out_dep_path = try std.fmt.allocPrint(arena, "{s}.d", .{out_h_path}); + + if (comp.verbose_cimport) log.info("writing C import source to {s}", .{out_h_path}); + try cache_dir.writeFile(.{ .sub_path = out_h_sub_path, .data = c_src }); + + var argv = std.array_list.Managed([]const u8).init(comp.gpa); + defer argv.deinit(); + try comp.addTranslateCCArgs(arena, &argv, .c, out_dep_path, owner_mod); + try argv.appendSlice(&.{ out_h_path, "-o", translated_path }); + + if (comp.verbose_cc) dump_argv(argv.items); + var stdout: []u8 = undefined; + try @import("main.zig").translateC(comp.gpa, arena, argv.items, prog_node, &stdout); + if (comp.verbose_cimport and stdout.len != 0) log.info("unexpected stdout: {s}", .{stdout}); + + const dep_sub_path = out_h_sub_path ++ ".d"; + if (comp.verbose_cimport) log.info("processing dep file at {s}", .{dep_sub_path}); + try man.addDepFilePost(cache_dir, dep_sub_path); + switch (comp.cache_use) { + .whole => |whole| if (whole.cache_manifest) |whole_cache_manifest| { + whole.cache_manifest_mutex.lock(); + defer whole.cache_manifest_mutex.unlock(); + try whole_cache_manifest.addDepFilePost(cache_dir, dep_sub_path); + }, + .incremental, .none => {}, + } + + const bin_digest = man.finalBin(); + const hex_digest = Cache.binToHex(bin_digest); + const o_sub_path = "o" ++ fs.path.sep_str ++ hex_digest; + + if (comp.verbose_cimport) log.info("renaming {s} to {s}", .{ tmp_sub_path, o_sub_path }); + try fs.rename(cache_dir, tmp_sub_path, cache_dir, o_sub_path); + + break :digest .{ bin_digest, false }; + }; + + if (man.have_exclusive_lock) { + // Write the updated manifest. This is a no-op if the manifest is not dirty. Note that it is + // possible we had a hit and the manifest is dirty, for example if the file mtime changed but + // the contents were the same, we hit the cache but the manifest is dirty and we need to update + // it to prevent doing a full file content comparison the next time around. + man.writeManifest() catch |err| { + log.warn("failed to write cache manifest for C import: {s}", .{@errorName(err)}); + }; + } + + return .{ + .digest = digest, + .cache_hit = is_hit, + .errors = std.zig.ErrorBundle.empty, + }; } fn workerUpdateCObject( @@ -6964,7 +7041,7 @@ fn addCommonCCArgs( pub fn addCCArgs( comp: *const Compilation, arena: Allocator, - argv: *std.ArrayList([]const u8), + argv: *std.array_list.Managed([]const u8), ext: FileExt, out_dep_path: ?[]const u8, mod: *Package.Module, diff --git a/src/Sema.zig b/src/Sema.zig index d0576de33d..73c5b13c21 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -5713,10 +5713,6 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr const extra = sema.code.extraData(Zir.Inst.Block, pl_node.payload_index); const body = sema.code.bodySlice(extra.end, extra.data.body_len); - // we check this here to avoid undefined symbols - if (!build_options.have_llvm) - return sema.fail(parent_block, src, "C import unavailable; Zig compiler built without LLVM extensions", .{}); - var c_import_buf = std.array_list.Managed(u8).init(gpa); defer c_import_buf.deinit(); @@ -5741,8 +5737,11 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr _ = try sema.analyzeInlineBody(&child_block, body, inst); - var c_import_res = comp.cImport(c_import_buf.items, parent_block.ownerModule()) catch |err| - return sema.fail(&child_block, src, "C import failed: {s}", .{@errorName(err)}); + const prog_node = zcu.cur_sema_prog_node.start("@cImport", 0); + defer prog_node.end(); + + var c_import_res = comp.cImport(c_import_buf.items, parent_block.ownerModule(), prog_node) catch |err| + return sema.fail(&child_block, src, "C import failed: {t}", .{err}); defer c_import_res.deinit(gpa); if (c_import_res.errors.errorMessageCount() != 0) { diff --git a/src/main.zig b/src/main.zig index 94120f0a1c..ea5225d933 100644 --- a/src/main.zig +++ b/src/main.zig @@ -4559,12 +4559,7 @@ fn cmdTranslateC( try argv.append(c_source_file.src_path); if (comp.verbose_cc) Compilation.dump_argv(argv.items); - try jitCmd(comp.gpa, arena, argv.items, .{ - .cmd_name = "translate-c", - .root_src_path = "translate-c/main.zig", - .depend_on_aro = true, - .progress_node = prog_node, - }); + try translateC(comp.gpa, arena, argv.items, prog_node, null); if (out_dep_path) |dep_file_path| { const dep_basename = fs.path.basename(dep_file_path); @@ -4585,6 +4580,22 @@ fn cmdTranslateC( return cleanExit(); } +pub fn translateC( + gpa: Allocator, + arena: Allocator, + argv: []const []const u8, + prog_node: std.Progress.Node, + capture: ?*[]u8, +) !void { + try jitCmd(gpa, arena, argv, .{ + .cmd_name = "translate-c", + .root_src_path = "translate-c/main.zig", + .depend_on_aro = true, + .progress_node = prog_node, + .capture = capture, + }); +} + const usage_init = \\Usage: zig init \\ -- cgit v1.2.3 From f4d328e2ac0583336085f647df18c7430b7948be Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 13 Aug 2025 15:04:25 -0700 Subject: Compilation: use renameTmpIntoCache solves several problems with this pattern --- src/Compilation.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/Compilation.zig') diff --git a/src/Compilation.zig b/src/Compilation.zig index d0f33f123d..a1369ec420 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -5718,7 +5718,7 @@ pub fn cImport( const o_sub_path = "o" ++ fs.path.sep_str ++ hex_digest; if (comp.verbose_cimport) log.info("renaming {s} to {s}", .{ tmp_sub_path, o_sub_path }); - try fs.rename(cache_dir, tmp_sub_path, cache_dir, o_sub_path); + try renameTmpIntoCache(comp.dirs.local_cache, tmp_sub_path, o_sub_path); break :digest .{ bin_digest, false }; }; -- cgit v1.2.3 From e1d6f478c9e96d89ad1f2683d6b372eb466b8339 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 13 Aug 2025 15:56:56 -0700 Subject: `@cImport`: don't pass args to Aro it doesn't understand --- src/Compilation.zig | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src/Compilation.zig') diff --git a/src/Compilation.zig b/src/Compilation.zig index a1369ec420..b50a158436 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -6692,7 +6692,7 @@ pub fn addTranslateCCArgs( const resource_path = try comp.dirs.zig_lib.join(arena, &.{"compiler/aro/include"}); try argv.appendSlice(&.{ "-isystem", resource_path }); - try comp.addCommonCCArgs(arena, argv, ext, out_dep_path, owner_mod); + try comp.addCommonCCArgs(arena, argv, ext, out_dep_path, owner_mod, .aro); try argv.appendSlice(&[_][]const u8{ "-target", try target.zigTriple(arena) }); @@ -6728,6 +6728,7 @@ fn addCommonCCArgs( ext: FileExt, out_dep_path: ?[]const u8, mod: *Package.Module, + c_frontend: Config.CFrontend, ) !void { const target = &mod.resolved_target.result; @@ -6911,6 +6912,8 @@ fn addCommonCCArgs( } } + const is_clang = c_frontend == .clang; + // Only C-family files support these flags. switch (ext) { .c, @@ -6922,7 +6925,7 @@ fn addCommonCCArgs( .mm, .hmm, => { - try argv.append("-fno-spell-checking"); + if (is_clang) try argv.append("-fno-spell-checking"); if (target.os.tag == .windows and target.abi.isGnu()) { // windows.h has files such as pshpack1.h which do #pragma packing, @@ -6954,7 +6957,7 @@ fn addCommonCCArgs( try argv.append(try std.fmt.allocPrint(arena, "-mcmodel={s}", .{@tagName(mod.code_model)})); } - { + if (is_clang) { var san_arg: std.ArrayListUnmanaged(u8) = .empty; const prefix = "-fsanitize="; if (mod.sanitize_c != .off) { @@ -7102,7 +7105,7 @@ pub fn addCCArgs( }); } - try comp.addCommonCCArgs(arena, argv, ext, out_dep_path, mod); + try comp.addCommonCCArgs(arena, argv, ext, out_dep_path, mod, comp.config.c_frontend); // Only assembly files support these flags. switch (ext) { -- cgit v1.2.3 From aa92c237e9174e2f48d11c6c23ac41067fa9bb57 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 21 Aug 2025 16:07:36 -0700 Subject: aro does not have a pragma-pack warning --- src/Compilation.zig | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'src/Compilation.zig') diff --git a/src/Compilation.zig b/src/Compilation.zig index b50a158436..46cb4de08f 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -6925,12 +6925,14 @@ fn addCommonCCArgs( .mm, .hmm, => { - if (is_clang) try argv.append("-fno-spell-checking"); + if (is_clang) { + try argv.append("-fno-spell-checking"); - if (target.os.tag == .windows and target.abi.isGnu()) { - // windows.h has files such as pshpack1.h which do #pragma packing, - // triggering a clang warning. So for this target, we disable this warning. - try argv.append("-Wno-pragma-pack"); + if (target.os.tag == .windows and target.abi.isGnu()) { + // windows.h has files such as pshpack1.h which do #pragma packing, + // triggering a clang warning. So for this target, we disable this warning. + try argv.append("-Wno-pragma-pack"); + } } if (mod.optimize_mode != .Debug) { -- cgit v1.2.3 From e05073b9e4a7a7a860779d3977a98ee6cd4b6391 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 21 Aug 2025 18:10:31 -0700 Subject: aro does not have -mmacos version flags or -Wno-overriding-option --- src/Compilation.zig | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/Compilation.zig') diff --git a/src/Compilation.zig b/src/Compilation.zig index 46cb4de08f..c31a9ae012 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -6731,6 +6731,7 @@ fn addCommonCCArgs( c_frontend: Config.CFrontend, ) !void { const target = &mod.resolved_target.result; + const is_clang = c_frontend == .clang; if (target_util.supports_fpic(target)) { // PIE needs to go before PIC because Clang interprets `-fno-PIE` to imply `-fno-PIC`, which @@ -6740,7 +6741,7 @@ fn addCommonCCArgs( } switch (target.os.tag) { - .ios, .macos, .tvos, .watchos => |os| { + .ios, .macos, .tvos, .watchos => |os| if (is_clang) { try argv.ensureUnusedCapacity(2); // Pass the proper -m-version-min argument for darwin. const ver = target.os.version_range.semver.min; @@ -6912,8 +6913,6 @@ fn addCommonCCArgs( } } - const is_clang = c_frontend == .clang; - // Only C-family files support these flags. switch (ext) { .c, -- cgit v1.2.3