authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-07-29 16:13:35-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-07-29 16:13:35-07:00
log38e0f049c531e83ec2eec80d50b624e6c3b8c486
tree76fb3cf957c9963a720e1845667666b0937e4619
parent73a444766e4d1406c194935b54e8167e747b165f
parent13945548fcd4fe3aab0879b670db1fe8131d8b0e
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #20389 from alexrp/riscv32

Some `riscv32-linux` porting work

21 files changed, 913 insertions(+), 222 deletions(-)

lib/c.zig+34
......@@ -319,6 +319,40 @@ fn clone() callconv(.Naked) void {
319319 \\3: bx r5
320320 );
321321 },
322 .riscv32 => {
323 // __clone(func, stack, flags, arg, ptid, tls, ctid)
324 // a0, a1, a2, a3, a4, a5, a6
325
326 // syscall(SYS_clone, flags, stack, ptid, tls, ctid)
327 // a7 a0, a1, a2, a3, a4
328 asm volatile (
329 \\ # Save func and arg to stack
330 \\ addi a1, a1, -8
331 \\ sw a0, 0(a1)
332 \\ sw a3, 4(a1)
333 \\
334 \\ # Call SYS_clone
335 \\ mv a0, a2
336 \\ mv a2, a4
337 \\ mv a3, a5
338 \\ mv a4, a6
339 \\ li a7, 220 # SYS_clone
340 \\ ecall
341 \\
342 \\ beqz a0, 1f
343 \\ # Parent
344 \\ ret
345 \\
346 \\ # Child
347 \\1: lw a1, 0(sp)
348 \\ lw a0, 4(sp)
349 \\ jalr a1
350 \\
351 \\ # Exit
352 \\ li a7, 93 # SYS_exit
353 \\ ecall
354 );
355 },
322356 .riscv64 => {
323357 // __clone(func, stack, flags, arg, ptid, tls, ctid)
324358 // a0, a1, a2, a3, a4, a5, a6
lib/std/Target.zig+10-1
......@@ -720,7 +720,16 @@ pub const Abi = enum {
720720
721721 pub inline fn isGnu(abi: Abi) bool {
722722 return switch (abi) {
723 .gnu, .gnuabin32, .gnuabi64, .gnueabi, .gnueabihf, .gnux32 => true,
723 .gnu,
724 .gnuabin32,
725 .gnuabi64,
726 .gnueabi,
727 .gnueabihf,
728 .gnuf32,
729 .gnusf,
730 .gnux32,
731 .gnuilp32,
732 => true,
724733 else => false,
725734 };
726735 }
lib/std/Thread.zig+31-18
......@@ -1082,11 +1082,11 @@ const LinuxThreadImpl = struct {
10821082 fn freeAndExit(self: *ThreadCompletion) noreturn {
10831083 switch (target.cpu.arch) {
10841084 .x86 => asm volatile (
1085 \\ movl $91, %%eax
1085 \\ movl $91, %%eax # SYS_munmap
10861086 \\ movl %[ptr], %%ebx
10871087 \\ movl %[len], %%ecx
10881088 \\ int $128
1089 \\ movl $1, %%eax
1089 \\ movl $1, %%eax # SYS_exit
10901090 \\ movl $0, %%ebx
10911091 \\ int $128
10921092 :
......@@ -1095,9 +1095,9 @@ const LinuxThreadImpl = struct {
10951095 : "memory"
10961096 ),
10971097 .x86_64 => asm volatile (
1098 \\ movq $11, %%rax
1098 \\ movq $11, %%rax # SYS_munmap
10991099 \\ syscall
1100 \\ movq $60, %%rax
1100 \\ movq $60, %%rax # SYS_exit
11011101 \\ movq $1, %%rdi
11021102 \\ syscall
11031103 :
......@@ -1105,11 +1105,11 @@ const LinuxThreadImpl = struct {
11051105 [len] "{rsi}" (self.mapped.len),
11061106 ),
11071107 .arm, .armeb, .thumb, .thumbeb => asm volatile (
1108 \\ mov r7, #91
1108 \\ mov r7, #91 // SYS_munmap
11091109 \\ mov r0, %[ptr]
11101110 \\ mov r1, %[len]
11111111 \\ svc 0
1112 \\ mov r7, #1
1112 \\ mov r7, #1 // SYS_exit
11131113 \\ mov r0, #0
11141114 \\ svc 0
11151115 :
......@@ -1118,11 +1118,11 @@ const LinuxThreadImpl = struct {
11181118 : "memory"
11191119 ),
11201120 .aarch64, .aarch64_be => asm volatile (
1121 \\ mov x8, #215
1121 \\ mov x8, #215 // SYS_munmap
11221122 \\ mov x0, %[ptr]
11231123 \\ mov x1, %[len]
11241124 \\ svc 0
1125 \\ mov x8, #93
1125 \\ mov x8, #93 // SYS_exit
11261126 \\ mov x0, #0
11271127 \\ svc 0
11281128 :
......@@ -1132,11 +1132,11 @@ const LinuxThreadImpl = struct {
11321132 ),
11331133 .mips, .mipsel => asm volatile (
11341134 \\ move $sp, $25
1135 \\ li $2, 4091
1135 \\ li $2, 4091 # SYS_munmap
11361136 \\ move $4, %[ptr]
11371137 \\ move $5, %[len]
11381138 \\ syscall
1139 \\ li $2, 4001
1139 \\ li $2, 4001 # SYS_exit
11401140 \\ li $4, 0
11411141 \\ syscall
11421142 :
......@@ -1145,11 +1145,11 @@ const LinuxThreadImpl = struct {
11451145 : "memory"
11461146 ),
11471147 .mips64, .mips64el => asm volatile (
1148 \\ li $2, 4091
1148 \\ li $2, 4091 # SYS_munmap
11491149 \\ move $4, %[ptr]
11501150 \\ move $5, %[len]
11511151 \\ syscall
1152 \\ li $2, 4001
1152 \\ li $2, 4001 # SYS_exit
11531153 \\ li $4, 0
11541154 \\ syscall
11551155 :
......@@ -1158,11 +1158,11 @@ const LinuxThreadImpl = struct {
11581158 : "memory"
11591159 ),
11601160 .powerpc, .powerpcle, .powerpc64, .powerpc64le => asm volatile (
1161 \\ li 0, 91
1161 \\ li 0, 91 # SYS_munmap
11621162 \\ mr %[ptr], 3
11631163 \\ mr %[len], 4
11641164 \\ sc
1165 \\ li 0, 1
1165 \\ li 0, 1 # SYS_exit
11661166 \\ li 3, 0
11671167 \\ sc
11681168 \\ blr
......@@ -1171,12 +1171,25 @@ const LinuxThreadImpl = struct {
11711171 [len] "r" (self.mapped.len),
11721172 : "memory"
11731173 ),
1174 .riscv32 => asm volatile (
1175 \\ li a7, 215 # SYS_munmap
1176 \\ mv a0, %[ptr]
1177 \\ mv a1, %[len]
1178 \\ ecall
1179 \\ li a7, 93 # SYS_exit
1180 \\ mv a0, zero
1181 \\ ecall
1182 :
1183 : [ptr] "r" (@intFromPtr(self.mapped.ptr)),
1184 [len] "r" (self.mapped.len),
1185 : "memory"
1186 ),
11741187 .riscv64 => asm volatile (
1175 \\ li a7, 215
1188 \\ li a7, 215 # SYS_munmap
11761189 \\ mv a0, %[ptr]
11771190 \\ mv a1, %[len]
11781191 \\ ecall
1179 \\ li a7, 93
1192 \\ li a7, 93 # SYS_exit
11801193 \\ mv a0, zero
11811194 \\ ecall
11821195 :
......@@ -1196,14 +1209,14 @@ const LinuxThreadImpl = struct {
11961209 \\ ba 1b
11971210 \\ restore
11981211 \\ 2:
1199 \\ mov 73, %%g1
1212 \\ mov 73, %%g1 # SYS_munmap
12001213 \\ mov %[ptr], %%o0
12011214 \\ mov %[len], %%o1
12021215 \\ # Flush register window contents to prevent background
12031216 \\ # memory access before unmapping the stack.
12041217 \\ flushw
12051218 \\ t 0x6d
1206 \\ mov 1, %%g1
1219 \\ mov 1, %%g1 # SYS_exit
12071220 \\ mov 1, %%o0
12081221 \\ t 0x6d
12091222 :
lib/std/debug.zig+2-1
......@@ -747,7 +747,8 @@ pub const StackIterator = struct {
747747 .SUCCESS => return bytes_read == buf.len,
748748 .FAULT => return false,
749749 .INVAL, .PERM, .SRCH => unreachable, // own pid is always valid
750 .NOMEM, .NOSYS => {},
750 .NOMEM => {},
751 .NOSYS => {}, // QEMU is known not to implement this syscall.
751752 else => unreachable, // unexpected
752753 }
753754 var path_buf: [
lib/std/fs/Dir.zig+27-2
......@@ -334,7 +334,6 @@ pub const Iterator = switch (native_os) {
334334 first_iter: bool,
335335
336336 const Self = @This();
337 const linux = std.os.linux;
338337
339338 pub const Error = IteratorError;
340339
......@@ -2690,8 +2689,33 @@ pub fn statFile(self: Dir, sub_path: []const u8) StatFileError!Stat {
26902689 const st = try std.os.fstatat_wasi(self.fd, sub_path, .{ .SYMLINK_FOLLOW = true });
26912690 return Stat.fromWasi(st);
26922691 }
2692 if (native_os == .linux) {
2693 const sub_path_c = try posix.toPosixPath(sub_path);
2694 var stx = std.mem.zeroes(linux.Statx);
2695
2696 const rc = linux.statx(
2697 self.fd,
2698 &sub_path_c,
2699 linux.AT.NO_AUTOMOUNT,
2700 linux.STATX_TYPE | linux.STATX_MODE | linux.STATX_ATIME | linux.STATX_MTIME | linux.STATX_CTIME,
2701 &stx,
2702 );
2703
2704 return switch (linux.E.init(rc)) {
2705 .SUCCESS => Stat.fromLinux(stx),
2706 .ACCES => error.AccessDenied,
2707 .BADF => unreachable,
2708 .FAULT => unreachable,
2709 .INVAL => unreachable,
2710 .LOOP => error.SymLinkLoop,
2711 .NAMETOOLONG => unreachable, // Handled by posix.toPosixPath() above.
2712 .NOENT, .NOTDIR => error.FileNotFound,
2713 .NOMEM => error.SystemResources,
2714 else => |err| posix.unexpectedErrno(err),
2715 };
2716 }
26932717 const st = try posix.fstatat(self.fd, sub_path, 0);
2694 return Stat.fromSystem(st);
2718 return Stat.fromPosix(st);
26952719}
26962720
26972721pub const ChmodError = File.ChmodError;
......@@ -2751,6 +2775,7 @@ const path = fs.path;
27512775const fs = std.fs;
27522776const Allocator = std.mem.Allocator;
27532777const assert = std.debug.assert;
2778const linux = std.os.linux;
27542779const windows = std.os.windows;
27552780const native_os = builtin.os.tag;
27562781const have_flock = @TypeOf(posix.system.flock) != void;
lib/std/fs/File.zig+76-30
......@@ -342,7 +342,7 @@ pub fn seekTo(self: File, offset: u64) SeekError!void {
342342 return posix.lseek_SET(self.handle, offset);
343343}
344344
345pub const GetSeekPosError = posix.SeekError || posix.FStatError;
345pub const GetSeekPosError = posix.SeekError || StatError;
346346
347347/// TODO: integrate with async I/O
348348pub fn getPos(self: File) GetSeekPosError!u64 {
......@@ -357,7 +357,7 @@ pub fn getEndPos(self: File) GetSeekPosError!u64 {
357357 return (try self.stat()).size;
358358}
359359
360pub const ModeError = posix.FStatError;
360pub const ModeError = StatError;
361361
362362/// TODO: integrate with async I/O
363363pub fn mode(self: File) ModeError!Mode {
......@@ -392,7 +392,7 @@ pub const Stat = struct {
392392 /// Last status/metadata change time in nanoseconds, relative to UTC 1970-01-01.
393393 ctime: i128,
394394
395 pub fn fromSystem(st: posix.Stat) Stat {
395 pub fn fromPosix(st: posix.Stat) Stat {
396396 const atime = st.atime();
397397 const mtime = st.mtime();
398398 const ctime = st.ctime();
......@@ -426,6 +426,31 @@ pub const Stat = struct {
426426 };
427427 }
428428
429 pub fn fromLinux(stx: linux.Statx) Stat {
430 const atime = stx.atime;
431 const mtime = stx.mtime;
432 const ctime = stx.ctime;
433
434 return .{
435 .inode = stx.ino,
436 .size = stx.size,
437 .mode = stx.mode,
438 .kind = switch (stx.mode & linux.S.IFMT) {
439 linux.S.IFDIR => .directory,
440 linux.S.IFCHR => .character_device,
441 linux.S.IFBLK => .block_device,
442 linux.S.IFREG => .file,
443 linux.S.IFIFO => .named_pipe,
444 linux.S.IFLNK => .sym_link,
445 linux.S.IFSOCK => .unix_domain_socket,
446 else => .unknown,
447 },
448 .atime = @as(i128, atime.sec) * std.time.ns_per_s + atime.nsec,
449 .mtime = @as(i128, mtime.sec) * std.time.ns_per_s + mtime.nsec,
450 .ctime = @as(i128, ctime.sec) * std.time.ns_per_s + ctime.nsec,
451 };
452 }
453
429454 pub fn fromWasi(st: std.os.wasi.filestat_t) Stat {
430455 return .{
431456 .inode = st.ino,
......@@ -502,8 +527,34 @@ pub fn stat(self: File) StatError!Stat {
502527 return Stat.fromWasi(st);
503528 }
504529
530 if (builtin.os.tag == .linux) {
531 var stx = std.mem.zeroes(linux.Statx);
532
533 const rc = linux.statx(
534 self.handle,
535 "",
536 linux.AT.EMPTY_PATH,
537 linux.STATX_TYPE | linux.STATX_MODE | linux.STATX_ATIME | linux.STATX_MTIME | linux.STATX_CTIME,
538 &stx,
539 );
540
541 return switch (linux.E.init(rc)) {
542 .SUCCESS => Stat.fromLinux(stx),
543 .ACCES => unreachable,
544 .BADF => unreachable,
545 .FAULT => unreachable,
546 .INVAL => unreachable,
547 .LOOP => unreachable,
548 .NAMETOOLONG => unreachable,
549 .NOENT => unreachable,
550 .NOMEM => error.SystemResources,
551 .NOTDIR => unreachable,
552 else => |err| posix.unexpectedErrno(err),
553 };
554 }
555
505556 const st = try posix.fstat(self.handle);
506 return Stat.fromSystem(st);
557 return Stat.fromPosix(st);
507558}
508559
509560pub const ChmodError = posix.FChmodError;
......@@ -731,7 +782,7 @@ pub const Metadata = struct {
731782
732783 /// Returns the time the file was created in nanoseconds since UTC 1970-01-01
733784 /// On Windows, this cannot return null
734 /// On Linux, this returns null if the filesystem does not support creation times, or if the kernel is older than 4.11
785 /// On Linux, this returns null if the filesystem does not support creation times
735786 /// On Unices, this returns null if the filesystem or OS does not support creation times
736787 /// On MacOS, this returns the ctime if the filesystem does not support creation times; this is insanity, and yet another reason to hate on Apple
737788 pub fn created(self: Self) ?i128 {
......@@ -822,7 +873,6 @@ pub const MetadataUnix = struct {
822873};
823874
824875/// `MetadataUnix`, but using Linux's `statx` syscall.
825/// On Linux versions below 4.11, `statx` will be filled with data from stat.
826876pub const MetadataLinux = struct {
827877 statx: std.os.linux.Statx,
828878
......@@ -1010,34 +1060,29 @@ pub fn metadata(self: File) MetadataError!Metadata {
10101060 };
10111061 },
10121062 .linux => blk: {
1013 const l = std.os.linux;
1014 var stx = std.mem.zeroes(l.Statx);
1015 const rcx = l.statx(self.handle, "\x00", l.AT.EMPTY_PATH, l.STATX_TYPE |
1016 l.STATX_MODE | l.STATX_ATIME | l.STATX_MTIME | l.STATX_BTIME, &stx);
1017
1018 switch (posix.errno(rcx)) {
1063 var stx = std.mem.zeroes(linux.Statx);
1064
1065 // We are gathering information for Metadata, which is meant to contain all the
1066 // native OS information about the file, so use all known flags.
1067 const rc = linux.statx(
1068 self.handle,
1069 "",
1070 linux.AT.EMPTY_PATH,
1071 linux.STATX_BASIC_STATS | linux.STATX_BTIME,
1072 &stx,
1073 );
1074
1075 switch (posix.errno(rc)) {
10191076 .SUCCESS => {},
1020 // NOSYS happens when `statx` is unsupported, which is the case on kernel versions before 4.11
1021 // Here, we call `fstat` and fill `stx` with the data we need
1022 .NOSYS => {
1023 const st = try posix.fstat(self.handle);
1024
1025 stx.mode = @as(u16, @intCast(st.mode));
1026
1027 // Hacky conversion from timespec to statx_timestamp
1028 stx.atime = std.mem.zeroes(l.statx_timestamp);
1029 stx.atime.sec = st.atim.sec;
1030 stx.atime.nsec = @as(u32, @intCast(st.atim.nsec)); // Guaranteed to succeed (nsec is always below 10^9)
1031
1032 stx.mtime = std.mem.zeroes(l.statx_timestamp);
1033 stx.mtime.sec = st.mtim.sec;
1034 stx.mtime.nsec = @as(u32, @intCast(st.mtim.nsec));
1035
1036 stx.mask = l.STATX_BASIC_STATS | l.STATX_MTIME;
1037 },
1077 .ACCES => unreachable,
10381078 .BADF => unreachable,
10391079 .FAULT => unreachable,
1080 .INVAL => unreachable,
1081 .LOOP => unreachable,
1082 .NAMETOOLONG => unreachable,
1083 .NOENT => unreachable,
10401084 .NOMEM => return error.SystemResources,
1085 .NOTDIR => unreachable,
10411086 else => |err| return posix.unexpectedErrno(err),
10421087 }
10431088
......@@ -1731,6 +1776,7 @@ const posix = std.posix;
17311776const io = std.io;
17321777const math = std.math;
17331778const assert = std.debug.assert;
1779const linux = std.os.linux;
17341780const windows = std.os.windows;
17351781const Os = std.builtin.Os;
17361782const maxInt = std.math.maxInt;
lib/std/os/linux.zig+61-37
......@@ -39,6 +39,7 @@ const arch_bits = switch (native_arch) {
3939 .x86_64 => @import("linux/x86_64.zig"),
4040 .aarch64, .aarch64_be => @import("linux/arm64.zig"),
4141 .arm, .armeb, .thumb, .thumbeb => @import("linux/arm-eabi.zig"),
42 .riscv32 => @import("linux/riscv32.zig"),
4243 .riscv64 => @import("linux/riscv64.zig"),
4344 .sparc64 => @import("linux/sparc64.zig"),
4445 .mips, .mipsel => @import("linux/mips.zig"),
......@@ -104,6 +105,7 @@ pub const SYS = switch (@import("builtin").cpu.arch) {
104105 .x86_64 => syscalls.X64,
105106 .aarch64, .aarch64_be => syscalls.Arm64,
106107 .arm, .armeb, .thumb, .thumbeb => syscalls.Arm,
108 .riscv32 => syscalls.RiscV32,
107109 .riscv64 => syscalls.RiscV64,
108110 .sparc64 => syscalls.Sparc64,
109111 .mips, .mipsel => syscalls.Mips,
......@@ -163,7 +165,7 @@ pub const MAP = switch (native_arch) {
163165 UNINITIALIZED: bool = false,
164166 _: u5 = 0,
165167 },
166 .riscv64 => packed struct(u32) {
168 .riscv32, .riscv64 => packed struct(u32) {
167169 TYPE: MAP_TYPE,
168170 FIXED: bool = false,
169171 ANONYMOUS: bool = false,
......@@ -268,7 +270,7 @@ pub const O = switch (native_arch) {
268270 TMPFILE: bool = false,
269271 _: u9 = 0,
270272 },
271 .x86, .riscv64 => packed struct(u32) {
273 .x86, .riscv32, .riscv64 => packed struct(u32) {
272274 ACCMODE: ACCMODE = .RDONLY,
273275 _2: u4 = 0,
274276 CREAT: bool = false,
......@@ -474,7 +476,7 @@ pub fn dup2(old: i32, new: i32) usize {
474476 } else {
475477 if (old == new) {
476478 if (std.debug.runtime_safety) {
477 const rc = syscall2(.fcntl, @as(usize, @bitCast(@as(isize, old))), F.GETFD);
479 const rc = fcntl(F.GETFD, @as(fd_t, old), 0);
478480 if (@as(isize, @bitCast(rc)) < 0) return rc;
479481 }
480482 return @as(usize, @intCast(old));
......@@ -1211,7 +1213,7 @@ pub fn llseek(fd: i32, offset: u64, result: ?*u64, whence: usize) usize {
12111213 // NOTE: The offset parameter splitting is independent from the target
12121214 // endianness.
12131215 return syscall5(
1214 ._llseek,
1216 .llseek,
12151217 @as(usize, @bitCast(@as(isize, fd))),
12161218 @as(usize, @truncate(offset >> 32)),
12171219 @as(usize, @truncate(offset)),
......@@ -1370,7 +1372,11 @@ pub fn waitid(id_type: P, id: i32, infop: *siginfo_t, flags: u32) usize {
13701372}
13711373
13721374pub fn fcntl(fd: fd_t, cmd: i32, arg: usize) usize {
1373 return syscall3(.fcntl, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, cmd))), arg);
1375 if (@hasField(SYS, "fcntl64")) {
1376 return syscall3(.fcntl64, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, cmd))), arg);
1377 } else {
1378 return syscall3(.fcntl, @as(usize, @bitCast(@as(isize, fd))), @as(usize, @bitCast(@as(isize, cmd))), arg);
1379 }
13741380}
13751381
13761382pub fn flock(fd: fd_t, operation: i32) usize {
......@@ -1836,7 +1842,11 @@ pub fn accept4(fd: i32, noalias addr: ?*sockaddr, noalias len: ?*socklen_t, flag
18361842}
18371843
18381844pub fn fstat(fd: i32, stat_buf: *Stat) usize {
1839 if (@hasField(SYS, "fstat64")) {
1845 if (native_arch == .riscv32) {
1846 // riscv32 has made the interesting decision to not implement some of
1847 // the older stat syscalls, including this one.
1848 @compileError("No fstat syscall on this architecture.");
1849 } else if (@hasField(SYS, "fstat64")) {
18401850 return syscall2(.fstat64, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(stat_buf));
18411851 } else {
18421852 return syscall2(.fstat, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(stat_buf));
......@@ -1844,7 +1854,11 @@ pub fn fstat(fd: i32, stat_buf: *Stat) usize {
18441854}
18451855
18461856pub fn stat(pathname: [*:0]const u8, statbuf: *Stat) usize {
1847 if (@hasField(SYS, "stat64")) {
1857 if (native_arch == .riscv32) {
1858 // riscv32 has made the interesting decision to not implement some of
1859 // the older stat syscalls, including this one.
1860 @compileError("No stat syscall on this architecture.");
1861 } else if (@hasField(SYS, "stat64")) {
18481862 return syscall2(.stat64, @intFromPtr(pathname), @intFromPtr(statbuf));
18491863 } else {
18501864 return syscall2(.stat, @intFromPtr(pathname), @intFromPtr(statbuf));
......@@ -1852,7 +1866,11 @@ pub fn stat(pathname: [*:0]const u8, statbuf: *Stat) usize {
18521866}
18531867
18541868pub fn lstat(pathname: [*:0]const u8, statbuf: *Stat) usize {
1855 if (@hasField(SYS, "lstat64")) {
1869 if (native_arch == .riscv32) {
1870 // riscv32 has made the interesting decision to not implement some of
1871 // the older stat syscalls, including this one.
1872 @compileError("No lstat syscall on this architecture.");
1873 } else if (@hasField(SYS, "lstat64")) {
18561874 return syscall2(.lstat64, @intFromPtr(pathname), @intFromPtr(statbuf));
18571875 } else {
18581876 return syscall2(.lstat, @intFromPtr(pathname), @intFromPtr(statbuf));
......@@ -1860,7 +1878,11 @@ pub fn lstat(pathname: [*:0]const u8, statbuf: *Stat) usize {
18601878}
18611879
18621880pub fn fstatat(dirfd: i32, path: [*:0]const u8, stat_buf: *Stat, flags: u32) usize {
1863 if (@hasField(SYS, "fstatat64")) {
1881 if (native_arch == .riscv32) {
1882 // riscv32 has made the interesting decision to not implement some of
1883 // the older stat syscalls, including this one.
1884 @compileError("No fstatat syscall on this architecture.");
1885 } else if (@hasField(SYS, "fstatat64")) {
18641886 return syscall4(.fstatat64, @as(usize, @bitCast(@as(isize, dirfd))), @intFromPtr(path), @intFromPtr(stat_buf), flags);
18651887 } else {
18661888 return syscall4(.fstatat, @as(usize, @bitCast(@as(isize, dirfd))), @intFromPtr(path), @intFromPtr(stat_buf), flags);
......@@ -1868,17 +1890,14 @@ pub fn fstatat(dirfd: i32, path: [*:0]const u8, stat_buf: *Stat, flags: u32) usi
18681890}
18691891
18701892pub fn statx(dirfd: i32, path: [*:0]const u8, flags: u32, mask: u32, statx_buf: *Statx) usize {
1871 if (@hasField(SYS, "statx")) {
1872 return syscall5(
1873 .statx,
1874 @as(usize, @bitCast(@as(isize, dirfd))),
1875 @intFromPtr(path),
1876 flags,
1877 mask,
1878 @intFromPtr(statx_buf),
1879 );
1880 }
1881 return @as(usize, @bitCast(-@as(isize, @intFromEnum(E.NOSYS))));
1893 return syscall5(
1894 .statx,
1895 @as(usize, @bitCast(@as(isize, dirfd))),
1896 @intFromPtr(path),
1897 flags,
1898 mask,
1899 @intFromPtr(statx_buf),
1900 );
18821901}
18831902
18841903pub fn listxattr(path: [*:0]const u8, list: [*]u8, size: usize) usize {
......@@ -2198,40 +2217,40 @@ pub fn process_vm_writev(pid: pid_t, local: []const iovec_const, remote: []const
21982217}
21992218
22002219pub fn fadvise(fd: fd_t, offset: i64, len: i64, advice: usize) usize {
2201 if (comptime builtin.cpu.arch.isMIPS()) {
2202 // MIPS requires a 7 argument syscall
2220 if (comptime native_arch.isARM() or native_arch.isPPC()) {
2221 // These architectures reorder the arguments so that a register is not skipped to align the
2222 // register number that `offset` is passed in.
22032223
22042224 const offset_halves = splitValue64(offset);
22052225 const length_halves = splitValue64(len);
22062226
2207 return syscall7(
2208 .fadvise64,
2227 return syscall6(
2228 .fadvise64_64,
22092229 @as(usize, @bitCast(@as(isize, fd))),
2210 0,
2230 advice,
22112231 offset_halves[0],
22122232 offset_halves[1],
22132233 length_halves[0],
22142234 length_halves[1],
2215 advice,
22162235 );
2217 } else if (comptime builtin.cpu.arch.isARM()) {
2218 // ARM reorders the arguments
2236 } else if (comptime native_arch == .mips or native_arch == .mipsel) {
2237 // MIPS O32 does not deal with the register alignment issue, so pass a dummy value.
22192238
22202239 const offset_halves = splitValue64(offset);
22212240 const length_halves = splitValue64(len);
22222241
2223 return syscall6(
2224 .fadvise64_64,
2242 return syscall7(
2243 .fadvise64,
22252244 @as(usize, @bitCast(@as(isize, fd))),
2226 advice,
2245 0,
22272246 offset_halves[0],
22282247 offset_halves[1],
22292248 length_halves[0],
22302249 length_halves[1],
2250 advice,
22312251 );
2232 } else if (@hasField(SYS, "fadvise64_64") and usize_bits != 64) {
2233 // The extra usize check is needed to avoid SPARC64 because it provides both
2234 // fadvise64 and fadvise64_64 but the latter behaves differently than other platforms.
2252 } else if (comptime usize_bits < 64) {
2253 // Other 32-bit architectures do not require register alignment.
22352254
22362255 const offset_halves = splitValue64(offset);
22372256 const length_halves = splitValue64(len);
......@@ -2246,8 +2265,11 @@ pub fn fadvise(fd: fd_t, offset: i64, len: i64, advice: usize) usize {
22462265 advice,
22472266 );
22482267 } else {
2268 // On 64-bit architectures, fadvise64_64 and fadvise64 are the same. Generally, older ports
2269 // call it fadvise64 (x86, PowerPC, etc), while newer ports call it fadvise64_64 (RISC-V,
2270 // LoongArch, etc). SPARC is the odd one out because it has both.
22492271 return syscall4(
2250 .fadvise64,
2272 if (@hasField(SYS, "fadvise64_64")) .fadvise64_64 else .fadvise64,
22512273 @as(usize, @bitCast(@as(isize, fd))),
22522274 @as(usize, @bitCast(offset)),
22532275 @as(usize, @bitCast(len)),
......@@ -6295,12 +6317,13 @@ pub const POSIX_FADV = switch (native_arch) {
62956317};
62966318
62976319/// The timespec struct used by the kernel.
6298pub const kernel_timespec = if (@sizeOf(usize) >= 8) timespec else extern struct {
6320pub const kernel_timespec = extern struct {
62996321 sec: i64,
63006322 nsec: i64,
63016323};
63026324
6303pub const timespec = extern struct {
6325// https://github.com/ziglang/zig/issues/4726#issuecomment-2190337877
6326pub const timespec = if (!builtin.link_libc and native_arch == .riscv32) kernel_timespec else extern struct {
63046327 sec: isize,
63056328 nsec: isize,
63066329};
......@@ -7338,6 +7361,7 @@ pub const AUDIT = struct {
73387361 .x86_64 => .X86_64,
73397362 .aarch64 => .AARCH64,
73407363 .arm, .thumb => .ARM,
7364 .riscv32 => .RISCV32,
73417365 .riscv64 => .RISCV64,
73427366 .sparc64 => .SPARC64,
73437367 .mips => .MIPS,
lib/std/os/linux/riscv32.zig created+197
......@@ -0,0 +1,197 @@
1const std = @import("../../std.zig");
2const iovec = std.posix.iovec;
3const iovec_const = std.posix.iovec_const;
4const linux = std.os.linux;
5const SYS = linux.SYS;
6const uid_t = std.os.linux.uid_t;
7const gid_t = std.os.linux.gid_t;
8const pid_t = std.os.linux.pid_t;
9const sockaddr = linux.sockaddr;
10const socklen_t = linux.socklen_t;
11const timespec = std.os.linux.timespec;
12
13pub fn syscall0(number: SYS) usize {
14 return asm volatile ("ecall"
15 : [ret] "={x10}" (-> usize),
16 : [number] "{x17}" (@intFromEnum(number)),
17 : "memory"
18 );
19}
20
21pub fn syscall1(number: SYS, arg1: usize) usize {
22 return asm volatile ("ecall"
23 : [ret] "={x10}" (-> usize),
24 : [number] "{x17}" (@intFromEnum(number)),
25 [arg1] "{x10}" (arg1),
26 : "memory"
27 );
28}
29
30pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {
31 return asm volatile ("ecall"
32 : [ret] "={x10}" (-> usize),
33 : [number] "{x17}" (@intFromEnum(number)),
34 [arg1] "{x10}" (arg1),
35 [arg2] "{x11}" (arg2),
36 : "memory"
37 );
38}
39
40pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
41 return asm volatile ("ecall"
42 : [ret] "={x10}" (-> usize),
43 : [number] "{x17}" (@intFromEnum(number)),
44 [arg1] "{x10}" (arg1),
45 [arg2] "{x11}" (arg2),
46 [arg3] "{x12}" (arg3),
47 : "memory"
48 );
49}
50
51pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize {
52 return asm volatile ("ecall"
53 : [ret] "={x10}" (-> usize),
54 : [number] "{x17}" (@intFromEnum(number)),
55 [arg1] "{x10}" (arg1),
56 [arg2] "{x11}" (arg2),
57 [arg3] "{x12}" (arg3),
58 [arg4] "{x13}" (arg4),
59 : "memory"
60 );
61}
62
63pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize {
64 return asm volatile ("ecall"
65 : [ret] "={x10}" (-> usize),
66 : [number] "{x17}" (@intFromEnum(number)),
67 [arg1] "{x10}" (arg1),
68 [arg2] "{x11}" (arg2),
69 [arg3] "{x12}" (arg3),
70 [arg4] "{x13}" (arg4),
71 [arg5] "{x14}" (arg5),
72 : "memory"
73 );
74}
75
76pub fn syscall6(
77 number: SYS,
78 arg1: usize,
79 arg2: usize,
80 arg3: usize,
81 arg4: usize,
82 arg5: usize,
83 arg6: usize,
84) usize {
85 return asm volatile ("ecall"
86 : [ret] "={x10}" (-> usize),
87 : [number] "{x17}" (@intFromEnum(number)),
88 [arg1] "{x10}" (arg1),
89 [arg2] "{x11}" (arg2),
90 [arg3] "{x12}" (arg3),
91 [arg4] "{x13}" (arg4),
92 [arg5] "{x14}" (arg5),
93 [arg6] "{x15}" (arg6),
94 : "memory"
95 );
96}
97
98const CloneFn = *const fn (arg: usize) callconv(.C) u8;
99
100pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
101
102pub const restore = restore_rt;
103
104pub fn restore_rt() callconv(.Naked) noreturn {
105 asm volatile (
106 \\ ecall
107 :
108 : [number] "{x17}" (@intFromEnum(SYS.rt_sigreturn)),
109 : "memory"
110 );
111}
112
113pub const F = struct {
114 pub const DUPFD = 0;
115 pub const GETFD = 1;
116 pub const SETFD = 2;
117 pub const GETFL = 3;
118 pub const SETFL = 4;
119 pub const GETLK = 5;
120 pub const SETLK = 6;
121 pub const SETLKW = 7;
122 pub const SETOWN = 8;
123 pub const GETOWN = 9;
124 pub const SETSIG = 10;
125 pub const GETSIG = 11;
126
127 pub const RDLCK = 0;
128 pub const WRLCK = 1;
129 pub const UNLCK = 2;
130
131 pub const SETOWN_EX = 15;
132 pub const GETOWN_EX = 16;
133
134 pub const GETOWNER_UIDS = 17;
135};
136
137pub const blksize_t = i32;
138pub const nlink_t = u32;
139pub const time_t = i64;
140pub const mode_t = u32;
141pub const off_t = i64;
142pub const ino_t = u64;
143pub const dev_t = u64;
144pub const blkcnt_t = i64;
145
146pub const timeval = extern struct {
147 sec: time_t,
148 usec: i64,
149};
150
151pub const Flock = extern struct {
152 type: i16,
153 whence: i16,
154 start: off_t,
155 len: off_t,
156 pid: pid_t,
157 __unused: [4]u8,
158};
159
160pub const msghdr = extern struct {
161 name: ?*sockaddr,
162 namelen: socklen_t,
163 iov: [*]iovec,
164 iovlen: i32,
165 __pad1: i32 = 0,
166 control: ?*anyopaque,
167 controllen: socklen_t,
168 __pad2: socklen_t = 0,
169 flags: i32,
170};
171
172pub const msghdr_const = extern struct {
173 name: ?*const sockaddr,
174 namelen: socklen_t,
175 iov: [*]const iovec_const,
176 iovlen: i32,
177 __pad1: i32 = 0,
178 control: ?*const anyopaque,
179 controllen: socklen_t,
180 __pad2: socklen_t = 0,
181 flags: i32,
182};
183
184/// No `Stat` structure on this platform, only `Statx`.
185pub const Stat = void;
186
187pub const Elf_Symndx = u32;
188
189pub const MMAP2_UNIT = 4096;
190
191pub const VDSO = struct {};
192
193/// TODO
194pub const ucontext_t = void;
195
196/// TODO
197pub const getcontext = {};
lib/std/os/linux/riscv64.zig+5-5
......@@ -136,12 +136,12 @@ pub const F = struct {
136136
137137pub const blksize_t = i32;
138138pub const nlink_t = u32;
139pub const time_t = isize;
139pub const time_t = i64;
140140pub const mode_t = u32;
141pub const off_t = isize;
142pub const ino_t = usize;
143pub const dev_t = usize;
144pub const blkcnt_t = isize;
141pub const off_t = i64;
142pub const ino_t = u64;
143pub const dev_t = u64;
144pub const blkcnt_t = i64;
145145
146146pub const timeval = extern struct {
147147 sec: time_t,
lib/std/os/linux/start_pie.zig+2-2
......@@ -26,7 +26,7 @@ const R_RELATIVE = switch (builtin.cpu.arch) {
2626 .hexagon => R_HEXAGON_RELATIVE,
2727 .loongarch32, .loongarch64 => R_LARCH_RELATIVE,
2828 .m68k => R_68K_RELATIVE,
29 .riscv64 => R_RISCV_RELATIVE,
29 .riscv32, .riscv64 => R_RISCV_RELATIVE,
3030 .s390x => R_390_RELATIVE,
3131 else => @compileError("Missing R_RELATIVE definition for this target"),
3232};
......@@ -111,7 +111,7 @@ fn getDynamicSymbol() [*]elf.Dyn {
111111 \\ lea (%[ret], %%pc), %[ret]
112112 : [ret] "=r" (-> [*]elf.Dyn),
113113 ),
114 .riscv64 => asm volatile (
114 .riscv32, .riscv64 => asm volatile (
115115 \\ .weak _DYNAMIC
116116 \\ .hidden _DYNAMIC
117117 \\ lla %[ret], _DYNAMIC
lib/std/os/linux/syscalls.zig+337-33
......@@ -142,16 +142,16 @@ pub const X86 = enum(usize) {
142142 afs_syscall = 137,
143143 setfsuid = 138,
144144 setfsgid = 139,
145 _llseek = 140,
145 llseek = 140,
146146 getdents = 141,
147 _newselect = 142,
147 newselect = 142,
148148 flock = 143,
149149 msync = 144,
150150 readv = 145,
151151 writev = 146,
152152 getsid = 147,
153153 fdatasync = 148,
154 _sysctl = 149,
154 sysctl = 149,
155155 mlock = 150,
156156 munlock = 151,
157157 mlockall = 152,
......@@ -607,7 +607,7 @@ pub const X64 = enum(usize) {
607607 vhangup = 153,
608608 modify_ldt = 154,
609609 pivot_root = 155,
610 _sysctl = 156,
610 sysctl = 156,
611611 prctl = 157,
612612 arch_prctl = 158,
613613 adjtimex = 159,
......@@ -927,16 +927,16 @@ pub const Arm = enum(usize) {
927927 personality = 136,
928928 setfsuid = 138,
929929 setfsgid = 139,
930 _llseek = 140,
930 llseek = 140,
931931 getdents = 141,
932 _newselect = 142,
932 newselect = 142,
933933 flock = 143,
934934 msync = 144,
935935 readv = 145,
936936 writev = 146,
937937 getsid = 147,
938938 fdatasync = 148,
939 _sysctl = 149,
939 sysctl = 149,
940940 mlock = 150,
941941 munlock = 151,
942942 mlockall = 152,
......@@ -1454,12 +1454,12 @@ pub const Sparc64 = enum(usize) {
14541454 afs_syscall = 227,
14551455 setfsuid = 228,
14561456 setfsgid = 229,
1457 _newselect = 230,
1457 newselect = 230,
14581458 splice = 232,
14591459 stime = 233,
14601460 statfs64 = 234,
14611461 fstatfs64 = 235,
1462 _llseek = 236,
1462 llseek = 236,
14631463 mlock = 237,
14641464 munlock = 238,
14651465 mlockall = 239,
......@@ -1474,7 +1474,7 @@ pub const Sparc64 = enum(usize) {
14741474 sched_rr_get_interval = 248,
14751475 nanosleep = 249,
14761476 mremap = 250,
1477 _sysctl = 251,
1477 sysctl = 251,
14781478 getsid = 252,
14791479 fdatasync = 253,
14801480 nfsservctl = 254,
......@@ -1771,9 +1771,9 @@ pub const Mips = enum(usize) {
17711771 afs_syscall = Linux + 137,
17721772 setfsuid = Linux + 138,
17731773 setfsgid = Linux + 139,
1774 _llseek = Linux + 140,
1774 llseek = Linux + 140,
17751775 getdents = Linux + 141,
1776 _newselect = Linux + 142,
1776 newselect = Linux + 142,
17771777 flock = Linux + 143,
17781778 msync = Linux + 144,
17791779 readv = Linux + 145,
......@@ -1783,7 +1783,7 @@ pub const Mips = enum(usize) {
17831783 sysmips = Linux + 149,
17841784 getsid = Linux + 151,
17851785 fdatasync = Linux + 152,
1786 _sysctl = Linux + 153,
1786 sysctl = Linux + 153,
17871787 mlock = Linux + 154,
17881788 munlock = Linux + 155,
17891789 mlockall = Linux + 156,
......@@ -2087,7 +2087,7 @@ pub const Mips64 = enum(usize) {
20872087 writev = Linux + 19,
20882088 access = Linux + 20,
20892089 pipe = Linux + 21,
2090 _newselect = Linux + 22,
2090 newselect = Linux + 22,
20912091 sched_yield = Linux + 23,
20922092 mremap = Linux + 24,
20932093 msync = Linux + 25,
......@@ -2217,7 +2217,7 @@ pub const Mips64 = enum(usize) {
22172217 munlockall = Linux + 149,
22182218 vhangup = Linux + 150,
22192219 pivot_root = Linux + 151,
2220 _sysctl = Linux + 152,
2220 sysctl = Linux + 152,
22212221 prctl = Linux + 153,
22222222 adjtimex = Linux + 154,
22232223 setrlimit = Linux + 155,
......@@ -2568,16 +2568,16 @@ pub const PowerPC = enum(usize) {
25682568 afs_syscall = 137,
25692569 setfsuid = 138,
25702570 setfsgid = 139,
2571 _llseek = 140,
2571 llseek = 140,
25722572 getdents = 141,
2573 _newselect = 142,
2573 newselect = 142,
25742574 flock = 143,
25752575 msync = 144,
25762576 readv = 145,
25772577 writev = 146,
25782578 getsid = 147,
25792579 fdatasync = 148,
2580 _sysctl = 149,
2580 sysctl = 149,
25812581 mlock = 150,
25822582 munlock = 151,
25832583 mlockall = 152,
......@@ -3008,16 +3008,16 @@ pub const PowerPC64 = enum(usize) {
30083008 afs_syscall = 137,
30093009 setfsuid = 138,
30103010 setfsgid = 139,
3011 _llseek = 140,
3011 llseek = 140,
30123012 getdents = 141,
3013 _newselect = 142,
3013 newselect = 142,
30143014 flock = 143,
30153015 msync = 144,
30163016 readv = 145,
30173017 writev = 146,
30183018 getsid = 147,
30193019 fdatasync = 148,
3020 _sysctl = 149,
3020 sysctl = 149,
30213021 mlock = 150,
30223022 munlock = 151,
30233023 mlockall = 152,
......@@ -3351,7 +3351,7 @@ pub const Arm64 = enum(usize) {
33513351 pwrite64 = 68,
33523352 preadv = 69,
33533353 pwritev = 70,
3354 sendfile = 71,
3354 sendfile64 = 71,
33553355 pselect6 = 72,
33563356 ppoll = 73,
33573357 signalfd4 = 74,
......@@ -3359,8 +3359,8 @@ pub const Arm64 = enum(usize) {
33593359 splice = 76,
33603360 tee = 77,
33613361 readlinkat = 78,
3362 fstatat = 79,
3363 fstat = 80,
3362 fstatat64 = 79,
3363 fstat64 = 80,
33643364 sync = 81,
33653365 fsync = 82,
33663366 fdatasync = 83,
......@@ -3503,7 +3503,7 @@ pub const Arm64 = enum(usize) {
35033503 clone = 220,
35043504 execve = 221,
35053505 mmap = 222,
3506 fadvise64 = 223,
3506 fadvise64_64 = 223,
35073507 swapon = 224,
35083508 swapoff = 225,
35093509 mprotect = 226,
......@@ -3594,9 +3594,313 @@ pub const Arm64 = enum(usize) {
35943594 futex_requeue = 456,
35953595};
35963596
3597pub const RiscV64 = enum(usize) {
3598 pub const arch_specific_syscall = 244;
3597pub const RiscV32 = enum(usize) {
3598 io_setup = 0,
3599 io_destroy = 1,
3600 io_submit = 2,
3601 io_cancel = 3,
3602 setxattr = 5,
3603 lsetxattr = 6,
3604 fsetxattr = 7,
3605 getxattr = 8,
3606 lgetxattr = 9,
3607 fgetxattr = 10,
3608 listxattr = 11,
3609 llistxattr = 12,
3610 flistxattr = 13,
3611 removexattr = 14,
3612 lremovexattr = 15,
3613 fremovexattr = 16,
3614 getcwd = 17,
3615 lookup_dcookie = 18,
3616 eventfd2 = 19,
3617 epoll_create1 = 20,
3618 epoll_ctl = 21,
3619 epoll_pwait = 22,
3620 dup = 23,
3621 dup3 = 24,
3622 fcntl64 = 25,
3623 inotify_init1 = 26,
3624 inotify_add_watch = 27,
3625 inotify_rm_watch = 28,
3626 ioctl = 29,
3627 ioprio_set = 30,
3628 ioprio_get = 31,
3629 flock = 32,
3630 mknodat = 33,
3631 mkdirat = 34,
3632 unlinkat = 35,
3633 symlinkat = 36,
3634 linkat = 37,
3635 umount2 = 39,
3636 mount = 40,
3637 pivot_root = 41,
3638 nfsservctl = 42,
3639 statfs64 = 43,
3640 fstatfs64 = 44,
3641 truncate64 = 45,
3642 ftruncate64 = 46,
3643 fallocate = 47,
3644 faccessat = 48,
3645 chdir = 49,
3646 fchdir = 50,
3647 chroot = 51,
3648 fchmod = 52,
3649 fchmodat = 53,
3650 fchownat = 54,
3651 fchown = 55,
3652 openat = 56,
3653 close = 57,
3654 vhangup = 58,
3655 pipe2 = 59,
3656 quotactl = 60,
3657 getdents64 = 61,
3658 llseek = 62,
3659 read = 63,
3660 write = 64,
3661 readv = 65,
3662 writev = 66,
3663 pread64 = 67,
3664 pwrite64 = 68,
3665 preadv = 69,
3666 pwritev = 70,
3667 sendfile64 = 71,
3668 signalfd4 = 74,
3669 vmsplice = 75,
3670 splice = 76,
3671 tee = 77,
3672 readlinkat = 78,
3673 sync = 81,
3674 fsync = 82,
3675 fdatasync = 83,
3676 sync_file_range = 84,
3677 timerfd_create = 85,
3678 acct = 89,
3679 capget = 90,
3680 capset = 91,
3681 personality = 92,
3682 exit = 93,
3683 exit_group = 94,
3684 waitid = 95,
3685 set_tid_address = 96,
3686 unshare = 97,
3687 set_robust_list = 99,
3688 get_robust_list = 100,
3689 getitimer = 102,
3690 setitimer = 103,
3691 kexec_load = 104,
3692 init_module = 105,
3693 delete_module = 106,
3694 timer_create = 107,
3695 timer_getoverrun = 109,
3696 timer_delete = 111,
3697 syslog = 116,
3698 ptrace = 117,
3699 sched_setparam = 118,
3700 sched_setscheduler = 119,
3701 sched_getscheduler = 120,
3702 sched_getparam = 121,
3703 sched_setaffinity = 122,
3704 sched_getaffinity = 123,
3705 sched_yield = 124,
3706 sched_get_priority_max = 125,
3707 sched_get_priority_min = 126,
3708 restart_syscall = 128,
3709 kill = 129,
3710 tkill = 130,
3711 tgkill = 131,
3712 sigaltstack = 132,
3713 rt_sigsuspend = 133,
3714 rt_sigaction = 134,
3715 rt_sigprocmask = 135,
3716 rt_sigpending = 136,
3717 rt_sigqueueinfo = 138,
3718 rt_sigreturn = 139,
3719 setpriority = 140,
3720 getpriority = 141,
3721 reboot = 142,
3722 setregid = 143,
3723 setgid = 144,
3724 setreuid = 145,
3725 setuid = 146,
3726 setresuid = 147,
3727 getresuid = 148,
3728 setresgid = 149,
3729 getresgid = 150,
3730 setfsuid = 151,
3731 setfsgid = 152,
3732 times = 153,
3733 setpgid = 154,
3734 getpgid = 155,
3735 getsid = 156,
3736 setsid = 157,
3737 getgroups = 158,
3738 setgroups = 159,
3739 uname = 160,
3740 sethostname = 161,
3741 setdomainname = 162,
3742 getrusage = 165,
3743 umask = 166,
3744 prctl = 167,
3745 getcpu = 168,
3746 getpid = 172,
3747 getppid = 173,
3748 getuid = 174,
3749 geteuid = 175,
3750 getgid = 176,
3751 getegid = 177,
3752 gettid = 178,
3753 sysinfo = 179,
3754 mq_open = 180,
3755 mq_unlink = 181,
3756 mq_notify = 184,
3757 mq_getsetattr = 185,
3758 msgget = 186,
3759 msgctl = 187,
3760 msgrcv = 188,
3761 msgsnd = 189,
3762 semget = 190,
3763 semctl = 191,
3764 semop = 193,
3765 shmget = 194,
3766 shmctl = 195,
3767 shmat = 196,
3768 shmdt = 197,
3769 socket = 198,
3770 socketpair = 199,
3771 bind = 200,
3772 listen = 201,
3773 accept = 202,
3774 connect = 203,
3775 getsockname = 204,
3776 getpeername = 205,
3777 sendto = 206,
3778 recvfrom = 207,
3779 setsockopt = 208,
3780 getsockopt = 209,
3781 shutdown = 210,
3782 sendmsg = 211,
3783 recvmsg = 212,
3784 readahead = 213,
3785 brk = 214,
3786 munmap = 215,
3787 mremap = 216,
3788 add_key = 217,
3789 request_key = 218,
3790 keyctl = 219,
3791 clone = 220,
3792 execve = 221,
3793 mmap2 = 222,
3794 fadvise64_64 = 223,
3795 swapon = 224,
3796 swapoff = 225,
3797 mprotect = 226,
3798 msync = 227,
3799 mlock = 228,
3800 munlock = 229,
3801 mlockall = 230,
3802 munlockall = 231,
3803 mincore = 232,
3804 madvise = 233,
3805 remap_file_pages = 234,
3806 mbind = 235,
3807 get_mempolicy = 236,
3808 set_mempolicy = 237,
3809 migrate_pages = 238,
3810 move_pages = 239,
3811 rt_tgsigqueueinfo = 240,
3812 perf_event_open = 241,
3813 accept4 = 242,
3814 prlimit64 = 261,
3815 fanotify_init = 262,
3816 fanotify_mark = 263,
3817 name_to_handle_at = 264,
3818 open_by_handle_at = 265,
3819 syncfs = 267,
3820 setns = 268,
3821 sendmmsg = 269,
3822 process_vm_readv = 270,
3823 process_vm_writev = 271,
3824 kcmp = 272,
3825 finit_module = 273,
3826 sched_setattr = 274,
3827 sched_getattr = 275,
3828 renameat2 = 276,
3829 seccomp = 277,
3830 getrandom = 278,
3831 memfd_create = 279,
3832 bpf = 280,
3833 execveat = 281,
3834 userfaultfd = 282,
3835 membarrier = 283,
3836 mlock2 = 284,
3837 copy_file_range = 285,
3838 preadv2 = 286,
3839 pwritev2 = 287,
3840 pkey_mprotect = 288,
3841 pkey_alloc = 289,
3842 pkey_free = 290,
3843 statx = 291,
3844 rseq = 293,
3845 kexec_file_load = 294,
3846 clock_gettime = 403,
3847 clock_settime = 404,
3848 clock_adjtime = 405,
3849 clock_getres = 406,
3850 clock_nanosleep = 407,
3851 timer_gettime = 408,
3852 timer_settime = 409,
3853 timerfd_gettime = 410,
3854 timerfd_settime = 411,
3855 utimensat = 412,
3856 pselect6 = 413,
3857 ppoll = 414,
3858 io_pgetevents = 416,
3859 recvmmsg = 417,
3860 mq_timedsend = 418,
3861 mq_timedreceive = 419,
3862 semtimedop = 420,
3863 rt_sigtimedwait = 421,
3864 futex = 422,
3865 sched_rr_get_interval = 423,
3866 pidfd_send_signal = 424,
3867 io_uring_setup = 425,
3868 io_uring_enter = 426,
3869 io_uring_register = 427,
3870 open_tree = 428,
3871 move_mount = 429,
3872 fsopen = 430,
3873 fsconfig = 431,
3874 fsmount = 432,
3875 fspick = 433,
3876 pidfd_open = 434,
3877 clone3 = 435,
3878 close_range = 436,
3879 openat2 = 437,
3880 pidfd_getfd = 438,
3881 faccessat2 = 439,
3882 process_madvise = 440,
3883 epoll_pwait2 = 441,
3884 mount_setattr = 442,
3885 quotactl_fd = 443,
3886 landlock_create_ruleset = 444,
3887 landlock_add_rule = 445,
3888 landlock_restrict_self = 446,
3889 memfd_secret = 447,
3890 process_mrelease = 448,
3891 futex_waitv = 449,
3892 set_mempolicy_home_node = 450,
3893 cachestat = 451,
3894 fchmodat2 = 452,
3895 map_shadow_stack = 453,
3896 futex_wake = 454,
3897 futex_wait = 455,
3898 futex_requeue = 456,
3899 riscv_flush_icache = (244 + 15),
3900 riscv_hwprobe = (244 + 14),
3901};
35993902
3903pub const RiscV64 = enum(usize) {
36003904 io_setup = 0,
36013905 io_destroy = 1,
36023906 io_submit = 2,
......@@ -3667,7 +3971,7 @@ pub const RiscV64 = enum(usize) {
36673971 pwrite64 = 68,
36683972 preadv = 69,
36693973 pwritev = 70,
3670 sendfile = 71,
3974 sendfile64 = 71,
36713975 pselect6 = 72,
36723976 ppoll = 73,
36733977 signalfd4 = 74,
......@@ -3675,8 +3979,8 @@ pub const RiscV64 = enum(usize) {
36753979 splice = 76,
36763980 tee = 77,
36773981 readlinkat = 78,
3678 fstatat = 79,
3679 fstat = 80,
3982 fstatat64 = 79,
3983 fstat64 = 80,
36803984 sync = 81,
36813985 fsync = 82,
36823986 fdatasync = 83,
......@@ -3819,7 +4123,7 @@ pub const RiscV64 = enum(usize) {
38194123 clone = 220,
38204124 execve = 221,
38214125 mmap = 222,
3822 fadvise64 = 223,
4126 fadvise64_64 = 223,
38234127 swapon = 224,
38244128 swapoff = 225,
38254129 mprotect = 226,
......@@ -3908,8 +4212,8 @@ pub const RiscV64 = enum(usize) {
39084212 futex_wake = 454,
39094213 futex_wait = 455,
39104214 futex_requeue = 456,
3911
3912 riscv_flush_icache = arch_specific_syscall + 15,
4215 riscv_flush_icache = (244 + 15),
4216 riscv_hwprobe = (244 + 14),
39134217};
39144218
39154219pub const LoongArch64 = enum(usize) {
lib/std/os/linux/test.zig+2-2
......@@ -79,11 +79,11 @@ test "statx" {
7979 var statx_buf: linux.Statx = undefined;
8080 switch (linux.E.init(linux.statx(file.handle, "", linux.AT.EMPTY_PATH, linux.STATX_BASIC_STATS, &statx_buf))) {
8181 .SUCCESS => {},
82 // The statx syscall was only introduced in linux 4.11
83 .NOSYS => return error.SkipZigTest,
8482 else => unreachable,
8583 }
8684
85 if (builtin.cpu.arch == .riscv32) return error.SkipZigTest; // No fstatat, so the rest of the test is meaningless.
86
8787 var stat_buf: linux.Stat = undefined;
8888 switch (linux.E.init(linux.fstatat(file.handle, "", &stat_buf, linux.AT.EMPTY_PATH))) {
8989 .SUCCESS => {},
lib/std/os/linux/tls.zig+1-1
......@@ -170,7 +170,7 @@ pub fn setThreadPointer(addr: usize) void {
170170 const rc = @call(.always_inline, linux.syscall1, .{ .set_tls, addr });
171171 assert(rc == 0);
172172 },
173 .riscv64 => {
173 .riscv32, .riscv64 => {
174174 asm volatile (
175175 \\ mv tp, %[addr]
176176 :
lib/std/posix.zig+4-32
......@@ -615,7 +615,6 @@ pub fn getrandom(buffer: []u8) GetRandomError!void {
615615 .INVAL => unreachable,
616616 .FAULT => unreachable,
617617 .INTR => continue,
618 .NOSYS => return getRandomBytesDevURandom(buf),
619618 else => return unexpectedErrno(err),
620619 }
621620 }
......@@ -4534,7 +4533,6 @@ pub const FanotifyInitError = error{
45344533 ProcessFdQuotaExceeded,
45354534 SystemFdQuotaExceeded,
45364535 SystemResources,
4537 OperationNotSupported,
45384536 PermissionDenied,
45394537} || UnexpectedError;
45404538
......@@ -4546,7 +4544,6 @@ pub fn fanotify_init(flags: std.os.linux.fanotify.InitFlags, event_f_flags: u32)
45464544 .MFILE => return error.ProcessFdQuotaExceeded,
45474545 .NFILE => return error.SystemFdQuotaExceeded,
45484546 .NOMEM => return error.SystemResources,
4549 .NOSYS => return error.OperationNotSupported,
45504547 .PERM => return error.PermissionDenied,
45514548 else => |err| return unexpectedErrno(err),
45524549 }
......@@ -4559,7 +4556,6 @@ pub const FanotifyMarkError = error{
45594556 FileNotFound,
45604557 SystemResources,
45614558 UserMarkQuotaExceeded,
4562 NotImplemented,
45634559 NotDir,
45644560 OperationNotSupported,
45654561 PermissionDenied,
......@@ -4600,7 +4596,6 @@ pub fn fanotify_markZ(
46004596 .NOENT => return error.FileNotFound,
46014597 .NOMEM => return error.SystemResources,
46024598 .NOSPC => return error.UserMarkQuotaExceeded,
4603 .NOSYS => return error.NotImplemented,
46044599 .NOTDIR => return error.NotDir,
46054600 .OPNOTSUPP => return error.OperationNotSupported,
46064601 .PERM => return error.PermissionDenied,
......@@ -6183,13 +6178,6 @@ pub fn sendfile(
61836178
61846179 switch (native_os) {
61856180 .linux => sf: {
6186 // sendfile() first appeared in Linux 2.2, glibc 2.1.
6187 const call_sf = comptime if (builtin.link_libc)
6188 std.c.versionCheck(.{ .major = 2, .minor = 1, .patch = 0 })
6189 else
6190 builtin.os.version_range.linux.range.max.order(.{ .major = 2, .minor = 2, .patch = 0 }) != .lt;
6191 if (!call_sf) break :sf;
6192
61936181 if (headers.len != 0) {
61946182 const amt = try writev(out_fd, headers);
61956183 total_written += amt;
......@@ -6223,14 +6211,14 @@ pub fn sendfile(
62236211 .OVERFLOW => unreachable, // We avoid passing too large of a `count`.
62246212 .NOTCONN => return error.BrokenPipe, // `out_fd` is an unconnected socket
62256213
6226 .INVAL, .NOSYS => {
6214 .INVAL => {
62276215 // EINVAL could be any of the following situations:
62286216 // * Descriptor is not valid or locked
62296217 // * an mmap(2)-like operation is not available for in_fd
62306218 // * count is negative
62316219 // * out_fd has the APPEND flag set
62326220 // Because of the "mmap(2)-like operation" possibility, we fall back to doing read/write
6233 // manually, the same as ENOSYS.
6221 // manually.
62346222 break :sf;
62356223 },
62366224 .AGAIN => return error.WouldBlock,
......@@ -6456,21 +6444,15 @@ pub const CopyFileRangeError = error{
64566444/// `flags` has different meanings per operating system; refer to the respective man pages.
64576445///
64586446/// These systems support in-kernel data copying:
6459/// * Linux 4.5 (cross-filesystem 5.3)
6447/// * Linux (cross-filesystem from version 5.3)
64606448/// * FreeBSD 13.0
64616449///
64626450/// Other systems fall back to calling `pread` / `pwrite`.
64636451///
64646452/// Maximum offsets on Linux and FreeBSD are `maxInt(i64)`.
64656453pub fn copy_file_range(fd_in: fd_t, off_in: u64, fd_out: fd_t, off_out: u64, len: usize, flags: u32) CopyFileRangeError!usize {
6466 const global = struct {
6467 var has_copy_file_range = true;
6468 };
6469
64706454 if ((comptime builtin.os.isAtLeast(.freebsd, .{ .major = 13, .minor = 0, .patch = 0 }) orelse false) or
6471 ((comptime builtin.os.isAtLeast(.linux, .{ .major = 4, .minor = 5, .patch = 0 }) orelse false and
6472 std.c.versionCheck(.{ .major = 2, .minor = 27, .patch = 0 })) and
6473 @atomicLoad(bool, &global.has_copy_file_range, .monotonic)))
6455 (comptime builtin.os.tag == .linux and std.c.versionCheck(.{ .major = 2, .minor = 27, .patch = 0 })))
64746456 {
64756457 var off_in_copy: i64 = @bitCast(off_in);
64766458 var off_out_copy: i64 = @bitCast(off_out);
......@@ -6504,10 +6486,6 @@ pub fn copy_file_range(fd_in: fd_t, off_in: u64, fd_out: fd_t, off_out: u64, len
65046486 .PERM => return error.PermissionDenied,
65056487 .TXTBSY => return error.SwapFile,
65066488 .XDEV => break, // support for cross-filesystem copy added in Linux 5.3, use fallback
6507 .NOSYS => {
6508 @atomicStore(bool, &global.has_copy_file_range, false, .monotonic);
6509 break;
6510 },
65116489 else => |err| return unexpectedErrno(err),
65126490 }
65136491 }
......@@ -6775,10 +6753,6 @@ pub const MemFdCreateError = error{
67756753 OutOfMemory,
67766754 /// Either the name provided exceeded `NAME_MAX`, or invalid flags were passed.
67776755 NameTooLong,
6778
6779 /// memfd_create is available in Linux 3.17 and later. This error is returned
6780 /// for older kernel versions.
6781 SystemOutdated,
67826756} || UnexpectedError;
67836757
67846758pub fn memfd_createZ(name: [*:0]const u8, flags: u32) MemFdCreateError!fd_t {
......@@ -6795,7 +6769,6 @@ pub fn memfd_createZ(name: [*:0]const u8, flags: u32) MemFdCreateError!fd_t {
67956769 .NFILE => return error.SystemFdQuotaExceeded,
67966770 .MFILE => return error.ProcessFdQuotaExceeded,
67976771 .NOMEM => return error.OutOfMemory,
6798 .NOSYS => return error.SystemOutdated,
67996772 else => |err| return unexpectedErrno(err),
68006773 }
68016774 },
......@@ -6915,7 +6888,6 @@ pub fn signalfd(fd: fd_t, mask: *const sigset_t, flags: u32) !fd_t {
69156888 .NOMEM => return error.SystemResources,
69166889 .MFILE => return error.ProcessResources,
69176890 .NODEV => return error.InodeMountFail,
6918 .NOSYS => return error.SystemOutdated,
69196891 else => |err| return unexpectedErrno(err),
69206892 }
69216893}
lib/std/posix/test.zig+1-5
......@@ -580,11 +580,7 @@ test "memfd_create" {
580580 else => return error.SkipZigTest,
581581 }
582582
583 const fd = posix.memfd_create("test", 0) catch |err| switch (err) {
584 // Related: https://github.com/ziglang/zig/issues/4019
585 error.SystemOutdated => return error.SkipZigTest,
586 else => |e| return e,
587 };
583 const fd = try posix.memfd_create("test", 0);
588584 defer posix.close(fd);
589585 try expect((try posix.write(fd, "test")) == 4);
590586 try posix.lseek_SET(fd, 0);
lib/std/start.zig+1-1
......@@ -272,7 +272,7 @@ fn _start() callconv(.Naked) noreturn {
272272 \\ bstrins.d $sp, $zero, 3, 0
273273 \\ b %[posixCallMainAndExit]
274274 ,
275 .riscv64 =>
275 .riscv32, .riscv64 =>
276276 \\ li s0, 0
277277 \\ li ra, 0
278278 \\ mv a0, sp
lib/std/zig/target.zig+1-1
......@@ -56,7 +56,7 @@ pub const available_libcs = [_]ArchOsAbi{
5656 .{ .arch = .powerpc, .os = .linux, .abi = .gnueabi },
5757 .{ .arch = .powerpc, .os = .linux, .abi = .gnueabihf },
5858 .{ .arch = .powerpc, .os = .linux, .abi = .musl },
59 .{ .arch = .riscv32, .os = .linux, .abi = .gnuilp32, .glibc_min = .{ .major = 2, .minor = 27, .patch = 0 } },
59 .{ .arch = .riscv32, .os = .linux, .abi = .gnuilp32, .glibc_min = .{ .major = 2, .minor = 33, .patch = 0 } },
6060 .{ .arch = .riscv32, .os = .linux, .abi = .musl },
6161 .{ .arch = .riscv64, .os = .linux, .abi = .gnu, .glibc_min = .{ .major = 2, .minor = 27, .patch = 0 } },
6262 .{ .arch = .riscv64, .os = .linux, .abi = .musl },
src/link/Elf.zig+1-1
......@@ -3150,7 +3150,7 @@ fn addLinkerDefinedSymbols(self: *Elf) !void {
31503150 }
31513151 }
31523152
3153 if (self.getTarget().cpu.arch == .riscv64 and self.isEffectivelyDynLib()) {
3153 if (self.getTarget().cpu.arch.isRISCV() and self.isEffectivelyDynLib()) {
31543154 self.global_pointer_index = try linker_defined.addGlobal("__global_pointer$", self);
31553155 }
31563156
src/musl.zig+1
......@@ -301,6 +301,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: std.Progre
301301pub fn needsCrtiCrtn(target: std.Target) bool {
302302 // zig fmt: off
303303 return switch (target.cpu.arch) {
304 .riscv32,
304305 .riscv64,
305306 .wasm32, .wasm64 => return false,
306307 else => true,
tools/gen_stubs.zig+7-2
......@@ -2,13 +2,14 @@
22//! ./gen_stubs /path/to/musl/build-all >libc.S
33//!
44//! The directory 'build-all' is expected to contain these subdirectories:
5//! arm x86 mips mips64 powerpc powerpc64 riscv64 x86_64
5//! arm x86 mips mips64 powerpc powerpc64 riscv32 riscv64 x86_64
66//!
77//! ...each with 'lib/libc.so' inside of them.
88//!
99//! When building the resulting libc.S file, these defines are required:
1010//! * `-DPTR64`: when the architecture is 64-bit
1111//! * One of the following, corresponding to the CPU architecture:
12//! - `-DARCH_riscv32`
1213//! - `-DARCH_riscv64`
1314//! - `-DARCH_mips`
1415//! - `-DARCH_mips64`
......@@ -68,7 +69,8 @@ const MultiSym = struct {
6869 }
6970
7071 fn is32Only(ms: MultiSym) bool {
71 return ms.present[archIndex(.riscv64)] == false and
72 return ms.present[archIndex(.riscv32)] == true and
73 ms.present[archIndex(.riscv64)] == false and
7274 ms.present[archIndex(.mips)] == true and
7375 ms.present[archIndex(.mips64)] == false and
7476 ms.present[archIndex(.x86)] == true and
......@@ -110,6 +112,7 @@ const MultiSym = struct {
110112
111113 fn isPtrSize(ms: MultiSym) bool {
112114 const map = .{
115 .{ .riscv32, 4 },
113116 .{ .riscv64, 8 },
114117 .{ .mips, 4 },
115118 .{ .mips64, 8 },
......@@ -132,6 +135,7 @@ const MultiSym = struct {
132135
133136 fn isPtr2Size(ms: MultiSym) bool {
134137 const map = .{
138 .{ .riscv32, 8 },
135139 .{ .riscv64, 16 },
136140 .{ .mips, 8 },
137141 .{ .mips64, 16 },
......@@ -154,6 +158,7 @@ const MultiSym = struct {
154158
155159 fn isWeak64(ms: MultiSym) bool {
156160 const map = .{
161 .{ .riscv32, 1 },
157162 .{ .riscv64, 2 },
158163 .{ .mips, 1 },
159164 .{ .mips64, 2 },
tools/generate_linux_syscalls.zig+112-48
......@@ -10,7 +10,12 @@ const zig = std.zig;
1010const fs = std.fs;
1111
1212const stdlib_renames = std.StaticStringMap([]const u8).initComptime(.{
13 // Remove underscore prefix.
14 .{ "_llseek", "llseek" },
15 .{ "_newselect", "newselect" },
16 .{ "_sysctl", "sysctl" },
1317 // Most 64-bit archs.
18 .{ "newfstat", "fstat64" },
1419 .{ "newfstatat", "fstatat64" },
1520 // POWER.
1621 .{ "sync_file_range2", "sync_file_range" },
......@@ -19,6 +24,24 @@ const stdlib_renames = std.StaticStringMap([]const u8).initComptime(.{
1924 .{ "arm_fadvise64_64", "fadvise64_64" },
2025});
2126
27// Only for newer architectures where we use the C preprocessor.
28const stdlib_renames_new = std.StaticStringMap([]const u8).initComptime(.{
29 .{ "newuname", "uname" },
30 .{ "umount", "umount2" },
31});
32
33// We use this to deal with the fact that multiple syscalls can be mapped to sys_ni_syscall.
34// Thankfully it's only 2 well-known syscalls in newer kernel ports at the moment.
35fn getOverridenNameNew(value: []const u8) ?[]const u8 {
36 if (mem.eql(u8, value, "18")) {
37 return "sys_lookup_dcookie";
38 } else if (mem.eql(u8, value, "42")) {
39 return "sys_nfsservctl";
40 } else {
41 return null;
42 }
43}
44
2245pub fn main() !void {
2346 var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
2447 defer arena.deinit();
......@@ -60,8 +83,9 @@ pub fn main() !void {
6083 // abi is always i386
6184 _ = fields.next() orelse return error.Incomplete;
6285 const name = fields.next() orelse return error.Incomplete;
86 const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name;
6387
64 try writer.print(" {p} = {s},\n", .{ zig.fmtId(name), number });
88 try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), number });
6589 }
6690
6791 try writer.writeAll("};\n\n");
......@@ -80,8 +104,8 @@ pub fn main() !void {
80104 // The x32 abi syscalls are always at the end.
81105 if (mem.eql(u8, abi, "x32")) break;
82106 const name = fields.next() orelse return error.Incomplete;
83
84107 const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name;
108
85109 try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), number });
86110 }
87111
......@@ -105,8 +129,8 @@ pub fn main() !void {
105129 const abi = fields.next() orelse return error.Incomplete;
106130 if (mem.eql(u8, abi, "oabi")) continue;
107131 const name = fields.next() orelse return error.Incomplete;
108
109132 const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name;
133
110134 try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), number });
111135 }
112136
......@@ -136,8 +160,9 @@ pub fn main() !void {
136160 const abi = fields.next() orelse return error.Incomplete;
137161 if (mem.eql(u8, abi, "32")) continue;
138162 const name = fields.next() orelse return error.Incomplete;
163 const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name;
139164
140 try writer.print(" {p} = {s},\n", .{ zig.fmtId(name), number });
165 try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), number });
141166 }
142167
143168 try writer.writeAll("};\n\n");
......@@ -161,8 +186,9 @@ pub fn main() !void {
161186 _ = fields.next() orelse return error.Incomplete;
162187 const name = fields.next() orelse return error.Incomplete;
163188 if (mem.startsWith(u8, name, "unused")) continue;
189 const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name;
164190
165 try writer.print(" {p} = Linux + {s},\n", .{ zig.fmtId(name), number });
191 try writer.print(" {p} = Linux + {s},\n", .{ zig.fmtId(fixed_name), number });
166192 }
167193
168194 try writer.writeAll("};\n\n");
......@@ -232,11 +258,6 @@ pub fn main() !void {
232258 // Newer architectures (starting with aarch64 c. 2012) now use the same C
233259 // header file for their syscall numbers. Arch-specific headers are used to
234260 // define pre-proc. vars that add additional (usually obsolete) syscalls.
235 //
236 // TODO:
237 // - It would be better to use libclang/translate-c directly to extract the definitions.
238 // - The `-dD` option only does minimal pre-processing and doesn't resolve addition,
239 // so arch specific syscalls are dealt with manually.
240261 {
241262 try writer.writeAll("pub const Arm64 = enum(usize) {\n");
242263
......@@ -254,6 +275,8 @@ pub fn main() !void {
254275 // Using -I=[dir] includes the zig linux headers, which we don't want.
255276 "-Iinclude",
256277 "-Iinclude/uapi",
278 // Output the syscall in a format we can easily recognize.
279 "-D __SYSCALL(nr, nm)=zigsyscall nm nr",
257280 "arch/arm64/include/uapi/asm/unistd.h",
258281 };
259282
......@@ -277,32 +300,79 @@ pub fn main() !void {
277300 };
278301
279302 var lines = mem.tokenizeScalar(u8, defines, '\n');
280 loop: while (lines.next()) |line| {
281 var fields = mem.tokenizeAny(u8, line, " \t");
282 const cmd = fields.next() orelse return error.Incomplete;
283 if (!mem.eql(u8, cmd, "#define")) continue;
284 const define = fields.next() orelse return error.Incomplete;
285 const number = fields.next() orelse continue;
303 while (lines.next()) |line| {
304 var fields = mem.tokenizeAny(u8, line, " ");
305 const prefix = fields.next() orelse return error.Incomplete;
286306
287 if (!std.ascii.isDigit(number[0])) continue;
288 if (!mem.startsWith(u8, define, "__NR")) continue;
289 const name = mem.trimLeft(u8, mem.trimLeft(u8, define, "__NR3264_"), "__NR_");
290 if (mem.eql(u8, name, "arch_specific_syscall")) continue;
291 if (mem.eql(u8, name, "syscalls")) break :loop;
307 if (!mem.eql(u8, prefix, "zigsyscall")) continue;
292308
293 const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name;
294 try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), number });
309 const sys_name = fields.next() orelse return error.Incomplete;
310 const value = fields.rest();
311 const name = (getOverridenNameNew(value) orelse sys_name)["sys_".len..];
312 const fixed_name = if (stdlib_renames_new.get(name)) |f| f else if (stdlib_renames.get(name)) |f| f else name;
313
314 try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), value });
295315 }
296316
297317 try writer.writeAll("};\n\n");
298318 }
299319 {
300 try writer.writeAll(
301 \\pub const RiscV64 = enum(usize) {
302 \\ pub const arch_specific_syscall = 244;
303 \\
304 \\
305 );
320 try writer.writeAll("pub const RiscV32 = enum(usize) {\n");
321
322 const child_args = [_][]const u8{
323 zig_exe,
324 "cc",
325 "-target",
326 "riscv32-linux-gnuilp32",
327 "-E",
328 "-dD",
329 "-P",
330 "-nostdinc",
331 "-Iinclude",
332 "-Iinclude/uapi",
333 "-Iarch/riscv/include/uapi",
334 "-D __SYSCALL(nr, nm)=zigsyscall nm nr",
335 "arch/riscv/include/uapi/asm/unistd.h",
336 };
337
338 const child_result = try std.process.Child.run(.{
339 .allocator = allocator,
340 .argv = &child_args,
341 .cwd = linux_path,
342 .cwd_dir = linux_dir,
343 });
344 if (child_result.stderr.len > 0) std.debug.print("{s}\n", .{child_result.stderr});
345
346 const defines = switch (child_result.term) {
347 .Exited => |code| if (code == 0) child_result.stdout else {
348 std.debug.print("zig cc exited with code {d}\n", .{code});
349 std.process.exit(1);
350 },
351 else => {
352 std.debug.print("zig cc crashed\n", .{});
353 std.process.exit(1);
354 },
355 };
356
357 var lines = mem.tokenizeScalar(u8, defines, '\n');
358 while (lines.next()) |line| {
359 var fields = mem.tokenizeAny(u8, line, " ");
360 const prefix = fields.next() orelse return error.Incomplete;
361
362 if (!mem.eql(u8, prefix, "zigsyscall")) continue;
363
364 const sys_name = fields.next() orelse return error.Incomplete;
365 const value = fields.rest();
366 const name = (getOverridenNameNew(value) orelse sys_name)["sys_".len..];
367 const fixed_name = if (stdlib_renames_new.get(name)) |f| f else if (stdlib_renames.get(name)) |f| f else name;
368
369 try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), value });
370 }
371
372 try writer.writeAll("};\n\n");
373 }
374 {
375 try writer.writeAll("pub const RiscV64 = enum(usize) {\n");
306376
307377 const child_args = [_][]const u8{
308378 zig_exe,
......@@ -315,6 +385,8 @@ pub fn main() !void {
315385 "-nostdinc",
316386 "-Iinclude",
317387 "-Iinclude/uapi",
388 "-Iarch/riscv/include/uapi",
389 "-D __SYSCALL(nr, nm)=zigsyscall nm nr",
318390 "arch/riscv/include/uapi/asm/unistd.h",
319391 };
320392
......@@ -338,29 +410,21 @@ pub fn main() !void {
338410 };
339411
340412 var lines = mem.tokenizeScalar(u8, defines, '\n');
341 loop: while (lines.next()) |line| {
342 var fields = mem.tokenizeAny(u8, line, " \t");
343 const cmd = fields.next() orelse return error.Incomplete;
344 if (!mem.eql(u8, cmd, "#define")) continue;
345 const define = fields.next() orelse return error.Incomplete;
346 const number = fields.next() orelse continue;
413 while (lines.next()) |line| {
414 var fields = mem.tokenizeAny(u8, line, " ");
415 const prefix = fields.next() orelse return error.Incomplete;
347416
348 if (!std.ascii.isDigit(number[0])) continue;
349 if (!mem.startsWith(u8, define, "__NR")) continue;
350 const name = mem.trimLeft(u8, mem.trimLeft(u8, define, "__NR3264_"), "__NR_");
351 if (mem.eql(u8, name, "arch_specific_syscall")) continue;
352 if (mem.eql(u8, name, "syscalls")) break :loop;
417 if (!mem.eql(u8, prefix, "zigsyscall")) continue;
353418
354 const fixed_name = if (stdlib_renames.get(name)) |fixed| fixed else name;
355 try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), number });
419 const sys_name = fields.next() orelse return error.Incomplete;
420 const value = fields.rest();
421 const name = (getOverridenNameNew(value) orelse sys_name)["sys_".len..];
422 const fixed_name = if (stdlib_renames_new.get(name)) |f| f else if (stdlib_renames.get(name)) |f| f else name;
423
424 try writer.print(" {p} = {s},\n", .{ zig.fmtId(fixed_name), value });
356425 }
357426
358 try writer.writeAll(
359 \\
360 \\ riscv_flush_icache = arch_specific_syscall + 15,
361 \\};
362 \\
363 );
427 try writer.writeAll("};\n\n");
364428 }
365429 {
366430 try writer.writeAll(