commit b732070fd36267fb055347e3aa8a1851e4054d50 (tree) parent 55c46870b23ac16670beaa3ff1c082b703738307 Author: Alex Rønne Petersen <alex@alexrp.com> Date: Tue, 18 Feb 2025 00:51:59 +0100 Merge pull request #22589 from alexrp/target-changes Some miscellaneous target and calling convention changes Diffstat:
68 files changed, 764 insertions(+), 747 deletions(-)
diff --git a/build.zig b/build.zig @@ -742,7 +742,7 @@ fn addCmakeCfgOptionsToExe( const mod = exe.root_module; const target = mod.resolved_target.?.result; - if (target.isDarwin()) { + if (target.os.tag.isDarwin()) { // useful for package maintainers exe.headerpad_max_install_names = true; } diff --git a/lib/compiler/aro/aro/Compilation.zig b/lib/compiler/aro/aro/Compilation.zig @@ -308,7 +308,7 @@ fn generateSystemDefines(comp: *Compilation, w: anytype) !void { ), else => {}, } - if (comp.target.isAndroid()) { + if (comp.target.abi.isAndroid()) { try w.writeAll("#define __ANDROID__ 1\n"); } @@ -734,7 +734,7 @@ pub fn float80Type(comp: *const Compilation) ?Type { /// Smallest integer type with at least N bits pub fn intLeastN(comp: *const Compilation, bits: usize, signedness: std.builtin.Signedness) Type { - if (bits == 64 and (comp.target.isDarwin() or comp.target.isWasm())) { + if (bits == 64 and (comp.target.os.tag.isDarwin() or comp.target.cpu.arch.isWasm())) { // WebAssembly and Darwin use `long long` for `int_least64_t` and `int_fast64_t`. return .{ .specifier = if (signedness == .signed) .long_long else .ulong_long }; } diff --git a/lib/compiler/aro/aro/Driver/GCCDetector.zig b/lib/compiler/aro/aro/Driver/GCCDetector.zig @@ -183,7 +183,7 @@ fn collectLibDirsAndTriples( // TODO return; } - if (target.isAndroid()) { + if (target.abi.isAndroid()) { const AArch64AndroidTriples: [1][]const u8 = .{"aarch64-linux-android"}; const ARMAndroidTriples: [1][]const u8 = .{"arm-linux-androideabi"}; const MIPSELAndroidTriples: [1][]const u8 = .{"mipsel-linux-android"}; diff --git a/lib/compiler/aro/aro/Toolchain.zig b/lib/compiler/aro/aro/Toolchain.zig @@ -161,7 +161,7 @@ pub fn getLinkerPath(tc: *const Toolchain, buf: []u8) ![]const u8 { } else { var linker_name = try std.ArrayList(u8).initCapacity(tc.driver.comp.gpa, 5 + use_linker.len); // "ld64." ++ use_linker defer linker_name.deinit(); - if (tc.getTarget().isDarwin()) { + if (tc.getTarget().os.tag.isDarwin()) { linker_name.appendSliceAssumeCapacity("ld64."); } else { linker_name.appendSliceAssumeCapacity("ld."); @@ -343,7 +343,7 @@ pub fn buildLinkerArgs(tc: *Toolchain, argv: *std.ArrayList([]const u8)) !void { } fn getDefaultRuntimeLibKind(tc: *const Toolchain) RuntimeLibKind { - if (tc.getTarget().isAndroid()) { + if (tc.getTarget().abi.isAndroid()) { return .compiler_rt; } return .libgcc; @@ -369,7 +369,7 @@ pub fn getCompilerRt(tc: *const Toolchain, component: []const u8, file_kind: Fil fn getLibGCCKind(tc: *const Toolchain) LibGCCKind { const target = tc.getTarget(); - if (tc.driver.static_libgcc or tc.driver.static or tc.driver.static_pie or target.isAndroid()) { + if (tc.driver.static_libgcc or tc.driver.static or tc.driver.static_pie or target.abi.isAndroid()) { return .static; } if (tc.driver.shared_libgcc) { @@ -384,7 +384,7 @@ fn getUnwindLibKind(tc: *const Toolchain) !UnwindLibKind { switch (tc.getRuntimeLibKind()) { .compiler_rt => { const target = tc.getTarget(); - if (target.isAndroid() or target.os.tag == .aix) { + if (target.abi.isAndroid() or target.os.tag == .aix) { return .compiler_rt; } else { return .none; @@ -417,14 +417,14 @@ fn getAsNeededOption(is_solaris: bool, needed: bool) []const u8 { fn addUnwindLibrary(tc: *const Toolchain, argv: *std.ArrayList([]const u8)) !void { const unw = try tc.getUnwindLibKind(); const target = tc.getTarget(); - if ((target.isAndroid() and unw == .libgcc) or + if ((target.abi.isAndroid() and unw == .libgcc) or target.os.tag == .elfiamcu or target.ofmt == .wasm or target_util.isWindowsMSVCEnvironment(target) or unw == .none) return; const lgk = tc.getLibGCCKind(); - const as_needed = lgk == .unspecified and !target.isAndroid() and !target_util.isCygwinMinGW(target) and target.os.tag != .aix; + const as_needed = lgk == .unspecified and !target.abi.isAndroid() and !target_util.isCygwinMinGW(target) and target.os.tag != .aix; if (as_needed) { try argv.append(getAsNeededOption(target.os.tag == .solaris, true)); } @@ -483,7 +483,7 @@ pub fn addRuntimeLibs(tc: *const Toolchain, argv: *std.ArrayList([]const u8)) !v }, } - if (target.isAndroid() and !tc.driver.static and !tc.driver.static_pie) { + if (target.abi.isAndroid() and !tc.driver.static and !tc.driver.static_pie) { try argv.append("-ldl"); } } diff --git a/lib/compiler/aro/aro/Type.zig b/lib/compiler/aro/aro/Type.zig @@ -1102,7 +1102,7 @@ pub fn alignof(ty: Type, comp: *const Compilation) u29 { .double => comp.target.cTypeAlignment(.double), .long_double => comp.target.cTypeAlignment(.longdouble), - .int128, .uint128 => if (comp.target.cpu.arch == .s390x and comp.target.os.tag == .linux and comp.target.isGnu()) 8 else 16, + .int128, .uint128 => if (comp.target.cpu.arch == .s390x and comp.target.os.tag == .linux and comp.target.abi.isGnu()) 8 else 16, .fp16, .float16 => 2, .float128 => 16, diff --git a/lib/compiler/aro/aro/target.zig b/lib/compiler/aro/aro/target.zig @@ -117,8 +117,8 @@ pub fn int64Type(target: std.Target) Type { .sparc64 => return intMaxType(target), - .x86, .x86_64 => if (!target.isDarwin()) return intMaxType(target), - .aarch64, .aarch64_be => if (!target.isDarwin() and target.os.tag != .openbsd and target.os.tag != .windows) return .{ .specifier = .long }, + .x86, .x86_64 => if (!target.os.tag.isDarwin()) return intMaxType(target), + .aarch64, .aarch64_be => if (!target.os.tag.isDarwin() and target.os.tag != .openbsd and target.os.tag != .windows) return .{ .specifier = .long }, else => {}, } return .{ .specifier = .long_long }; @@ -144,7 +144,7 @@ pub fn defaultFunctionAlignment(target: std.Target) u8 { } pub fn isTlsSupported(target: std.Target) bool { - if (target.isDarwin()) { + if (target.os.tag.isDarwin()) { var supported = false; switch (target.os.tag) { .macos => supported = !(target.os.isAtLeast(.macos, .{ .major = 10, .minor = 7, .patch = 0 }) orelse false), @@ -199,7 +199,7 @@ pub fn minZeroWidthBitfieldAlignment(target: std.Target) ?u29 { pub fn unnamedFieldAffectsAlignment(target: std.Target) bool { switch (target.cpu.arch) { .aarch64 => { - if (target.isDarwin() or target.os.tag == .windows) return false; + if (target.os.tag.isDarwin() or target.os.tag == .windows) return false; return true; }, .armeb => { @@ -229,7 +229,7 @@ pub fn packAllEnums(target: std.Target) bool { pub fn defaultAlignment(target: std.Target) u29 { switch (target.cpu.arch) { .avr => return 1, - .arm => if (target.isAndroid() or target.os.tag == .ios) return 16 else return 8, + .arm => if (target.abi.isAndroid() or target.os.tag == .ios) return 16 else return 8, .sparc => if (std.Target.sparc.featureSetHas(target.cpu.features, .v9)) return 16 else return 8, .mips, .mipsel => switch (target.abi) { .none, .gnuabi64 => return 16, @@ -242,9 +242,8 @@ pub fn defaultAlignment(target: std.Target) u29 { pub fn systemCompiler(target: std.Target) LangOpts.Compiler { // Android is linux but not gcc, so these checks go first // the rest for documentation as fn returns .clang - if (target.isDarwin() or - target.isAndroid() or - target.isBSD() or + if (target.abi.isAndroid() or + target.os.tag.isBSD() or target.os.tag == .fuchsia or target.os.tag == .solaris or target.os.tag == .haiku or @@ -268,7 +267,7 @@ pub fn systemCompiler(target: std.Target) LangOpts.Compiler { pub fn hasFloat128(target: std.Target) bool { if (target.cpu.arch.isWasm()) return true; - if (target.isDarwin()) return false; + if (target.os.tag.isDarwin()) return false; if (target.cpu.arch.isPowerPC()) return std.Target.powerpc.featureSetHas(target.cpu.features, .float128); return switch (target.os.tag) { .dragonfly, @@ -461,7 +460,6 @@ pub fn get32BitArchVariant(target: std.Target) ?std.Target { .amdgcn, .avr, .msp430, - .spu_2, .ve, .bpfel, .bpfeb, @@ -522,7 +520,6 @@ pub fn get64BitArchVariant(target: std.Target) ?std.Target { .lanai, .m68k, .msp430, - .spu_2, .xcore, .xtensa, => return null, @@ -620,8 +617,6 @@ pub fn toLLVMTriple(target: std.Target, buf: []u8) []const u8 { .wasm32 => "wasm32", .wasm64 => "wasm64", .ve => "ve", - // Note: spu_2 is not supported in LLVM; this is the Zig arch name - .spu_2 => "spu_2", }; writer.writeAll(llvm_arch) catch unreachable; writer.writeByte('-') catch unreachable; diff --git a/lib/compiler/aro/aro/toolchains/Linux.zig b/lib/compiler/aro/aro/toolchains/Linux.zig @@ -27,7 +27,7 @@ pub fn discover(self: *Linux, tc: *Toolchain) !void { fn buildExtraOpts(self: *Linux, tc: *const Toolchain) !void { const gpa = tc.driver.comp.gpa; const target = tc.getTarget(); - const is_android = target.isAndroid(); + const is_android = target.abi.isAndroid(); if (self.distro.isAlpine() or is_android) { try self.extra_opts.ensureUnusedCapacity(gpa, 2); self.extra_opts.appendAssumeCapacity("-z"); @@ -113,7 +113,7 @@ fn findPaths(self: *Linux, tc: *Toolchain) !void { try tc.addPathIfExists(&.{ sysroot, "/lib", multiarch_triple }, .file); try tc.addPathIfExists(&.{ sysroot, "/lib", "..", os_lib_dir }, .file); - if (target.isAndroid()) { + if (target.abi.isAndroid()) { // TODO } try tc.addPathIfExists(&.{ sysroot, "/usr", "lib", multiarch_triple }, .file); @@ -156,7 +156,7 @@ fn getStatic(self: *const Linux, d: *const Driver) bool { pub fn getDefaultLinker(self: *const Linux, target: std.Target) []const u8 { _ = self; - if (target.isAndroid()) { + if (target.abi.isAndroid()) { return "ld.lld"; } return "ld"; @@ -169,7 +169,7 @@ pub fn buildLinkerArgs(self: *const Linux, tc: *const Toolchain, argv: *std.Arra const is_pie = self.getPIE(d); const is_static_pie = try self.getStaticPIE(d); const is_static = self.getStatic(d); - const is_android = target.isAndroid(); + const is_android = target.abi.isAndroid(); const is_iamcu = target.os.tag == .elfiamcu; const is_ve = target.cpu.arch == .ve; const has_crt_begin_end_files = target.abi != .none; // TODO: clang checks for MIPS vendor @@ -326,7 +326,7 @@ pub fn buildLinkerArgs(self: *const Linux, tc: *const Toolchain, argv: *std.Arra } fn getMultiarchTriple(target: std.Target) ?[]const u8 { - const is_android = target.isAndroid(); + const is_android = target.abi.isAndroid(); const is_mips_r6 = std.Target.mips.featureSetHas(target.cpu.features, .mips32r6); return switch (target.cpu.arch) { .arm, .thumb => if (is_android) "arm-linux-androideabi" else if (target.abi == .gnueabihf) "arm-linux-gnueabihf" else "arm-linux-gnueabi", @@ -380,7 +380,7 @@ pub fn defineSystemIncludes(self: *const Linux, tc: *const Toolchain) !void { // musl prefers /usr/include before builtin includes, so musl targets will add builtins // at the end of this function (unless disabled with nostdlibinc) - if (!tc.driver.nobuiltininc and (!target.isMusl() or tc.driver.nostdlibinc)) { + if (!tc.driver.nobuiltininc and (!target.abi.isMusl() or tc.driver.nostdlibinc)) { try comp.addBuiltinIncludeDir(tc.driver.aro_name); } @@ -411,7 +411,7 @@ pub fn defineSystemIncludes(self: *const Linux, tc: *const Toolchain) !void { try comp.addSystemIncludeDir("/usr/include"); std.debug.assert(!tc.driver.nostdlibinc); - if (!tc.driver.nobuiltininc and target.isMusl()) { + if (!tc.driver.nobuiltininc and target.abi.isMusl()) { try comp.addBuiltinIncludeDir(tc.driver.aro_name); } } diff --git a/lib/compiler_rt/common.zig b/lib/compiler_rt/common.zig @@ -14,7 +14,7 @@ else /// For WebAssembly this allows the symbol to be resolved to other modules, but will not /// export it to the host runtime. pub const visibility: std.builtin.SymbolVisibility = - if (builtin.target.isWasm() and linkage != .internal) .hidden else .default; + if (builtin.target.cpu.arch.isWasm() and linkage != .internal) .hidden else .default; pub const want_aeabi = switch (builtin.abi) { .eabi, @@ -92,7 +92,7 @@ pub const panic = if (builtin.is_test) std.debug.FullPanic(std.debug.defaultPani pub fn F16T(comptime OtherType: type) type { return switch (builtin.cpu.arch) { .arm, .armeb, .thumb, .thumbeb => if (std.Target.arm.featureSetHas(builtin.cpu.features, .has_v8)) - switch (builtin.abi.floatAbi()) { + switch (builtin.abi.float()) { .soft => u16, .hard => f16, } @@ -100,7 +100,7 @@ pub fn F16T(comptime OtherType: type) type { u16, .aarch64, .aarch64_be => f16, .riscv32, .riscv64 => f16, - .x86, .x86_64 => if (builtin.target.isDarwin()) switch (OtherType) { + .x86, .x86_64 => if (builtin.target.os.tag.isDarwin()) switch (OtherType) { // Starting with LLVM 16, Darwin uses different abi for f16 // depending on the type of the other return/argument..??? f32, f64 => u16, diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig @@ -465,7 +465,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile { if (compile.linkage != null and compile.linkage.? == .static) { compile.out_lib_filename = compile.out_filename; } else if (compile.version) |version| { - if (target.isDarwin()) { + if (target.os.tag.isDarwin()) { compile.major_only_filename = owner.fmt("lib{s}.{d}.dylib", .{ compile.name, version.major, @@ -480,7 +480,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile { compile.out_lib_filename = compile.out_filename; } } else { - if (target.isDarwin()) { + if (target.os.tag.isDarwin()) { compile.out_lib_filename = compile.out_filename; } else if (target.os.tag == .windows) { compile.out_lib_filename = owner.fmt("{s}.lib", .{compile.name}); @@ -1524,7 +1524,7 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 { try zig_args.append(b.fmt("{}", .{version})); } - if (compile.rootModuleTarget().isDarwin()) { + if (compile.rootModuleTarget().os.tag.isDarwin()) { const install_name = compile.install_name orelse b.fmt("@rpath/{s}{s}{s}", .{ compile.rootModuleTarget().libPrefix(), compile.name, diff --git a/lib/std/Target.zig b/lib/std/Target.zig @@ -144,10 +144,6 @@ pub const Os = struct { }; } - pub inline fn isGnuLibC(tag: Os.Tag, abi: Abi) bool { - return (tag == .hurd or tag == .linux) and abi.isGnu(); - } - pub fn defaultVersionRange(tag: Tag, arch: Cpu.Arch, abi: Abi) Os { return .{ .tag = tag, @@ -218,23 +214,6 @@ pub const Os = struct { .windows => .windows, }; } - - pub fn archName(tag: Tag, arch: Cpu.Arch) [:0]const u8 { - return switch (tag) { - .linux => switch (arch) { - .arm, .armeb, .thumb, .thumbeb => "arm", - .aarch64, .aarch64_be => "aarch64", - .loongarch32, .loongarch64 => "loongarch", - .mips, .mipsel, .mips64, .mips64el => "mips", - .powerpc, .powerpcle, .powerpc64, .powerpc64le => "powerpc", - .riscv32, .riscv64 => "riscv", - .sparc, .sparc64 => "sparc", - .x86, .x86_64 => "x86", - else => @tagName(arch), - }, - else => @tagName(arch), - }; - } }; /// Based on NTDDI version constants from @@ -763,6 +742,7 @@ pub const mips = @import("Target/mips.zig"); pub const msp430 = @import("Target/msp430.zig"); pub const nvptx = @import("Target/nvptx.zig"); pub const powerpc = @import("Target/powerpc.zig"); +pub const propeller = @import("Target/propeller.zig"); pub const riscv = @import("Target/riscv.zig"); pub const sparc = @import("Target/sparc.zig"); pub const spirv = @import("Target/spirv.zig"); @@ -772,7 +752,6 @@ pub const wasm = @import("Target/wasm.zig"); pub const x86 = @import("Target/x86.zig"); pub const xcore = @import("Target/xcore.zig"); pub const xtensa = @import("Target/xtensa.zig"); -pub const propeller = @import("Target/propeller.zig"); pub const Abi = enum { none, @@ -990,7 +969,12 @@ pub const Abi = enum { }; } - pub inline fn floatAbi(abi: Abi) FloatAbi { + pub const Float = enum { + hard, + soft, + }; + + pub inline fn float(abi: Abi) Float { return switch (abi) { .androideabi, .eabi, @@ -1081,20 +1065,17 @@ pub fn toElfMachine(target: Target) std.elf.EM { .msp430 => .MSP430, .powerpc, .powerpcle => .PPC, .powerpc64, .powerpc64le => .PPC64, + .propeller => .PROPELLER, .riscv32, .riscv64 => .RISCV, .s390x => .S390, .sparc => if (Target.sparc.featureSetHas(target.cpu.features, .v9)) .SPARC32PLUS else .SPARC, .sparc64 => .SPARCV9, - .spu_2 => .SPU_2, .ve => .VE, .x86 => if (target.os.tag == .elfiamcu) .IAMCU else .@"386", .x86_64 => .X86_64, .xcore => .XCORE, .xtensa => .XTENSA, - .propeller1 => .PROPELLER, - .propeller2 => .PROPELLER2, - .nvptx, .nvptx64, .spirv, @@ -1148,14 +1129,12 @@ pub fn toCoffMachine(target: Target) std.coff.MachineType { .spirv, .spirv32, .spirv64, - .spu_2, .ve, .wasm32, .wasm64, .xcore, .xtensa, - .propeller1, - .propeller2, + .propeller, => .UNKNOWN, }; } @@ -1368,8 +1347,7 @@ pub const Cpu = struct { powerpcle, powerpc64, powerpc64le, - propeller1, - propeller2, + propeller, riscv32, riscv64, s390x, @@ -1378,7 +1356,6 @@ pub const Cpu = struct { spirv, spirv32, spirv64, - spu_2, ve, wasm32, wasm64, @@ -1520,14 +1497,6 @@ pub const Cpu = struct { }; } - /// Returns if the architecture is a Parallax propeller architecture. - pub inline fn isPropeller(arch: Arch) bool { - return switch (arch) { - .propeller1, .propeller2 => true, - else => false, - }; - } - pub fn parseCpuModel(arch: Arch, cpu_name: []const u8) !*const Cpu.Model { for (arch.allCpuModels()) |cpu| { if (std.mem.eql(u8, cpu_name, cpu.name)) { @@ -1564,7 +1533,6 @@ pub const Cpu = struct { .xcore, .thumb, .ve, - .spu_2, // GPU bitness is opaque. For now, assume little endian. .spirv, .spirv32, @@ -1572,8 +1540,7 @@ pub const Cpu = struct { .loongarch32, .loongarch64, .arc, - .propeller1, - .propeller2, + .propeller, => .little, .armeb, @@ -1593,26 +1560,6 @@ pub const Cpu = struct { }; } - /// Returns whether this architecture supports the address space - pub fn supportsAddressSpace(arch: Arch, address_space: std.builtin.AddressSpace) bool { - const is_nvptx = arch.isNvptx(); - const is_spirv = arch.isSpirV(); - const is_gpu = is_nvptx or is_spirv or arch == .amdgcn; - return switch (address_space) { - .generic => true, - .fs, .gs, .ss => arch == .x86_64 or arch == .x86, - .global, .constant, .local, .shared => is_gpu, - .param => is_nvptx, - .input, .output, .uniform, .push_constant, .storage_buffer => is_spirv, - // TODO this should also check how many flash banks the cpu has - .flash, .flash1, .flash2, .flash3, .flash4, .flash5 => arch == .avr, - - // Propeller address spaces: - .cog, .hub => arch.isPropeller(), - .lut => (arch == .propeller2), - }; - } - /// Returns a name that matches the lib/std/target/* source file name. pub fn genericName(arch: Arch) [:0]const u8 { return switch (arch) { @@ -1622,6 +1569,7 @@ pub const Cpu = struct { .loongarch32, .loongarch64 => "loongarch", .mips, .mipsel, .mips64, .mips64el => "mips", .powerpc, .powerpcle, .powerpc64, .powerpc64le => "powerpc", + .propeller => "propeller", .riscv32, .riscv64 => "riscv", .sparc, .sparc64 => "sparc", .s390x => "s390x", @@ -1629,7 +1577,6 @@ pub const Cpu = struct { .nvptx, .nvptx64 => "nvptx", .wasm32, .wasm64 => "wasm", .spirv, .spirv32, .spirv64 => "spirv", - .propeller1, .propeller2 => "propeller", else => @tagName(arch), }; } @@ -1770,10 +1717,8 @@ pub const Cpu = struct { .aarch64_vfabi_sve, => &.{ .aarch64, .aarch64_be }, - .arm_apcs, .arm_aapcs, .arm_aapcs_vfp, - .arm_aapcs16_vfp, .arm_interrupt, => &.{ .arm, .armeb, .thumb, .thumbeb }, @@ -1813,7 +1758,7 @@ pub const Cpu = struct { .powerpc_aix_altivec, => &.{ .powerpc, .powerpcle }, - .wasm_watc, + .wasm_mvp, => &.{ .wasm64, .wasm32 }, .arc_sysv, @@ -1854,11 +1799,8 @@ pub const Cpu = struct { .msp430_eabi, => &.{.msp430}, - .propeller1_sysv, - => &.{.propeller1}, - - .propeller2_sysv, - => &.{.propeller2}, + .propeller_sysv, + => &.{.propeller}, .s390x_sysv, .s390x_sysv_vx, @@ -1937,8 +1879,7 @@ pub const Cpu = struct { .msp430 => &msp430.cpu.generic, .powerpc, .powerpcle => &powerpc.cpu.ppc, .powerpc64, .powerpc64le => &powerpc.cpu.ppc64, - .propeller1 => &propeller.cpu.generic, - .propeller2 => &propeller.cpu.generic, + .propeller => &propeller.cpu.p1, .riscv32 => &riscv.cpu.generic_rv32, .riscv64 => &riscv.cpu.generic_rv64, .spirv, .spirv32, .spirv64 => &spirv.cpu.generic, @@ -1954,7 +1895,6 @@ pub const Cpu = struct { .xtensa => &xtensa.cpu.generic, .kalimba, - .spu_2, => &S.generic_model, }; } @@ -2015,6 +1955,35 @@ pub const Cpu = struct { pub fn baseline(arch: Arch, os: Os) Cpu { return Model.baseline(arch, os).toCpu(arch); } + + /// Returns whether this architecture supports `address_space`. If `context` is `null`, this + /// function simply answers the general question of whether the architecture has any concept + /// of `address_space`; if non-`null`, the function additionally checks whether + /// `address_space` is valid in that context. + pub fn supportsAddressSpace( + cpu: Cpu, + address_space: std.builtin.AddressSpace, + context: ?std.builtin.AddressSpace.Context, + ) bool { + const arch = cpu.arch; + + const is_nvptx = arch.isNvptx(); + const is_spirv = arch.isSpirV(); + const is_gpu = is_nvptx or is_spirv or arch == .amdgcn; + + return switch (address_space) { + .generic => true, + .fs, .gs, .ss => (arch == .x86_64 or arch == .x86) and (context == null or context == .pointer), + .flash, .flash1, .flash2, .flash3, .flash4, .flash5 => arch == .avr, // TODO this should also check how many flash banks the cpu has + .cog, .hub => arch == .propeller, + .lut => arch == .propeller and std.Target.propeller.featureSetHas(cpu.features, .p2), + + .global, .local, .shared => is_gpu, + .constant => is_gpu and (context == null or context == .constant), + .param => is_nvptx, + .input, .output, .uniform, .push_constant, .storage_buffer => is_spirv, + }; + } }; pub fn zigTriple(target: Target, allocator: Allocator) Allocator.Error![]u8 { @@ -2054,48 +2023,29 @@ pub fn libPrefix(target: Target) [:0]const u8 { } pub inline fn isMinGW(target: Target) bool { - return target.os.tag == .windows and target.isGnu(); -} - -pub inline fn isGnu(target: Target) bool { - return target.abi.isGnu(); -} - -pub inline fn isMusl(target: Target) bool { - return target.abi.isMusl(); -} - -pub inline fn isAndroid(target: Target) bool { - return target.abi.isAndroid(); -} - -pub inline fn isWasm(target: Target) bool { - return target.cpu.arch.isWasm(); -} - -pub inline fn isDarwin(target: Target) bool { - return target.os.tag.isDarwin(); -} - -pub inline fn isBSD(target: Target) bool { - return target.os.tag.isBSD(); + return target.os.tag == .windows and target.abi.isGnu(); } pub inline fn isGnuLibC(target: Target) bool { - return target.os.tag.isGnuLibC(target.abi); + return switch (target.os.tag) { + .hurd, .linux => target.abi.isGnu(), + else => false, + }; } -pub inline fn isSpirV(target: Target) bool { - return target.cpu.arch.isSpirV(); +pub inline fn isMuslLibC(target: Target) bool { + return target.os.tag == .linux and target.abi.isMusl(); } -pub const FloatAbi = enum { - hard, - soft, -}; +pub inline fn isDarwinLibC(target: Target) bool { + return switch (target.abi) { + .none, .macabi, .simulator => target.os.tag.isDarwin(), + else => false, + }; +} -pub inline fn floatAbi(target: Target) FloatAbi { - return target.abi.floatAbi(); +pub inline fn isWasiLibC(target: Target) bool { + return target.os.tag == .wasi and target.abi.isMusl(); } pub const DynamicLinker = struct { @@ -2627,7 +2577,6 @@ pub fn ptrBitWidth_cpu_abi(cpu: Cpu, abi: Abi) u16 { return switch (cpu.arch) { .avr, .msp430, - .spu_2, => 16, .arc, @@ -2653,8 +2602,7 @@ pub fn ptrBitWidth_cpu_abi(cpu: Cpu, abi: Abi) u16 { .spirv32, .loongarch32, .xtensa, - .propeller1, - .propeller2, + .propeller, => 32, .aarch64, @@ -2733,7 +2681,7 @@ pub fn stackAlignment(target: Target) u16 { /// Note that char signedness is implementation-defined and many compilers provide /// an option to override the default signedness e.g. GCC's -funsigned-char / -fsigned-char pub fn charSignedness(target: Target) std.builtin.Signedness { - if (target.isDarwin() or target.os.tag == .windows or target.os.tag == .uefi) return .signed; + if (target.os.tag.isDarwin() or target.os.tag == .windows or target.os.tag == .uefi) return .signed; return switch (target.cpu.arch) { .arm, @@ -3164,10 +3112,8 @@ pub fn cTypeAlignment(target: Target, c_type: CType) u16 { .x86, .xcore, .kalimba, - .spu_2, .xtensa, - .propeller1, - .propeller2, + .propeller, => 4, .arm, @@ -3260,10 +3206,8 @@ pub fn cTypePreferredAlignment(target: Target, c_type: CType) u16 { .csky, .xcore, .kalimba, - .spu_2, .xtensa, - .propeller1, - .propeller2, + .propeller, => 4, .arc, @@ -3330,7 +3274,7 @@ pub fn cCallingConvention(target: Target) ?std.builtin.CallingConvention { .windows => .{ .aarch64_aapcs_win = .{} }, else => .{ .aarch64_aapcs = .{} }, }, - .arm, .armeb, .thumb, .thumbeb => switch (target.abi.floatAbi()) { + .arm, .armeb, .thumb, .thumbeb => switch (target.abi.float()) { .soft => .{ .arm_aapcs = .{} }, .hard => .{ .arm_aapcs_vfp = .{} }, }, @@ -3343,7 +3287,7 @@ pub fn cCallingConvention(target: Target) ?std.builtin.CallingConvention { .riscv32 => .{ .riscv32_ilp32 = .{} }, .sparc64 => .{ .sparc64_sysv = .{} }, .sparc => .{ .sparc_sysv = .{} }, - .powerpc64 => if (target.isMusl()) + .powerpc64 => if (target.abi.isMusl()) .{ .powerpc64_elf_v2 = .{} } else .{ .powerpc64_elf = .{} }, @@ -3352,8 +3296,7 @@ pub fn cCallingConvention(target: Target) ?std.builtin.CallingConvention { .aix => .{ .powerpc_aix = .{} }, else => .{ .powerpc_sysv = .{} }, }, - .wasm32 => .{ .wasm_watc = .{} }, - .wasm64 => .{ .wasm_watc = .{} }, + .wasm32, .wasm64 => .{ .wasm_mvp = .{} }, .arc => .{ .arc_sysv = .{} }, .avr => .avr_gnu, .bpfel, .bpfeb => .{ .bpf_std = .{} }, @@ -3368,10 +3311,8 @@ pub fn cCallingConvention(target: Target) ?std.builtin.CallingConvention { else .{ .m68k_sysv = .{} }, .msp430 => .{ .msp430_eabi = .{} }, - .propeller1 => .{ .propeller1_sysv = .{} }, - .propeller2 => .{ .propeller2_sysv = .{} }, + .propeller => .{ .propeller_sysv = .{} }, .s390x => .{ .s390x_sysv = .{} }, - .spu_2 => null, .ve => .{ .ve_sysv = .{} }, .xcore => .{ .xcore_xs1 = .{} }, .xtensa => .{ .xtensa_call0 = .{} }, @@ -3381,10 +3322,6 @@ pub fn cCallingConvention(target: Target) ?std.builtin.CallingConvention { }; } -pub fn osArchName(target: std.Target) [:0]const u8 { - return target.os.tag.archName(target.cpu.arch); -} - const Target = @This(); const std = @import("std.zig"); const builtin = @import("builtin"); diff --git a/lib/std/Target/Query.zig b/lib/std/Target/Query.zig @@ -26,7 +26,7 @@ os_version_min: ?OsVersion = null, os_version_max: ?OsVersion = null, /// `null` means default when cross compiling, or native when `os_tag` is native. -/// If `isGnuLibC()` is `false`, this must be `null` and is ignored. +/// If `isGnu()` is `false`, this must be `null` and is ignored. glibc_version: ?SemanticVersion = null, /// `null` means default when cross compiling, or native when `os_tag` is native. @@ -235,8 +235,7 @@ pub fn parse(args: ParseOptions) !Query { const abi_ver_text = abi_it.rest(); if (abi_it.next() != null) { - const tag = result.os_tag orelse builtin.os.tag; - if (tag.isGnuLibC(abi)) { + if (abi.isGnu()) { result.glibc_version = parseVersion(abi_ver_text) catch |err| switch (err) { error.Overflow => return error.InvalidAbiVersion, error.InvalidVersion => return error.InvalidAbiVersion, diff --git a/lib/std/Target/propeller.zig b/lib/std/Target/propeller.zig @@ -1,20 +1,46 @@ +//! This file is auto-generated by tools/update_cpu_features.zig. + const std = @import("../std.zig"); const CpuFeature = std.Target.Cpu.Feature; const CpuModel = std.Target.Cpu.Model; -pub const Feature = enum {}; +pub const Feature = enum { + p2, +}; pub const featureSet = CpuFeature.FeatureSetFns(Feature).featureSet; pub const featureSetHas = CpuFeature.FeatureSetFns(Feature).featureSetHas; pub const featureSetHasAny = CpuFeature.FeatureSetFns(Feature).featureSetHasAny; pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll; -pub const all_features: [0]CpuFeature = .{}; +pub const all_features = blk: { + const len = @typeInfo(Feature).@"enum".fields.len; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; + result[@intFromEnum(Feature.p2)] = .{ + .llvm_name = null, + .description = "Enable Propeller 2", + .dependencies = featureSet(&[_]Feature{}), + }; + const ti = @typeInfo(Feature); + for (&result, 0..) |*elem, i| { + elem.index = i; + elem.name = ti.@"enum".fields[i].name; + } + break :blk result; +}; pub const cpu = struct { - pub const generic = CpuModel{ - .name = "generic", + pub const p1: CpuModel = .{ + .name = "p1", .llvm_name = null, .features = featureSet(&[_]Feature{}), }; + pub const p2: CpuModel = .{ + .name = "p2", + .llvm_name = null, + .features = featureSet(&[_]Feature{ + .p2, + }), + }; }; diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig @@ -734,7 +734,7 @@ const PosixThreadImpl = struct { else => { var count: c_int = undefined; var count_len: usize = @sizeOf(c_int); - const name = if (comptime target.isDarwin()) "hw.logicalcpu" else "hw.ncpu"; + const name = if (comptime target.os.tag.isDarwin()) "hw.logicalcpu" else "hw.ncpu"; posix.sysctlbynameZ(name, &count, &count_len, null, 0) catch |err| switch (err) { error.NameTooLong, error.UnknownName => unreachable, else => |e| return e, diff --git a/lib/std/Thread/Futex.zig b/lib/std/Thread/Futex.zig @@ -80,7 +80,7 @@ else if (builtin.os.tag == .openbsd) OpenbsdImpl else if (builtin.os.tag == .dragonfly) DragonflyImpl -else if (builtin.target.isWasm()) +else if (builtin.target.cpu.arch.isWasm()) WasmImpl else if (std.Thread.use_pthreads) PosixImpl diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig @@ -220,8 +220,6 @@ pub const CallingConvention = union(enum(u8)) { }; /// Deprecated; use `.x86_thiscall`. pub const Thiscall: CallingConvention = .{ .x86_thiscall = .{} }; - /// Deprecated; do not use. - pub const APCS: CallingConvention = .{ .arm_apcs = .{} }; /// Deprecated; use `.arm_aapcs`. pub const AAPCS: CallingConvention = .{ .arm_aapcs = .{} }; /// Deprecated; use `.arm_aapcs_vfp`. @@ -284,14 +282,10 @@ pub const CallingConvention = union(enum(u8)) { aarch64_vfabi_sve: CommonOptions, // Calling convetions for the `arm`, `armeb`, `thumb`, and `thumbeb` architectures. - /// Deprecated; do not use. - arm_apcs: CommonOptions, // Removal of `arm_apcs` is blocked by #21842. /// ARM Architecture Procedure Call Standard arm_aapcs: CommonOptions, /// ARM Architecture Procedure Call Standard Vector Floating-Point arm_aapcs_vfp: CommonOptions, - /// Deprecated; do not use. - arm_aapcs16_vfp: CommonOptions, // Removal of `arm_aapcs16_vfp` is blocked by #21842. arm_interrupt: ArmInterruptOptions, // Calling conventions for the `mips64` and `mips64el` architectures. @@ -331,7 +325,7 @@ pub const CallingConvention = union(enum(u8)) { powerpc_aix_altivec: CommonOptions, /// The standard `wasm32` and `wasm64` calling convention, as specified in the WebAssembly Tool Conventions. - wasm_watc: CommonOptions, + wasm_mvp: CommonOptions, /// The standard `arc` calling convention. arc_sysv: CommonOptions, @@ -371,11 +365,8 @@ pub const CallingConvention = union(enum(u8)) { /// The standard `msp430` calling convention. msp430_eabi: CommonOptions, - /// The standard `propeller1` calling convention. - propeller1_sysv: CommonOptions, - - /// The standard `propeller2` calling convention. - propeller2_sysv: CommonOptions, + /// The standard `propeller` calling convention. + propeller_sysv: CommonOptions, // Calling conventions for the `s390x` architecture. s390x_sysv: CommonOptions, @@ -500,6 +491,21 @@ pub const CallingConvention = union(enum(u8)) { /// This data structure is used by the Zig language code generation and /// therefore must be kept in sync with the compiler implementation. pub const AddressSpace = enum(u5) { + /// The places where a user can specify an address space attribute + pub const Context = enum { + /// A function is specified to be placed in a certain address space. + function, + /// A (global) variable is specified to be placed in a certain address space. + /// In contrast to .constant, these values (and thus the address space they will be + /// placed in) are required to be mutable. + variable, + /// A (global) constant value is specified to be placed in a certain address space. + /// In contrast to .variable, values placed in this address space are not required to be mutable. + constant, + /// A pointer is ascripted to point into a certain address space. + pointer, + }; + // CPU address spaces. generic, gs, @@ -951,7 +957,7 @@ pub const VaList = switch (builtin.cpu.arch) { .amdgcn => *u8, .avr => *anyopaque, .bpfel, .bpfeb => *anyopaque, - .hexagon => if (builtin.target.isMusl()) VaListHexagon else *u8, + .hexagon => if (builtin.target.abi.isMusl()) VaListHexagon else *u8, .loongarch32, .loongarch64 => *anyopaque, .mips, .mipsel, .mips64, .mips64el => *anyopaque, .riscv32, .riscv64 => *anyopaque, diff --git a/lib/std/c.zig b/lib/std/c.zig @@ -2808,7 +2808,7 @@ pub const Sigaction = switch (native_os) { .mipsel, .mips64, .mips64el, - => if (builtin.target.isMusl()) + => if (builtin.target.abi.isMusl()) linux.Sigaction else if (builtin.target.ptrBitWidth() == 64) extern struct { pub const handler_fn = *align(1) const fn (i32) callconv(.c) void; @@ -6701,7 +6701,7 @@ pub const Stat = switch (native_os) { return self.ctim; } }, - .mips, .mipsel => if (builtin.target.isMusl()) extern struct { + .mips, .mipsel => if (builtin.target.abi.isMusl()) extern struct { dev: dev_t, __pad0: [2]i32, ino: ino_t, @@ -6762,7 +6762,7 @@ pub const Stat = switch (native_os) { return self.ctim; } }, - .mips64, .mips64el => if (builtin.target.isMusl()) extern struct { + .mips64, .mips64el => if (builtin.target.abi.isMusl()) extern struct { dev: dev_t, __pad0: [3]i32, ino: ino_t, @@ -9863,16 +9863,16 @@ pub const LC = enum(c_int) { pub extern "c" fn setlocale(category: LC, locale: ?[*:0]const u8) ?[*:0]const u8; -pub const getcontext = if (builtin.target.isAndroid() or builtin.target.os.tag == .openbsd) +pub const getcontext = if (builtin.target.abi.isAndroid() or builtin.target.os.tag == .openbsd) {} // android bionic and openbsd libc does not implement getcontext -else if (native_os == .linux and builtin.target.isMusl()) +else if (native_os == .linux and builtin.target.abi.isMusl()) linux.getcontext else private.getcontext; pub const max_align_t = if (native_abi == .msvc or native_abi == .itanium) f64 -else if (builtin.target.isDarwin()) +else if (native_os.isDarwin()) c_longdouble else extern struct { diff --git a/lib/std/c/darwin.zig b/lib/std/c/darwin.zig @@ -979,7 +979,7 @@ pub const kevent64_s = extern struct { // to make sure the struct is laid out the same. These values were // produced from C code using the offsetof macro. comptime { - if (builtin.target.isDarwin()) { + if (builtin.target.os.tag.isDarwin()) { assert(@offsetOf(kevent64_s, "ident") == 0); assert(@offsetOf(kevent64_s, "filter") == 8); assert(@offsetOf(kevent64_s, "flags") == 10); diff --git a/lib/std/debug.zig b/lib/std/debug.zig @@ -292,7 +292,7 @@ pub fn dumpHexFallible(bytes: []const u8) !void { /// TODO multithreaded awareness pub fn dumpCurrentStackTrace(start_addr: ?usize) void { nosuspend { - if (builtin.target.isWasm()) { + if (builtin.target.cpu.arch.isWasm()) { if (native_os == .wasi) { const stderr = io.getStdErr().writer(); stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return; @@ -380,7 +380,7 @@ pub inline fn getContext(context: *ThreadContext) bool { /// TODO multithreaded awareness pub fn dumpStackTraceFromBase(context: *ThreadContext) void { nosuspend { - if (builtin.target.isWasm()) { + if (builtin.target.cpu.arch.isWasm()) { if (native_os == .wasi) { const stderr = io.getStdErr().writer(); stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return; @@ -478,7 +478,7 @@ pub fn captureStackTrace(first_address: ?usize, stack_trace: *std.builtin.StackT /// TODO multithreaded awareness pub fn dumpStackTrace(stack_trace: std.builtin.StackTrace) void { nosuspend { - if (builtin.target.isWasm()) { + if (builtin.target.cpu.arch.isWasm()) { if (native_os == .wasi) { const stderr = io.getStdErr().writer(); stderr.print("Unable to dump stack trace: not implemented for Wasm\n", .{}) catch return; @@ -759,7 +759,7 @@ pub const StackIterator = struct { pub fn initWithContext(first_address: ?usize, debug_info: *SelfInfo, context: *posix.ucontext_t) !StackIterator { // The implementation of DWARF unwinding on aarch64-macos is not complete. However, Apple mandates that // the frame pointer register is always used, so on this platform we can safely use the FP-based unwinder. - if (builtin.target.isDarwin() and native_arch == .aarch64) + if (builtin.target.os.tag.isDarwin() and native_arch == .aarch64) return init(first_address, @truncate(context.mcontext.ss.fp)); if (SelfInfo.supports_unwinding) { diff --git a/lib/std/debug/Dwarf/abi.zig b/lib/std/debug/Dwarf/abi.zig @@ -17,7 +17,6 @@ pub fn supportsUnwinding(target: std.Target) bool { .spirv, .spirv32, .spirv64, - .spu_2, => false, // Enabling this causes relocation errors such as: diff --git a/lib/std/debug/SelfInfo.zig b/lib/std/debug/SelfInfo.zig @@ -121,13 +121,13 @@ pub fn deinit(self: *SelfInfo) void { } pub fn getModuleForAddress(self: *SelfInfo, address: usize) !*Module { - if (builtin.target.isDarwin()) { + if (builtin.target.os.tag.isDarwin()) { return self.lookupModuleDyld(address); } else if (native_os == .windows) { return self.lookupModuleWin32(address); } else if (native_os == .haiku) { return self.lookupModuleHaiku(address); - } else if (builtin.target.isWasm()) { + } else if (builtin.target.cpu.arch.isWasm()) { return self.lookupModuleWasm(address); } else { return self.lookupModuleDl(address); @@ -138,13 +138,13 @@ pub fn getModuleForAddress(self: *SelfInfo, address: usize) !*Module { // This can be called when getModuleForAddress fails, so implementations should provide // a path that doesn't rely on any side-effects of a prior successful module lookup. pub fn getModuleNameForAddress(self: *SelfInfo, address: usize) ?[]const u8 { - if (builtin.target.isDarwin()) { + if (builtin.target.os.tag.isDarwin()) { return self.lookupModuleNameDyld(address); } else if (native_os == .windows) { return self.lookupModuleNameWin32(address); } else if (native_os == .haiku) { return null; - } else if (builtin.target.isWasm()) { + } else if (builtin.target.cpu.arch.isWasm()) { return null; } else { return self.lookupModuleNameDl(address); diff --git a/lib/std/elf.zig b/lib/std/elf.zig @@ -1178,8 +1178,6 @@ pub const EM = enum(u16) { MIPS_RS3_LE = 10, /// Old version of Sparc v9, from before the ABI (deprecated) OLD_SPARCV9 = 11, - /// SPU Mark II - SPU_2 = 13, /// HPPA PARISC = 15, /// Fujitsu VPP500 (also old version of PowerPC; deprecated) diff --git a/lib/std/fs/Dir.zig b/lib/std/fs/Dir.zig @@ -2587,7 +2587,7 @@ const CopyFileRawError = error{SystemResources} || posix.CopyFileRangeError || p // The copy starts at offset 0, the initial offsets are preserved. // No metadata is transferred over. fn copy_file(fd_in: posix.fd_t, fd_out: posix.fd_t, maybe_size: ?u64) CopyFileRawError!void { - if (builtin.target.isDarwin()) { + if (builtin.target.os.tag.isDarwin()) { const rc = posix.system.fcopyfile(fd_in, fd_out, null, .{ .DATA = true }); switch (posix.errno(rc)) { .SUCCESS => return, diff --git a/lib/std/heap.zig b/lib/std/heap.zig @@ -348,7 +348,7 @@ pub const page_allocator: Allocator = if (@hasDecl(root, "os") and @hasDecl(root.os, "heap") and @hasDecl(root.os.heap, "page_allocator")) root.os.heap.page_allocator -else if (builtin.target.isWasm()) .{ +else if (builtin.target.cpu.arch.isWasm()) .{ .ptr = undefined, .vtable = &WasmAllocator.vtable, } else if (builtin.target.os.tag == .plan9) .{ @@ -508,7 +508,7 @@ test PageAllocator { const allocator = page_allocator; try testAllocator(allocator); try testAllocatorAligned(allocator); - if (!builtin.target.isWasm()) { + if (!builtin.target.cpu.arch.isWasm()) { try testAllocatorLargeAlignment(allocator); try testAllocatorAlignedShrink(allocator); } @@ -990,7 +990,7 @@ test { _ = FixedBufferAllocator; _ = ThreadSafeAllocator; _ = SbrkAllocator; - if (builtin.target.isWasm()) { + if (builtin.target.cpu.arch.isWasm()) { _ = WasmAllocator; } if (!builtin.single_threaded) _ = smp_allocator; diff --git a/lib/std/heap/WasmAllocator.zig b/lib/std/heap/WasmAllocator.zig @@ -7,7 +7,7 @@ const wasm = std.wasm; const math = std.math; comptime { - if (!builtin.target.isWasm()) { + if (!builtin.target.cpu.arch.isWasm()) { @compileError("only available for wasm32 arch"); } if (!builtin.single_threaded) { diff --git a/lib/std/heap/debug_allocator.zig b/lib/std/heap/debug_allocator.zig @@ -1140,7 +1140,7 @@ test "shrink" { } test "large object - grow" { - if (builtin.target.isWasm()) { + if (builtin.target.cpu.arch.isWasm()) { // Not expected to pass on targets that do not have memory mapping. return error.SkipZigTest; } @@ -1319,7 +1319,7 @@ test "realloc large object to larger alignment" { } test "large object rejects shrinking to small" { - if (builtin.target.isWasm()) { + if (builtin.target.cpu.arch.isWasm()) { // Not expected to pass on targets that do not have memory mapping. return error.SkipZigTest; } diff --git a/lib/std/math/big/int_test.zig b/lib/std/math/big/int_test.zig @@ -2262,7 +2262,7 @@ test "bitNotWrap more than two limbs" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO // LLVM: unexpected runtime library name: __umodei4 - if (builtin.zig_backend == .stage2_llvm and comptime builtin.target.isWasm()) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_llvm and comptime builtin.target.cpu.arch.isWasm()) return error.SkipZigTest; // TODO var a = try Managed.initSet(testing.allocator, maxInt(Limb)); defer a.deinit(); diff --git a/lib/std/math/gamma.zig b/lib/std/math/gamma.zig @@ -263,7 +263,7 @@ test gamma { } test "gamma.special" { - if (builtin.cpu.arch.isArm() and builtin.target.floatAbi() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234 + if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234 inline for (&.{ f32, f64 }) |T| { try expect(std.math.isNan(gamma(T, -std.math.nan(T)))); diff --git a/lib/std/math/log10.zig b/lib/std/math/log10.zig @@ -135,7 +135,7 @@ test log10_int { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_llvm and comptime builtin.target.isWasm()) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_llvm and comptime builtin.target.cpu.arch.isWasm()) return error.SkipZigTest; // TODO inline for ( .{ u8, u16, u32, u64, u128, u256, u512 }, diff --git a/lib/std/posix.zig b/lib/std/posix.zig @@ -3583,7 +3583,7 @@ pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!socket_t return rc; } - const have_sock_flags = !builtin.target.isDarwin() and native_os != .haiku; + const have_sock_flags = !builtin.target.os.tag.isDarwin() and native_os != .haiku; const filtered_sock_type = if (!have_sock_flags) socket_type & ~@as(u32, SOCK.NONBLOCK | SOCK.CLOEXEC) else @@ -3879,7 +3879,7 @@ pub fn accept( /// description of the `CLOEXEC` flag in `open` for reasons why this may be useful. flags: u32, ) AcceptError!socket_t { - const have_accept4 = !(builtin.target.isDarwin() or native_os == .windows or native_os == .haiku); + const have_accept4 = !(builtin.target.os.tag.isDarwin() or native_os == .windows or native_os == .haiku); assert(0 == (flags & ~@as(u32, SOCK.NONBLOCK | SOCK.CLOEXEC))); // Unsupported flag(s) const accepted_sock: socket_t = while (true) { diff --git a/lib/std/zig/LibCDirs.zig b/lib/std/zig/LibCDirs.zig @@ -127,7 +127,7 @@ fn detectFromInstallation(arena: Allocator, target: std.Target, lci: *const LibC var sysroot: ?[]const u8 = null; - if (target.isDarwin()) d: { + if (target.os.tag.isDarwin()) d: { const down1 = std.fs.path.dirname(lci.sys_include_dir.?) orelse break :d; const down2 = std.fs.path.dirname(down1) orelse break :d; try framework_list.append(try std.fs.path.join(arena, &.{ down2, "System", "Library", "Frameworks" })); @@ -150,7 +150,7 @@ pub fn detectFromBuilding( ) !LibCDirs { const s = std.fs.path.sep_str; - if (target.isDarwin()) { + if (target.os.tag.isDarwin()) { const list = try arena.alloc([]const u8, 1); list[0] = try std.fmt.allocPrint( arena, @@ -187,7 +187,7 @@ pub fn detectFromBuilding( "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "generic-{s}", .{ zig_lib_dir, generic_name }, ); - const generic_arch_name = target.osArchName(); + const generic_arch_name = std.zig.target.osArchName(target); const arch_os_include_dir = try std.fmt.allocPrint( arena, "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-{s}-any", diff --git a/lib/std/zig/LibCInstallation.zig b/lib/std/zig/LibCInstallation.zig @@ -81,7 +81,7 @@ pub fn parse( } const os_tag = target.os.tag; - if (self.crt_dir == null and !target.isDarwin()) { + if (self.crt_dir == null and !target.os.tag.isDarwin()) { log.err("crt_dir may not be empty for {s}", .{@tagName(os_tag)}); return error.ParseError; } @@ -167,7 +167,7 @@ pub const FindNativeOptions = struct { pub fn findNative(args: FindNativeOptions) FindError!LibCInstallation { var self: LibCInstallation = .{}; - if (is_darwin and args.target.isDarwin()) { + if (is_darwin and args.target.os.tag.isDarwin()) { if (!std.zig.system.darwin.isSdkInstalled(args.allocator)) return error.DarwinSdkNotFound; const sdk = std.zig.system.darwin.getSdk(args.allocator, args.target) orelse @@ -444,7 +444,7 @@ fn findNativeCrtDirPosix(self: *LibCInstallation, args: FindNativeOptions) FindE self.crt_dir = try ccPrintFileName(.{ .allocator = args.allocator, .search_basename = switch (args.target.os.tag) { - .linux => if (args.target.isAndroid()) "crtbegin_dynamic.o" else "crt1.o", + .linux => if (args.target.abi.isAndroid()) "crtbegin_dynamic.o" else "crt1.o", else => "crt1.o", }, .want_dirname = .only_dir, @@ -734,7 +734,7 @@ pub const CrtBasenames = struct { const target = args.target; - if (target.isAndroid()) return switch (mode) { + if (target.abi.isAndroid()) return switch (mode) { .dynamic_lib => .{ .crtbegin = "crtbegin_so.o", .crtend = "crtend_so.o", @@ -1025,7 +1025,7 @@ const fs = std.fs; const Allocator = std.mem.Allocator; const Path = std.Build.Cache.Path; -const is_darwin = builtin.target.isDarwin(); +const is_darwin = builtin.target.os.tag.isDarwin(); const is_windows = builtin.target.os.tag == .windows; const is_haiku = builtin.target.os.tag == .haiku; diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig @@ -415,7 +415,7 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target { } // https://github.com/llvm/llvm-project/issues/105978 - if (result.cpu.arch.isArm() and result.abi.floatAbi() == .soft) { + if (result.cpu.arch.isArm() and result.abi.float() == .soft) { result.cpu.features.removeFeature(@intFromEnum(Target.arm.Feature.vfp2)); } } diff --git a/lib/std/zig/system/NativePaths.zig b/lib/std/zig/system/NativePaths.zig @@ -83,7 +83,7 @@ pub fn detect(arena: Allocator, native_target: std.Target) !NativePaths { // TODO: consider also adding homebrew paths // TODO: consider also adding macports paths - if (builtin.target.isDarwin()) { + if (builtin.target.os.tag.isDarwin()) { if (std.zig.system.darwin.isSdkInstalled(arena)) sdk: { const sdk = std.zig.system.darwin.getSdk(arena, native_target) orelse break :sdk; try self.addLibDir(try std.fs.path.join(arena, &.{ sdk, "usr/lib" })); diff --git a/lib/std/zig/target.zig b/lib/std/zig/target.zig @@ -129,6 +129,23 @@ pub fn glibcRuntimeTriple( }; } +pub fn osArchName(target: std.Target) [:0]const u8 { + return switch (target.os.tag) { + .linux => switch (target.cpu.arch) { + .arm, .armeb, .thumb, .thumbeb => "arm", + .aarch64, .aarch64_be => "aarch64", + .loongarch32, .loongarch64 => "loongarch", + .mips, .mipsel, .mips64, .mips64el => "mips", + .powerpc, .powerpcle, .powerpc64, .powerpc64le => "powerpc", + .riscv32, .riscv64 => "riscv", + .sparc, .sparc64 => "sparc", + .x86, .x86_64 => "x86", + else => @tagName(target.cpu.arch), + }, + else => @tagName(target.cpu.arch), + }; +} + pub fn muslArchName(arch: std.Target.Cpu.Arch, abi: std.Target.Abi) [:0]const u8 { return switch (abi) { .muslabin32 => "mipsn32", diff --git a/src/Compilation.zig b/src/Compilation.zig @@ -1766,11 +1766,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil if (comp.config.link_libc and is_exe_or_dyn_lib) { // If the "is darwin" check is moved below the libc_installation check below, // error.LibCInstallationMissingCrtDir is returned from lci.resolveCrtPaths(). - if (target.isDarwin()) { - switch (target.abi) { - .none, .simulator, .macabi => {}, - else => return error.LibCUnavailable, - } + if (target.isDarwinLibC()) { // TODO delete logic from MachO flush() and queue up tasks here instead. } else if (comp.libc_installation) |lci| { const basenames = LibCInstallation.CrtBasenames.get(.{ @@ -1793,7 +1789,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil // Loads the libraries provided by `target_util.libcFullLinkFlags(target)`. comp.link_task_queue.shared.appendAssumeCapacity(.load_host_libc); comp.remaining_prelink_tasks += 1; - } else if (target.isMusl() and !target.isWasm()) { + } else if (target.isMuslLibC()) { if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable; if (musl.needsCrt0(comp.config.output_mode, comp.config.link_mode, comp.config.pie)) |f| { @@ -1817,7 +1813,7 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil comp.queued_jobs.glibc_crt_file[@intFromEnum(glibc.CrtFile.libc_nonshared_a)] = true; comp.remaining_prelink_tasks += 1; - } else if (target.isWasm() and target.os.tag == .wasi) { + } else if (target.isWasiLibC()) { if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable; for (comp.wasi_emulated_libs) |crt_file| { @@ -1839,11 +1835,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil // When linking mingw-w64 there are some import libs we always need. try comp.windows_libs.ensureUnusedCapacity(gpa, mingw.always_link_libs.len); for (mingw.always_link_libs) |name| comp.windows_libs.putAssumeCapacity(name, {}); - } else if (target.isDarwin()) { - switch (target.abi) { - .none, .simulator, .macabi => {}, - else => return error.LibCUnavailable, - } } else if (target.os.tag == .freestanding and capable_of_building_zig_libc) { comp.queued_jobs.zig_libc = true; comp.remaining_prelink_tasks += 1; @@ -5545,7 +5536,7 @@ pub fn addCCArgs( // 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.floatAbi()); + const fabi = @tagName(target.abi.float()); try argv.append(switch (target.cpu.arch) { // For whatever reason, Clang doesn't support `-mfloat-abi` for s390x. @@ -5598,7 +5589,7 @@ pub fn addCCArgs( if (ext != .assembly) { try argv.append(if (target.os.tag == .freestanding) "-ffreestanding" else "-fhosted"); - if (target_util.clangSupportsNoImplicitFloatArg(target) and target.floatAbi() == .soft) { + if (target_util.clangSupportsNoImplicitFloatArg(target) and target.abi.float() == .soft) { try argv.append("-mno-implicit-float"); } @@ -5646,7 +5637,7 @@ pub fn addCCArgs( // LLVM IR files don't support these flags. if (ext != .ll and ext != .bc) { // https://github.com/llvm/llvm-project/issues/105972 - if (target.cpu.arch.isPowerPC() and target.floatAbi() == .soft) { + if (target.cpu.arch.isPowerPC() and target.abi.float() == .soft) { try argv.append("-D__NO_FPRS__"); try argv.append("-D_SOFT_FLOAT"); try argv.append("-D_SOFT_DOUBLE"); diff --git a/src/Sema.zig b/src/Sema.zig @@ -9378,7 +9378,7 @@ pub fn handleExternLibName( ); break :blk; } - if (!target.isWasm() and !block.ownerModule().pic) { + if (!target.cpu.arch.isWasm() and !block.ownerModule().pic) { return sema.fail( block, src_loc, @@ -9407,10 +9407,8 @@ const calling_conventions_supporting_var_args = [_]std.builtin.CallingConvention .aarch64_aapcs_win, .aarch64_vfabi, .aarch64_vfabi_sve, - .arm_apcs, .arm_aapcs, .arm_aapcs_vfp, - .arm_aapcs16_vfp, .mips64_n64, .mips64_n32, .mips_o32, @@ -9427,7 +9425,7 @@ const calling_conventions_supporting_var_args = [_]std.builtin.CallingConvention .powerpc_sysv_altivec, .powerpc_aix, .powerpc_aix_altivec, - .wasm_watc, + .wasm_mvp, .arc_sysv, .avr_gnu, .bpf_std, @@ -26513,7 +26511,7 @@ fn zirWasmMemorySize( const index_src = block.builtinCallArgSrc(extra.node, 0); const builtin_src = block.nodeOffset(extra.node); const target = sema.pt.zcu.getTarget(); - if (!target.isWasm()) { + if (!target.cpu.arch.isWasm()) { return sema.fail(block, builtin_src, "builtin @wasmMemorySize is available when targeting WebAssembly; targeted CPU architecture is {s}", .{@tagName(target.cpu.arch)}); } @@ -26538,7 +26536,7 @@ fn zirWasmMemoryGrow( const index_src = block.builtinCallArgSrc(extra.node, 0); const delta_src = block.builtinCallArgSrc(extra.node, 1); const target = sema.pt.zcu.getTarget(); - if (!target.isWasm()) { + if (!target.cpu.arch.isWasm()) { return sema.fail(block, builtin_src, "builtin @wasmMemoryGrow is available when targeting WebAssembly; targeted CPU architecture is {s}", .{@tagName(target.cpu.arch)}); } @@ -37222,30 +37220,12 @@ fn analyzeComptimeAlloc( } }))); } -/// The places where a user can specify an address space attribute -pub const AddressSpaceContext = enum { - /// A function is specified to be placed in a certain address space. - function, - - /// A (global) variable is specified to be placed in a certain address space. - /// In contrast to .constant, these values (and thus the address space they will be - /// placed in) are required to be mutable. - variable, - - /// A (global) constant value is specified to be placed in a certain address space. - /// In contrast to .variable, values placed in this address space are not required to be mutable. - constant, - - /// A pointer is ascripted to point into a certain address space. - pointer, -}; - fn resolveAddressSpace( sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref, - ctx: AddressSpaceContext, + ctx: std.builtin.AddressSpace.Context, ) !std.builtin.AddressSpace { const air_ref = try sema.resolveInst(zir_ref); return sema.analyzeAsAddressSpace(block, src, air_ref, ctx); @@ -37256,7 +37236,7 @@ pub fn analyzeAsAddressSpace( block: *Block, src: LazySrcLoc, air_ref: Air.Inst.Ref, - ctx: AddressSpaceContext, + ctx: std.builtin.AddressSpace.Context, ) !std.builtin.AddressSpace { const pt = sema.pt; const addrspace_ty = try sema.getBuiltinType(src, .AddressSpace); @@ -37264,30 +37244,8 @@ pub fn analyzeAsAddressSpace( const addrspace_val = try sema.resolveConstDefinedValue(block, src, coerced, .{ .simple = .@"addrspace" }); const address_space = try sema.interpretBuiltinType(block, src, addrspace_val, std.builtin.AddressSpace); const target = pt.zcu.getTarget(); - const arch = target.cpu.arch; - - const is_nv = arch.isNvptx(); - const is_amd = arch == .amdgcn; - const is_spirv = arch.isSpirV(); - const is_gpu = is_nv or is_amd or is_spirv; - - const supported = switch (address_space) { - // TODO: on spir-v only when os is opencl. - .generic => true, - .gs, .fs, .ss => (arch == .x86 or arch == .x86_64) and ctx == .pointer, - // TODO: check that .shared and .local are left uninitialized - .param => is_nv, - .input, .output, .uniform, .push_constant, .storage_buffer => is_spirv, - .global, .shared, .local => is_gpu, - .constant => is_gpu and (ctx == .constant), - // TODO this should also check how many flash banks the cpu has - .flash, .flash1, .flash2, .flash3, .flash4, .flash5 => arch == .avr, - - .cog, .hub => arch.isPropeller(), - .lut => (arch == .propeller2), - }; - - if (!supported) { + + if (!target.cpu.supportsAddressSpace(address_space, ctx)) { // TODO error messages could be made more elaborate here const entity = switch (ctx) { .function => "functions", @@ -37299,7 +37257,7 @@ pub fn analyzeAsAddressSpace( block, src, "{s} with address space '{s}' are not supported on {s}", - .{ entity, @tagName(address_space), arch.genericName() }, + .{ entity, @tagName(address_space), target.cpu.arch.genericName() }, ); } @@ -38729,7 +38687,7 @@ pub fn resolveNavPtrModifiers( }; const @"addrspace": std.builtin.AddressSpace = as: { - const addrspace_ctx: Sema.AddressSpaceContext = switch (zir_decl.kind) { + const addrspace_ctx: std.builtin.AddressSpace.Context = switch (zir_decl.kind) { .@"var" => .variable, else => switch (nav_ty.zigTypeTag(zcu)) { .@"fn" => .function, diff --git a/src/Type.zig b/src/Type.zig @@ -1647,7 +1647,7 @@ pub fn maxIntAlignment(target: std.Target) u16 { .avr => 1, .msp430 => 2, .xcore => 4, - .propeller1, .propeller2 => 4, + .propeller => 4, .arm, .armeb, @@ -1698,7 +1698,6 @@ pub fn maxIntAlignment(target: std.Target) u16 { // Below this comment are unverified but based on the fact that C requires // int128_t to be 16 bytes aligned, it's a safe default. - .spu_2, .csky, .arc, .m68k, diff --git a/src/Zcu.zig b/src/Zcu.zig @@ -3594,7 +3594,6 @@ pub fn atomicPtrAlignment( const max_atomic_bits: u16 = switch (target.cpu.arch) { .avr, .msp430, - .spu_2, => 16, .arc, @@ -3620,8 +3619,7 @@ pub fn atomicPtrAlignment( .spirv32, .loongarch32, .xtensa, - .propeller1, - .propeller2, + .propeller, => 32, .amdgcn, @@ -4211,9 +4209,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.builtin.CallingConvention) union(enu => |opts| opts.incoming_stack_alignment == null, .arm_aapcs_vfp, - => |opts| opts.incoming_stack_alignment == null and target.os.tag != .watchos, - .arm_aapcs16_vfp, - => |opts| opts.incoming_stack_alignment == null and target.os.tag == .watchos, + => |opts| opts.incoming_stack_alignment == null, .arm_interrupt, => |opts| opts.incoming_stack_alignment == null, @@ -4241,7 +4237,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.builtin.CallingConvention) union(enu }; }, .stage2_wasm => switch (cc) { - .wasm_watc => |opts| opts.incoming_stack_alignment == null, + .wasm_mvp => |opts| opts.incoming_stack_alignment == null, else => false, }, .stage2_arm => switch (cc) { diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig @@ -1396,7 +1396,7 @@ fn resolveCallingConventionValues( result.local_index += 1; } }, - .wasm_watc => { + .wasm_mvp => { for (fn_info.param_types.get(ip)) |ty| { const ty_classes = abi.classifyType(Type.fromInterned(ty), zcu); for (ty_classes) |class| { @@ -1421,7 +1421,7 @@ pub fn firstParamSRet( switch (cc) { .@"inline" => unreachable, .auto => return isByRef(return_type, zcu, target), - .wasm_watc => { + .wasm_mvp => { const ty_classes = abi.classifyType(return_type, zcu); if (ty_classes[0] == .indirect) return true; if (ty_classes[0] == .direct and ty_classes[1] == .direct) return true; @@ -1434,7 +1434,7 @@ pub fn firstParamSRet( /// Lowers a Zig type and its value based on a given calling convention to ensure /// it matches the ABI. fn lowerArg(cg: *CodeGen, cc: std.builtin.CallingConvention, ty: Type, value: WValue) !void { - if (cc != .wasm_watc) { + if (cc != .wasm_mvp) { return cg.lowerToStack(value); } @@ -2124,7 +2124,7 @@ fn airRet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { // to the stack instead if (cg.return_value != .none) { try cg.store(cg.return_value, operand, ret_ty, 0); - } else if (fn_info.cc == .wasm_watc and ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { + } else if (fn_info.cc == .wasm_mvp and ret_ty.hasRuntimeBitsIgnoreComptime(zcu)) { switch (ret_ty.zigTypeTag(zcu)) { // Aggregate types can be lowered as a singular value .@"struct", .@"union" => { @@ -2268,7 +2268,7 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie } else if (first_param_sret) { break :result_value sret; // TODO: Make this less fragile and optimize - } else if (zcu.typeToFunc(fn_ty).?.cc == .wasm_watc and ret_ty.zigTypeTag(zcu) == .@"struct" or ret_ty.zigTypeTag(zcu) == .@"union") { + } else if (zcu.typeToFunc(fn_ty).?.cc == .wasm_mvp and ret_ty.zigTypeTag(zcu) == .@"struct" or ret_ty.zigTypeTag(zcu) == .@"union") { const result_local = try cg.allocLocal(ret_ty); try cg.addLocal(.local_set, result_local.local.value); const scalar_type = abi.scalarType(ret_ty, zcu); @@ -2546,7 +2546,7 @@ fn airArg(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { const arg = cg.args[arg_index]; const cc = zcu.typeToFunc(zcu.navValue(cg.owner_nav).typeOf(zcu)).?.cc; const arg_ty = cg.typeOfIndex(inst); - if (cc == .wasm_watc) { + if (cc == .wasm_mvp) { const arg_classes = abi.classifyType(arg_ty, zcu); for (arg_classes) |class| { if (class != .none) { @@ -7047,7 +7047,7 @@ fn callIntrinsic( // Always pass over C-ABI - const want_sret_param = firstParamSRet(.{ .wasm_watc = .{} }, return_type, zcu, cg.target); + const want_sret_param = firstParamSRet(.{ .wasm_mvp = .{} }, return_type, zcu, cg.target); // if we want return as first param, we allocate a pointer to stack, // and emit it as our first argument const sret = if (want_sret_param) blk: { @@ -7060,7 +7060,7 @@ fn callIntrinsic( for (args, 0..) |arg, arg_i| { assert(!(want_sret_param and arg == .stack)); assert(Type.fromInterned(param_types[arg_i]).hasRuntimeBitsIgnoreComptime(zcu)); - try cg.lowerArg(.{ .wasm_watc = .{} }, Type.fromInterned(param_types[arg_i]), arg); + try cg.lowerArg(.{ .wasm_mvp = .{} }, Type.fromInterned(param_types[arg_i]), arg); } try cg.addInst(.{ .tag = .call_intrinsic, .data = .{ .intrinsic = intrinsic } }); diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig @@ -90078,7 +90078,7 @@ fn floatCompilerRtAbiName(float_bits: u32) u8 { fn floatCompilerRtAbiType(self: *CodeGen, ty: Type, other_ty: Type) Type { if (ty.toIntern() == .f16_type and (other_ty.toIntern() == .f32_type or other_ty.toIntern() == .f64_type) and - self.target.isDarwin()) return .u16; + self.target.os.tag.isDarwin()) return .u16; return ty; } diff --git a/src/codegen/c.zig b/src/codegen/c.zig @@ -7725,7 +7725,7 @@ fn toCallingConvention(cc: std.builtin.CallingConvention, zcu: *Zcu) ?[]const u8 .aarch64_vfabi_sve => "aarch64_sve_pcs", .arm_aapcs => "pcs(\"aapcs\")", - .arm_aapcs_vfp, .arm_aapcs16_vfp => "pcs(\"aapcs-vfp\")", + .arm_aapcs_vfp => "pcs(\"aapcs-vfp\")", .arm_interrupt => |opts| switch (opts.type) { .generic => "interrupt", diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig @@ -98,9 +98,7 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 { .ve => "ve", .kalimba, - .spu_2, - .propeller1, - .propeller2, + .propeller, => unreachable, // Gated by hasLlvmSupport(). }; @@ -1303,7 +1301,7 @@ pub const Object = struct { .large => .Large, }; - const float_abi: llvm.TargetMachine.FloatABI = if (comp.root_mod.resolved_target.result.floatAbi() == .hard) + const float_abi: llvm.TargetMachine.FloatABI = if (comp.root_mod.resolved_target.result.abi.float() == .hard) .Hard else .Soft; @@ -2941,7 +2939,7 @@ pub const Object = struct { function_index.setLinkage(.internal, &o.builder); function_index.setUnnamedAddr(.unnamed_addr, &o.builder); } else { - if (target.isWasm()) { + if (target.cpu.arch.isWasm()) { try attributes.addFnAttr(.{ .string = .{ .kind = try o.builder.string("wasm-import-name"), .value = try o.builder.string(nav.name.toSlice(ip)), @@ -3158,7 +3156,7 @@ pub const Object = struct { .value = try o.builder.string(std.mem.span(s)), } }, &o.builder); } - if (target.floatAbi() == .soft) { + if (target.abi.float() == .soft) { // `use-soft-float` means "use software routines for floating point computations". In // other words, it configures how LLVM lowers basic float instructions like `fcmp`, // `fadd`, etc. The float calling convention is configured on `TargetMachine` and is @@ -4832,7 +4830,7 @@ pub const NavGen = struct { const global_index = o.nav_map.get(nav_index).?; const decl_name = decl_name: { - if (zcu.getTarget().isWasm() and ty.zigTypeTag(zcu) == .@"fn") { + if (zcu.getTarget().cpu.arch.isWasm() and ty.zigTypeTag(zcu) == .@"fn") { if (lib_name.toSlice(ip)) |lib_name_slice| { if (!std.mem.eql(u8, lib_name_slice, "c")) { break :decl_name try o.builder.strtabStringFmt("{}|{s}", .{ nav.name.fmt(ip), lib_name_slice }); @@ -6569,7 +6567,7 @@ pub const FuncGen = struct { // Workaround for: // * https://github.com/llvm/llvm-project/blob/56905dab7da50bccfcceaeb496b206ff476127e1/llvm/lib/MC/WasmObjectWriter.cpp#L560 // * https://github.com/llvm/llvm-project/blob/56905dab7da50bccfcceaeb496b206ff476127e1/llvm/test/MC/WebAssembly/blockaddress.ll - if (zcu.comp.getTarget().isWasm()) break :jmp_table null; + if (zcu.comp.getTarget().cpu.arch.isWasm()) break :jmp_table null; // On a 64-bit target, 1024 pointers in our jump table is about 8K of pointers. This seems just // about acceptable - it won't fill L1d cache on most CPUs. @@ -10026,7 +10024,7 @@ pub const FuncGen = struct { // of the length. This means we need to emit a check where we skip the memset when the length // is 0 as we allow for undefined pointers in 0-sized slices. // This logic can be removed once https://github.com/ziglang/zig/issues/16360 is done. - const intrinsic_len0_traps = o.target.isWasm() and + const intrinsic_len0_traps = o.target.cpu.arch.isWasm() and ptr_ty.isSlice(zcu) and std.Target.wasm.featureSetHas(o.target.cpu.features, .bulk_memory); @@ -10183,7 +10181,7 @@ pub const FuncGen = struct { // For this reason we must add a check for 0-sized slices as its pointer field can be undefined. // We only have to do this for slices as arrays will have a valid pointer. // This logic can be removed once https://github.com/ziglang/zig/issues/16360 is done. - if (o.target.isWasm() and + if (o.target.cpu.arch.isWasm() and std.Target.wasm.featureSetHas(o.target.cpu.features, .bulk_memory) and dest_ptr_ty.isSlice(zcu)) { @@ -11768,16 +11766,8 @@ fn toLlvmCallConvTag(cc_tag: std.builtin.CallingConvention.Tag, target: std.Targ .x86_interrupt => .x86_intrcc, .aarch64_vfabi => .aarch64_vector_pcs, .aarch64_vfabi_sve => .aarch64_sve_vector_pcs, - .arm_apcs => .arm_apcscc, .arm_aapcs => .arm_aapcscc, - .arm_aapcs_vfp => if (target.os.tag != .watchos) - .arm_aapcs_vfpcc - else - null, - .arm_aapcs16_vfp => if (target.os.tag == .watchos) - .arm_aapcs_vfpcc - else - null, + .arm_aapcs_vfp => .arm_aapcs_vfpcc, .riscv64_lp64_v => .riscv_vectorcallcc, .riscv32_ilp32_v => .riscv_vectorcallcc, .avr_builtin => .avr_builtincc, @@ -11821,7 +11811,7 @@ fn toLlvmCallConvTag(cc_tag: std.builtin.CallingConvention.Tag, target: std.Targ .powerpc_sysv_altivec, .powerpc_aix, .powerpc_aix_altivec, - .wasm_watc, + .wasm_mvp, .arc_sysv, .avr_gnu, .bpf_std, @@ -11834,8 +11824,7 @@ fn toLlvmCallConvTag(cc_tag: std.builtin.CallingConvention.Tag, target: std.Targ .m68k_sysv, .m68k_gnu, .msp430_eabi, - .propeller1_sysv, - .propeller2_sysv, + .propeller_sysv, .s390x_sysv, .s390x_sysv_vx, .ve_sysv, @@ -11999,12 +11988,12 @@ fn firstParamSRet(fn_info: InternPool.Key.FuncType, zcu: *Zcu, target: std.Targe .x86_64_win => x86_64_abi.classifyWindows(return_type, zcu) == .memory, .x86_sysv, .x86_win => isByRef(return_type, zcu), .x86_stdcall => !isScalar(zcu, return_type), - .wasm_watc => wasm_c_abi.classifyType(return_type, zcu)[0] == .indirect, + .wasm_mvp => wasm_c_abi.classifyType(return_type, zcu)[0] == .indirect, .aarch64_aapcs, .aarch64_aapcs_darwin, .aarch64_aapcs_win, => aarch64_c_abi.classifyType(return_type, zcu) == .memory, - .arm_aapcs, .arm_aapcs_vfp, .arm_aapcs16_vfp => switch (arm_c_abi.classifyType(return_type, zcu, .ret)) { + .arm_aapcs, .arm_aapcs_vfp => switch (arm_c_abi.classifyType(return_type, zcu, .ret)) { .memory, .i64_array => true, .i32_array => |size| size != 1, .byval => false, @@ -12054,7 +12043,7 @@ fn lowerFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!Bu .integer => return o.builder.intType(@intCast(return_type.bitSize(zcu))), .double_integer => return o.builder.arrayType(2, .i64), }, - .arm_aapcs, .arm_aapcs_vfp, .arm_aapcs16_vfp => switch (arm_c_abi.classifyType(return_type, zcu, .ret)) { + .arm_aapcs, .arm_aapcs_vfp => switch (arm_c_abi.classifyType(return_type, zcu, .ret)) { .memory, .i64_array => return .void, .i32_array => |len| return if (len == 1) .i32 else .void, .byval => return o.lowerType(return_type), @@ -12084,7 +12073,7 @@ fn lowerFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!Bu return o.builder.structType(.normal, types[0..types_len]); }, }, - .wasm_watc => { + .wasm_mvp => { if (isScalar(zcu, return_type)) { return o.lowerType(return_type); } @@ -12303,7 +12292,7 @@ const ParamTypeIterator = struct { .double_integer => return Lowering{ .i64_array = 2 }, } }, - .arm_aapcs, .arm_aapcs_vfp, .arm_aapcs16_vfp => { + .arm_aapcs, .arm_aapcs_vfp => { it.zig_index += 1; it.llvm_index += 1; switch (arm_c_abi.classifyType(ty, zcu, .arg)) { @@ -12349,7 +12338,7 @@ const ParamTypeIterator = struct { }, } }, - .wasm_watc => { + .wasm_mvp => { it.zig_index += 1; it.llvm_index += 1; if (isScalar(zcu, ty)) { @@ -12707,7 +12696,7 @@ fn backendSupportsF16(target: std.Target) bool { .armeb, .thumb, .thumbeb, - => target.floatAbi() == .soft or std.Target.arm.featureSetHas(target.cpu.features, .fp_armv8), + => target.abi.float() == .soft or std.Target.arm.featureSetHas(target.cpu.features, .fp_armv8), .aarch64, .aarch64_be, => std.Target.aarch64.featureSetHas(target.cpu.features, .fp_armv8), @@ -12734,7 +12723,7 @@ fn backendSupportsF128(target: std.Target) bool { .armeb, .thumb, .thumbeb, - => target.floatAbi() == .soft or std.Target.arm.featureSetHas(target.cpu.features, .fp_armv8), + => target.abi.float() == .soft or std.Target.arm.featureSetHas(target.cpu.features, .fp_armv8), .aarch64, .aarch64_be, => std.Target.aarch64.featureSetHas(target.cpu.features, .fp_armv8), @@ -13024,9 +13013,7 @@ pub fn initializeLLVMTarget(arch: std.Target.Cpu.Arch) void { // LLVM does does not have a backend for these. .kalimba, - .spu_2, - .propeller1, - .propeller2, + .propeller, => unreachable, } } diff --git a/src/glibc.zig b/src/glibc.zig @@ -469,7 +469,7 @@ fn add_include_dirs(comp: *Compilation, arena: Allocator, args: *std.ArrayList([ try args.append("-I"); try args.append(try lib_path(comp, arena, lib_libc ++ "include" ++ s ++ "generic-glibc")); - const arch_name = target.osArchName(); + const arch_name = std.zig.target.osArchName(target); try args.append("-I"); try args.append(try std.fmt.allocPrint(arena, "{s}" ++ s ++ "libc" ++ s ++ "include" ++ s ++ "{s}-linux-any", .{ comp.zig_lib_directory.path.?, arch_name, diff --git a/src/libtsan.zig b/src/libtsan.zig @@ -36,7 +36,7 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo .watchos => if (target.abi == .simulator) "clang_rt.tsan_watchossim_dynamic" else "clang_rt.tsan_watchos_dynamic", else => "tsan", }; - const link_mode: std.builtin.LinkMode = if (target.isDarwin()) .dynamic else .static; + const link_mode: std.builtin.LinkMode = if (target.os.tag.isDarwin()) .dynamic else .static; const output_mode = .Lib; const basename = try std.zig.binNameAlloc(arena, .{ .root_name = root_name, @@ -52,9 +52,9 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo const optimize_mode = comp.compilerRtOptMode(); const strip = comp.compilerRtStrip(); - const link_libcpp = target.isDarwin(); const unwind_tables: std.builtin.UnwindTables = if (target.cpu.arch == .x86 and target.os.tag == .windows) .none else .@"async"; + const link_libcpp = target.os.tag.isDarwin(); const config = Compilation.Config.resolve(.{ .output_mode = output_mode, @@ -276,14 +276,14 @@ pub fn buildTsan(comp: *Compilation, prog_node: std.Progress.Node) BuildError!vo }); } - const skip_linker_dependencies = !target.isDarwin(); - const linker_allow_shlib_undefined = target.isDarwin(); - const install_name = if (target.isDarwin()) + const skip_linker_dependencies = !target.os.tag.isDarwin(); + const linker_allow_shlib_undefined = target.os.tag.isDarwin(); + const install_name = if (target.os.tag.isDarwin()) try std.fmt.allocPrintZ(arena, "@rpath/{s}", .{basename}) else null; // Workaround for https://github.com/llvm/llvm-project/issues/97627 - const headerpad_size: ?u32 = if (target.isDarwin()) 32 else null; + const headerpad_size: ?u32 = if (target.os.tag.isDarwin()) 32 else null; const sub_compilation = Compilation.create(comp.gpa, arena, .{ .local_cache_directory = comp.global_cache_directory, .global_cache_directory = comp.global_cache_directory, diff --git a/src/libunwind.zig b/src/libunwind.zig @@ -136,7 +136,7 @@ pub fn buildStaticLib(comp: *Compilation, prog_node: std.Progress.Node) BuildErr if (!comp.config.any_non_single_threaded) { try cflags.append("-D_LIBUNWIND_HAS_NO_THREADS"); } - if (target.cpu.arch.isArm() and target.abi.floatAbi() == .hard) { + if (target.cpu.arch.isArm() and target.abi.float() == .hard) { try cflags.append("-DCOMPILER_RT_ARMHF_TARGET"); } try cflags.append("-Wno-bitwise-conditional-parentheses"); diff --git a/src/link.zig b/src/link.zig @@ -2067,7 +2067,7 @@ fn resolveLibInput( const lib_name = name_query.name; - if (target.isDarwin() and link_mode == .dynamic) tbd: { + if (target.os.tag.isDarwin() and link_mode == .dynamic) tbd: { // Prefer .tbd over .dylib. const test_path: Path = .{ .root_dir = lib_directory, @@ -2104,7 +2104,7 @@ fn resolveLibInput( // In the case of Darwin, the main check will be .dylib, so here we // additionally check for .so files. - if (target.isDarwin() and link_mode == .dynamic) so: { + if (target.os.tag.isDarwin() and link_mode == .dynamic) so: { const test_path: Path = .{ .root_dir = lib_directory, .sub_path = try std.fmt.allocPrint(arena, "lib{s}.so", .{lib_name}), diff --git a/src/link/Coff.zig b/src/link/Coff.zig @@ -1881,7 +1881,7 @@ fn linkWithLLD(coff: *Coff, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: try argv.append(try allocPrint(arena, "-MLLVM:-target-abi={s}", .{mabi})); } - try argv.append(try allocPrint(arena, "-MLLVM:-float-abi={s}", .{if (target.abi.floatAbi() == .hard) "hard" else "soft"})); + try argv.append(try allocPrint(arena, "-MLLVM:-float-abi={s}", .{if (target.abi.float() == .hard) "hard" else "soft"})); if (comp.config.lto != .none) { switch (optimize_mode) { diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig @@ -3538,11 +3538,8 @@ fn updateLazyType( .aarch64_vfabi => .LLVM_AAPCS, .aarch64_vfabi_sve => .LLVM_AAPCS, - .arm_apcs => .normal, .arm_aapcs => .LLVM_AAPCS, - .arm_aapcs_vfp, - .arm_aapcs16_vfp, - => .LLVM_AAPCS_VFP, + .arm_aapcs_vfp => .LLVM_AAPCS_VFP, .riscv64_lp64_v, .riscv32_ilp32_v, diff --git a/src/link/Elf.zig b/src/link/Elf.zig @@ -1709,7 +1709,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s try argv.appendSlice(&.{ "-mllvm", - try std.fmt.allocPrint(arena, "-float-abi={s}", .{if (target.abi.floatAbi() == .hard) "hard" else "soft"}), + try std.fmt.allocPrint(arena, "-float-abi={s}", .{if (target.abi.float() == .hard) "hard" else "soft"}), }); if (comp.config.lto != .none) { @@ -2053,7 +2053,7 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s try argv.append(lib_path); } try argv.append(try comp.crtFileAsString(arena, "libc_nonshared.a")); - } else if (target.isMusl()) { + } else if (target.abi.isMusl()) { try argv.append(try comp.crtFileAsString(arena, switch (link_mode) { .static => "libc.a", .dynamic => "libc.so", diff --git a/src/link/MachO.zig b/src/link/MachO.zig @@ -3548,7 +3548,7 @@ pub fn getTarget(self: MachO) std.Target { pub fn invalidateKernelCache(dir: fs.Dir, sub_path: []const u8) !void { const tracy = trace(@src()); defer tracy.end(); - if (builtin.target.isDarwin() and builtin.target.cpu.arch == .aarch64) { + if (builtin.target.os.tag.isDarwin() and builtin.target.cpu.arch == .aarch64) { try dir.copyFile(sub_path, dir, sub_path, .{}); } } diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig @@ -4600,7 +4600,7 @@ fn convertZcuFnType( if (CodeGen.firstParamSRet(cc, return_type, zcu, target)) { try params_buffer.append(gpa, .i32); // memory address is always a 32-bit handle } else if (return_type.hasRuntimeBitsIgnoreComptime(zcu)) { - if (cc == .wasm_watc) { + if (cc == .wasm_mvp) { const res_classes = abi.classifyType(return_type, zcu); assert(res_classes[0] == .direct and res_classes[1] == .none); const scalar_type = abi.scalarType(return_type, zcu); @@ -4618,7 +4618,7 @@ fn convertZcuFnType( if (!param_type.hasRuntimeBitsIgnoreComptime(zcu)) continue; switch (cc) { - .wasm_watc => { + .wasm_mvp => { const param_classes = abi.classifyType(param_type, zcu); if (param_classes[1] == .none) { if (param_classes[0] == .direct) { diff --git a/src/main.zig b/src/main.zig @@ -3983,7 +3983,7 @@ fn createModule( } create_module.lib_dir_args = undefined; // From here we use lib_directories instead. - if (resolved_target.is_native_os and target.isDarwin()) { + if (resolved_target.is_native_os and target.os.tag.isDarwin()) { // If we want to link against frameworks, we need system headers. if (create_module.frameworks.count() > 0) create_module.want_native_include_dirs = true; diff --git a/src/target.zig b/src/target.zig @@ -12,7 +12,7 @@ pub const default_stack_protector_buffer_size = 4; pub fn cannotDynamicLink(target: std.Target) bool { return switch (target.os.tag) { .freestanding => true, - else => target.isSpirV(), + else => target.cpu.arch.isSpirV(), }; } @@ -40,12 +40,12 @@ pub fn libcNeedsLibUnwind(target: std.Target) bool { } pub fn requiresPIE(target: std.Target) bool { - return target.isAndroid() or target.isDarwin() or target.os.tag == .openbsd; + return target.abi.isAndroid() or target.os.tag.isDarwin() or target.os.tag == .openbsd; } /// This function returns whether non-pic code is completely invalid on the given target. pub fn requiresPIC(target: std.Target, linking_libc: bool) bool { - return target.isAndroid() or + return target.abi.isAndroid() or target.os.tag == .windows or target.os.tag == .uefi or osRequiresLibC(target) or (linking_libc and target.isGnuLibC()); @@ -195,9 +195,7 @@ pub fn hasLlvmSupport(target: std.Target, ofmt: std.Target.ObjectFormat) bool { // No LLVM backend exists. .kalimba, - .spu_2, - .propeller1, - .propeller2, + .propeller, => false, }; } @@ -247,7 +245,7 @@ pub fn clangSupportsStackProtector(target: std.Target) bool { } pub fn libcProvidesStackProtector(target: std.Target) bool { - return !target.isMinGW() and target.os.tag != .wasi and !target.isSpirV(); + return !target.isMinGW() and target.os.tag != .wasi and !target.cpu.arch.isSpirV(); } pub fn supportsReturnAddress(target: std.Target) bool { @@ -444,12 +442,11 @@ pub fn addrSpaceCastIsValid( from: AddressSpace, to: AddressSpace, ) bool { - const arch = target.cpu.arch; - switch (arch) { - .x86_64, .x86 => return arch.supportsAddressSpace(from) and arch.supportsAddressSpace(to), + switch (target.cpu.arch) { + .x86_64, .x86 => return target.cpu.supportsAddressSpace(from, null) and target.cpu.supportsAddressSpace(to, null), .nvptx64, .nvptx, .amdgcn => { - const to_generic = arch.supportsAddressSpace(from) and to == .generic; - const from_generic = arch.supportsAddressSpace(to) and from == .generic; + const to_generic = target.cpu.supportsAddressSpace(from, null) and to == .generic; + const from_generic = target.cpu.supportsAddressSpace(to, null) and from == .generic; return to_generic or from_generic; }, else => return from == .generic and to == .generic, diff --git a/stage1/zig.h b/stage1/zig.h @@ -9,6 +9,7 @@ #define zig_clang #define zig_gnuc #elif defined(__GNUC__) +#define zig_gcc #define zig_gnuc #elif defined(__IBMC__) #define zig_xlc @@ -171,7 +172,7 @@ #define zig_callconv(c) __attribute__((c)) #endif -#if zig_has_attribute(naked) || defined(zig_gnuc) +#if zig_has_attribute(naked) || defined(zig_gcc) #define zig_naked_decl __attribute__((naked)) #define zig_naked __attribute__((naked)) #elif defined(zig_msvc) @@ -265,7 +266,7 @@ #define zig_linksection_fn zig_linksection #endif -#if zig_has_builtin(unreachable) || defined(zig_gnuc) || defined(zig_tinyc) +#if zig_has_builtin(unreachable) || defined(zig_gcc) || defined(zig_tinyc) #define zig_unreachable() __builtin_unreachable() #elif defined(zig_msvc) #define zig_unreachable() __assume(0) @@ -293,11 +294,11 @@ #endif /* zig_macho */ #endif /* zig_msvc */ -#if (zig_has_attribute(alias) || defined(zig_tinyc)) && !defined(zig_macho) -#define zig_export(symbol, name) __attribute__((alias(symbol))) -#elif defined(zig_msvc) +#if defined(zig_msvc) #define zig_export(symbol, name) ; \ __pragma(comment(linker, "/alternatename:" zig_mangle_c(name) "=" zig_mangle_c(symbol))) +#elif (zig_has_attribute(alias) || defined(zig_tinyc)) && !defined(zig_macho) +#define zig_export(symbol, name) __attribute__((alias(symbol))) #else #define zig_export(symbol, name) ; \ __asm(zig_mangle_c(name) " = " zig_mangle_c(symbol)) @@ -321,7 +322,7 @@ #if defined(zig_msvc) #define zig_import(Type, fn_name, libc_name, sig_args, call_args) zig_extern Type fn_name sig_args;\ __pragma(comment(linker, "/alternatename:" zig_mangle_c(#fn_name) "=" zig_mangle_c(#libc_name))); -#define zig_import_builtin(Type, fn_name, libc_name, sig_args, call_args) zig_import(Type, fn_name, sig_args, call_args) +#define zig_import_builtin(Type, fn_name, libc_name, sig_args, call_args) zig_import(Type, fn_name, libc_name, sig_args, call_args) #else /* zig_msvc */ #define zig_import(Type, fn_name, libc_name, sig_args, call_args) zig_extern Type fn_name sig_args __asm(zig_mangle_c(#libc_name)); #define zig_import_builtin(Type, fn_name, libc_name, sig_args, call_args) zig_extern Type libc_name sig_args; \ @@ -331,7 +332,7 @@ #define zig_expand_import_0(Type, fn_name, libc_name, sig_args, call_args) zig_import(Type, fn_name, libc_name, sig_args, call_args) #define zig_expand_import_1(Type, fn_name, libc_name, sig_args, call_args) zig_import_builtin(Type, fn_name, libc_name, sig_args, call_args) -#if zig_has_attribute(weak) || defined(zig_gnuc) || defined(zig_tinyc) +#if zig_has_attribute(weak) || defined(zig_gcc) || defined(zig_tinyc) #define zig_weak_linkage __attribute__((weak)) #define zig_weak_linkage_fn __attribute__((weak)) #elif defined(zig_msvc) @@ -418,7 +419,7 @@ #define zig_breakpoint() zig_breakpoint_unavailable #endif -#if zig_has_builtin(return_address) || defined(zig_gnuc) || defined(zig_tinyc) +#if zig_has_builtin(return_address) || defined(zig_gcc) || defined(zig_tinyc) #define zig_return_address() __builtin_extract_return_addr(__builtin_return_address(0)) #elif defined(zig_msvc) #define zig_return_address() _ReturnAddress() @@ -426,7 +427,7 @@ #define zig_return_address() 0 #endif -#if zig_has_builtin(frame_address) || defined(zig_gnuc) || defined(zig_tinyc) +#if zig_has_builtin(frame_address) || defined(zig_gcc) || defined(zig_tinyc) #define zig_frame_address() __builtin_frame_address(0) #elif defined(zig_msvc) #define zig_frame_address() _AddressOfReturnAddress() @@ -434,7 +435,7 @@ #define zig_frame_address() 0 #endif -#if zig_has_builtin(prefetch) || defined(zig_gnuc) +#if zig_has_builtin(prefetch) || defined(zig_gcc) #define zig_prefetch(addr, rw, locality) __builtin_prefetch(addr, rw, locality) #else #define zig_prefetch(addr, rw, locality) @@ -452,7 +453,7 @@ #define zig_noreturn [[noreturn]] #elif __STDC_VERSION__ >= 201112L #define zig_noreturn _Noreturn -#elif zig_has_attribute(noreturn) || defined(zig_gnuc) || defined(zig_tinyc) +#elif zig_has_attribute(noreturn) || defined(zig_gcc) || defined(zig_tinyc) #define zig_noreturn __attribute__((noreturn)) #elif defined(zig_msvc) #define zig_noreturn __declspec(noreturn) @@ -650,7 +651,7 @@ typedef ptrdiff_t intptr_t; zig_operator(Type, Type, operation, operator) #define zig_shift_operator(Type, operation, operator) \ zig_operator(Type, uint8_t, operation, operator) -#define zig_int_helpers(w) \ +#define zig_int_helpers(w, PromotedUnsigned) \ zig_basic_operator(uint##w##_t, and_u##w, &) \ zig_basic_operator( int##w##_t, and_i##w, &) \ zig_basic_operator(uint##w##_t, or_u##w, |) \ @@ -726,19 +727,51 @@ typedef ptrdiff_t intptr_t; } \ \ static inline uint##w##_t zig_mulw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ - return zig_wrap_u##w(lhs * rhs, bits); \ + return zig_wrap_u##w((PromotedUnsigned)lhs * rhs, bits); \ } \ \ static inline int##w##_t zig_mulw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \ return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs * (uint##w##_t)rhs), bits); \ } -zig_int_helpers(8) -zig_int_helpers(16) -zig_int_helpers(32) -zig_int_helpers(64) +#if UINT8_MAX <= UINT_MAX +zig_int_helpers(8, unsigned int) +#elif UINT8_MAX <= ULONG_MAX +zig_int_helpers(8, unsigned long) +#elif UINT8_MAX <= ULLONG_MAX +zig_int_helpers(8, unsigned long long) +#else +zig_int_helpers(8, uint8_t) +#endif +#if UINT16_MAX <= UINT_MAX +zig_int_helpers(16, unsigned int) +#elif UINT16_MAX <= ULONG_MAX +zig_int_helpers(16, unsigned long) +#elif UINT16_MAX <= ULLONG_MAX +zig_int_helpers(16, unsigned long long) +#else +zig_int_helpers(16, uint16_t) +#endif +#if UINT32_MAX <= UINT_MAX +zig_int_helpers(32, unsigned int) +#elif UINT32_MAX <= ULONG_MAX +zig_int_helpers(32, unsigned long) +#elif UINT32_MAX <= ULLONG_MAX +zig_int_helpers(32, unsigned long long) +#else +zig_int_helpers(32, uint32_t) +#endif +#if UINT64_MAX <= UINT_MAX +zig_int_helpers(64, unsigned int) +#elif UINT64_MAX <= ULONG_MAX +zig_int_helpers(64, unsigned long) +#elif UINT64_MAX <= ULLONG_MAX +zig_int_helpers(64, unsigned long long) +#else +zig_int_helpers(64, uint64_t) +#endif static inline bool zig_addo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) { -#if zig_has_builtin(add_overflow) || defined(zig_gnuc) +#if zig_has_builtin(add_overflow) || defined(zig_gcc) uint32_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); *res = zig_wrap_u32(full_res, bits); @@ -751,7 +784,7 @@ static inline bool zig_addo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8 zig_extern int32_t __addosi4(int32_t lhs, int32_t rhs, int *overflow); static inline bool zig_addo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) { -#if zig_has_builtin(add_overflow) || defined(zig_gnuc) +#if zig_has_builtin(add_overflow) || defined(zig_gcc) int32_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); #else @@ -764,7 +797,7 @@ static inline bool zig_addo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t } static inline bool zig_addo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) { -#if zig_has_builtin(add_overflow) || defined(zig_gnuc) +#if zig_has_builtin(add_overflow) || defined(zig_gcc) uint64_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); *res = zig_wrap_u64(full_res, bits); @@ -777,7 +810,7 @@ static inline bool zig_addo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8 zig_extern int64_t __addodi4(int64_t lhs, int64_t rhs, int *overflow); static inline bool zig_addo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) { -#if zig_has_builtin(add_overflow) || defined(zig_gnuc) +#if zig_has_builtin(add_overflow) || defined(zig_gcc) int64_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); #else @@ -790,7 +823,7 @@ static inline bool zig_addo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t } static inline bool zig_addo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) { -#if zig_has_builtin(add_overflow) || defined(zig_gnuc) +#if zig_has_builtin(add_overflow) || defined(zig_gcc) uint8_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); *res = zig_wrap_u8(full_res, bits); @@ -804,7 +837,7 @@ static inline bool zig_addo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t b } static inline bool zig_addo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits) { -#if zig_has_builtin(add_overflow) || defined(zig_gnuc) +#if zig_has_builtin(add_overflow) || defined(zig_gcc) int8_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); *res = zig_wrap_i8(full_res, bits); @@ -818,7 +851,7 @@ static inline bool zig_addo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits } static inline bool zig_addo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8_t bits) { -#if zig_has_builtin(add_overflow) || defined(zig_gnuc) +#if zig_has_builtin(add_overflow) || defined(zig_gcc) uint16_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); *res = zig_wrap_u16(full_res, bits); @@ -832,7 +865,7 @@ static inline bool zig_addo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8 } static inline bool zig_addo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t bits) { -#if zig_has_builtin(add_overflow) || defined(zig_gnuc) +#if zig_has_builtin(add_overflow) || defined(zig_gcc) int16_t full_res; bool overflow = __builtin_add_overflow(lhs, rhs, &full_res); *res = zig_wrap_i16(full_res, bits); @@ -846,7 +879,7 @@ static inline bool zig_addo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t } static inline bool zig_subo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) { -#if zig_has_builtin(sub_overflow) || defined(zig_gnuc) +#if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint32_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); *res = zig_wrap_u32(full_res, bits); @@ -859,7 +892,7 @@ static inline bool zig_subo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8 zig_extern int32_t __subosi4(int32_t lhs, int32_t rhs, int *overflow); static inline bool zig_subo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) { -#if zig_has_builtin(sub_overflow) || defined(zig_gnuc) +#if zig_has_builtin(sub_overflow) || defined(zig_gcc) int32_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); #else @@ -872,7 +905,7 @@ static inline bool zig_subo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t } static inline bool zig_subo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) { -#if zig_has_builtin(sub_overflow) || defined(zig_gnuc) +#if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint64_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); *res = zig_wrap_u64(full_res, bits); @@ -885,7 +918,7 @@ static inline bool zig_subo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8 zig_extern int64_t __subodi4(int64_t lhs, int64_t rhs, int *overflow); static inline bool zig_subo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) { -#if zig_has_builtin(sub_overflow) || defined(zig_gnuc) +#if zig_has_builtin(sub_overflow) || defined(zig_gcc) int64_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); #else @@ -898,7 +931,7 @@ static inline bool zig_subo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t } static inline bool zig_subo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) { -#if zig_has_builtin(sub_overflow) || defined(zig_gnuc) +#if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint8_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); *res = zig_wrap_u8(full_res, bits); @@ -912,7 +945,7 @@ static inline bool zig_subo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t b } static inline bool zig_subo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits) { -#if zig_has_builtin(sub_overflow) || defined(zig_gnuc) +#if zig_has_builtin(sub_overflow) || defined(zig_gcc) int8_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); *res = zig_wrap_i8(full_res, bits); @@ -926,7 +959,7 @@ static inline bool zig_subo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits } static inline bool zig_subo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8_t bits) { -#if zig_has_builtin(sub_overflow) || defined(zig_gnuc) +#if zig_has_builtin(sub_overflow) || defined(zig_gcc) uint16_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); *res = zig_wrap_u16(full_res, bits); @@ -940,7 +973,7 @@ static inline bool zig_subo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8 } static inline bool zig_subo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t bits) { -#if zig_has_builtin(sub_overflow) || defined(zig_gnuc) +#if zig_has_builtin(sub_overflow) || defined(zig_gcc) int16_t full_res; bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res); *res = zig_wrap_i16(full_res, bits); @@ -954,7 +987,7 @@ static inline bool zig_subo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t } static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) { -#if zig_has_builtin(mul_overflow) || defined(zig_gnuc) +#if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint32_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); *res = zig_wrap_u32(full_res, bits); @@ -967,7 +1000,7 @@ static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8 zig_extern int32_t __mulosi4(int32_t lhs, int32_t rhs, int *overflow); static inline bool zig_mulo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) { -#if zig_has_builtin(mul_overflow) || defined(zig_gnuc) +#if zig_has_builtin(mul_overflow) || defined(zig_gcc) int32_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); #else @@ -980,7 +1013,7 @@ static inline bool zig_mulo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t } static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) { -#if zig_has_builtin(mul_overflow) || defined(zig_gnuc) +#if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint64_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); *res = zig_wrap_u64(full_res, bits); @@ -993,7 +1026,7 @@ static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8 zig_extern int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow); static inline bool zig_mulo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) { -#if zig_has_builtin(mul_overflow) || defined(zig_gnuc) +#if zig_has_builtin(mul_overflow) || defined(zig_gcc) int64_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); #else @@ -1006,7 +1039,7 @@ static inline bool zig_mulo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t } static inline bool zig_mulo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) { -#if zig_has_builtin(mul_overflow) || defined(zig_gnuc) +#if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint8_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); *res = zig_wrap_u8(full_res, bits); @@ -1020,7 +1053,7 @@ static inline bool zig_mulo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t b } static inline bool zig_mulo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits) { -#if zig_has_builtin(mul_overflow) || defined(zig_gnuc) +#if zig_has_builtin(mul_overflow) || defined(zig_gcc) int8_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); *res = zig_wrap_i8(full_res, bits); @@ -1034,7 +1067,7 @@ static inline bool zig_mulo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits } static inline bool zig_mulo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8_t bits) { -#if zig_has_builtin(mul_overflow) || defined(zig_gnuc) +#if zig_has_builtin(mul_overflow) || defined(zig_gcc) uint16_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); *res = zig_wrap_u16(full_res, bits); @@ -1048,7 +1081,7 @@ static inline bool zig_mulo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8 } static inline bool zig_mulo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t bits) { -#if zig_has_builtin(mul_overflow) || defined(zig_gnuc) +#if zig_has_builtin(mul_overflow) || defined(zig_gcc) int16_t full_res; bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res); *res = zig_wrap_i16(full_res, bits); @@ -1157,7 +1190,7 @@ static inline int8_t zig_byte_swap_i8(int8_t val, uint8_t bits) { static inline uint16_t zig_byte_swap_u16(uint16_t val, uint8_t bits) { uint16_t full_res; -#if zig_has_builtin(bswap16) || defined(zig_gnuc) +#if zig_has_builtin(bswap16) || defined(zig_gcc) full_res = __builtin_bswap16(val); #else full_res = (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 0), 8) << 8 | @@ -1172,7 +1205,7 @@ static inline int16_t zig_byte_swap_i16(int16_t val, uint8_t bits) { static inline uint32_t zig_byte_swap_u32(uint32_t val, uint8_t bits) { uint32_t full_res; -#if zig_has_builtin(bswap32) || defined(zig_gnuc) +#if zig_has_builtin(bswap32) || defined(zig_gcc) full_res = __builtin_bswap32(val); #else full_res = (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 0), 16) << 16 | @@ -1187,7 +1220,7 @@ static inline int32_t zig_byte_swap_i32(int32_t val, uint8_t bits) { static inline uint64_t zig_byte_swap_u64(uint64_t val, uint8_t bits) { uint64_t full_res; -#if zig_has_builtin(bswap64) || defined(zig_gnuc) +#if zig_has_builtin(bswap64) || defined(zig_gcc) full_res = __builtin_bswap64(val); #else full_res = (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 0), 32) << 32 | @@ -1267,7 +1300,7 @@ static inline int64_t zig_bit_reverse_i64(int64_t val, uint8_t bits) { static inline uint8_t zig_popcount_i##w(int##w##_t val, uint8_t bits) { \ return zig_popcount_u##w((uint##w##_t)val, bits); \ } -#if zig_has_builtin(popcount) || defined(zig_gnuc) || defined(zig_tinyc) +#if zig_has_builtin(popcount) || defined(zig_gcc) || defined(zig_tinyc) #define zig_builtin_popcount(w) \ static inline uint8_t zig_popcount_u##w(uint##w##_t val, uint8_t bits) { \ (void)bits; \ @@ -1296,7 +1329,7 @@ zig_builtin_popcount(64) static inline uint8_t zig_ctz_i##w(int##w##_t val, uint8_t bits) { \ return zig_ctz_u##w((uint##w##_t)val, bits); \ } -#if zig_has_builtin(ctz) || defined(zig_gnuc) || defined(zig_tinyc) +#if zig_has_builtin(ctz) || defined(zig_gcc) || defined(zig_tinyc) #define zig_builtin_ctz(w) \ static inline uint8_t zig_ctz_u##w(uint##w##_t val, uint8_t bits) { \ if (val == 0) return bits; \ @@ -1321,7 +1354,7 @@ zig_builtin_ctz(64) static inline uint8_t zig_clz_i##w(int##w##_t val, uint8_t bits) { \ return zig_clz_u##w((uint##w##_t)val, bits); \ } -#if zig_has_builtin(clz) || defined(zig_gnuc) || defined(zig_tinyc) +#if zig_has_builtin(clz) || defined(zig_gcc) || defined(zig_tinyc) #define zig_builtin_clz(w) \ static inline uint8_t zig_clz_u##w(uint##w##_t val, uint8_t bits) { \ if (val == 0) return bits; \ @@ -3176,7 +3209,7 @@ long double __cdecl nanl(char const* input); #define __builtin_infl() zig_msvc_flt_infl #endif -#if (zig_has_builtin(nan) && zig_has_builtin(nans) && zig_has_builtin(inf)) || defined(zig_gnuc) +#if (zig_has_builtin(nan) && zig_has_builtin(nans) && zig_has_builtin(inf)) || defined(zig_gcc) #define zig_make_special_f16(sign, name, arg, repr) sign zig_make_f16 (__builtin_##name, )(arg) #define zig_make_special_f32(sign, name, arg, repr) sign zig_make_f32 (__builtin_##name, )(arg) #define zig_make_special_f64(sign, name, arg, repr) sign zig_make_f64 (__builtin_##name, )(arg) @@ -3202,7 +3235,7 @@ typedef double zig_f16; #elif LDBL_MANT_DIG == 11 typedef long double zig_f16; #define zig_make_f16(fp, repr) fp##l -#elif FLT16_MANT_DIG == 11 && (zig_has_builtin(inff16) || defined(zig_gnuc)) +#elif FLT16_MANT_DIG == 11 && (zig_has_builtin(inff16) || defined(zig_gcc)) typedef _Float16 zig_f16; #define zig_make_f16(fp, repr) fp##f16 #elif defined(__SIZEOF_FP16__) @@ -3324,7 +3357,7 @@ typedef zig_u128 zig_f80; #define zig_init_special_f80(sign, name, arg, repr) repr #endif -#if !defined(zig_clang) && defined(zig_gnuc) && defined(zig_x86) +#if defined(zig_gcc) && defined(zig_x86) #define zig_f128_has_miscompilations 1 #else #define zig_f128_has_miscompilations 0 @@ -3729,7 +3762,11 @@ zig_float_builtins(64) res = zig_atomicrmw_expected; \ } while (0) -#if (__STDC_VERSION__ >= 201112L || (zig_has_include(<stdatomic.h>) && !defined(zig_msvc))) && !defined(__STDC_NO_ATOMICS__) +#if (__STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__)) || (zig_has_include(<stdatomic.h>) && !defined(zig_msvc)) +#define zig_c11_atomics +#endif + +#if defined(zig_c11_atomics) #include <stdatomic.h> typedef enum memory_order zig_memory_order; #define zig_memory_order_relaxed memory_order_relaxed @@ -3765,9 +3802,9 @@ typedef int zig_memory_order; #define zig_memory_order_acq_rel __ATOMIC_ACQ_REL #define zig_memory_order_seq_cst __ATOMIC_SEQ_CST #define zig_atomic(Type) Type -#define zig_cmpxchg_strong( obj, expected, desired, succ, fail, Type, ReprType) __atomic_compare_exchange(obj, &(expected), &(desired), false, succ, fail) -#define zig_cmpxchg_weak( obj, expected, desired, succ, fail, Type, ReprType) __atomic_compare_exchange(obj, &(expected), &(desired), true, succ, fail) -#define zig_atomicrmw_xchg(res, obj, arg, order, Type, ReprType) __atomic_exchange(obj, &(arg), &(res), order) +#define zig_cmpxchg_strong( obj, expected, desired, succ, fail, Type, ReprType) __atomic_compare_exchange(obj, (ReprType *)&(expected), (ReprType *)&(desired), false, succ, fail) +#define zig_cmpxchg_weak( obj, expected, desired, succ, fail, Type, ReprType) __atomic_compare_exchange(obj, (ReprType *)&(expected), (ReprType *)&(desired), true, succ, fail) +#define zig_atomicrmw_xchg(res, obj, arg, order, Type, ReprType) __atomic_exchange(obj, (ReprType *)&(arg), &(res), order) #define zig_atomicrmw_add(res, obj, arg, order, Type, ReprType) res = __atomic_fetch_add (obj, arg, order) #define zig_atomicrmw_sub(res, obj, arg, order, Type, ReprType) res = __atomic_fetch_sub (obj, arg, order) #define zig_atomicrmw_or(res, obj, arg, order, Type, ReprType) res = __atomic_fetch_or (obj, arg, order) @@ -3776,7 +3813,7 @@ typedef int zig_memory_order; #define zig_atomicrmw_nand(res, obj, arg, order, Type, ReprType) res = __atomic_fetch_nand(obj, arg, order) #define zig_atomicrmw_min(res, obj, arg, order, Type, ReprType) res = __atomic_fetch_min (obj, arg, order) #define zig_atomicrmw_max(res, obj, arg, order, Type, ReprType) res = __atomic_fetch_max (obj, arg, order) -#define zig_atomic_store( obj, arg, order, Type, ReprType) __atomic_store (obj, &(arg), order) +#define zig_atomic_store( obj, arg, order, Type, ReprType) __atomic_store (obj, (ReprType *)&(arg), order) #define zig_atomic_load(res, obj, order, Type, ReprType) __atomic_load (obj, &(res), order) #undef zig_atomicrmw_xchg_float #define zig_atomicrmw_xchg_float zig_atomicrmw_xchg @@ -3823,7 +3860,7 @@ typedef int zig_memory_order; #define zig_atomic_load(res, obj, order, Type, ReprType) zig_atomics_unavailable #endif -#if defined(zig_msvc) && defined(zig_x86) +#if !defined(zig_c11_atomics) && defined(zig_msvc) && defined(zig_x86) /* TODO: zig_msvc_atomic_load should load 32 bit without interlocked on x86, and load 64 bit without interlocked on x64 */ @@ -4069,7 +4106,7 @@ static inline void zig_msvc_atomic_store_i128(zig_i128 volatile* obj, zig_i128 a #endif /* zig_x86_32 */ -#endif /* zig_msvc && zig_x86 */ +#endif /* !zig_c11_atomics && zig_msvc && zig_x86 */ /* ======================== Special Case Intrinsics ========================= */ diff --git a/stage1/zig1.wasm b/stage1/zig1.wasm Binary files differ. diff --git a/test/behavior/floatop.zig b/test/behavior/floatop.zig @@ -126,7 +126,7 @@ test "cmp f16" { if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.cpu.arch.isArm() and builtin.target.floatAbi() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234 + if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234 try testCmp(f16); try comptime testCmp(f16); @@ -135,7 +135,7 @@ test "cmp f16" { test "cmp f32/f64" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; - if (builtin.cpu.arch.isArm() and builtin.target.floatAbi() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234 + if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234 try testCmp(f32); try comptime testCmp(f32); diff --git a/test/behavior/math.zig b/test/behavior/math.zig @@ -1639,7 +1639,7 @@ test "NaN comparison" { if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.cpu.arch.isArm() and builtin.target.floatAbi() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234 + if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234 try testNanEqNan(f16); try testNanEqNan(f32); @@ -1795,7 +1795,7 @@ test "runtime comparison to NaN is comptime-known" { if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.cpu.arch.isArm() and builtin.target.floatAbi() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234 + if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234 const S = struct { fn doTheTest(comptime F: type, x: F) void { @@ -1826,7 +1826,7 @@ test "runtime int comparison to inf is comptime-known" { if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_x86_64 and builtin.target.ofmt != .elf and builtin.target.ofmt != .macho) return error.SkipZigTest; if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; - if (builtin.cpu.arch.isArm() and builtin.target.floatAbi() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234 + if (builtin.cpu.arch.isArm() and builtin.target.abi.float() == .soft) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/21234 const S = struct { fn doTheTest(comptime F: type, x: u32) void { diff --git a/test/c_abi/main.zig b/test/c_abi/main.zig @@ -135,7 +135,7 @@ export fn zig_f64(x: f64) void { expect(x == 56.78) catch @panic("test failure: zig_f64"); } export fn zig_longdouble(x: c_longdouble) void { - if (!builtin.target.isWasm()) return; // waiting for #1481 + if (!builtin.target.cpu.arch.isWasm()) return; // waiting for #1481 expect(x == 12.34) catch @panic("test failure: zig_longdouble"); } @@ -1661,7 +1661,7 @@ test "bool simd vector" { } { - if (!builtin.target.isWasm()) c_vector_256_bool(.{ + if (!builtin.target.cpu.arch.isWasm()) c_vector_256_bool(.{ false, true, true, @@ -2179,7 +2179,7 @@ test "bool simd vector" { try expect(vec[255] == false); } { - if (!builtin.target.isWasm()) c_vector_512_bool(.{ + if (!builtin.target.cpu.arch.isWasm()) c_vector_512_bool(.{ true, true, true, @@ -5593,7 +5593,7 @@ test "f80 extra struct" { comptime { skip: { - if (builtin.target.isWasm()) break :skip; + if (builtin.target.cpu.arch.isWasm()) break :skip; _ = struct { export fn zig_f128(x: f128) f128 { diff --git a/test/cases/compile_errors/@import_zon_bad_type.zig b/test/cases/compile_errors/@import_zon_bad_type.zig @@ -117,9 +117,9 @@ export fn testMutablePointer() void { // tmp.zig:37:38: note: imported here // neg_inf.zon:1:1: error: expected type '?u8' // tmp.zig:57:28: note: imported here -// neg_inf.zon:1:1: error: expected type 'tmp.testNonExhaustiveEnum__enum_490' +// neg_inf.zon:1:1: error: expected type 'tmp.testNonExhaustiveEnum__enum_487' // tmp.zig:62:39: note: imported here -// neg_inf.zon:1:1: error: expected type 'tmp.testUntaggedUnion__union_492' +// neg_inf.zon:1:1: error: expected type 'tmp.testUntaggedUnion__union_489' // tmp.zig:67:44: note: imported here -// neg_inf.zon:1:1: error: expected type 'tmp.testTaggedUnionVoid__union_495' +// neg_inf.zon:1:1: error: expected type 'tmp.testTaggedUnionVoid__union_492' // tmp.zig:72:50: note: imported here diff --git a/test/cases/compile_errors/anytype_param_requires_comptime.zig b/test/cases/compile_errors/anytype_param_requires_comptime.zig @@ -15,6 +15,6 @@ pub export fn entry() void { // error // // :7:25: error: unable to resolve comptime value -// :7:25: note: initializer of comptime-only struct 'tmp.S.foo__anon_464.C' must be comptime-known +// :7:25: note: initializer of comptime-only struct 'tmp.S.foo__anon_461.C' must be comptime-known // :4:16: note: struct requires comptime because of this field // :4:16: note: types are not available at runtime diff --git a/test/cases/compile_errors/bogus_method_call_on_slice.zig b/test/cases/compile_errors/bogus_method_call_on_slice.zig @@ -16,5 +16,5 @@ pub export fn entry2() void { // // :3:6: error: no field or member function named 'copy' in '[]const u8' // :9:8: error: no field or member function named 'bar' in '@TypeOf(.{})' -// :12:18: error: no field or member function named 'bar' in 'tmp.entry2__struct_468' +// :12:18: error: no field or member function named 'bar' in 'tmp.entry2__struct_465' // :12:6: note: struct declared here diff --git a/test/cases/compile_errors/callconv_apcs_aapcs_aapcsvfp_on_unsupported_platform.zig b/test/cases/compile_errors/callconv_apcs_aapcs_aapcsvfp_on_unsupported_platform.zig @@ -1,10 +1,8 @@ -export fn entry1() callconv(.APCS) void {} export fn entry2() callconv(.AAPCS) void {} export fn entry3() callconv(.AAPCSVFP) void {} // error // target=x86_64-linux-none // -// :1:30: error: calling convention 'arm_apcs' only available on architectures 'arm', 'armeb', 'thumb', 'thumbeb' -// :2:30: error: calling convention 'arm_aapcs' only available on architectures 'arm', 'armeb', 'thumb', 'thumbeb' -// :3:30: error: calling convention 'arm_aapcs_vfp' only available on architectures 'arm', 'armeb', 'thumb', 'thumbeb' +// :1:30: error: calling convention 'arm_aapcs' only available on architectures 'arm', 'armeb', 'thumb', 'thumbeb' +// :2:30: error: calling convention 'arm_aapcs_vfp' only available on architectures 'arm', 'armeb', 'thumb', 'thumbeb' diff --git a/test/cases/compile_errors/coerce_anon_struct.zig b/test/cases/compile_errors/coerce_anon_struct.zig @@ -6,6 +6,6 @@ export fn foo() void { // error // -// :4:16: error: expected type 'tmp.T', found 'tmp.foo__struct_457' +// :4:16: error: expected type 'tmp.T', found 'tmp.foo__struct_454' // :3:16: note: struct declared here // :1:11: note: struct declared here diff --git a/test/cases/compile_errors/redundant_try.zig b/test/cases/compile_errors/redundant_try.zig @@ -44,9 +44,9 @@ comptime { // // :5:23: error: expected error union type, found 'comptime_int' // :10:23: error: expected error union type, found '@TypeOf(.{})' -// :15:23: error: expected error union type, found 'tmp.test2__struct_494' +// :15:23: error: expected error union type, found 'tmp.test2__struct_491' // :15:23: note: struct declared here -// :20:27: error: expected error union type, found 'tmp.test3__struct_496' +// :20:27: error: expected error union type, found 'tmp.test3__struct_493' // :20:27: note: struct declared here // :25:23: error: expected error union type, found 'struct { comptime *const [5:0]u8 = "hello" }' // :31:13: error: expected error union type, found 'u32' diff --git a/test/standalone/stack_iterator/build.zig b/test/standalone/stack_iterator/build.zig @@ -24,7 +24,7 @@ pub fn build(b: *std.Build) void { .root_source_file = b.path("unwind.zig"), .target = target, .optimize = optimize, - .unwind_tables = if (target.result.isDarwin()) .@"async" else null, + .unwind_tables = if (target.result.os.tag.isDarwin()) .@"async" else null, .omit_frame_pointer = false, }), }); @@ -94,7 +94,7 @@ pub fn build(b: *std.Build) void { .root_source_file = b.path("shared_lib_unwind.zig"), .target = target, .optimize = optimize, - .unwind_tables = if (target.result.isDarwin()) .@"async" else null, + .unwind_tables = if (target.result.os.tag.isDarwin()) .@"async" else null, .omit_frame_pointer = true, }), }); diff --git a/test/standalone/stack_iterator/shared_lib_unwind.zig b/test/standalone/stack_iterator/shared_lib_unwind.zig @@ -36,8 +36,8 @@ extern fn frame0( pub fn main() !void { // Disabled until the DWARF unwinder bugs on .aarch64 are solved - if (builtin.omit_frame_pointer and comptime builtin.target.isDarwin() and builtin.cpu.arch == .aarch64) return; - if (builtin.target.isDarwin() and builtin.cpu.arch == .x86_64) return; // https://github.com/ziglang/zig/issues/21337 + if (builtin.omit_frame_pointer and comptime builtin.target.os.tag.isDarwin() and builtin.cpu.arch == .aarch64) return; + if (builtin.target.os.tag.isDarwin() and builtin.cpu.arch == .x86_64) return; // https://github.com/ziglang/zig/issues/21337 if (!std.debug.have_ucontext or !std.debug.have_getcontext) return; diff --git a/test/standalone/stack_iterator/unwind.zig b/test/standalone/stack_iterator/unwind.zig @@ -88,7 +88,7 @@ noinline fn frame0(expected: *[4]usize, unwound: *[4]usize) void { pub fn main() !void { // Disabled until the DWARF unwinder bugs on .aarch64 are solved - if (builtin.omit_frame_pointer and comptime builtin.target.isDarwin() and builtin.cpu.arch == .aarch64) return; + if (builtin.omit_frame_pointer and comptime builtin.target.os.tag.isDarwin() and builtin.cpu.arch == .aarch64) return; if (!std.debug.have_ucontext or !std.debug.have_getcontext) return; diff --git a/tools/update_cpu_features.zig b/tools/update_cpu_features.zig @@ -34,10 +34,12 @@ const Feature = struct { flatten: bool = false, }; -const LlvmTarget = struct { +const ArchTarget = struct { zig_name: []const u8, - llvm_name: []const u8, - td_name: []const u8, + llvm: ?struct { + name: []const u8, + td_name: []const u8, + }, feature_overrides: []const FeatureOverride = &.{}, extra_cpus: []const Cpu = &.{}, extra_features: []const Feature = &.{}, @@ -45,11 +47,13 @@ const LlvmTarget = struct { branch_quota: ?usize = null, }; -const llvm_targets = [_]LlvmTarget{ +const targets = [_]ArchTarget{ .{ .zig_name = "aarch64", - .llvm_name = "AArch64", - .td_name = "AArch64.td", + .llvm = .{ + .name = "AArch64", + .td_name = "AArch64", + }, .branch_quota = 2000, .feature_overrides = &.{ .{ @@ -391,8 +395,10 @@ const llvm_targets = [_]LlvmTarget{ }, .{ .zig_name = "amdgcn", - .llvm_name = "AMDGPU", - .td_name = "AMDGPU.td", + .llvm = .{ + .name = "AMDGPU", + .td_name = "AMDGPU", + }, .feature_overrides = &.{ .{ .llvm_name = "DumpCode", @@ -418,13 +424,17 @@ const llvm_targets = [_]LlvmTarget{ }, .{ .zig_name = "arc", - .llvm_name = "ARC", - .td_name = "ARC.td", + .llvm = .{ + .name = "ARC", + .td_name = "ARC", + }, }, .{ .zig_name = "arm", - .llvm_name = "ARM", - .td_name = "ARM.td", + .llvm = .{ + .name = "ARM", + .td_name = "ARM", + }, .branch_quota = 10000, .feature_overrides = &.{ .{ @@ -928,66 +938,113 @@ const llvm_targets = [_]LlvmTarget{ }, .{ .zig_name = "avr", - .llvm_name = "AVR", - .td_name = "AVR.td", + .llvm = .{ + .name = "AVR", + .td_name = "AVR", + }, }, .{ .zig_name = "bpf", - .llvm_name = "BPF", - .td_name = "BPF.td", + .llvm = .{ + .name = "BPF", + .td_name = "BPF", + }, }, .{ .zig_name = "csky", - .llvm_name = "CSKY", - .td_name = "CSKY.td", + .llvm = .{ + .name = "CSKY", + .td_name = "CSKY", + }, }, .{ .zig_name = "hexagon", - .llvm_name = "Hexagon", - .td_name = "Hexagon.td", + .llvm = .{ + .name = "Hexagon", + .td_name = "Hexagon", + }, }, .{ .zig_name = "lanai", - .llvm_name = "Lanai", - .td_name = "Lanai.td", + .llvm = .{ + .name = "Lanai", + .td_name = "Lanai", + }, }, .{ .zig_name = "loongarch", - .llvm_name = "LoongArch", - .td_name = "LoongArch.td", + .llvm = .{ + .name = "LoongArch", + .td_name = "LoongArch", + }, }, .{ .zig_name = "m68k", - .llvm_name = "M68k", - .td_name = "M68k.td", + .llvm = .{ + .name = "M68k", + .td_name = "M68k", + }, }, .{ .zig_name = "msp430", - .llvm_name = "MSP430", - .td_name = "MSP430.td", + .llvm = .{ + .name = "MSP430", + .td_name = "MSP430", + }, }, .{ .zig_name = "mips", - .llvm_name = "Mips", - .td_name = "Mips.td", + .llvm = .{ + .name = "Mips", + .td_name = "Mips", + }, }, .{ .zig_name = "nvptx", - .llvm_name = "NVPTX", - .td_name = "NVPTX.td", + .llvm = .{ + .name = "NVPTX", + .td_name = "NVPTX", + }, }, .{ .zig_name = "powerpc", - .llvm_name = "PowerPC", - .td_name = "PPC.td", + .llvm = .{ + .name = "PowerPC", + .td_name = "PPC", + }, .omit_cpus = &.{ "ppc32", }, }, .{ + .zig_name = "propeller", + .llvm = null, + .extra_features = &.{ + .{ + .zig_name = "p2", + .desc = "Enable Propeller 2", + .deps = &.{}, + }, + }, + .extra_cpus = &.{ + .{ + .llvm_name = null, + .zig_name = "p1", + .features = &.{}, + }, + .{ + .llvm_name = null, + .zig_name = "p2", + .features = &.{"p2"}, + }, + }, + }, + .{ .zig_name = "riscv", - .llvm_name = "RISCV", - .td_name = "RISCV.td", + .llvm = .{ + .name = "RISCV", + .td_name = "RISCV", + }, .branch_quota = 2000, .feature_overrides = &.{ .{ @@ -1010,29 +1067,38 @@ const llvm_targets = [_]LlvmTarget{ }, .{ .zig_name = "sparc", - .llvm_name = "Sparc", - .td_name = "Sparc.td", + .llvm = .{ + .name = "Sparc", + .td_name = "Sparc", + }, }, // TODO: merge tools/update_spirv_features.zig into this script //.{ // .zig_name = "spirv", - // .llvm_name = "SPIRV", - // .td_name = "SPIRV.td", + // .llvm = .{ + // .name = "SPIRV", + // }, //}, .{ .zig_name = "s390x", - .llvm_name = "SystemZ", - .td_name = "SystemZ.td", + .llvm = .{ + .name = "SystemZ", + .td_name = "SystemZ", + }, }, .{ .zig_name = "ve", - .llvm_name = "VE", - .td_name = "VE.td", + .llvm = .{ + .name = "VE", + .td_name = "VE", + }, }, .{ .zig_name = "wasm", - .llvm_name = "WebAssembly", - .td_name = "WebAssembly.td", + .llvm = .{ + .name = "WebAssembly", + .td_name = "WebAssembly", + }, .extra_features = &.{ .{ .zig_name = "nontrapping_bulk_memory_len0", @@ -1057,8 +1123,10 @@ const llvm_targets = [_]LlvmTarget{ }, .{ .zig_name = "x86", - .llvm_name = "X86", - .td_name = "X86.td", + .llvm = .{ + .name = "X86", + .td_name = "X86", + }, .feature_overrides = &.{ .{ .llvm_name = "64bit-mode", @@ -1362,13 +1430,17 @@ const llvm_targets = [_]LlvmTarget{ }, .{ .zig_name = "xcore", - .llvm_name = "XCore", - .td_name = "XCore.td", + .llvm = .{ + .name = "XCore", + .td_name = "XCore", + }, }, .{ .zig_name = "xtensa", - .llvm_name = "Xtensa", - .td_name = "Xtensa.td", + .llvm = .{ + .name = "Xtensa", + .td_name = "Xtensa", + }, }, }; @@ -1413,33 +1485,33 @@ pub fn main() anyerror!void { var zig_src_dir = try fs.cwd().openDir(zig_src_root, .{}); defer zig_src_dir.close(); - const root_progress = std.Progress.start(.{ .estimated_total_items = llvm_targets.len }); + const root_progress = std.Progress.start(.{ .estimated_total_items = targets.len }); defer root_progress.end(); if (builtin.single_threaded) { - for (llvm_targets) |llvm_target| { - if (filter) |zig_name| if (!std.mem.eql(u8, llvm_target.zig_name, zig_name)) continue; + for (targets) |target| { + if (filter) |zig_name| if (!std.mem.eql(u8, target.zig_name, zig_name)) continue; try processOneTarget(.{ .llvm_tblgen_exe = llvm_tblgen_exe, .llvm_src_root = llvm_src_root, .zig_src_dir = zig_src_dir, .root_progress = root_progress, - .llvm_target = llvm_target, + .target = target, }); } } else { var pool: std.Thread.Pool = undefined; - try pool.init(.{ .allocator = arena, .n_jobs = llvm_targets.len }); + try pool.init(.{ .allocator = arena, .n_jobs = targets.len }); defer pool.deinit(); - for (llvm_targets) |llvm_target| { - if (filter) |zig_name| if (!std.mem.eql(u8, llvm_target.zig_name, zig_name)) continue; + for (targets) |target| { + if (filter) |zig_name| if (!std.mem.eql(u8, target.zig_name, zig_name)) continue; const job = Job{ .llvm_tblgen_exe = llvm_tblgen_exe, .llvm_src_root = llvm_src_root, .zig_src_dir = zig_src_dir, .root_progress = root_progress, - .llvm_target = llvm_target, + .target = target, }; try pool.spawn(processOneTarget, .{job}); } @@ -1451,162 +1523,147 @@ const Job = struct { llvm_src_root: []const u8, zig_src_dir: std.fs.Dir, root_progress: std.Progress.Node, - llvm_target: LlvmTarget, + target: ArchTarget, }; fn processOneTarget(job: Job) void { errdefer |err| std.debug.panic("panic: {s}", .{@errorName(err)}); - const llvm_target = job.llvm_target; + const target = job.target; var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator); defer arena_state.deinit(); const arena = arena_state.allocator(); - const progress_node = job.root_progress.start(llvm_target.zig_name, 3); + const progress_node = job.root_progress.start(target.zig_name, 3); defer progress_node.end(); - const tblgen_progress = progress_node.start("running llvm-tblgen", 0); - - const child_args = [_][]const u8{ - job.llvm_tblgen_exe, - "--dump-json", - try std.fmt.allocPrint(arena, "{s}/llvm/lib/Target/{s}/{s}", .{ - job.llvm_src_root, - llvm_target.llvm_name, - llvm_target.td_name, - }), - try std.fmt.allocPrint(arena, "-I={s}/llvm/include", .{job.llvm_src_root}), - try std.fmt.allocPrint(arena, "-I={s}/llvm/lib/Target/{s}", .{ - job.llvm_src_root, llvm_target.llvm_name, - }), - }; + var features_table = std.StringHashMap(Feature).init(arena); + var all_features = std.ArrayList(Feature).init(arena); + var all_cpus = std.ArrayList(Cpu).init(arena); - const child_result = try std.process.Child.run(.{ - .allocator = arena, - .argv = &child_args, - .max_output_bytes = 500 * 1024 * 1024, - }); - tblgen_progress.end(); - if (child_result.stderr.len != 0) { - std.debug.print("{s}\n", .{child_result.stderr}); - } + if (target.llvm) |llvm| { + const tblgen_progress = progress_node.start("running llvm-tblgen", 0); - const json_text = switch (child_result.term) { - .Exited => |code| if (code == 0) child_result.stdout else { - std.debug.print("llvm-tblgen exited with code {d}\n", .{code}); - std.process.exit(1); - }, - else => { - std.debug.print("llvm-tblgen crashed\n", .{}); - std.process.exit(1); - }, - }; + const child_args = [_][]const u8{ + job.llvm_tblgen_exe, + "--dump-json", + try std.fmt.allocPrint(arena, "{s}/llvm/lib/Target/{s}/{s}.td", .{ + job.llvm_src_root, + llvm.name, + llvm.td_name, + }), + try std.fmt.allocPrint(arena, "-I={s}/llvm/include", .{job.llvm_src_root}), + try std.fmt.allocPrint(arena, "-I={s}/llvm/lib/Target/{s}", .{ + job.llvm_src_root, llvm.name, + }), + }; - const json_parse_progress = progress_node.start("parsing JSON", 0); + const child_result = try std.process.Child.run(.{ + .allocator = arena, + .argv = &child_args, + .max_output_bytes = 500 * 1024 * 1024, + }); + tblgen_progress.end(); + if (child_result.stderr.len != 0) { + std.debug.print("{s}\n", .{child_result.stderr}); + } - const parsed = try json.parseFromSlice(json.Value, arena, json_text, .{}); - defer parsed.deinit(); - const root_map = &parsed.value.object; - json_parse_progress.end(); + const json_text = switch (child_result.term) { + .Exited => |code| if (code == 0) child_result.stdout else { + std.debug.print("llvm-tblgen exited with code {d}\n", .{code}); + std.process.exit(1); + }, + else => { + std.debug.print("llvm-tblgen crashed\n", .{}); + std.process.exit(1); + }, + }; - const render_progress = progress_node.start("rendering Zig code", 0); + const json_parse_progress = progress_node.start("parsing JSON", 0); - // So far, LLVM only has a few aliases for the same CPU. - var cpu_aliases = std.StringHashMap(std.SegmentedList(struct { - llvm: []const u8, - zig: []const u8, - }, 4)).init(arena); + const parsed = try json.parseFromSlice(json.Value, arena, json_text, .{}); + defer parsed.deinit(); + const root_map = &parsed.value.object; + json_parse_progress.end(); - { - var it = root_map.iterator(); - while (it.next()) |kv| { - if (kv.key_ptr.len == 0) continue; - if (kv.key_ptr.*[0] == '!') continue; - if (kv.value_ptr.* != .object) continue; - if (hasSuperclass(&kv.value_ptr.object, "ProcessorAlias")) { - // Note that `Name` is actually the alias, while `Alias` is the name that will have - // a full `Processor` object defined. - const llvm_alias = kv.value_ptr.object.get("Name").?.string; - const llvm_name = kv.value_ptr.object.get("Alias").?.string; - - const gop = try cpu_aliases.getOrPut(try llvmNameToZigName(arena, llvm_name)); - - if (!gop.found_existing) gop.value_ptr.* = .{}; - - try gop.value_ptr.append(arena, .{ - .llvm = llvm_alias, - .zig = try llvmNameToZigName(arena, llvm_alias), - }); + const collate_progress = progress_node.start("collating LLVM data", 0); + + // So far, LLVM only has a few aliases for the same CPU. + var cpu_aliases = std.StringHashMap(std.SegmentedList(struct { + llvm: []const u8, + zig: []const u8, + }, 4)).init(arena); + + { + var it = root_map.iterator(); + while (it.next()) |kv| { + if (kv.key_ptr.len == 0) continue; + if (kv.key_ptr.*[0] == '!') continue; + if (kv.value_ptr.* != .object) continue; + if (hasSuperclass(&kv.value_ptr.object, "ProcessorAlias")) { + // Note that `Name` is actually the alias, while `Alias` is the name that will have + // a full `Processor` object defined. + const llvm_alias = kv.value_ptr.object.get("Name").?.string; + const llvm_name = kv.value_ptr.object.get("Alias").?.string; + + const gop = try cpu_aliases.getOrPut(try llvmNameToZigName(arena, llvm_name)); + + if (!gop.found_existing) gop.value_ptr.* = .{}; + + try gop.value_ptr.append(arena, .{ + .llvm = llvm_alias, + .zig = try llvmNameToZigName(arena, llvm_alias), + }); + } } } - } - var features_table = std.StringHashMap(Feature).init(arena); - var all_features = std.ArrayList(Feature).init(arena); - var all_cpus = std.ArrayList(Cpu).init(arena); - { - var it = root_map.iterator(); - while (it.next()) |kv| { - if (kv.key_ptr.len == 0) continue; - if (kv.key_ptr.*[0] == '!') continue; - if (kv.value_ptr.* != .object) continue; - if (hasSuperclass(&kv.value_ptr.object, "SubtargetFeature")) { - const llvm_name = kv.value_ptr.object.get("Name").?.string; - if (llvm_name.len == 0) continue; - - var zig_name = try llvmNameToZigName(arena, llvm_name); - var desc = kv.value_ptr.object.get("Desc").?.string; - var deps = std.ArrayList([]const u8).init(arena); - var omit = false; - var flatten = false; - var omit_deps: []const []const u8 = &.{}; - var extra_deps: []const []const u8 = &.{}; - for (llvm_target.feature_overrides) |feature_override| { - if (mem.eql(u8, llvm_name, feature_override.llvm_name)) { - if (feature_override.omit) { - // Still put the feature into the table so that we can - // expand dependencies for the feature overrides marked `flatten`. - omit = true; - } - if (feature_override.flatten) { - flatten = true; - } - if (feature_override.zig_name) |override_name| { - zig_name = override_name; - } - if (feature_override.desc) |override_desc| { - desc = override_desc; + { + var it = root_map.iterator(); + while (it.next()) |kv| { + if (kv.key_ptr.len == 0) continue; + if (kv.key_ptr.*[0] == '!') continue; + if (kv.value_ptr.* != .object) continue; + if (hasSuperclass(&kv.value_ptr.object, "SubtargetFeature")) { + const llvm_name = kv.value_ptr.object.get("Name").?.string; + if (llvm_name.len == 0) continue; + + var zig_name = try llvmNameToZigName(arena, llvm_name); + var desc = kv.value_ptr.object.get("Desc").?.string; + var deps = std.ArrayList([]const u8).init(arena); + var omit = false; + var flatten = false; + var omit_deps: []const []const u8 = &.{}; + var extra_deps: []const []const u8 = &.{}; + for (target.feature_overrides) |feature_override| { + if (mem.eql(u8, llvm_name, feature_override.llvm_name)) { + if (feature_override.omit) { + // Still put the feature into the table so that we can + // expand dependencies for the feature overrides marked `flatten`. + omit = true; + } + if (feature_override.flatten) { + flatten = true; + } + if (feature_override.zig_name) |override_name| { + zig_name = override_name; + } + if (feature_override.desc) |override_desc| { + desc = override_desc; + } + omit_deps = feature_override.omit_deps; + extra_deps = feature_override.extra_deps; + break; } - omit_deps = feature_override.omit_deps; - extra_deps = feature_override.extra_deps; - break; } - } - const implies = kv.value_ptr.object.get("Implies").?.array; - for (implies.items) |imply| { - const other_key = imply.object.get("def").?.string; - const other_obj = root_map.get(other_key).?.object; - const other_llvm_name = other_obj.get("Name").?.string; - const other_zig_name = (try llvmFeatureNameToZigNameOmit( - arena, - llvm_target, - other_llvm_name, - )) orelse continue; - for (omit_deps) |omit_dep| { - if (mem.eql(u8, other_zig_name, omit_dep)) break; - } else { - try deps.append(other_zig_name); - } - } - // This is used by AArch64. - if (kv.value_ptr.object.get("DefaultExts")) |exts_val| { - for (exts_val.array.items) |ext| { - const other_key = ext.object.get("def").?.string; + const implies = kv.value_ptr.object.get("Implies").?.array; + for (implies.items) |imply| { + const other_key = imply.object.get("def").?.string; const other_obj = root_map.get(other_key).?.object; const other_llvm_name = other_obj.get("Name").?.string; const other_zig_name = (try llvmFeatureNameToZigNameOmit( arena, - llvm_target, + target, other_llvm_name, )) orelse continue; for (omit_deps) |omit_dep| { @@ -1615,118 +1672,141 @@ fn processOneTarget(job: Job) void { try deps.append(other_zig_name); } } + // This is used by AArch64. + if (kv.value_ptr.object.get("DefaultExts")) |exts_val| { + for (exts_val.array.items) |ext| { + const other_key = ext.object.get("def").?.string; + const other_obj = root_map.get(other_key).?.object; + const other_llvm_name = other_obj.get("Name").?.string; + const other_zig_name = (try llvmFeatureNameToZigNameOmit( + arena, + target, + other_llvm_name, + )) orelse continue; + for (omit_deps) |omit_dep| { + if (mem.eql(u8, other_zig_name, omit_dep)) break; + } else { + try deps.append(other_zig_name); + } + } + } + for (extra_deps) |extra_dep| { + try deps.append(extra_dep); + } + const feature: Feature = .{ + .llvm_name = llvm_name, + .zig_name = zig_name, + .desc = desc, + .deps = deps.items, + .flatten = flatten, + }; + try features_table.put(zig_name, feature); + if (!omit and !flatten) { + try all_features.append(feature); + } } - for (extra_deps) |extra_dep| { - try deps.append(extra_dep); - } - const feature: Feature = .{ - .llvm_name = llvm_name, - .zig_name = zig_name, - .desc = desc, - .deps = deps.items, - .flatten = flatten, - }; - try features_table.put(zig_name, feature); - if (!omit and !flatten) { - try all_features.append(feature); - } - } - if (hasSuperclass(&kv.value_ptr.object, "Processor")) { - const llvm_name = kv.value_ptr.object.get("Name").?.string; - if (llvm_name.len == 0) continue; - const omitted = for (llvm_target.omit_cpus) |omit_cpu_name| { - if (mem.eql(u8, omit_cpu_name, llvm_name)) break true; - } else false; - if (omitted) continue; - - var zig_name = try llvmNameToZigName(arena, llvm_name); - var deps = std.ArrayList([]const u8).init(arena); - var omit_deps: []const []const u8 = &.{}; - var extra_deps: []const []const u8 = &.{}; - for (llvm_target.feature_overrides) |feature_override| { - if (mem.eql(u8, llvm_name, feature_override.llvm_name)) { - if (feature_override.omit) { - continue; + if (hasSuperclass(&kv.value_ptr.object, "Processor")) { + const llvm_name = kv.value_ptr.object.get("Name").?.string; + if (llvm_name.len == 0) continue; + const omitted = for (target.omit_cpus) |omit_cpu_name| { + if (mem.eql(u8, omit_cpu_name, llvm_name)) break true; + } else false; + if (omitted) continue; + + var zig_name = try llvmNameToZigName(arena, llvm_name); + var deps = std.ArrayList([]const u8).init(arena); + var omit_deps: []const []const u8 = &.{}; + var extra_deps: []const []const u8 = &.{}; + for (target.feature_overrides) |feature_override| { + if (mem.eql(u8, llvm_name, feature_override.llvm_name)) { + if (feature_override.omit) { + continue; + } + if (feature_override.zig_name) |override_name| { + zig_name = override_name; + } + omit_deps = feature_override.omit_deps; + extra_deps = feature_override.extra_deps; + break; } - if (feature_override.zig_name) |override_name| { - zig_name = override_name; + } + const features = kv.value_ptr.object.get("Features").?.array; + for (features.items) |feature| { + const feature_key = feature.object.get("def").?.string; + const feature_obj = root_map.get(feature_key).?.object; + const feature_llvm_name = feature_obj.get("Name").?.string; + if (feature_llvm_name.len == 0) continue; + const feature_zig_name = (try llvmFeatureNameToZigNameOmit( + arena, + target, + feature_llvm_name, + )) orelse continue; + for (omit_deps) |omit_dep| { + if (mem.eql(u8, feature_zig_name, omit_dep)) break; + } else { + try deps.append(feature_zig_name); } - omit_deps = feature_override.omit_deps; - extra_deps = feature_override.extra_deps; - break; } - } - const features = kv.value_ptr.object.get("Features").?.array; - for (features.items) |feature| { - const feature_key = feature.object.get("def").?.string; - const feature_obj = root_map.get(feature_key).?.object; - const feature_llvm_name = feature_obj.get("Name").?.string; - if (feature_llvm_name.len == 0) continue; - const feature_zig_name = (try llvmFeatureNameToZigNameOmit( - arena, - llvm_target, - feature_llvm_name, - )) orelse continue; - for (omit_deps) |omit_dep| { - if (mem.eql(u8, feature_zig_name, omit_dep)) break; - } else { + for (extra_deps) |extra_dep| { + try deps.append(extra_dep); + } + const tune_features = kv.value_ptr.object.get("TuneFeatures").?.array; + for (tune_features.items) |feature| { + const feature_key = feature.object.get("def").?.string; + const feature_obj = root_map.get(feature_key).?.object; + const feature_llvm_name = feature_obj.get("Name").?.string; + if (feature_llvm_name.len == 0) continue; + const feature_zig_name = (try llvmFeatureNameToZigNameOmit( + arena, + target, + feature_llvm_name, + )) orelse continue; try deps.append(feature_zig_name); } - } - for (extra_deps) |extra_dep| { - try deps.append(extra_dep); - } - const tune_features = kv.value_ptr.object.get("TuneFeatures").?.array; - for (tune_features.items) |feature| { - const feature_key = feature.object.get("def").?.string; - const feature_obj = root_map.get(feature_key).?.object; - const feature_llvm_name = feature_obj.get("Name").?.string; - if (feature_llvm_name.len == 0) continue; - const feature_zig_name = (try llvmFeatureNameToZigNameOmit( - arena, - llvm_target, - feature_llvm_name, - )) orelse continue; - try deps.append(feature_zig_name); - } - try all_cpus.append(.{ - .llvm_name = llvm_name, - .zig_name = zig_name, - .features = deps.items, - }); - - if (cpu_aliases.get(zig_name)) |aliases| { - var alias_it = aliases.constIterator(0); - - alias_it: while (alias_it.next()) |alias| { - for (llvm_target.omit_cpus) |omit_cpu_name| { - if (mem.eql(u8, omit_cpu_name, alias.llvm)) continue :alias_it; - } + try all_cpus.append(.{ + .llvm_name = llvm_name, + .zig_name = zig_name, + .features = deps.items, + }); + + if (cpu_aliases.get(zig_name)) |aliases| { + var alias_it = aliases.constIterator(0); - try all_cpus.append(.{ - .llvm_name = alias.llvm, - .zig_name = alias.zig, - .features = deps.items, - }); + alias_it: while (alias_it.next()) |alias| { + for (target.omit_cpus) |omit_cpu_name| { + if (mem.eql(u8, omit_cpu_name, alias.llvm)) continue :alias_it; + } + + try all_cpus.append(.{ + .llvm_name = alias.llvm, + .zig_name = alias.zig, + .features = deps.items, + }); + } } } } } + + collate_progress.end(); } - for (llvm_target.extra_features) |extra_feature| { + + for (target.extra_features) |extra_feature| { try features_table.put(extra_feature.zig_name, extra_feature); try all_features.append(extra_feature); } - for (llvm_target.extra_cpus) |extra_cpu| { + for (target.extra_cpus) |extra_cpu| { try all_cpus.append(extra_cpu); } mem.sort(Feature, all_features.items, {}, featureLessThan); mem.sort(Cpu, all_cpus.items, {}, cpuLessThan); + const render_progress = progress_node.start("rendering Zig code", 0); + var target_dir = try job.zig_src_dir.openDir("lib/std/Target", .{}); defer target_dir.close(); - const zig_code_basename = try std.fmt.allocPrint(arena, "{s}.zig", .{llvm_target.zig_name}); + const zig_code_basename = try std.fmt.allocPrint(arena, "{s}.zig", .{target.zig_name}); var zig_code_file = try target_dir.createFile(zig_code_basename, .{}); defer zig_code_file.close(); @@ -1760,7 +1840,7 @@ fn processOneTarget(job: Job) void { \\pub const all_features = blk: { \\ ); - if (llvm_target.branch_quota) |branch_quota| { + if (target.branch_quota) |branch_quota| { try w.print(" @setEvalBranchQuota({d});\n", .{branch_quota}); } try w.writeAll( @@ -1941,10 +2021,10 @@ fn llvmNameToZigName(arena: mem.Allocator, llvm_name: []const u8) ![]const u8 { fn llvmFeatureNameToZigNameOmit( arena: mem.Allocator, - llvm_target: LlvmTarget, + target: ArchTarget, llvm_name: []const u8, ) !?[]const u8 { - for (llvm_target.feature_overrides) |feature_override| { + for (target.feature_overrides) |feature_override| { if (mem.eql(u8, feature_override.llvm_name, llvm_name)) { if (feature_override.omit) return null; return feature_override.zig_name orelse break;