From c560e26fb7f7aee4f4a998970c1b7a73b3cae2ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Wed, 2 Oct 2024 04:26:06 +0200 Subject: [PATCH 1/7] std.os.linux: Rename some arch bits files to match std.Target.Cpu.Arch tags. --- lib/std/os/linux.zig | 6 +++--- lib/std/os/linux/{arm64.zig => aarch64.zig} | 0 lib/std/os/linux/{arm-eabi.zig => arm.zig} | 0 lib/std/os/linux/{start_pie.zig => pie.zig} | 0 lib/std/os/linux/thumb.zig | 2 +- 5 files changed, 4 insertions(+), 4 deletions(-) rename lib/std/os/linux/{arm64.zig => aarch64.zig} (100%) rename lib/std/os/linux/{arm-eabi.zig => arm.zig} (100%) rename lib/std/os/linux/{start_pie.zig => pie.zig} (100%) diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index aaf08395fa48..58e13a9b122e 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -37,8 +37,8 @@ const syscall_bits = switch (native_arch) { const arch_bits = switch (native_arch) { .x86 => @import("linux/x86.zig"), .x86_64 => @import("linux/x86_64.zig"), - .aarch64, .aarch64_be => @import("linux/arm64.zig"), - .arm, .armeb, .thumb, .thumbeb => @import("linux/arm-eabi.zig"), + .aarch64, .aarch64_be => @import("linux/aarch64.zig"), + .arm, .armeb, .thumb, .thumbeb => @import("linux/arm.zig"), .riscv32 => @import("linux/riscv32.zig"), .riscv64 => @import("linux/riscv64.zig"), .sparc64 => @import("linux/sparc64.zig"), @@ -116,7 +116,7 @@ pub const user_desc = arch_bits.user_desc; pub const getcontext = arch_bits.getcontext; pub const tls = @import("linux/tls.zig"); -pub const pie = @import("linux/start_pie.zig"); +pub const pie = @import("linux/pie.zig"); pub const BPF = @import("linux/bpf.zig"); pub const IOCTL = @import("linux/ioctl.zig"); pub const SECCOMP = @import("linux/seccomp.zig"); diff --git a/lib/std/os/linux/arm64.zig b/lib/std/os/linux/aarch64.zig similarity index 100% rename from lib/std/os/linux/arm64.zig rename to lib/std/os/linux/aarch64.zig diff --git a/lib/std/os/linux/arm-eabi.zig b/lib/std/os/linux/arm.zig similarity index 100% rename from lib/std/os/linux/arm-eabi.zig rename to lib/std/os/linux/arm.zig diff --git a/lib/std/os/linux/start_pie.zig b/lib/std/os/linux/pie.zig similarity index 100% rename from lib/std/os/linux/start_pie.zig rename to lib/std/os/linux/pie.zig diff --git a/lib/std/os/linux/thumb.zig b/lib/std/os/linux/thumb.zig index baaf130578d9..a464030858b2 100644 --- a/lib/std/os/linux/thumb.zig +++ b/lib/std/os/linux/thumb.zig @@ -141,7 +141,7 @@ pub fn syscall6( ); } -pub const clone = @import("arm-eabi.zig").clone; +pub const clone = @import("arm.zig").clone; pub fn restore() callconv(.Naked) noreturn { asm volatile ( From 6dd19961b3f274728f57e15c10ad517d129ffcf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Wed, 2 Oct 2024 08:13:50 +0200 Subject: [PATCH 2/7] std.atomic: Provide a more accurate cache_line value for hexagon v73+. --- lib/std/atomic.zig | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/std/atomic.zig b/lib/std/atomic.zig index 0f25bd448a9d..6d7a9832dfc3 100644 --- a/lib/std/atomic.zig +++ b/lib/std/atomic.zig @@ -459,18 +459,20 @@ pub const cache_line = switch (builtin.cpu.arch) { .powerpc64le, => 128, + // https://github.com/llvm/llvm-project/blob/e379094328e49731a606304f7e3559d4f1fa96f9/clang/lib/Basic/Targets/Hexagon.h#L145-L151 + .hexagon, + => if (std.Target.hexagon.featureSetHas(builtin.target.cpu.features, .v73)) 64 else 32, + // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_arm.go#L7 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mips.go#L7 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mipsle.go#L7 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mips64x.go#L9 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_riscv64.go#L7 - // - https://github.com/torvalds/linux/blob/3a7e02c040b130b5545e4b115aada7bacd80a2b6/arch/hexagon/include/asm/cache.h#L13 // - https://github.com/torvalds/linux/blob/3a7e02c040b130b5545e4b115aada7bacd80a2b6/arch/sparc/include/asm/cache.h#L14 .arm, .armeb, .thumb, .thumbeb, - .hexagon, .mips, .mipsel, .mips64, From fe30df6b8c398000c737b9370750dda5a4c24911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Wed, 2 Oct 2024 08:14:36 +0200 Subject: [PATCH 3/7] std.os.linux: Add hexagon arch bits. --- lib/std/os/linux.zig | 5 +- lib/std/os/linux/hexagon.zig | 254 +++++++++++++++++++++++++++++++++++ 2 files changed, 257 insertions(+), 2 deletions(-) create mode 100644 lib/std/os/linux/hexagon.zig diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 58e13a9b122e..197e2f3dbcf1 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -39,6 +39,7 @@ const arch_bits = switch (native_arch) { .x86_64 => @import("linux/x86_64.zig"), .aarch64, .aarch64_be => @import("linux/aarch64.zig"), .arm, .armeb, .thumb, .thumbeb => @import("linux/arm.zig"), + .hexagon => @import("linux/hexagon.zig"), .riscv32 => @import("linux/riscv32.zig"), .riscv64 => @import("linux/riscv64.zig"), .sparc64 => @import("linux/sparc64.zig"), @@ -277,7 +278,7 @@ pub const MAP = switch (native_arch) { UNINITIALIZED: bool = false, _: u5 = 0, }, - .s390x => packed struct(u32) { + .hexagon, .s390x => packed struct(u32) { TYPE: MAP_TYPE, FIXED: bool = false, ANONYMOUS: bool = false, @@ -441,7 +442,7 @@ pub const O = switch (native_arch) { TMPFILE: bool = false, _: u9 = 0, }, - .s390x => packed struct(u32) { + .hexagon, .s390x => packed struct(u32) { ACCMODE: ACCMODE = .RDONLY, _2: u4 = 0, CREAT: bool = false, diff --git a/lib/std/os/linux/hexagon.zig b/lib/std/os/linux/hexagon.zig new file mode 100644 index 000000000000..e9bf9ab57c47 --- /dev/null +++ b/lib/std/os/linux/hexagon.zig @@ -0,0 +1,254 @@ +const std = @import("../../std.zig"); +const iovec = std.posix.iovec; +const iovec_const = std.posix.iovec_const; +const linux = std.os.linux; +const SYS = linux.SYS; +const uid_t = std.os.linux.uid_t; +const gid_t = std.os.linux.gid_t; +const pid_t = std.os.linux.pid_t; +const sockaddr = linux.sockaddr; +const socklen_t = linux.socklen_t; +const timespec = std.os.linux.timespec; + +pub fn syscall0(number: SYS) usize { + return asm volatile ("trap0(#1)" + : [ret] "={r0}" (-> usize), + : [number] "{r6}" (@intFromEnum(number)), + : "memory" + ); +} + +pub fn syscall1(number: SYS, arg1: usize) usize { + return asm volatile ("trap0(#1)" + : [ret] "={r0}" (-> usize), + : [number] "{r6}" (@intFromEnum(number)), + [arg1] "{r0}" (arg1), + : "memory" + ); +} + +pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize { + return asm volatile ("trap0(#1)" + : [ret] "={r0}" (-> usize), + : [number] "{r6}" (@intFromEnum(number)), + [arg1] "{r0}" (arg1), + [arg2] "{r1}" (arg2), + : "memory" + ); +} + +pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize { + return asm volatile ("trap0(#1)" + : [ret] "={r0}" (-> usize), + : [number] "{r6}" (@intFromEnum(number)), + [arg1] "{r0}" (arg1), + [arg2] "{r1}" (arg2), + [arg3] "{r2}" (arg3), + : "memory" + ); +} + +pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize { + return asm volatile ("trap0(#1)" + : [ret] "={r0}" (-> usize), + : [number] "{r6}" (@intFromEnum(number)), + [arg1] "{r0}" (arg1), + [arg2] "{r1}" (arg2), + [arg3] "{r2}" (arg3), + [arg4] "{r3}" (arg4), + : "memory" + ); +} + +pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize { + return asm volatile ("trap0(#1)" + : [ret] "={r0}" (-> usize), + : [number] "{r6}" (@intFromEnum(number)), + [arg1] "{r0}" (arg1), + [arg2] "{r1}" (arg2), + [arg3] "{r2}" (arg3), + [arg4] "{r3}" (arg4), + [arg5] "{r4}" (arg5), + : "memory" + ); +} + +pub fn syscall6( + number: SYS, + arg1: usize, + arg2: usize, + arg3: usize, + arg4: usize, + arg5: usize, + arg6: usize, +) usize { + return asm volatile ("trap0(#1)" + : [ret] "={r0}" (-> usize), + : [number] "{r6}" (@intFromEnum(number)), + [arg1] "{r0}" (arg1), + [arg2] "{r1}" (arg2), + [arg3] "{r2}" (arg3), + [arg4] "{r3}" (arg4), + [arg5] "{r4}" (arg5), + [arg6] "{r5}" (arg6), + : "memory" + ); +} + +pub fn clone() callconv(.Naked) usize { + // __clone(func, stack, flags, arg, ptid, tls, ctid) + // r0, r1, r2, r3, r4, r5, +0 + // + // syscall(SYS_clone, flags, stack, ptid, ctid, tls) + // r6 r0, r1, r2, r3, r4 + asm volatile ( + \\ allocframe(#8) + \\ + \\ r11 = r0 + \\ r10 = r3 + \\ + \\ r6 = #220 // SYS_clone + \\ r0 = r2 + \\ r1 = and(r1, #-8) + \\ r2 = r4 + \\ r3 = memw(r30 + #8) + \\ r4 = r5 + \\ trap0(#1) + \\ + \\ p0 = cmp.eq(r0, #0) + \\ if (!p0) dealloc_return + \\ + \\ r0 = r10 + \\ callr r11 + \\ + \\ r6 = #93 // SYS_exit + \\ r0 = #0 + \\ trap0(#1) + ); +} + +pub const restore = restore_rt; + +pub fn restore_rt() callconv(.Naked) noreturn { + asm volatile ( + \\ trap0(#0) + : + : [number] "{r6}" (@intFromEnum(SYS.rt_sigreturn)), + : "memory" + ); +} + +pub const F = struct { + pub const DUPFD = 0; + pub const GETFD = 1; + pub const SETFD = 2; + pub const GETFL = 3; + pub const SETFL = 4; + pub const GETLK = 5; + pub const SETLK = 6; + pub const SETLKW = 7; + pub const SETOWN = 8; + pub const GETOWN = 9; + pub const SETSIG = 10; + pub const GETSIG = 11; + + pub const RDLCK = 0; + pub const WRLCK = 1; + pub const UNLCK = 2; + + pub const SETOWN_EX = 15; + pub const GETOWN_EX = 16; + + pub const GETOWNER_UIDS = 17; +}; + +pub const timeval = extern struct { + sec: time_t, + usec: i32, +}; + +pub const Flock = extern struct { + type: i16, + whence: i16, + start: off_t, + len: off_t, + pid: pid_t, + __unused: [4]u8, +}; + +pub const msghdr = extern struct { + name: ?*sockaddr, + namelen: socklen_t, + iov: [*]iovec, + iovlen: i32, + __pad1: i32 = 0, + control: ?*anyopaque, + controllen: socklen_t, + __pad2: socklen_t = 0, + flags: i32, +}; + +pub const msghdr_const = extern struct { + name: ?*const sockaddr, + namelen: socklen_t, + iov: [*]const iovec_const, + iovlen: i32, + __pad1: i32 = 0, + control: ?*const anyopaque, + controllen: socklen_t, + __pad2: socklen_t = 0, + flags: i32, +}; + +pub const blksize_t = i32; +pub const nlink_t = u32; +pub const time_t = i32; +pub const mode_t = u32; +pub const off_t = i64; +pub const ino_t = u64; +pub const dev_t = u64; +pub const blkcnt_t = i64; + +// The `stat` definition used by the Linux kernel. +pub const Stat = extern struct { + dev: dev_t, + ino: ino_t, + mode: mode_t, + nlink: nlink_t, + uid: uid_t, + gid: gid_t, + rdev: dev_t, + __pad: u32, + size: off_t, + blksize: blksize_t, + __pad2: i32, + blocks: blkcnt_t, + atim: timespec, + mtim: timespec, + ctim: timespec, + __unused: [2]u32, + + pub fn atime(self: @This()) timespec { + return self.atim; + } + + pub fn mtime(self: @This()) timespec { + return self.mtim; + } + + pub fn ctime(self: @This()) timespec { + return self.ctim; + } +}; + +pub const Elf_Symndx = u32; + +pub const MMAP2_UNIT = 4096; + +pub const VDSO = void; + +/// TODO +pub const ucontext_t = void; + +/// TODO +pub const getcontext = {}; From 8060fad4250d0157ac412f95c76511770e1eb097 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Wed, 2 Oct 2024 08:14:54 +0200 Subject: [PATCH 4/7] generate_linux_syscalls: Rename mmap_pgoff to mmap2. --- lib/std/os/linux/syscalls.zig | 4 ++-- tools/generate_linux_syscalls.zig | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/std/os/linux/syscalls.zig b/lib/std/os/linux/syscalls.zig index d08a77b47c55..ef04387ea62d 100644 --- a/lib/std/os/linux/syscalls.zig +++ b/lib/std/os/linux/syscalls.zig @@ -6852,7 +6852,7 @@ pub const Arc = enum(usize) { keyctl = 219, clone = 220, execve = 221, - mmap_pgoff = 222, + mmap2 = 222, fadvise64_64 = 223, swapon = 224, swapoff = 225, @@ -7538,7 +7538,7 @@ pub const Hexagon = enum(usize) { keyctl = 219, clone = 220, execve = 221, - mmap_pgoff = 222, + mmap2 = 222, fadvise64_64 = 223, swapon = 224, swapoff = 225, diff --git a/tools/generate_linux_syscalls.zig b/tools/generate_linux_syscalls.zig index f11633491e9b..df1b5127dfb8 100644 --- a/tools/generate_linux_syscalls.zig +++ b/tools/generate_linux_syscalls.zig @@ -22,6 +22,8 @@ const stdlib_renames = std.StaticStringMap([]const u8).initComptime(.{ // ARM EABI/Thumb. .{ "arm_sync_file_range", "sync_file_range" }, .{ "arm_fadvise64_64", "fadvise64_64" }, + // ARC and Hexagon. + .{ "mmap_pgoff", "mmap2" }, }); // Only for newer architectures where we use the C preprocessor. From 56b0c7bd2f5936c17571e878f835cf0d542ca1fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Wed, 2 Oct 2024 08:15:19 +0200 Subject: [PATCH 5/7] std.zig.system: Force disable the small_data feature for hexagon. This works around the fact that LLVM and LLD both have broken support for the small data area, yet the feature is on by default for all Hexagon CPUs. I want to eventually replace this hack with a flag in update_cpu_features.zig for marking features that should always be off by default and not be accessible to users. That way, the compiler will have full control over them. --- lib/std/zig/system.zig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig index 046bd3854e45..9fcaaf0cb15c 100644 --- a/lib/std/zig/system.zig +++ b/lib/std/zig/system.zig @@ -385,6 +385,16 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target { query.cpu_features_sub, ); + if (cpu_arch == .hexagon) { + // Both LLVM and LLD have broken support for the small data area. Yet LLVM has the feature + // on by default for all Hexagon CPUs. Clang sort of solves this by defaulting the `-gpsize` + // command line parameter for the Hexagon backend to 0, so that no constants get placed in + // the SDA. (This of course breaks down if the user passes `-G ` to Clang...) We can't do + // the `-gpsize` hack because we can have multiple concurrent LLVM emit jobs, and command + // line options in LLVM are shared globally. So just force this feature off. Lovely stuff. + result.cpu.features.removeFeature(@intFromEnum(Target.hexagon.Feature.small_data)); + } + // https://github.com/llvm/llvm-project/issues/105978 if (result.cpu.arch.isArmOrThumb() and result.floatAbi() == .soft) { result.cpu.features.removeFeature(@intFromEnum(Target.arm.Feature.vfp2)); From f31173d379eb7c63f214579ffbba611c1fa38900 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Wed, 2 Oct 2024 08:16:05 +0200 Subject: [PATCH 6/7] llvm: Disable f16 lowering for hexagon. In theory, this should work for v68+. In practice, it runs into an LLVM assertion when using a `freeze` instruction on `f16` values, similar to the issue we had for LoongArch. --- src/codegen/llvm.zig | 1 + 1 file changed, 1 insertion(+) diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 2cd1af783e23..52b196004856 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -12380,6 +12380,7 @@ fn backendSupportsF80(target: std.Target) bool { /// if it produces miscompilations. fn backendSupportsF16(target: std.Target) bool { return switch (target.cpu.arch) { + .hexagon, .powerpc, .powerpcle, .powerpc64, From 45644b7e152e851b9f9f51095e3ce1ca7fcc8a56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Wed, 2 Oct 2024 08:16:35 +0200 Subject: [PATCH 7/7] link.Elf: Fix default page size for hexagon. --- src/link/Elf.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 919122799f6c..c25d49c3bfbf 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -189,7 +189,7 @@ pub fn createEmpty( }; const page_size: u32 = switch (target.cpu.arch) { - .aarch64, .powerpc64le => 0x10000, + .aarch64, .hexagon, .powerpc64le => 0x10000, .sparc64 => 0x2000, else => 0x1000, };