Skip to content

Commit be5378b

Browse files
authored
Merge pull request #21587 from alexrp/hexagon-porting
Some initial `hexagon-linux` port work
2 parents 008bb1f + 45644b7 commit be5378b

12 files changed

+281
-11
lines changed

lib/std/atomic.zig

+4-2
Original file line numberDiff line numberDiff line change
@@ -433,18 +433,20 @@ pub const cache_line = switch (builtin.cpu.arch) {
433433
.powerpc64le,
434434
=> 128,
435435

436+
// https://github.com/llvm/llvm-project/blob/e379094328e49731a606304f7e3559d4f1fa96f9/clang/lib/Basic/Targets/Hexagon.h#L145-L151
437+
.hexagon,
438+
=> if (std.Target.hexagon.featureSetHas(builtin.target.cpu.features, .v73)) 64 else 32,
439+
436440
// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_arm.go#L7
437441
// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mips.go#L7
438442
// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mipsle.go#L7
439443
// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mips64x.go#L9
440444
// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_riscv64.go#L7
441-
// - https://github.com/torvalds/linux/blob/3a7e02c040b130b5545e4b115aada7bacd80a2b6/arch/hexagon/include/asm/cache.h#L13
442445
// - https://github.com/torvalds/linux/blob/3a7e02c040b130b5545e4b115aada7bacd80a2b6/arch/sparc/include/asm/cache.h#L14
443446
.arm,
444447
.armeb,
445448
.thumb,
446449
.thumbeb,
447-
.hexagon,
448450
.mips,
449451
.mipsel,
450452
.mips64,

lib/std/os/linux.zig

+6-5
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,9 @@ const syscall_bits = switch (native_arch) {
3737
const arch_bits = switch (native_arch) {
3838
.x86 => @import("linux/x86.zig"),
3939
.x86_64 => @import("linux/x86_64.zig"),
40-
.aarch64, .aarch64_be => @import("linux/arm64.zig"),
41-
.arm, .armeb, .thumb, .thumbeb => @import("linux/arm-eabi.zig"),
40+
.aarch64, .aarch64_be => @import("linux/aarch64.zig"),
41+
.arm, .armeb, .thumb, .thumbeb => @import("linux/arm.zig"),
42+
.hexagon => @import("linux/hexagon.zig"),
4243
.riscv32 => @import("linux/riscv32.zig"),
4344
.riscv64 => @import("linux/riscv64.zig"),
4445
.sparc64 => @import("linux/sparc64.zig"),
@@ -116,7 +117,7 @@ pub const user_desc = arch_bits.user_desc;
116117
pub const getcontext = arch_bits.getcontext;
117118

118119
pub const tls = @import("linux/tls.zig");
119-
pub const pie = @import("linux/start_pie.zig");
120+
pub const pie = @import("linux/pie.zig");
120121
pub const BPF = @import("linux/bpf.zig");
121122
pub const IOCTL = @import("linux/ioctl.zig");
122123
pub const SECCOMP = @import("linux/seccomp.zig");
@@ -277,7 +278,7 @@ pub const MAP = switch (native_arch) {
277278
UNINITIALIZED: bool = false,
278279
_: u5 = 0,
279280
},
280-
.s390x => packed struct(u32) {
281+
.hexagon, .s390x => packed struct(u32) {
281282
TYPE: MAP_TYPE,
282283
FIXED: bool = false,
283284
ANONYMOUS: bool = false,
@@ -441,7 +442,7 @@ pub const O = switch (native_arch) {
441442
TMPFILE: bool = false,
442443
_: u9 = 0,
443444
},
444-
.s390x => packed struct(u32) {
445+
.hexagon, .s390x => packed struct(u32) {
445446
ACCMODE: ACCMODE = .RDONLY,
446447
_2: u4 = 0,
447448
CREAT: bool = false,
File renamed without changes.
File renamed without changes.

lib/std/os/linux/hexagon.zig

+254
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
const std = @import("../../std.zig");
2+
const iovec = std.posix.iovec;
3+
const iovec_const = std.posix.iovec_const;
4+
const linux = std.os.linux;
5+
const SYS = linux.SYS;
6+
const uid_t = std.os.linux.uid_t;
7+
const gid_t = std.os.linux.gid_t;
8+
const pid_t = std.os.linux.pid_t;
9+
const sockaddr = linux.sockaddr;
10+
const socklen_t = linux.socklen_t;
11+
const timespec = std.os.linux.timespec;
12+
13+
pub fn syscall0(number: SYS) usize {
14+
return asm volatile ("trap0(#1)"
15+
: [ret] "={r0}" (-> usize),
16+
: [number] "{r6}" (@intFromEnum(number)),
17+
: "memory"
18+
);
19+
}
20+
21+
pub fn syscall1(number: SYS, arg1: usize) usize {
22+
return asm volatile ("trap0(#1)"
23+
: [ret] "={r0}" (-> usize),
24+
: [number] "{r6}" (@intFromEnum(number)),
25+
[arg1] "{r0}" (arg1),
26+
: "memory"
27+
);
28+
}
29+
30+
pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {
31+
return asm volatile ("trap0(#1)"
32+
: [ret] "={r0}" (-> usize),
33+
: [number] "{r6}" (@intFromEnum(number)),
34+
[arg1] "{r0}" (arg1),
35+
[arg2] "{r1}" (arg2),
36+
: "memory"
37+
);
38+
}
39+
40+
pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
41+
return asm volatile ("trap0(#1)"
42+
: [ret] "={r0}" (-> usize),
43+
: [number] "{r6}" (@intFromEnum(number)),
44+
[arg1] "{r0}" (arg1),
45+
[arg2] "{r1}" (arg2),
46+
[arg3] "{r2}" (arg3),
47+
: "memory"
48+
);
49+
}
50+
51+
pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize {
52+
return asm volatile ("trap0(#1)"
53+
: [ret] "={r0}" (-> usize),
54+
: [number] "{r6}" (@intFromEnum(number)),
55+
[arg1] "{r0}" (arg1),
56+
[arg2] "{r1}" (arg2),
57+
[arg3] "{r2}" (arg3),
58+
[arg4] "{r3}" (arg4),
59+
: "memory"
60+
);
61+
}
62+
63+
pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize {
64+
return asm volatile ("trap0(#1)"
65+
: [ret] "={r0}" (-> usize),
66+
: [number] "{r6}" (@intFromEnum(number)),
67+
[arg1] "{r0}" (arg1),
68+
[arg2] "{r1}" (arg2),
69+
[arg3] "{r2}" (arg3),
70+
[arg4] "{r3}" (arg4),
71+
[arg5] "{r4}" (arg5),
72+
: "memory"
73+
);
74+
}
75+
76+
pub 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 ("trap0(#1)"
86+
: [ret] "={r0}" (-> usize),
87+
: [number] "{r6}" (@intFromEnum(number)),
88+
[arg1] "{r0}" (arg1),
89+
[arg2] "{r1}" (arg2),
90+
[arg3] "{r2}" (arg3),
91+
[arg4] "{r3}" (arg4),
92+
[arg5] "{r4}" (arg5),
93+
[arg6] "{r5}" (arg6),
94+
: "memory"
95+
);
96+
}
97+
98+
pub fn clone() callconv(.Naked) usize {
99+
// __clone(func, stack, flags, arg, ptid, tls, ctid)
100+
// r0, r1, r2, r3, r4, r5, +0
101+
//
102+
// syscall(SYS_clone, flags, stack, ptid, ctid, tls)
103+
// r6 r0, r1, r2, r3, r4
104+
asm volatile (
105+
\\ allocframe(#8)
106+
\\
107+
\\ r11 = r0
108+
\\ r10 = r3
109+
\\
110+
\\ r6 = #220 // SYS_clone
111+
\\ r0 = r2
112+
\\ r1 = and(r1, #-8)
113+
\\ r2 = r4
114+
\\ r3 = memw(r30 + #8)
115+
\\ r4 = r5
116+
\\ trap0(#1)
117+
\\
118+
\\ p0 = cmp.eq(r0, #0)
119+
\\ if (!p0) dealloc_return
120+
\\
121+
\\ r0 = r10
122+
\\ callr r11
123+
\\
124+
\\ r6 = #93 // SYS_exit
125+
\\ r0 = #0
126+
\\ trap0(#1)
127+
);
128+
}
129+
130+
pub const restore = restore_rt;
131+
132+
pub fn restore_rt() callconv(.Naked) noreturn {
133+
asm volatile (
134+
\\ trap0(#0)
135+
:
136+
: [number] "{r6}" (@intFromEnum(SYS.rt_sigreturn)),
137+
: "memory"
138+
);
139+
}
140+
141+
pub const F = struct {
142+
pub const DUPFD = 0;
143+
pub const GETFD = 1;
144+
pub const SETFD = 2;
145+
pub const GETFL = 3;
146+
pub const SETFL = 4;
147+
pub const GETLK = 5;
148+
pub const SETLK = 6;
149+
pub const SETLKW = 7;
150+
pub const SETOWN = 8;
151+
pub const GETOWN = 9;
152+
pub const SETSIG = 10;
153+
pub const GETSIG = 11;
154+
155+
pub const RDLCK = 0;
156+
pub const WRLCK = 1;
157+
pub const UNLCK = 2;
158+
159+
pub const SETOWN_EX = 15;
160+
pub const GETOWN_EX = 16;
161+
162+
pub const GETOWNER_UIDS = 17;
163+
};
164+
165+
pub const timeval = extern struct {
166+
sec: time_t,
167+
usec: i32,
168+
};
169+
170+
pub const Flock = extern struct {
171+
type: i16,
172+
whence: i16,
173+
start: off_t,
174+
len: off_t,
175+
pid: pid_t,
176+
__unused: [4]u8,
177+
};
178+
179+
pub const msghdr = extern struct {
180+
name: ?*sockaddr,
181+
namelen: socklen_t,
182+
iov: [*]iovec,
183+
iovlen: i32,
184+
__pad1: i32 = 0,
185+
control: ?*anyopaque,
186+
controllen: socklen_t,
187+
__pad2: socklen_t = 0,
188+
flags: i32,
189+
};
190+
191+
pub const msghdr_const = extern struct {
192+
name: ?*const sockaddr,
193+
namelen: socklen_t,
194+
iov: [*]const iovec_const,
195+
iovlen: i32,
196+
__pad1: i32 = 0,
197+
control: ?*const anyopaque,
198+
controllen: socklen_t,
199+
__pad2: socklen_t = 0,
200+
flags: i32,
201+
};
202+
203+
pub const blksize_t = i32;
204+
pub const nlink_t = u32;
205+
pub const time_t = i32;
206+
pub const mode_t = u32;
207+
pub const off_t = i64;
208+
pub const ino_t = u64;
209+
pub const dev_t = u64;
210+
pub const blkcnt_t = i64;
211+
212+
// The `stat` definition used by the Linux kernel.
213+
pub const Stat = extern struct {
214+
dev: dev_t,
215+
ino: ino_t,
216+
mode: mode_t,
217+
nlink: nlink_t,
218+
uid: uid_t,
219+
gid: gid_t,
220+
rdev: dev_t,
221+
__pad: u32,
222+
size: off_t,
223+
blksize: blksize_t,
224+
__pad2: i32,
225+
blocks: blkcnt_t,
226+
atim: timespec,
227+
mtim: timespec,
228+
ctim: timespec,
229+
__unused: [2]u32,
230+
231+
pub fn atime(self: @This()) timespec {
232+
return self.atim;
233+
}
234+
235+
pub fn mtime(self: @This()) timespec {
236+
return self.mtim;
237+
}
238+
239+
pub fn ctime(self: @This()) timespec {
240+
return self.ctim;
241+
}
242+
};
243+
244+
pub const Elf_Symndx = u32;
245+
246+
pub const MMAP2_UNIT = 4096;
247+
248+
pub const VDSO = void;
249+
250+
/// TODO
251+
pub const ucontext_t = void;
252+
253+
/// TODO
254+
pub const getcontext = {};
File renamed without changes.

lib/std/os/linux/syscalls.zig

+2-2
Original file line numberDiff line numberDiff line change
@@ -6852,7 +6852,7 @@ pub const Arc = enum(usize) {
68526852
keyctl = 219,
68536853
clone = 220,
68546854
execve = 221,
6855-
mmap_pgoff = 222,
6855+
mmap2 = 222,
68566856
fadvise64_64 = 223,
68576857
swapon = 224,
68586858
swapoff = 225,
@@ -7538,7 +7538,7 @@ pub const Hexagon = enum(usize) {
75387538
keyctl = 219,
75397539
clone = 220,
75407540
execve = 221,
7541-
mmap_pgoff = 222,
7541+
mmap2 = 222,
75427542
fadvise64_64 = 223,
75437543
swapon = 224,
75447544
swapoff = 225,

lib/std/os/linux/thumb.zig

+1-1
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ pub fn syscall6(
141141
);
142142
}
143143

144-
pub const clone = @import("arm-eabi.zig").clone;
144+
pub const clone = @import("arm.zig").clone;
145145

146146
pub fn restore() callconv(.Naked) noreturn {
147147
asm volatile (

lib/std/zig/system.zig

+10
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,16 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target {
386386
query.cpu_features_sub,
387387
);
388388

389+
if (cpu_arch == .hexagon) {
390+
// Both LLVM and LLD have broken support for the small data area. Yet LLVM has the feature
391+
// on by default for all Hexagon CPUs. Clang sort of solves this by defaulting the `-gpsize`
392+
// command line parameter for the Hexagon backend to 0, so that no constants get placed in
393+
// the SDA. (This of course breaks down if the user passes `-G <n>` to Clang...) We can't do
394+
// the `-gpsize` hack because we can have multiple concurrent LLVM emit jobs, and command
395+
// line options in LLVM are shared globally. So just force this feature off. Lovely stuff.
396+
result.cpu.features.removeFeature(@intFromEnum(Target.hexagon.Feature.small_data));
397+
}
398+
389399
// https://github.com/llvm/llvm-project/issues/105978
390400
if (result.cpu.arch.isArmOrThumb() and result.floatAbi() == .soft) {
391401
result.cpu.features.removeFeature(@intFromEnum(Target.arm.Feature.vfp2));

src/codegen/llvm.zig

+1
Original file line numberDiff line numberDiff line change
@@ -12444,6 +12444,7 @@ fn backendSupportsF80(target: std.Target) bool {
1244412444
/// if it produces miscompilations.
1244512445
fn backendSupportsF16(target: std.Target) bool {
1244612446
return switch (target.cpu.arch) {
12447+
.hexagon,
1244712448
.powerpc,
1244812449
.powerpcle,
1244912450
.powerpc64,

src/link/Elf.zig

+1-1
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ pub fn createEmpty(
189189
};
190190

191191
const page_size: u32 = switch (target.cpu.arch) {
192-
.aarch64, .powerpc64le => 0x10000,
192+
.aarch64, .hexagon, .powerpc64le => 0x10000,
193193
.sparc64 => 0x2000,
194194
else => 0x1000,
195195
};

tools/generate_linux_syscalls.zig

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ const stdlib_renames = std.StaticStringMap([]const u8).initComptime(.{
2222
// ARM EABI/Thumb.
2323
.{ "arm_sync_file_range", "sync_file_range" },
2424
.{ "arm_fadvise64_64", "fadvise64_64" },
25+
// ARC and Hexagon.
26+
.{ "mmap_pgoff", "mmap2" },
2527
});
2628

2729
// Only for newer architectures where we use the C preprocessor.

0 commit comments

Comments
 (0)