Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some initial hexagon-linux port work #21587

Merged
merged 7 commits into from
Oct 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions lib/std/atomic.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
11 changes: 6 additions & 5 deletions lib/std/os/linux.zig
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@ 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"),
.hexagon => @import("linux/hexagon.zig"),
.riscv32 => @import("linux/riscv32.zig"),
.riscv64 => @import("linux/riscv64.zig"),
.sparc64 => @import("linux/sparc64.zig"),
Expand Down Expand Up @@ -116,7 +117,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");
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
File renamed without changes.
File renamed without changes.
254 changes: 254 additions & 0 deletions lib/std/os/linux/hexagon.zig
Original file line number Diff line number Diff line change
@@ -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 = {};
File renamed without changes.
4 changes: 2 additions & 2 deletions lib/std/os/linux/syscalls.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion lib/std/os/linux/thumb.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down
10 changes: 10 additions & 0 deletions lib/std/zig/system.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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 <n>` 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));
Expand Down
1 change: 1 addition & 0 deletions src/codegen/llvm.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion src/link/Elf.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down
2 changes: 2 additions & 0 deletions tools/generate_linux_syscalls.zig
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down