aboutsummaryrefslogtreecommitdiff
path: root/lib/std
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2025-07-23 09:18:50 +0200
committerGitHub <noreply@github.com>2025-07-23 09:18:50 +0200
commit2365392e0e2830b147d82ff055bbed3099b21171 (patch)
treeb37fa80f50f5ee9efea3b805ab357c64fedd6199 /lib/std
parent5c576573bb67b2d5f481f9f02af1d768b729d796 (diff)
parente9b9a27a52fa765ccb8cd838fc24ccfb2085a363 (diff)
downloadzig-2365392e0e2830b147d82ff055bbed3099b21171.tar.gz
zig-2365392e0e2830b147d82ff055bbed3099b21171.zip
Merge pull request #24536 from jacobly0/aarch64
aarch64: add new from scratch self-hosted backend
Diffstat (limited to 'lib/std')
-rw-r--r--lib/std/Io/Writer.zig4
-rw-r--r--lib/std/Progress.zig5
-rw-r--r--lib/std/builtin.zig7
-rw-r--r--lib/std/elf.zig2
-rw-r--r--lib/std/fs/File.zig5
-rw-r--r--lib/std/math.zig93
-rw-r--r--lib/std/math/big/int_test.zig1
-rw-r--r--lib/std/math/float.zig6
-rw-r--r--lib/std/math/log10.zig1
-rw-r--r--lib/std/mem.zig7
-rw-r--r--lib/std/os/linux.zig1
-rw-r--r--lib/std/start.zig59
-rw-r--r--lib/std/testing.zig1
13 files changed, 85 insertions, 107 deletions
diff --git a/lib/std/Io/Writer.zig b/lib/std/Io/Writer.zig
index 0723073592..55672c557c 100644
--- a/lib/std/Io/Writer.zig
+++ b/lib/std/Io/Writer.zig
@@ -2239,6 +2239,10 @@ pub const Discarding = struct {
pub fn sendFile(w: *Writer, file_reader: *File.Reader, limit: Limit) FileError!usize {
if (File.Handle == void) return error.Unimplemented;
+ switch (builtin.zig_backend) {
+ else => {},
+ .stage2_aarch64 => return error.Unimplemented,
+ }
const d: *Discarding = @alignCast(@fieldParentPtr("writer", w));
d.count += w.end;
w.end = 0;
diff --git a/lib/std/Progress.zig b/lib/std/Progress.zig
index 2634553d25..5ee5828970 100644
--- a/lib/std/Progress.zig
+++ b/lib/std/Progress.zig
@@ -408,6 +408,9 @@ pub const have_ipc = switch (builtin.os.tag) {
const noop_impl = builtin.single_threaded or switch (builtin.os.tag) {
.wasi, .freestanding => true,
else => false,
+} or switch (builtin.zig_backend) {
+ .stage2_aarch64 => true,
+ else => false,
};
/// Initializes a global Progress instance.
@@ -754,7 +757,7 @@ fn appendTreeSymbol(symbol: TreeSymbol, buf: []u8, start_i: usize) usize {
}
fn clearWrittenWithEscapeCodes() anyerror!void {
- if (!global_progress.need_clear) return;
+ if (noop_impl or !global_progress.need_clear) return;
global_progress.need_clear = false;
try write(clear);
diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig
index 8f4aefc713..54376426e2 100644
--- a/lib/std/builtin.zig
+++ b/lib/std/builtin.zig
@@ -772,7 +772,7 @@ pub const Endian = enum {
/// This data structure is used by the Zig language code generation and
/// therefore must be kept in sync with the compiler implementation.
-pub const Signedness = enum {
+pub const Signedness = enum(u1) {
signed,
unsigned,
};
@@ -894,7 +894,10 @@ pub const VaList = switch (builtin.cpu.arch) {
.aarch64, .aarch64_be => switch (builtin.os.tag) {
.windows => *u8,
.ios, .macos, .tvos, .watchos, .visionos => *u8,
- else => @compileError("disabled due to miscompilations"), // VaListAarch64,
+ else => switch (builtin.zig_backend) {
+ .stage2_aarch64 => VaListAarch64,
+ else => @compileError("disabled due to miscompilations"),
+ },
},
.arm, .armeb, .thumb, .thumbeb => switch (builtin.os.tag) {
.ios, .macos, .tvos, .watchos, .visionos => *u8,
diff --git a/lib/std/elf.zig b/lib/std/elf.zig
index 47b3add84f..2583e83d19 100644
--- a/lib/std/elf.zig
+++ b/lib/std/elf.zig
@@ -2001,7 +2001,7 @@ pub const R_AARCH64 = enum(u32) {
TLSLE_LDST64_TPREL_LO12 = 558,
/// Likewise; no check.
TLSLE_LDST64_TPREL_LO12_NC = 559,
- /// PC-rel. load immediate 20:2.
+ /// PC-rel. load immediate 20:2.
TLSDESC_LD_PREL19 = 560,
/// PC-rel. ADR immediate 20:0.
TLSDESC_ADR_PREL21 = 561,
diff --git a/lib/std/fs/File.zig b/lib/std/fs/File.zig
index 138807972e..39111f634d 100644
--- a/lib/std/fs/File.zig
+++ b/lib/std/fs/File.zig
@@ -1554,7 +1554,10 @@ pub const Writer = struct {
return .{
.vtable = &.{
.drain = drain,
- .sendFile = sendFile,
+ .sendFile = switch (builtin.zig_backend) {
+ else => sendFile,
+ .stage2_aarch64 => std.io.Writer.unimplementedSendFile,
+ },
},
.buffer = buffer,
};
diff --git a/lib/std/math.zig b/lib/std/math.zig
index 1cd9a83a14..9f2d12a65e 100644
--- a/lib/std/math.zig
+++ b/lib/std/math.zig
@@ -45,6 +45,7 @@ pub const rad_per_deg = 0.017453292519943295769236907684886127134428718885417254
/// 180.0/pi
pub const deg_per_rad = 57.295779513082320876798154814105170332405472466564321549160243861;
+pub const Sign = enum(u1) { positive, negative };
pub const FloatRepr = float.FloatRepr;
pub const floatExponentBits = float.floatExponentBits;
pub const floatMantissaBits = float.floatMantissaBits;
@@ -594,27 +595,30 @@ pub fn shlExact(comptime T: type, a: T, shift_amt: Log2Int(T)) !T {
/// Shifts left. Overflowed bits are truncated.
/// A negative shift amount results in a right shift.
pub fn shl(comptime T: type, a: T, shift_amt: anytype) T {
+ const is_shl = shift_amt >= 0;
const abs_shift_amt = @abs(shift_amt);
-
- const casted_shift_amt = blk: {
- if (@typeInfo(T) == .vector) {
- const C = @typeInfo(T).vector.child;
- const len = @typeInfo(T).vector.len;
- if (abs_shift_amt >= @typeInfo(C).int.bits) return @splat(0);
- break :blk @as(@Vector(len, Log2Int(C)), @splat(@as(Log2Int(C), @intCast(abs_shift_amt))));
- } else {
- if (abs_shift_amt >= @typeInfo(T).int.bits) return 0;
- break :blk @as(Log2Int(T), @intCast(abs_shift_amt));
- }
+ const casted_shift_amt = casted_shift_amt: switch (@typeInfo(T)) {
+ .int => |info| {
+ if (abs_shift_amt < info.bits) break :casted_shift_amt @as(
+ Log2Int(T),
+ @intCast(abs_shift_amt),
+ );
+ if (info.signedness == .unsigned or is_shl) return 0;
+ return a >> (info.bits - 1);
+ },
+ .vector => |info| {
+ const Child = info.child;
+ const child_info = @typeInfo(Child).int;
+ if (abs_shift_amt < child_info.bits) break :casted_shift_amt @as(
+ @Vector(info.len, Log2Int(Child)),
+ @splat(@as(Log2Int(Child), @intCast(abs_shift_amt))),
+ );
+ if (child_info.signedness == .unsigned or is_shl) return @splat(0);
+ return a >> @splat(child_info.bits - 1);
+ },
+ else => comptime unreachable,
};
-
- if (@TypeOf(shift_amt) == comptime_int or @typeInfo(@TypeOf(shift_amt)).int.signedness == .signed) {
- if (shift_amt < 0) {
- return a >> casted_shift_amt;
- }
- }
-
- return a << casted_shift_amt;
+ return if (is_shl) a << casted_shift_amt else a >> casted_shift_amt;
}
test shl {
@@ -629,32 +633,40 @@ test shl {
try testing.expect(shl(@Vector(1, u32), @Vector(1, u32){42}, @as(usize, 1))[0] == @as(u32, 42) << 1);
try testing.expect(shl(@Vector(1, u32), @Vector(1, u32){42}, @as(isize, -1))[0] == @as(u32, 42) >> 1);
try testing.expect(shl(@Vector(1, u32), @Vector(1, u32){42}, 33)[0] == 0);
+
+ try testing.expect(shl(i8, -1, -100) == -1);
+ try testing.expect(shl(i8, -1, 100) == 0);
+ try testing.expect(@reduce(.And, shl(@Vector(2, i8), .{ -1, 1 }, -100) == @Vector(2, i8){ -1, 0 }));
+ try testing.expect(@reduce(.And, shl(@Vector(2, i8), .{ -1, 1 }, 100) == @Vector(2, i8){ 0, 0 }));
}
/// Shifts right. Overflowed bits are truncated.
/// A negative shift amount results in a left shift.
pub fn shr(comptime T: type, a: T, shift_amt: anytype) T {
+ const is_shl = shift_amt < 0;
const abs_shift_amt = @abs(shift_amt);
-
- const casted_shift_amt = blk: {
- if (@typeInfo(T) == .vector) {
- const C = @typeInfo(T).vector.child;
- const len = @typeInfo(T).vector.len;
- if (abs_shift_amt >= @typeInfo(C).int.bits) return @splat(0);
- break :blk @as(@Vector(len, Log2Int(C)), @splat(@as(Log2Int(C), @intCast(abs_shift_amt))));
- } else {
- if (abs_shift_amt >= @typeInfo(T).int.bits) return 0;
- break :blk @as(Log2Int(T), @intCast(abs_shift_amt));
- }
+ const casted_shift_amt = casted_shift_amt: switch (@typeInfo(T)) {
+ .int => |info| {
+ if (abs_shift_amt < info.bits) break :casted_shift_amt @as(
+ Log2Int(T),
+ @intCast(abs_shift_amt),
+ );
+ if (info.signedness == .unsigned or is_shl) return 0;
+ return a >> (info.bits - 1);
+ },
+ .vector => |info| {
+ const Child = info.child;
+ const child_info = @typeInfo(Child).int;
+ if (abs_shift_amt < child_info.bits) break :casted_shift_amt @as(
+ @Vector(info.len, Log2Int(Child)),
+ @splat(@as(Log2Int(Child), @intCast(abs_shift_amt))),
+ );
+ if (child_info.signedness == .unsigned or is_shl) return @splat(0);
+ return a >> @splat(child_info.bits - 1);
+ },
+ else => comptime unreachable,
};
-
- if (@TypeOf(shift_amt) == comptime_int or @typeInfo(@TypeOf(shift_amt)).int.signedness == .signed) {
- if (shift_amt < 0) {
- return a << casted_shift_amt;
- }
- }
-
- return a >> casted_shift_amt;
+ return if (is_shl) a << casted_shift_amt else a >> casted_shift_amt;
}
test shr {
@@ -669,6 +681,11 @@ test shr {
try testing.expect(shr(@Vector(1, u32), @Vector(1, u32){42}, @as(usize, 1))[0] == @as(u32, 42) >> 1);
try testing.expect(shr(@Vector(1, u32), @Vector(1, u32){42}, @as(isize, -1))[0] == @as(u32, 42) << 1);
try testing.expect(shr(@Vector(1, u32), @Vector(1, u32){42}, 33)[0] == 0);
+
+ try testing.expect(shr(i8, -1, -100) == 0);
+ try testing.expect(shr(i8, -1, 100) == -1);
+ try testing.expect(@reduce(.And, shr(@Vector(2, i8), .{ -1, 1 }, -100) == @Vector(2, i8){ 0, 0 }));
+ try testing.expect(@reduce(.And, shr(@Vector(2, i8), .{ -1, 1 }, 100) == @Vector(2, i8){ -1, 0 }));
}
/// Rotates right. Only unsigned values can be rotated. Negative shift
diff --git a/lib/std/math/big/int_test.zig b/lib/std/math/big/int_test.zig
index f44b254cf1..bb6deeb778 100644
--- a/lib/std/math/big/int_test.zig
+++ b/lib/std/math/big/int_test.zig
@@ -2774,7 +2774,6 @@ test "bitNotWrap more than two limbs" {
// This test requires int sizes greater than 128 bits.
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
- 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.cpu.arch.isWasm()) return error.SkipZigTest; // TODO
diff --git a/lib/std/math/float.zig b/lib/std/math/float.zig
index df7d7fe1ab..6ffbd85bd2 100644
--- a/lib/std/math/float.zig
+++ b/lib/std/math/float.zig
@@ -4,8 +4,6 @@ const assert = std.debug.assert;
const expect = std.testing.expect;
const expectEqual = std.testing.expectEqual;
-pub const Sign = enum(u1) { positive, negative };
-
pub fn FloatRepr(comptime Float: type) type {
const fractional_bits = floatFractionalBits(Float);
const exponent_bits = floatExponentBits(Float);
@@ -14,7 +12,7 @@ pub fn FloatRepr(comptime Float: type) type {
mantissa: StoredMantissa,
exponent: BiasedExponent,
- sign: Sign,
+ sign: std.math.Sign,
pub const StoredMantissa = @Type(.{ .int = .{
.signedness = .unsigned,
@@ -69,7 +67,7 @@ pub fn FloatRepr(comptime Float: type) type {
/// This currently truncates denormal values, which needs to be fixed before this can be used to
/// produce a rounded value.
- pub fn reconstruct(normalized: Normalized, sign: Sign) Float {
+ pub fn reconstruct(normalized: Normalized, sign: std.math.Sign) Float {
if (normalized.exponent > BiasedExponent.max_normal.unbias()) return @bitCast(Repr{
.mantissa = 0,
.exponent = .infinite,
diff --git a/lib/std/math/log10.zig b/lib/std/math/log10.zig
index 655a42215e..9ac5c6da24 100644
--- a/lib/std/math/log10.zig
+++ b/lib/std/math/log10.zig
@@ -132,7 +132,6 @@ inline fn less_than_5(x: u32) u32 {
test log10_int {
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
- 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.cpu.arch.isWasm()) return error.SkipZigTest; // TODO
diff --git a/lib/std/mem.zig b/lib/std/mem.zig
index 1a61076f32..3b72a2b579 100644
--- a/lib/std/mem.zig
+++ b/lib/std/mem.zig
@@ -676,6 +676,7 @@ test lessThan {
const eqlBytes_allowed = switch (builtin.zig_backend) {
// These backends don't support vectors yet.
+ .stage2_aarch64,
.stage2_powerpc,
.stage2_riscv64,
=> false,
@@ -4482,7 +4483,7 @@ pub fn doNotOptimizeAway(val: anytype) void {
);
asm volatile (""
:
- : [val2] "r" (val2),
+ : [_] "r" (val2),
);
} else doNotOptimizeAway(&val);
},
@@ -4490,7 +4491,7 @@ pub fn doNotOptimizeAway(val: anytype) void {
if ((t.float.bits == 32 or t.float.bits == 64) and builtin.zig_backend != .stage2_c) {
asm volatile (""
:
- : [val] "rm" (val),
+ : [_] "rm" (val),
);
} else doNotOptimizeAway(&val);
},
@@ -4500,7 +4501,7 @@ pub fn doNotOptimizeAway(val: anytype) void {
} else {
asm volatile (""
:
- : [val] "m" (val),
+ : [_] "m" (val),
: .{ .memory = true });
}
},
diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig
index 75494145b9..a02451c0fd 100644
--- a/lib/std/os/linux.zig
+++ b/lib/std/os/linux.zig
@@ -503,7 +503,6 @@ pub var elf_aux_maybe: ?[*]std.elf.Auxv = null;
/// Whether an external or internal getauxval implementation is used.
const extern_getauxval = switch (builtin.zig_backend) {
// Calling extern functions is not yet supported with these backends
- .stage2_aarch64,
.stage2_arm,
.stage2_powerpc,
.stage2_riscv64,
diff --git a/lib/std/start.zig b/lib/std/start.zig
index 22ccda1e40..43355d34f4 100644
--- a/lib/std/start.zig
+++ b/lib/std/start.zig
@@ -101,17 +101,11 @@ comptime {
// Simplified start code for stage2 until it supports more language features ///
fn main2() callconv(.c) c_int {
- root.main();
- return 0;
+ return callMain();
}
fn _start2() callconv(.withStackAlign(.c, 1)) noreturn {
- callMain2();
-}
-
-fn callMain2() noreturn {
- root.main();
- exit2(0);
+ std.posix.exit(callMain());
}
fn spirvMain2() callconv(.kernel) void {
@@ -119,51 +113,7 @@ fn spirvMain2() callconv(.kernel) void {
}
fn wWinMainCRTStartup2() callconv(.c) noreturn {
- root.main();
- exit2(0);
-}
-
-fn exit2(code: usize) noreturn {
- switch (native_os) {
- .linux => switch (builtin.cpu.arch) {
- .x86_64 => {
- asm volatile ("syscall"
- :
- : [number] "{rax}" (231),
- [arg1] "{rdi}" (code),
- : .{ .rcx = true, .r11 = true, .memory = true });
- },
- .arm => {
- asm volatile ("svc #0"
- :
- : [number] "{r7}" (1),
- [arg1] "{r0}" (code),
- : .{ .memory = true });
- },
- .aarch64 => {
- asm volatile ("svc #0"
- :
- : [number] "{x8}" (93),
- [arg1] "{x0}" (code),
- : .{ .memory = true });
- },
- .sparc64 => {
- asm volatile ("ta 0x6d"
- :
- : [number] "{g1}" (1),
- [arg1] "{o0}" (code),
- : .{ .o0 = true, .o1 = true, .o2 = true, .o3 = true, .o4 = true, .o5 = true, .o6 = true, .o7 = true, .memory = true });
- },
- else => @compileError("TODO"),
- },
- // exits(0)
- .plan9 => std.os.plan9.exits(null),
- .windows => {
- std.os.windows.ntdll.RtlExitUserProcess(@truncate(code));
- },
- else => @compileError("TODO"),
- }
- unreachable;
+ std.posix.exit(callMain());
}
////////////////////////////////////////////////////////////////////////////////
@@ -676,10 +626,11 @@ pub inline fn callMain() u8 {
const result = root.main() catch |err| {
switch (builtin.zig_backend) {
+ .stage2_aarch64,
.stage2_powerpc,
.stage2_riscv64,
=> {
- std.debug.print("error: failed with error\n", .{});
+ _ = std.posix.write(std.posix.STDERR_FILENO, "error: failed with error\n") catch {};
return 1;
},
else => {},
diff --git a/lib/std/testing.zig b/lib/std/testing.zig
index f9027a4f47..e80e961b13 100644
--- a/lib/std/testing.zig
+++ b/lib/std/testing.zig
@@ -33,6 +33,7 @@ pub var log_level = std.log.Level.warn;
// Disable printing in tests for simple backends.
pub const backend_can_print = switch (builtin.zig_backend) {
+ .stage2_aarch64,
.stage2_powerpc,
.stage2_riscv64,
.stage2_spirv,