authorgravatar for dev@vole.devvole-dev <dev@vole.dev> 2021-10-30 10:30:28-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-12-03 16:53:33-07:00
logff38f560402aa61ce8e4ae38b4fa0ff2ddbaede6
treecc248ce8fc3c3d76d968cb348fc8d130a7e40366
parent84704ef43e5414860aa9d3dc0f94f9737404f6e5

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

15 files changed, 141 insertions(+), 31 deletions(-)

lib/std/build.zig+4
......@@ -1474,6 +1474,7 @@ pub const LibExeObjStep = struct {
14741474 name_prefix: []const u8,
14751475 filter: ?[]const u8,
14761476 test_evented_io: bool = false,
1477 target_abi: ?std.Target.TargetAbi = null,
14771478 code_model: std.builtin.CodeModel = .default,
14781479 wasi_exec_model: ?std.builtin.WasiExecModel = null,
14791480
......@@ -2458,6 +2459,9 @@ pub const LibExeObjStep = struct {
24582459 try zig_args.append(builder.fmt("--global-base={d}", .{global_base}));
24592460 }
24602461
2462 if (self.target_abi) |target_abi| {
2463 try zig_args.append(builder.fmt("-mabi={s}", .{@tagName(target_abi)}));
2464 }
24612465 if (self.code_model != .default) {
24622466 try zig_args.append("-mcmodel");
24632467 try zig_args.append(@tagName(self.code_model));
lib/std/target.zig+78
......@@ -560,6 +560,84 @@ pub const Target = struct {
560560 }
561561 };
562562
563 /// processor specific ABI
564 pub const TargetAbi = enum {
565 //TODO add ARM, Mips, and PowerPC
566 ilp32,
567 ilp32d,
568 ilp32e,
569 ilp32f,
570 lp64,
571 lp64d,
572 lp64f,
573
574 const Riscv32ABI = struct {
575 fn default(features: Cpu.Feature.Set) TargetAbi {
576 if (riscv.featureSetHas(features, .d)) {
577 return .ilp32d;
578 } else if (riscv.featureSetHas(features, .e)) {
579 return .ilp32e;
580 } else {
581 return .ilp32;
582 }
583 }
584 fn validate(target_abi: TargetAbi, features: Cpu.Feature.Set) ParseError!void {
585 const has_e = riscv.featureSetHas(features, .e);
586 const has_f = riscv.featureSetHas(features, .f);
587 const has_d = riscv.featureSetHas(features, .d);
588 return switch (target_abi) {
589 .ilp32e => if (has_e) {} else error.FeatureAbiMismatch,
590 .ilp32 => if (!has_e) {} else error.FeatureAbiMismatch,
591 .ilp32f => if (!has_e and has_f) {} else error.FeatureAbiMismatch,
592 .ilp32d => if (!has_e and has_d) {} else error.FeatureAbiMismatch,
593 else => error.ArchAbiMismatch,
594 };
595 }
596 };
597 const Riscv64ABI = struct {
598 fn default(features: Cpu.Feature.Set) TargetAbi {
599 if (riscv.featureSetHas(features, .d)) {
600 return .lp64d;
601 } else {
602 return .lp64;
603 }
604 }
605 fn validate(target_abi: TargetAbi, features: Cpu.Feature.Set) ParseError!void {
606 const has_f = riscv.featureSetHas(features, .f);
607 const has_d = riscv.featureSetHas(features, .d);
608 return switch (target_abi) {
609 .lp64 => {},
610 .lp64f => if (has_f) {} else error.FeatureAbiMismatch,
611 .lp64d => if (has_d) {} else error.FeatureAbiMismatch,
612 else => error.ArchAbiMismatch,
613 };
614 }
615 };
616 pub fn default(arch: Cpu.Arch, features: Cpu.Feature.Set) ?TargetAbi {
617 return switch (arch) {
618 .riscv32 => Riscv32ABI.default(features),
619 .riscv64 => Riscv64ABI.default(features),
620 else => null,
621 };
622 }
623
624 pub const ParseError = error{
625 InvalidAbi,
626 ArchAbiMismatch,
627 FeatureAbiMismatch,
628 };
629 pub fn parse(cpu: Cpu, abi_string: []const u8) ParseError!TargetAbi {
630 const target_abi = std.meta.stringToEnum(TargetAbi, abi_string) orelse return error.InvalidAbi;
631
632 switch (cpu.arch) {
633 .riscv32 => try Riscv32ABI.validate(target_abi, cpu.features),
634 .riscv64 => try Riscv64ABI.validate(target_abi, cpu.features),
635 else => return error.ArchAbiMismatch,
636 }
637 return target_abi;
638 }
639 };
640
563641 pub const ObjectFormat = enum {
564642 /// Common Object File Format (Windows)
565643 coff,
src/Compilation.zig+30-16
......@@ -767,6 +767,7 @@ pub const InitOptions = struct {
767767 compatibility_version: ?std.builtin.Version = null,
768768 libc_installation: ?*const LibCInstallation = null,
769769 machine_code_model: std.builtin.CodeModel = .default,
770 target_abi: ?std.Target.TargetAbi,
770771 clang_preprocessor_mode: ClangPreprocessorMode = .no,
771772 /// This is for stage1 and should be deleted upon completion of self-hosting.
772773 color: @import("main.zig").Color = .auto,
......@@ -1176,6 +1177,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
11761177 cache.hash.add(options.target.os.getVersionRange());
11771178 cache.hash.add(options.is_native_os);
11781179 cache.hash.add(options.target.abi);
1180 cache.hash.addOptionalBytes(if (options.target_abi) |t| @tagName(t) else null);
11791181 cache.hash.add(ofmt);
11801182 cache.hash.add(pic);
11811183 cache.hash.add(pie);
......@@ -1488,6 +1490,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
14881490 .single_threaded = single_threaded,
14891491 .verbose_link = options.verbose_link,
14901492 .machine_code_model = options.machine_code_model,
1493 .target_abi = options.target_abi,
14911494 .dll_export_fns = dll_export_fns,
14921495 .error_return_tracing = error_return_tracing,
14931496 .llvm_cpu_features = llvm_cpu_features,
......@@ -1780,8 +1783,8 @@ pub fn getTarget(self: Compilation) Target {
17801783
17811784/// Detect changes to source files, perform semantic analysis, and update the output files.
17821785pub fn update(self: *Compilation) !void {
1783 const t = trace(@src());
1784 defer t.end();
1786 const tracy_trace = trace(@src());
1787 defer tracy_trace.end();
17851788
17861789 self.clearMiscFailures();
17871790
......@@ -2822,8 +2825,8 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {
28222825 if (!build_options.have_llvm)
28232826 return error.ZigCompilerNotBuiltWithLLVMExtensions;
28242827
2825 const t = trace(@src());
2826 defer t.end();
2828 const tracy_trace = trace(@src());
2829 defer tracy_trace.end();
28272830
28282831 const cimport_zig_basename = "cimport.zig";
28292832
......@@ -3077,8 +3080,8 @@ fn updateCObject(comp: *Compilation, c_object: *CObject, c_obj_prog_node: *std.P
30773080 const self_exe_path = comp.self_exe_path orelse
30783081 return comp.failCObj(c_object, "clang compilation disabled", .{});
30793082
3080 const t = trace(@src());
3081 defer t.end();
3083 const tracy_trace = trace(@src());
3084 defer tracy_trace.end();
30823085
30833086 log.debug("updating C object: {s}", .{c_object.src.src_path});
30843087
......@@ -3451,6 +3454,9 @@ pub fn addCCArgs(
34513454 try argv.append("-mthumb");
34523455 }
34533456
3457 if (comp.bin_file.options.target_abi) |target_abi| {
3458 try argv.append(try std.fmt.allocPrint(arena, "-mabi={s}", .{@tagName(target_abi)}));
3459 }
34543460 if (comp.sanitize_c and !comp.bin_file.options.tsan) {
34553461 try argv.append("-fsanitize=undefined");
34563462 try argv.append("-fsanitize-trap=undefined");
......@@ -3583,6 +3589,11 @@ pub fn addCCArgs(
35833589 // TODO
35843590 },
35853591 }
3592
3593 if (comp.bin_file.options.target_abi) |target_abi| {
3594 try argv.append(try std.fmt.allocPrint(arena, "-mabi={s}", .{@tagName(target_abi)}));
3595 }
3596
35863597 if (target_util.clangAssemblerSupportsMcpuArg(target)) {
35873598 if (target.cpu.model.llvm_name) |llvm_name| {
35883599 try argv.append(try std.fmt.allocPrint(arena, "-mcpu={s}", .{llvm_name}));
......@@ -4036,8 +4047,8 @@ fn wantBuildLibUnwindFromSource(comp: *Compilation) bool {
40364047}
40374048
40384049fn updateBuiltinZigFile(comp: *Compilation, mod: *Module) Allocator.Error!void {
4039 const t = trace(@src());
4040 defer t.end();
4050 const tracy_trace = trace(@src());
4051 defer tracy_trace.end();
40414052
40424053 const source = try comp.generateBuiltinZigSource(comp.gpa);
40434054 defer comp.gpa.free(source);
......@@ -4074,8 +4085,8 @@ pub fn dump_argv(argv: []const []const u8) void {
40744085}
40754086
40764087pub fn generateBuiltinZigSource(comp: *Compilation, allocator: Allocator) Allocator.Error![]u8 {
4077 const t = trace(@src());
4078 defer t.end();
4088 const tracy_trace = trace(@src());
4089 defer tracy_trace.end();
40794090
40804091 var buffer = std.ArrayList(u8).init(allocator);
40814092 defer buffer.deinit();
......@@ -4320,8 +4331,8 @@ fn buildOutputFromZig(
43204331 out: *?CRTFile,
43214332 misc_task_tag: MiscTask,
43224333) !void {
4323 const t = trace(@src());
4324 defer t.end();
4334 const tracy_trace = trace(@src());
4335 defer tracy_trace.end();
43254336
43264337 std.debug.assert(output_mode != .Exe);
43274338 const special_sub = "std" ++ std.fs.path.sep_str ++ "special";
......@@ -4378,6 +4389,7 @@ fn buildOutputFromZig(
43784389 .strip = comp.compilerRtStrip(),
43794390 .is_native_os = comp.bin_file.options.is_native_os,
43804391 .is_native_abi = comp.bin_file.options.is_native_abi,
4392 .target_abi = comp.bin_file.options.target_abi,
43814393 .self_exe_path = comp.self_exe_path,
43824394 .verbose_cc = comp.verbose_cc,
43834395 .verbose_link = comp.bin_file.options.verbose_link,
......@@ -4419,8 +4431,8 @@ fn buildOutputFromZig(
44194431}
44204432
44214433fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node) !void {
4422 const t = trace(@src());
4423 defer t.end();
4434 const tracy_trace = trace(@src());
4435 defer tracy_trace.end();
44244436
44254437 var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
44264438 defer arena_allocator.deinit();
......@@ -4566,6 +4578,7 @@ fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node
45664578 .is_native_cpu = false, // Only true when bootstrapping the compiler.
45674579 .llvm_cpu_name = if (target.cpu.model.llvm_name) |s| s.ptr else null,
45684580 .llvm_cpu_features = comp.bin_file.options.llvm_cpu_features.?,
4581 .llvm_target_abi = if (comp.bin_file.options.target_abi) |t| @tagName(t) else null,
45694582 };
45704583
45714584 comp.stage1_cache_manifest = &man;
......@@ -4773,8 +4786,8 @@ pub fn build_crt_file(
47734786 output_mode: std.builtin.OutputMode,
47744787 c_source_files: []const Compilation.CSourceFile,
47754788) !void {
4776 const t = trace(@src());
4777 defer t.end();
4789 const tracy_trace = trace(@src());
4790 defer tracy_trace.end();
47784791
47794792 const target = comp.getTarget();
47804793 const basename = try std.zig.binNameAlloc(comp.gpa, .{
......@@ -4817,6 +4830,7 @@ pub fn build_crt_file(
48174830 .strip = comp.compilerRtStrip(),
48184831 .is_native_os = comp.bin_file.options.is_native_os,
48194832 .is_native_abi = comp.bin_file.options.is_native_abi,
4833 .target_abi = comp.bin_file.options.target_abi,
48204834 .self_exe_path = comp.self_exe_path,
48214835 .c_source_files = c_source_files,
48224836 .verbose_cc = comp.verbose_cc,
src/codegen/llvm.zig+1-12
......@@ -244,18 +244,7 @@ pub const Object = struct {
244244 // TODO handle float ABI better- it should depend on the ABI portion of std.Target
245245 const float_abi: llvm.ABIType = .Default;
246246
247 // TODO a way to override this as part of std.Target ABI?
248 const abi_name: ?[*:0]const u8 = switch (options.target.cpu.arch) {
249 .riscv32 => switch (options.target.os.tag) {
250 .linux => "ilp32d",
251 else => "ilp32",
252 },
253 .riscv64 => switch (options.target.os.tag) {
254 .linux => "lp64d",
255 else => "lp64",
256 },
257 else => null,
258 };
247 const abi_name: ?[*:0]const u8 = if (options.target_abi) |t| @tagName(t) else null;
259248
260249 const target_machine = llvm.TargetMachine.create(
261250 target,
src/glibc.zig+1
......@@ -961,6 +961,7 @@ fn buildSharedLib(
961961 .strip = comp.compilerRtStrip(),
962962 .is_native_os = false,
963963 .is_native_abi = false,
964 .target_abi = comp.bin_file.options.target_abi,
964965 .self_exe_path = comp.self_exe_path,
965966 .verbose_cc = comp.verbose_cc,
966967 .verbose_link = comp.bin_file.options.verbose_link,
src/libcxx.zig+2
......@@ -200,6 +200,7 @@ pub fn buildLibCXX(comp: *Compilation) !void {
200200 .strip = comp.compilerRtStrip(),
201201 .is_native_os = comp.bin_file.options.is_native_os,
202202 .is_native_abi = comp.bin_file.options.is_native_abi,
203 .target_abi = comp.bin_file.options.target_abi,
203204 .self_exe_path = comp.self_exe_path,
204205 .c_source_files = c_source_files.items,
205206 .verbose_cc = comp.verbose_cc,
......@@ -332,6 +333,7 @@ pub fn buildLibCXXABI(comp: *Compilation) !void {
332333 .strip = comp.compilerRtStrip(),
333334 .is_native_os = comp.bin_file.options.is_native_os,
334335 .is_native_abi = comp.bin_file.options.is_native_abi,
336 .target_abi = comp.bin_file.options.target_abi,
335337 .self_exe_path = comp.self_exe_path,
336338 .c_source_files = c_source_files.items,
337339 .verbose_cc = comp.verbose_cc,
src/libtsan.zig+1
......@@ -218,6 +218,7 @@ pub fn buildTsan(comp: *Compilation) !void {
218218 .strip = comp.compilerRtStrip(),
219219 .is_native_os = comp.bin_file.options.is_native_os,
220220 .is_native_abi = comp.bin_file.options.is_native_abi,
221 .target_abi = comp.bin_file.options.target_abi,
221222 .self_exe_path = comp.self_exe_path,
222223 .c_source_files = c_source_files.items,
223224 .verbose_cc = comp.verbose_cc,
src/libunwind.zig+1
......@@ -124,6 +124,7 @@ pub fn buildStaticLib(comp: *Compilation) !void {
124124 .strip = comp.compilerRtStrip(),
125125 .is_native_os = comp.bin_file.options.is_native_os,
126126 .is_native_abi = comp.bin_file.options.is_native_abi,
127 .target_abi = comp.bin_file.options.target_abi,
127128 .self_exe_path = comp.self_exe_path,
128129 .c_source_files = &c_source_files,
129130 .verbose_cc = comp.verbose_cc,
src/link.zig+1
......@@ -134,6 +134,7 @@ pub const Options = struct {
134134 version_script: ?[]const u8,
135135 soname: ?[]const u8,
136136 llvm_cpu_features: ?[*:0]const u8,
137 target_abi: ?std.Target.TargetAbi,
137138
138139 objects: []const []const u8,
139140 framework_dirs: []const []const u8,
src/main.zig+16
......@@ -328,6 +328,7 @@ const usage_build_generic =
328328 \\Compile Options:
329329 \\ -target [name] <arch><sub>-<os>-<abi> see the targets command
330330 \\ -mcpu [cpu] Specify target CPU and feature set
331 \\ -mabi [target-abi] Specify processor specific target-abi
331332 \\ -mcmodel=[default|tiny| Limit range of code and data virtual addresses
332333 \\ small|kernel|
333334 \\ medium|large]
......@@ -653,6 +654,7 @@ fn buildOutputType(
653654 var sysroot: ?[]const u8 = null;
654655 var libc_paths_file: ?[]const u8 = try optionalStringEnvVar(arena, "ZIG_LIBC");
655656 var machine_code_model: std.builtin.CodeModel = .default;
657 var target_abi_str: ?[]const u8 = null;
656658 var runtime_args_start: ?usize = null;
657659 var test_filter: ?[]const u8 = null;
658660 var test_name_prefix: ?[]const u8 = null;
......@@ -926,6 +928,12 @@ fn buildOutputType(
926928 target_mcpu = arg["-mcpu=".len..];
927929 } else if (mem.startsWith(u8, arg, "-mcmodel=")) {
928930 machine_code_model = parseCodeModel(arg["-mcmodel=".len..]);
931 } else if (mem.eql(u8, arg, "-mabi")) {
932 if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
933 i += 1;
934 target_abi_str = args[i];
935 } else if (mem.startsWith(u8, arg, "-mabi=")) {
936 target_abi_str = arg["-mabi=".len..];
929937 } else if (mem.startsWith(u8, arg, "-O")) {
930938 optimize_mode_string = arg["-O".len..];
931939 } else if (mem.eql(u8, arg, "--dynamic-linker")) {
......@@ -1872,6 +1880,12 @@ fn buildOutputType(
18721880 const cross_target = try parseCrossTargetOrReportFatalError(arena, target_parse_options);
18731881 const target_info = try detectNativeTargetInfo(gpa, cross_target);
18741882
1883 const target_abi = if (target_abi_str) |s| std.Target.TargetAbi.parse(target_info.target.cpu, s) catch |err| switch (err) {
1884 error.InvalidAbi => fatal("invalid target-abi value '{s}'", .{target_abi_str}),
1885 error.ArchAbiMismatch => fatal("target-abi {s} is not valid for arch {s}", .{ target_abi_str, target_info.target.cpu.arch }),
1886 error.FeatureAbiMismatch => fatal("target-abi {s} is not compatible with CPU features", .{target_abi_str}),
1887 } else std.Target.TargetAbi.default(target_info.target.cpu.arch, target_info.target.cpu.features);
1888
18751889 if (target_info.target.os.tag != .freestanding) {
18761890 if (ensure_libc_on_non_freestanding)
18771891 link_libc = true;
......@@ -2459,6 +2473,7 @@ fn buildOutputType(
24592473 .verbose_cimport = verbose_cimport,
24602474 .verbose_llvm_cpu_features = verbose_llvm_cpu_features,
24612475 .machine_code_model = machine_code_model,
2476 .target_abi = target_abi,
24622477 .color = color,
24632478 .time_report = time_report,
24642479 .stack_report = stack_report,
......@@ -3382,6 +3397,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
33823397 .target = target_info.target,
33833398 .is_native_os = cross_target.isNativeOs(),
33843399 .is_native_abi = cross_target.isNativeAbi(),
3400 .target_abi = std.Target.TargetAbi.default(target_info.target.cpu.arch, target_info.target.cpu.features),
33853401 .dynamic_linker = target_info.dynamic_linker.get(),
33863402 .output_mode = .Exe,
33873403 .main_pkg = &main_pkg,
src/musl.zig+1
......@@ -214,6 +214,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void {
214214 .strip = comp.compilerRtStrip(),
215215 .is_native_os = false,
216216 .is_native_abi = false,
217 .target_abi = comp.bin_file.options.target_abi,
217218 .self_exe_path = comp.self_exe_path,
218219 .verbose_cc = comp.verbose_cc,
219220 .verbose_link = comp.bin_file.options.verbose_link,
src/stage1.zig+1
......@@ -364,6 +364,7 @@ pub const Stage2Target = extern struct {
364364
365365 llvm_cpu_name: ?[*:0]const u8,
366366 llvm_cpu_features: ?[*:0]const u8,
367 llvm_target_abi: ?[*:0]const u8,
367368};
368369
369370// ABI warning
src/stage1/codegen.cpp+2-3
......@@ -9487,9 +9487,8 @@ static void init(CodeGen *g) {
94879487 // TODO handle float ABI better- it should depend on the ABI portion of std.Target
94889488 ZigLLVMABIType float_abi = ZigLLVMABITypeDefault;
94899489
9490 // TODO a way to override this as part of std.Target ABI?
9491 const char *abi_name = nullptr;
9492 if (target_is_riscv(g->zig_target)) {
9490 const char *abi_name = g->zig_target->llvm_target_abi;
9491 if (abi_name == nullptr && target_is_riscv(g->zig_target)) {
94939492 // RISC-V Linux defaults to ilp32d/lp64d
94949493 if (g->zig_target->os == OsLinux) {
94959494 abi_name = (g->zig_target->arch == ZigLLVM_riscv32) ? "ilp32d" : "lp64d";
src/stage1/stage1.h+1
......@@ -112,6 +112,7 @@ struct ZigTarget {
112112
113113 const char *llvm_cpu_name;
114114 const char *llvm_cpu_features;
115 const char *llvm_target_abi;
115116};
116117
117118// ABI warning
src/test.zig+1
......@@ -907,6 +907,7 @@ pub const TestContext = struct {
907907 .object_format = case.object_format,
908908 .is_native_os = case.target.isNativeOs(),
909909 .is_native_abi = case.target.isNativeAbi(),
910 .target_abi = std.Target.TargetAbi.default(target.cpu.arch, target.cpu.features),
910911 .dynamic_linker = target_info.dynamic_linker.get(),
911912 .link_libc = link_libc,
912913 .use_llvm = use_llvm,