From ff38f560402aa61ce8e4ae38b4fa0ff2ddbaede6 Mon Sep 17 00:00:00 2001 From: vole-dev Date: Sat, 30 Oct 2021 10:30:28 -0500 Subject: [PATCH 1/3] default mabi based on RISC-V extensions and -mabi build option The target abi can also be set in build.zig via LibExeObjStep.target_abi The value passed in is checked that it is a valid value in std.Target.TargetAbi The target abi is also validated against the target cpu --- lib/std/build.zig | 4 +++ lib/std/target.zig | 78 ++++++++++++++++++++++++++++++++++++++++++ src/Compilation.zig | 46 ++++++++++++++++--------- src/codegen/llvm.zig | 13 +------ src/glibc.zig | 1 + src/libcxx.zig | 2 ++ src/libtsan.zig | 1 + src/libunwind.zig | 1 + src/link.zig | 1 + src/main.zig | 16 +++++++++ src/musl.zig | 1 + src/stage1.zig | 1 + src/stage1/codegen.cpp | 5 ++- src/stage1/stage1.h | 1 + src/test.zig | 1 + 15 files changed, 141 insertions(+), 31 deletions(-) diff --git a/lib/std/build.zig b/lib/std/build.zig index 30296081b757..cd551924a9e7 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -1474,6 +1474,7 @@ pub const LibExeObjStep = struct { name_prefix: []const u8, filter: ?[]const u8, test_evented_io: bool = false, + target_abi: ?std.Target.TargetAbi = null, code_model: std.builtin.CodeModel = .default, wasi_exec_model: ?std.builtin.WasiExecModel = null, @@ -2458,6 +2459,9 @@ pub const LibExeObjStep = struct { try zig_args.append(builder.fmt("--global-base={d}", .{global_base})); } + if (self.target_abi) |target_abi| { + try zig_args.append(builder.fmt("-mabi={s}", .{@tagName(target_abi)})); + } if (self.code_model != .default) { try zig_args.append("-mcmodel"); try zig_args.append(@tagName(self.code_model)); diff --git a/lib/std/target.zig b/lib/std/target.zig index c6ee53157d5e..43cd80bb3b24 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -560,6 +560,84 @@ pub const Target = struct { } }; + /// processor specific ABI + pub const TargetAbi = enum { + //TODO add ARM, Mips, and PowerPC + ilp32, + ilp32d, + ilp32e, + ilp32f, + lp64, + lp64d, + lp64f, + + const Riscv32ABI = struct { + fn default(features: Cpu.Feature.Set) TargetAbi { + if (riscv.featureSetHas(features, .d)) { + return .ilp32d; + } else if (riscv.featureSetHas(features, .e)) { + return .ilp32e; + } else { + return .ilp32; + } + } + fn validate(target_abi: TargetAbi, features: Cpu.Feature.Set) ParseError!void { + const has_e = riscv.featureSetHas(features, .e); + const has_f = riscv.featureSetHas(features, .f); + const has_d = riscv.featureSetHas(features, .d); + return switch (target_abi) { + .ilp32e => if (has_e) {} else error.FeatureAbiMismatch, + .ilp32 => if (!has_e) {} else error.FeatureAbiMismatch, + .ilp32f => if (!has_e and has_f) {} else error.FeatureAbiMismatch, + .ilp32d => if (!has_e and has_d) {} else error.FeatureAbiMismatch, + else => error.ArchAbiMismatch, + }; + } + }; + const Riscv64ABI = struct { + fn default(features: Cpu.Feature.Set) TargetAbi { + if (riscv.featureSetHas(features, .d)) { + return .lp64d; + } else { + return .lp64; + } + } + fn validate(target_abi: TargetAbi, features: Cpu.Feature.Set) ParseError!void { + const has_f = riscv.featureSetHas(features, .f); + const has_d = riscv.featureSetHas(features, .d); + return switch (target_abi) { + .lp64 => {}, + .lp64f => if (has_f) {} else error.FeatureAbiMismatch, + .lp64d => if (has_d) {} else error.FeatureAbiMismatch, + else => error.ArchAbiMismatch, + }; + } + }; + pub fn default(arch: Cpu.Arch, features: Cpu.Feature.Set) ?TargetAbi { + return switch (arch) { + .riscv32 => Riscv32ABI.default(features), + .riscv64 => Riscv64ABI.default(features), + else => null, + }; + } + + pub const ParseError = error{ + InvalidAbi, + ArchAbiMismatch, + FeatureAbiMismatch, + }; + pub fn parse(cpu: Cpu, abi_string: []const u8) ParseError!TargetAbi { + const target_abi = std.meta.stringToEnum(TargetAbi, abi_string) orelse return error.InvalidAbi; + + switch (cpu.arch) { + .riscv32 => try Riscv32ABI.validate(target_abi, cpu.features), + .riscv64 => try Riscv64ABI.validate(target_abi, cpu.features), + else => return error.ArchAbiMismatch, + } + return target_abi; + } + }; + pub const ObjectFormat = enum { /// Common Object File Format (Windows) coff, diff --git a/src/Compilation.zig b/src/Compilation.zig index ce7f204dd683..e58e9049b5ce 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -767,6 +767,7 @@ pub const InitOptions = struct { compatibility_version: ?std.builtin.Version = null, libc_installation: ?*const LibCInstallation = null, machine_code_model: std.builtin.CodeModel = .default, + target_abi: ?std.Target.TargetAbi, clang_preprocessor_mode: ClangPreprocessorMode = .no, /// This is for stage1 and should be deleted upon completion of self-hosting. color: @import("main.zig").Color = .auto, @@ -1176,6 +1177,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { cache.hash.add(options.target.os.getVersionRange()); cache.hash.add(options.is_native_os); cache.hash.add(options.target.abi); + cache.hash.addOptionalBytes(if (options.target_abi) |t| @tagName(t) else null); cache.hash.add(ofmt); cache.hash.add(pic); cache.hash.add(pie); @@ -1488,6 +1490,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .single_threaded = single_threaded, .verbose_link = options.verbose_link, .machine_code_model = options.machine_code_model, + .target_abi = options.target_abi, .dll_export_fns = dll_export_fns, .error_return_tracing = error_return_tracing, .llvm_cpu_features = llvm_cpu_features, @@ -1780,8 +1783,8 @@ pub fn getTarget(self: Compilation) Target { /// Detect changes to source files, perform semantic analysis, and update the output files. pub fn update(self: *Compilation) !void { - const t = trace(@src()); - defer t.end(); + const tracy_trace = trace(@src()); + defer tracy_trace.end(); self.clearMiscFailures(); @@ -2822,8 +2825,8 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult { if (!build_options.have_llvm) return error.ZigCompilerNotBuiltWithLLVMExtensions; - const t = trace(@src()); - defer t.end(); + const tracy_trace = trace(@src()); + defer tracy_trace.end(); const cimport_zig_basename = "cimport.zig"; @@ -3077,8 +3080,8 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P const self_exe_path = comp.self_exe_path orelse return comp.failCObj(c_object, "clang compilation disabled", .{}); - const t = trace(@src()); - defer t.end(); + const tracy_trace = trace(@src()); + defer tracy_trace.end(); log.debug("updating C object: {s}", .{c_object.src.src_path}); @@ -3451,6 +3454,9 @@ pub fn addCCArgs( try argv.append("-mthumb"); } + if (comp.bin_file.options.target_abi) |target_abi| { + try argv.append(try std.fmt.allocPrint(arena, "-mabi={s}", .{@tagName(target_abi)})); + } if (comp.sanitize_c and !comp.bin_file.options.tsan) { try argv.append("-fsanitize=undefined"); try argv.append("-fsanitize-trap=undefined"); @@ -3583,6 +3589,11 @@ pub fn addCCArgs( // TODO }, } + + if (comp.bin_file.options.target_abi) |target_abi| { + try argv.append(try std.fmt.allocPrint(arena, "-mabi={s}", .{@tagName(target_abi)})); + } + 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})); @@ -4036,8 +4047,8 @@ fn wantBuildLibUnwindFromSource(comp: *Compilation) bool { } fn updateBuiltinZigFile(comp: *Compilation, mod: *Module) Allocator.Error!void { - const t = trace(@src()); - defer t.end(); + const tracy_trace = trace(@src()); + defer tracy_trace.end(); const source = try comp.generateBuiltinZigSource(comp.gpa); defer comp.gpa.free(source); @@ -4074,8 +4085,8 @@ pub fn dump_argv(argv: []const []const u8) void { } pub fn generateBuiltinZigSource(comp: *Compilation, allocator: Allocator) Allocator.Error![]u8 { - const t = trace(@src()); - defer t.end(); + const tracy_trace = trace(@src()); + defer tracy_trace.end(); var buffer = std.ArrayList(u8).init(allocator); defer buffer.deinit(); @@ -4320,8 +4331,8 @@ fn buildOutputFromZig( out: *?CRTFile, misc_task_tag: MiscTask, ) !void { - const t = trace(@src()); - defer t.end(); + const tracy_trace = trace(@src()); + defer tracy_trace.end(); std.debug.assert(output_mode != .Exe); const special_sub = "std" ++ std.fs.path.sep_str ++ "special"; @@ -4378,6 +4389,7 @@ fn buildOutputFromZig( .strip = comp.compilerRtStrip(), .is_native_os = comp.bin_file.options.is_native_os, .is_native_abi = comp.bin_file.options.is_native_abi, + .target_abi = comp.bin_file.options.target_abi, .self_exe_path = comp.self_exe_path, .verbose_cc = comp.verbose_cc, .verbose_link = comp.bin_file.options.verbose_link, @@ -4419,8 +4431,8 @@ fn buildOutputFromZig( } fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node) !void { - const t = trace(@src()); - defer t.end(); + const tracy_trace = trace(@src()); + defer tracy_trace.end(); var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa); defer arena_allocator.deinit(); @@ -4566,6 +4578,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node .is_native_cpu = false, // Only true when bootstrapping the compiler. .llvm_cpu_name = if (target.cpu.model.llvm_name) |s| s.ptr else null, .llvm_cpu_features = comp.bin_file.options.llvm_cpu_features.?, + .llvm_target_abi = if (comp.bin_file.options.target_abi) |t| @tagName(t) else null, }; comp.stage1_cache_manifest = &man; @@ -4773,8 +4786,8 @@ pub fn build_crt_file( output_mode: std.builtin.OutputMode, c_source_files: []const Compilation.CSourceFile, ) !void { - const t = trace(@src()); - defer t.end(); + const tracy_trace = trace(@src()); + defer tracy_trace.end(); const target = comp.getTarget(); const basename = try std.zig.binNameAlloc(comp.gpa, .{ @@ -4817,6 +4830,7 @@ pub fn build_crt_file( .strip = comp.compilerRtStrip(), .is_native_os = comp.bin_file.options.is_native_os, .is_native_abi = comp.bin_file.options.is_native_abi, + .target_abi = comp.bin_file.options.target_abi, .self_exe_path = comp.self_exe_path, .c_source_files = c_source_files, .verbose_cc = comp.verbose_cc, diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 4600c2e07e69..886be120b0ca 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -244,18 +244,7 @@ pub const Object = struct { // TODO handle float ABI better- it should depend on the ABI portion of std.Target const float_abi: llvm.ABIType = .Default; - // TODO a way to override this as part of std.Target ABI? - const abi_name: ?[*:0]const u8 = switch (options.target.cpu.arch) { - .riscv32 => switch (options.target.os.tag) { - .linux => "ilp32d", - else => "ilp32", - }, - .riscv64 => switch (options.target.os.tag) { - .linux => "lp64d", - else => "lp64", - }, - else => null, - }; + const abi_name: ?[*:0]const u8 = if (options.target_abi) |t| @tagName(t) else null; const target_machine = llvm.TargetMachine.create( target, diff --git a/src/glibc.zig b/src/glibc.zig index e67c3360e9e3..8a49204cd172 100644 --- a/src/glibc.zig +++ b/src/glibc.zig @@ -961,6 +961,7 @@ fn buildSharedLib( .strip = comp.compilerRtStrip(), .is_native_os = false, .is_native_abi = false, + .target_abi = comp.bin_file.options.target_abi, .self_exe_path = comp.self_exe_path, .verbose_cc = comp.verbose_cc, .verbose_link = comp.bin_file.options.verbose_link, diff --git a/src/libcxx.zig b/src/libcxx.zig index fe96207c483a..312de1b55489 100644 --- a/src/libcxx.zig +++ b/src/libcxx.zig @@ -200,6 +200,7 @@ pub fn buildLibCXX(comp: *Compilation) !void { .strip = comp.compilerRtStrip(), .is_native_os = comp.bin_file.options.is_native_os, .is_native_abi = comp.bin_file.options.is_native_abi, + .target_abi = comp.bin_file.options.target_abi, .self_exe_path = comp.self_exe_path, .c_source_files = c_source_files.items, .verbose_cc = comp.verbose_cc, @@ -332,6 +333,7 @@ pub fn buildLibCXXABI(comp: *Compilation) !void { .strip = comp.compilerRtStrip(), .is_native_os = comp.bin_file.options.is_native_os, .is_native_abi = comp.bin_file.options.is_native_abi, + .target_abi = comp.bin_file.options.target_abi, .self_exe_path = comp.self_exe_path, .c_source_files = c_source_files.items, .verbose_cc = comp.verbose_cc, diff --git a/src/libtsan.zig b/src/libtsan.zig index 0f05957387ff..cb745ebc3554 100644 --- a/src/libtsan.zig +++ b/src/libtsan.zig @@ -218,6 +218,7 @@ pub fn buildTsan(comp: *Compilation) !void { .strip = comp.compilerRtStrip(), .is_native_os = comp.bin_file.options.is_native_os, .is_native_abi = comp.bin_file.options.is_native_abi, + .target_abi = comp.bin_file.options.target_abi, .self_exe_path = comp.self_exe_path, .c_source_files = c_source_files.items, .verbose_cc = comp.verbose_cc, diff --git a/src/libunwind.zig b/src/libunwind.zig index 95c58936fa6d..4c8626c36058 100644 --- a/src/libunwind.zig +++ b/src/libunwind.zig @@ -124,6 +124,7 @@ pub fn buildStaticLib(comp: *Compilation) !void { .strip = comp.compilerRtStrip(), .is_native_os = comp.bin_file.options.is_native_os, .is_native_abi = comp.bin_file.options.is_native_abi, + .target_abi = comp.bin_file.options.target_abi, .self_exe_path = comp.self_exe_path, .c_source_files = &c_source_files, .verbose_cc = comp.verbose_cc, diff --git a/src/link.zig b/src/link.zig index 79a1c634624c..c84130095189 100644 --- a/src/link.zig +++ b/src/link.zig @@ -134,6 +134,7 @@ pub const Options = struct { version_script: ?[]const u8, soname: ?[]const u8, llvm_cpu_features: ?[*:0]const u8, + target_abi: ?std.Target.TargetAbi, objects: []const []const u8, framework_dirs: []const []const u8, diff --git a/src/main.zig b/src/main.zig index 54adf80fa6ea..7b4bf0d3b19c 100644 --- a/src/main.zig +++ b/src/main.zig @@ -328,6 +328,7 @@ const usage_build_generic = \\Compile Options: \\ -target [name] -- see the targets command \\ -mcpu [cpu] Specify target CPU and feature set + \\ -mabi [target-abi] Specify processor specific target-abi \\ -mcmodel=[default|tiny| Limit range of code and data virtual addresses \\ small|kernel| \\ medium|large] @@ -653,6 +654,7 @@ fn buildOutputType( var sysroot: ?[]const u8 = null; var libc_paths_file: ?[]const u8 = try optionalStringEnvVar(arena, "ZIG_LIBC"); var machine_code_model: std.builtin.CodeModel = .default; + var target_abi_str: ?[]const u8 = null; var runtime_args_start: ?usize = null; var test_filter: ?[]const u8 = null; var test_name_prefix: ?[]const u8 = null; @@ -926,6 +928,12 @@ fn buildOutputType( target_mcpu = arg["-mcpu=".len..]; } else if (mem.startsWith(u8, arg, "-mcmodel=")) { machine_code_model = parseCodeModel(arg["-mcmodel=".len..]); + } else if (mem.eql(u8, arg, "-mabi")) { + if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); + i += 1; + target_abi_str = args[i]; + } else if (mem.startsWith(u8, arg, "-mabi=")) { + target_abi_str = arg["-mabi=".len..]; } else if (mem.startsWith(u8, arg, "-O")) { optimize_mode_string = arg["-O".len..]; } else if (mem.eql(u8, arg, "--dynamic-linker")) { @@ -1872,6 +1880,12 @@ fn buildOutputType( const cross_target = try parseCrossTargetOrReportFatalError(arena, target_parse_options); const target_info = try detectNativeTargetInfo(gpa, cross_target); + const target_abi = if (target_abi_str) |s| std.Target.TargetAbi.parse(target_info.target.cpu, s) catch |err| switch (err) { + error.InvalidAbi => fatal("invalid target-abi value '{s}'", .{target_abi_str}), + error.ArchAbiMismatch => fatal("target-abi {s} is not valid for arch {s}", .{ target_abi_str, target_info.target.cpu.arch }), + error.FeatureAbiMismatch => fatal("target-abi {s} is not compatible with CPU features", .{target_abi_str}), + } else std.Target.TargetAbi.default(target_info.target.cpu.arch, target_info.target.cpu.features); + if (target_info.target.os.tag != .freestanding) { if (ensure_libc_on_non_freestanding) link_libc = true; @@ -2459,6 +2473,7 @@ fn buildOutputType( .verbose_cimport = verbose_cimport, .verbose_llvm_cpu_features = verbose_llvm_cpu_features, .machine_code_model = machine_code_model, + .target_abi = target_abi, .color = color, .time_report = time_report, .stack_report = stack_report, @@ -3382,6 +3397,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi .target = target_info.target, .is_native_os = cross_target.isNativeOs(), .is_native_abi = cross_target.isNativeAbi(), + .target_abi = std.Target.TargetAbi.default(target_info.target.cpu.arch, target_info.target.cpu.features), .dynamic_linker = target_info.dynamic_linker.get(), .output_mode = .Exe, .main_pkg = &main_pkg, diff --git a/src/musl.zig b/src/musl.zig index cad6246c98c4..a2b707900b92 100644 --- a/src/musl.zig +++ b/src/musl.zig @@ -214,6 +214,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { .strip = comp.compilerRtStrip(), .is_native_os = false, .is_native_abi = false, + .target_abi = comp.bin_file.options.target_abi, .self_exe_path = comp.self_exe_path, .verbose_cc = comp.verbose_cc, .verbose_link = comp.bin_file.options.verbose_link, diff --git a/src/stage1.zig b/src/stage1.zig index 8e6090af0b97..8263427fbe6d 100644 --- a/src/stage1.zig +++ b/src/stage1.zig @@ -364,6 +364,7 @@ pub const Stage2Target = extern struct { llvm_cpu_name: ?[*:0]const u8, llvm_cpu_features: ?[*:0]const u8, + llvm_target_abi: ?[*:0]const u8, }; // ABI warning diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp index 8faebbe14846..cba820037e95 100644 --- a/src/stage1/codegen.cpp +++ b/src/stage1/codegen.cpp @@ -9487,9 +9487,8 @@ static void init(CodeGen *g) { // TODO handle float ABI better- it should depend on the ABI portion of std.Target ZigLLVMABIType float_abi = ZigLLVMABITypeDefault; - // TODO a way to override this as part of std.Target ABI? - const char *abi_name = nullptr; - if (target_is_riscv(g->zig_target)) { + const char *abi_name = g->zig_target->llvm_target_abi; + if (abi_name == nullptr && target_is_riscv(g->zig_target)) { // RISC-V Linux defaults to ilp32d/lp64d if (g->zig_target->os == OsLinux) { abi_name = (g->zig_target->arch == ZigLLVM_riscv32) ? "ilp32d" : "lp64d"; diff --git a/src/stage1/stage1.h b/src/stage1/stage1.h index ce8254eaefca..2b2e5a85b06a 100644 --- a/src/stage1/stage1.h +++ b/src/stage1/stage1.h @@ -112,6 +112,7 @@ struct ZigTarget { const char *llvm_cpu_name; const char *llvm_cpu_features; + const char *llvm_target_abi; }; // ABI warning diff --git a/src/test.zig b/src/test.zig index af0dbec24b93..c43815d3e0fc 100644 --- a/src/test.zig +++ b/src/test.zig @@ -907,6 +907,7 @@ pub const TestContext = struct { .object_format = case.object_format, .is_native_os = case.target.isNativeOs(), .is_native_abi = case.target.isNativeAbi(), + .target_abi = std.Target.TargetAbi.default(target.cpu.arch, target.cpu.features), .dynamic_linker = target_info.dynamic_linker.get(), .link_libc = link_libc, .use_llvm = use_llvm, From 9ede943e0753b250cb9a60a5b9b66ba9bff4a694 Mon Sep 17 00:00:00 2001 From: vole-dev Date: Sun, 31 Oct 2021 11:38:17 -0500 Subject: [PATCH 2/3] turn off LTO by default for RISCV even in Release mode --- src/Compilation.zig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Compilation.zig b/src/Compilation.zig index e58e9049b5ce..c9512dd26b92 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -993,6 +993,12 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { } else if (options.target.os.tag == .windows and link_libcpp) { // https://github.com/ziglang/zig/issues/8531 break :blk false; + } else if (options.target.cpu.arch.isRISCV()) { + // Clang and LLVM currently don't support RISC-V target-abi for LTO. + // Compiling with LTO may fail or produce undesired results. + // See https://reviews.llvm.org/D71387 + // See https://reviews.llvm.org/D102582 + break :blk false; } else switch (options.output_mode) { .Lib, .Obj => break :blk false, .Exe => switch (options.optimize_mode) { From 4c1a62326b5090fad67c004a6e58a6e4265a77ad Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 3 Dec 2021 17:33:20 -0700 Subject: [PATCH 3/3] stage2: use Target.Abi instead of introducing Target.TargetAbi This branch introduced std.Target.TargetAbi when we already had std.Target.Abi which was, unsurprisingly, already suited for this task. Also pull out the -mabi= cc flag addition to the common area instead of duplicating it for assembly and c files. --- lib/std/build.zig | 4 --- lib/std/target.zig | 78 -------------------------------------------- src/Compilation.zig | 20 ++++-------- src/codegen/llvm.zig | 5 ++- src/glibc.zig | 1 - src/libcxx.zig | 2 -- src/libtsan.zig | 1 - src/libunwind.zig | 1 - src/link.zig | 1 - src/main.zig | 16 --------- src/musl.zig | 1 - src/target.zig | 35 ++++++++++++++++++++ src/test.zig | 1 - 13 files changed, 43 insertions(+), 123 deletions(-) diff --git a/lib/std/build.zig b/lib/std/build.zig index cd551924a9e7..30296081b757 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -1474,7 +1474,6 @@ pub const LibExeObjStep = struct { name_prefix: []const u8, filter: ?[]const u8, test_evented_io: bool = false, - target_abi: ?std.Target.TargetAbi = null, code_model: std.builtin.CodeModel = .default, wasi_exec_model: ?std.builtin.WasiExecModel = null, @@ -2459,9 +2458,6 @@ pub const LibExeObjStep = struct { try zig_args.append(builder.fmt("--global-base={d}", .{global_base})); } - if (self.target_abi) |target_abi| { - try zig_args.append(builder.fmt("-mabi={s}", .{@tagName(target_abi)})); - } if (self.code_model != .default) { try zig_args.append("-mcmodel"); try zig_args.append(@tagName(self.code_model)); diff --git a/lib/std/target.zig b/lib/std/target.zig index 43cd80bb3b24..c6ee53157d5e 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -560,84 +560,6 @@ pub const Target = struct { } }; - /// processor specific ABI - pub const TargetAbi = enum { - //TODO add ARM, Mips, and PowerPC - ilp32, - ilp32d, - ilp32e, - ilp32f, - lp64, - lp64d, - lp64f, - - const Riscv32ABI = struct { - fn default(features: Cpu.Feature.Set) TargetAbi { - if (riscv.featureSetHas(features, .d)) { - return .ilp32d; - } else if (riscv.featureSetHas(features, .e)) { - return .ilp32e; - } else { - return .ilp32; - } - } - fn validate(target_abi: TargetAbi, features: Cpu.Feature.Set) ParseError!void { - const has_e = riscv.featureSetHas(features, .e); - const has_f = riscv.featureSetHas(features, .f); - const has_d = riscv.featureSetHas(features, .d); - return switch (target_abi) { - .ilp32e => if (has_e) {} else error.FeatureAbiMismatch, - .ilp32 => if (!has_e) {} else error.FeatureAbiMismatch, - .ilp32f => if (!has_e and has_f) {} else error.FeatureAbiMismatch, - .ilp32d => if (!has_e and has_d) {} else error.FeatureAbiMismatch, - else => error.ArchAbiMismatch, - }; - } - }; - const Riscv64ABI = struct { - fn default(features: Cpu.Feature.Set) TargetAbi { - if (riscv.featureSetHas(features, .d)) { - return .lp64d; - } else { - return .lp64; - } - } - fn validate(target_abi: TargetAbi, features: Cpu.Feature.Set) ParseError!void { - const has_f = riscv.featureSetHas(features, .f); - const has_d = riscv.featureSetHas(features, .d); - return switch (target_abi) { - .lp64 => {}, - .lp64f => if (has_f) {} else error.FeatureAbiMismatch, - .lp64d => if (has_d) {} else error.FeatureAbiMismatch, - else => error.ArchAbiMismatch, - }; - } - }; - pub fn default(arch: Cpu.Arch, features: Cpu.Feature.Set) ?TargetAbi { - return switch (arch) { - .riscv32 => Riscv32ABI.default(features), - .riscv64 => Riscv64ABI.default(features), - else => null, - }; - } - - pub const ParseError = error{ - InvalidAbi, - ArchAbiMismatch, - FeatureAbiMismatch, - }; - pub fn parse(cpu: Cpu, abi_string: []const u8) ParseError!TargetAbi { - const target_abi = std.meta.stringToEnum(TargetAbi, abi_string) orelse return error.InvalidAbi; - - switch (cpu.arch) { - .riscv32 => try Riscv32ABI.validate(target_abi, cpu.features), - .riscv64 => try Riscv64ABI.validate(target_abi, cpu.features), - else => return error.ArchAbiMismatch, - } - return target_abi; - } - }; - pub const ObjectFormat = enum { /// Common Object File Format (Windows) coff, diff --git a/src/Compilation.zig b/src/Compilation.zig index c9512dd26b92..b07761e7cb48 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -767,7 +767,6 @@ pub const InitOptions = struct { compatibility_version: ?std.builtin.Version = null, libc_installation: ?*const LibCInstallation = null, machine_code_model: std.builtin.CodeModel = .default, - target_abi: ?std.Target.TargetAbi, clang_preprocessor_mode: ClangPreprocessorMode = .no, /// This is for stage1 and should be deleted upon completion of self-hosting. color: @import("main.zig").Color = .auto, @@ -1183,7 +1182,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { cache.hash.add(options.target.os.getVersionRange()); cache.hash.add(options.is_native_os); cache.hash.add(options.target.abi); - cache.hash.addOptionalBytes(if (options.target_abi) |t| @tagName(t) else null); cache.hash.add(ofmt); cache.hash.add(pic); cache.hash.add(pie); @@ -1496,7 +1494,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .single_threaded = single_threaded, .verbose_link = options.verbose_link, .machine_code_model = options.machine_code_model, - .target_abi = options.target_abi, .dll_export_fns = dll_export_fns, .error_return_tracing = error_return_tracing, .llvm_cpu_features = llvm_cpu_features, @@ -3460,9 +3457,6 @@ pub fn addCCArgs( try argv.append("-mthumb"); } - if (comp.bin_file.options.target_abi) |target_abi| { - try argv.append(try std.fmt.allocPrint(arena, "-mabi={s}", .{@tagName(target_abi)})); - } if (comp.sanitize_c and !comp.bin_file.options.tsan) { try argv.append("-fsanitize=undefined"); try argv.append("-fsanitize-trap=undefined"); @@ -3595,11 +3589,6 @@ pub fn addCCArgs( // TODO }, } - - if (comp.bin_file.options.target_abi) |target_abi| { - try argv.append(try std.fmt.allocPrint(arena, "-mabi={s}", .{@tagName(target_abi)})); - } - 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})); @@ -3607,6 +3596,11 @@ pub fn addCCArgs( } }, } + + if (target_util.llvmMachineAbi(target)) |mabi| { + try argv.append(try std.fmt.allocPrint(arena, "-mabi={s}", .{mabi})); + } + if (out_dep_path) |p| { try argv.appendSlice(&[_][]const u8{ "-MD", "-MV", "-MF", p }); } @@ -4395,7 +4389,6 @@ fn buildOutputFromZig( .strip = comp.compilerRtStrip(), .is_native_os = comp.bin_file.options.is_native_os, .is_native_abi = comp.bin_file.options.is_native_abi, - .target_abi = comp.bin_file.options.target_abi, .self_exe_path = comp.self_exe_path, .verbose_cc = comp.verbose_cc, .verbose_link = comp.bin_file.options.verbose_link, @@ -4584,7 +4577,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node .is_native_cpu = false, // Only true when bootstrapping the compiler. .llvm_cpu_name = if (target.cpu.model.llvm_name) |s| s.ptr else null, .llvm_cpu_features = comp.bin_file.options.llvm_cpu_features.?, - .llvm_target_abi = if (comp.bin_file.options.target_abi) |t| @tagName(t) else null, + .llvm_target_abi = if (target_util.llvmMachineAbi(target)) |s| s.ptr else null, }; comp.stage1_cache_manifest = &man; @@ -4836,7 +4829,6 @@ pub fn build_crt_file( .strip = comp.compilerRtStrip(), .is_native_os = comp.bin_file.options.is_native_os, .is_native_abi = comp.bin_file.options.is_native_abi, - .target_abi = comp.bin_file.options.target_abi, .self_exe_path = comp.self_exe_path, .c_source_files = c_source_files, .verbose_cc = comp.verbose_cc, diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 886be120b0ca..58239fdaea47 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -15,6 +15,7 @@ const TypedValue = @import("../TypedValue.zig"); const Zir = @import("../Zir.zig"); const Air = @import("../Air.zig"); const Liveness = @import("../Liveness.zig"); +const target_util = @import("../target.zig"); const Value = @import("../value.zig").Value; const Type = @import("../type.zig").Type; @@ -244,8 +245,6 @@ pub const Object = struct { // TODO handle float ABI better- it should depend on the ABI portion of std.Target const float_abi: llvm.ABIType = .Default; - const abi_name: ?[*:0]const u8 = if (options.target_abi) |t| @tagName(t) else null; - const target_machine = llvm.TargetMachine.create( target, llvm_target_triple.ptr, @@ -256,7 +255,7 @@ pub const Object = struct { code_model, options.function_sections, float_abi, - abi_name, + if (target_util.llvmMachineAbi(options.target)) |s| s.ptr else null, ); errdefer target_machine.dispose(); diff --git a/src/glibc.zig b/src/glibc.zig index 8a49204cd172..e67c3360e9e3 100644 --- a/src/glibc.zig +++ b/src/glibc.zig @@ -961,7 +961,6 @@ fn buildSharedLib( .strip = comp.compilerRtStrip(), .is_native_os = false, .is_native_abi = false, - .target_abi = comp.bin_file.options.target_abi, .self_exe_path = comp.self_exe_path, .verbose_cc = comp.verbose_cc, .verbose_link = comp.bin_file.options.verbose_link, diff --git a/src/libcxx.zig b/src/libcxx.zig index 312de1b55489..fe96207c483a 100644 --- a/src/libcxx.zig +++ b/src/libcxx.zig @@ -200,7 +200,6 @@ pub fn buildLibCXX(comp: *Compilation) !void { .strip = comp.compilerRtStrip(), .is_native_os = comp.bin_file.options.is_native_os, .is_native_abi = comp.bin_file.options.is_native_abi, - .target_abi = comp.bin_file.options.target_abi, .self_exe_path = comp.self_exe_path, .c_source_files = c_source_files.items, .verbose_cc = comp.verbose_cc, @@ -333,7 +332,6 @@ pub fn buildLibCXXABI(comp: *Compilation) !void { .strip = comp.compilerRtStrip(), .is_native_os = comp.bin_file.options.is_native_os, .is_native_abi = comp.bin_file.options.is_native_abi, - .target_abi = comp.bin_file.options.target_abi, .self_exe_path = comp.self_exe_path, .c_source_files = c_source_files.items, .verbose_cc = comp.verbose_cc, diff --git a/src/libtsan.zig b/src/libtsan.zig index cb745ebc3554..0f05957387ff 100644 --- a/src/libtsan.zig +++ b/src/libtsan.zig @@ -218,7 +218,6 @@ pub fn buildTsan(comp: *Compilation) !void { .strip = comp.compilerRtStrip(), .is_native_os = comp.bin_file.options.is_native_os, .is_native_abi = comp.bin_file.options.is_native_abi, - .target_abi = comp.bin_file.options.target_abi, .self_exe_path = comp.self_exe_path, .c_source_files = c_source_files.items, .verbose_cc = comp.verbose_cc, diff --git a/src/libunwind.zig b/src/libunwind.zig index 4c8626c36058..95c58936fa6d 100644 --- a/src/libunwind.zig +++ b/src/libunwind.zig @@ -124,7 +124,6 @@ pub fn buildStaticLib(comp: *Compilation) !void { .strip = comp.compilerRtStrip(), .is_native_os = comp.bin_file.options.is_native_os, .is_native_abi = comp.bin_file.options.is_native_abi, - .target_abi = comp.bin_file.options.target_abi, .self_exe_path = comp.self_exe_path, .c_source_files = &c_source_files, .verbose_cc = comp.verbose_cc, diff --git a/src/link.zig b/src/link.zig index c84130095189..79a1c634624c 100644 --- a/src/link.zig +++ b/src/link.zig @@ -134,7 +134,6 @@ pub const Options = struct { version_script: ?[]const u8, soname: ?[]const u8, llvm_cpu_features: ?[*:0]const u8, - target_abi: ?std.Target.TargetAbi, objects: []const []const u8, framework_dirs: []const []const u8, diff --git a/src/main.zig b/src/main.zig index 7b4bf0d3b19c..54adf80fa6ea 100644 --- a/src/main.zig +++ b/src/main.zig @@ -328,7 +328,6 @@ const usage_build_generic = \\Compile Options: \\ -target [name] -- see the targets command \\ -mcpu [cpu] Specify target CPU and feature set - \\ -mabi [target-abi] Specify processor specific target-abi \\ -mcmodel=[default|tiny| Limit range of code and data virtual addresses \\ small|kernel| \\ medium|large] @@ -654,7 +653,6 @@ fn buildOutputType( var sysroot: ?[]const u8 = null; var libc_paths_file: ?[]const u8 = try optionalStringEnvVar(arena, "ZIG_LIBC"); var machine_code_model: std.builtin.CodeModel = .default; - var target_abi_str: ?[]const u8 = null; var runtime_args_start: ?usize = null; var test_filter: ?[]const u8 = null; var test_name_prefix: ?[]const u8 = null; @@ -928,12 +926,6 @@ fn buildOutputType( target_mcpu = arg["-mcpu=".len..]; } else if (mem.startsWith(u8, arg, "-mcmodel=")) { machine_code_model = parseCodeModel(arg["-mcmodel=".len..]); - } else if (mem.eql(u8, arg, "-mabi")) { - if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg}); - i += 1; - target_abi_str = args[i]; - } else if (mem.startsWith(u8, arg, "-mabi=")) { - target_abi_str = arg["-mabi=".len..]; } else if (mem.startsWith(u8, arg, "-O")) { optimize_mode_string = arg["-O".len..]; } else if (mem.eql(u8, arg, "--dynamic-linker")) { @@ -1880,12 +1872,6 @@ fn buildOutputType( const cross_target = try parseCrossTargetOrReportFatalError(arena, target_parse_options); const target_info = try detectNativeTargetInfo(gpa, cross_target); - const target_abi = if (target_abi_str) |s| std.Target.TargetAbi.parse(target_info.target.cpu, s) catch |err| switch (err) { - error.InvalidAbi => fatal("invalid target-abi value '{s}'", .{target_abi_str}), - error.ArchAbiMismatch => fatal("target-abi {s} is not valid for arch {s}", .{ target_abi_str, target_info.target.cpu.arch }), - error.FeatureAbiMismatch => fatal("target-abi {s} is not compatible with CPU features", .{target_abi_str}), - } else std.Target.TargetAbi.default(target_info.target.cpu.arch, target_info.target.cpu.features); - if (target_info.target.os.tag != .freestanding) { if (ensure_libc_on_non_freestanding) link_libc = true; @@ -2473,7 +2459,6 @@ fn buildOutputType( .verbose_cimport = verbose_cimport, .verbose_llvm_cpu_features = verbose_llvm_cpu_features, .machine_code_model = machine_code_model, - .target_abi = target_abi, .color = color, .time_report = time_report, .stack_report = stack_report, @@ -3397,7 +3382,6 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi .target = target_info.target, .is_native_os = cross_target.isNativeOs(), .is_native_abi = cross_target.isNativeAbi(), - .target_abi = std.Target.TargetAbi.default(target_info.target.cpu.arch, target_info.target.cpu.features), .dynamic_linker = target_info.dynamic_linker.get(), .output_mode = .Exe, .main_pkg = &main_pkg, diff --git a/src/musl.zig b/src/musl.zig index a2b707900b92..cad6246c98c4 100644 --- a/src/musl.zig +++ b/src/musl.zig @@ -214,7 +214,6 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { .strip = comp.compilerRtStrip(), .is_native_os = false, .is_native_abi = false, - .target_abi = comp.bin_file.options.target_abi, .self_exe_path = comp.self_exe_path, .verbose_cc = comp.verbose_cc, .verbose_link = comp.bin_file.options.verbose_link, diff --git a/src/target.zig b/src/target.zig index 9d22feff6660..5b2f6f5978d6 100644 --- a/src/target.zig +++ b/src/target.zig @@ -599,3 +599,38 @@ pub fn defaultAddressSpace( _ = context; return .generic; } + +pub fn llvmMachineAbi(target: std.Target) ?[:0]const u8 { + const have_float = switch (target.abi) { + .gnuilp32 => return "ilp32", + .gnueabihf, .musleabihf, .eabihf => true, + else => false, + }; + + switch (target.cpu.arch) { + .riscv64 => { + const featureSetHas = std.Target.riscv.featureSetHas; + if (featureSetHas(target.cpu.features, .d)) { + return "lp64d"; + } else if (have_float) { + return "lp64f"; + } else { + return "lp64"; + } + }, + .riscv32 => { + const featureSetHas = std.Target.riscv.featureSetHas; + if (featureSetHas(target.cpu.features, .d)) { + return "ilp32d"; + } else if (have_float) { + return "ilp32f"; + } else if (featureSetHas(target.cpu.features, .e)) { + return "ilp32e"; + } else { + return "ilp32"; + } + }, + //TODO add ARM, Mips, and PowerPC + else => return null, + } +} diff --git a/src/test.zig b/src/test.zig index c43815d3e0fc..af0dbec24b93 100644 --- a/src/test.zig +++ b/src/test.zig @@ -907,7 +907,6 @@ pub const TestContext = struct { .object_format = case.object_format, .is_native_os = case.target.isNativeOs(), .is_native_abi = case.target.isNativeAbi(), - .target_abi = std.Target.TargetAbi.default(target.cpu.arch, target.cpu.features), .dynamic_linker = target_info.dynamic_linker.get(), .link_libc = link_libc, .use_llvm = use_llvm,