Skip to content

Commit dd5390f

Browse files
committed
Add support for hexagon-unknown-none-elf as target
Signed-off-by: Brian Cain <[email protected]>
1 parent 90fdc1f commit dd5390f

File tree

6 files changed

+355
-1
lines changed

6 files changed

+355
-1
lines changed

compiler/rustc_target/src/spec/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1494,6 +1494,7 @@ supported_targets! {
14941494
("mips64-unknown-linux-muslabi64", mips64_unknown_linux_muslabi64),
14951495
("mips64el-unknown-linux-muslabi64", mips64el_unknown_linux_muslabi64),
14961496
("hexagon-unknown-linux-musl", hexagon_unknown_linux_musl),
1497+
("hexagon-unknown-none-elf", hexagon_unknown_none_elf),
14971498

14981499
("mips-unknown-linux-uclibc", mips_unknown_linux_uclibc),
14991500
("mipsel-unknown-linux-uclibc", mipsel_unknown_linux_uclibc),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
use crate::spec::{PanicStrategy, Target, TargetOptions};
2+
3+
pub fn target() -> Target {
4+
Target {
5+
llvm_target: "hexagon-unknown-none-elf".into(),
6+
pointer_width: 32,
7+
data_layout: concat!(
8+
"e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32",
9+
":32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32",
10+
":32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048",
11+
":2048:2048"
12+
)
13+
.into(),
14+
arch: "hexagon".into(),
15+
16+
options: TargetOptions {
17+
cpu: "hexagonv60".into(),
18+
panic_strategy: PanicStrategy::Abort,
19+
dynamic_linking: true,
20+
features: "-small-data,+hvx-length128b".into(),
21+
max_atomic_width: Some(32),
22+
emit_debug_gdb_scripts: false,
23+
c_enum_min_bits: Some(8),
24+
..Default::default()
25+
},
26+
}
27+
}

compiler/rustc_target/src/spec/tests/tests_impl.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,8 @@ impl Target {
116116

117117
// Check dynamic linking stuff
118118
// BPF: when targeting user space vms (like rbpf), those can load dynamic libraries.
119-
if self.os == "none" && self.arch != "bpf" {
119+
// hexagon: when targeting QuRT, that OS can load dynamic libraries.
120+
if self.os == "none" && (self.arch != "bpf" && self.arch != "hexagon") {
120121
assert!(!self.dynamic_linking);
121122
}
122123
if self.only_cdylib

src/doc/rustc/src/SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
- [\*-unknown-fuchsia](platform-support/fuchsia.md)
3535
- [\*-kmc-solid_\*](platform-support/kmc-solid.md)
3636
- [csky-unknown-linux-gnuabiv2\*](platform-support/csky-unknown-linux-gnuabiv2.md)
37+
- [hexagon-unknown-none-elf](platform-support/hexagon-unknown-none-elf.md)
3738
- [loongarch\*-unknown-linux-\*](platform-support/loongarch-linux.md)
3839
- [loongarch\*-unknown-none\*](platform-support/loongarch-none.md)
3940
- [m68k-unknown-linux-gnu](platform-support/m68k-unknown-linux-gnu.md)

src/doc/rustc/src/platform-support.md

+1
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ target | std | host | notes
263263
`bpfel-unknown-none` | * | | BPF (little endian)
264264
`csky-unknown-linux-gnuabiv2` | ✓ | | C-SKY abiv2 Linux (little endian)
265265
`csky-unknown-linux-gnuabiv2hf` | ✓ | | C-SKY abiv2 Linux, hardfloat (little endian)
266+
[`hexagon-unknown-none-elf`](platform-support/hexagon-unknown-none-elf.md)| * | Bare Hexagon (v60+, HVX)
266267
`hexagon-unknown-linux-musl` | ? | |
267268
`i386-apple-ios` | ✓ | | 32-bit x86 iOS [^x86_32-floats-return-ABI]
268269
[`i586-pc-nto-qnx700`](platform-support/nto-qnx.md) | * | | 32-bit x86 QNX Neutrino 7.0 RTOS [^x86_32-floats-return-ABI]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,323 @@
1+
# `hexagon-unknown-none-elf`
2+
3+
**Tier: 3**
4+
5+
Rust for baremetal Hexagon DSPs.
6+
7+
| Target | Descriptions |
8+
| ------------------------ | ----------------------------------------- |
9+
| hexagon-unknown-none-elf | Hexagon 32-bit (freestanding, hardfloat) |
10+
11+
## Target maintainers
12+
13+
- [Brian Cain](https://github.com/androm3da), `[email protected]`
14+
15+
## Requirements
16+
17+
This target is cross-compiled. There is no support for `std`. There is no
18+
default allocator, but it's possible to use `alloc` by supplying an allocator.
19+
20+
By default, code generated with this target should run on Hexagon DSP hardware.
21+
22+
- `-Ctarget-cpu=hexagonv73` adds support for instructions defined up to Hexagon V73.
23+
24+
Functions marked `extern "C"` use the [Hexagon architecture calling convention](https://lists.llvm.org/pipermail/llvm-dev/attachments/20190916/21516a52/attachment-0001.pdf).
25+
26+
This target generates PIC ELF binaries.
27+
28+
## Building the target
29+
30+
You can build Rust with support for the target by adding it to the `target`
31+
list in `config.toml`:
32+
33+
```toml
34+
[build]
35+
build-stage = 1
36+
host = ["<target for your host>"]
37+
target = ["<target for your host>", "hexagon-unknown-none-elf"]
38+
39+
[target.hexagon-unknown-none-elf]
40+
41+
cc = "hexagon-unknown-none-elf-clang"
42+
cxx = "hexagon-unknown-none-elf-clang++"
43+
linker = "hexagon-unknown-none-elf-clang"
44+
llvm-libunwind = 'in-tree'
45+
```
46+
47+
Replace `<target for your host>` with `x86_64-unknown-linux-gnu` or whatever
48+
else is appropriate for your host machine.
49+
50+
## Building Rust programs
51+
52+
Rust does not yet ship pre-compiled artifacts for this target. To compile for
53+
this target, you will either need to build Rust with the target enabled (see
54+
"Building the target" above), or build your own copy of `core` by using
55+
`build-std` or similar.
56+
57+
## Testing
58+
59+
Since `hexagon-unknown-none-elf` supports a variety of different environments and
60+
does not support `std`, this target does not support running the Rust test suite.
61+
62+
## Cross-compilation toolchains and C code
63+
64+
This target has been tested using `qemu-system-hexagon`.
65+
66+
A common use case for `hexagon-unknown-none-elf` is building libraries that
67+
link against C code and can be used in emulation or on a device with a
68+
Hexagon DSP.
69+
70+
The Hexagon SDK has libraries which are useful to link against when running
71+
on a device.
72+
73+
74+
# Sample library
75+
76+
Here's a sample library for use with the demonstrations below.
77+
78+
```rust
79+
#![no_std]
80+
#![no_main]
81+
#![feature(lang_items)]
82+
#![feature(asm_experimental_arch)]
83+
84+
use core::arch::asm;
85+
86+
extern "C" {
87+
fn putchar(ch: i32);
88+
fn _exit(code: i32) -> !;
89+
}
90+
91+
fn hexagon_specific() {
92+
let mut buffer = [0_u8; 128];
93+
94+
unsafe {
95+
let mut x = &buffer;
96+
asm!(
97+
"{{\n\t",
98+
" v0=vmem({addr}+#0)\n\t",
99+
" {tmp} = and({tmp}, #1)\n\t",
100+
"}}\n\t",
101+
addr = in(reg) x,
102+
tmp = out(reg) _,
103+
);
104+
}
105+
}
106+
107+
#[no_mangle]
108+
extern "C" fn hello() -> i32 {
109+
let message = "Hello, this is Rust!\n";
110+
for b in message.bytes() {
111+
unsafe {
112+
putchar(b as i32);
113+
}
114+
}
115+
hexagon_specific();
116+
0
117+
}
118+
119+
#[panic_handler]
120+
fn panic(_panic: &core::panic::PanicInfo) -> ! {
121+
unsafe {
122+
_exit(1);
123+
}
124+
}
125+
126+
#[lang = "eh_personality"]
127+
fn rust_eh_personality() {}
128+
129+
```
130+
131+
# Standalone OS
132+
133+
The script below will build an executable against "hexagon standalone OS"
134+
which is suitable for emulation or bare-metal on-device testing.
135+
136+
First, run `cargo new --bin demo1_hexagon` then add the source below as
137+
`src/main.rs`. This program demonstrates the console output via semihosting.
138+
139+
```rust
140+
#![no_std]
141+
#![no_main]
142+
143+
extern "C" {
144+
fn putchar(ch: i32);
145+
fn _exit(code: i32) -> !;
146+
}
147+
148+
#[no_mangle]
149+
extern "C" fn main() -> i32 {
150+
let message = "Hello, this is Rust!";
151+
for b in message.bytes() {
152+
unsafe {
153+
putchar(b as i32);
154+
}
155+
}
156+
0
157+
}
158+
159+
#[panic_handler]
160+
fn panic(_panic: &core::panic::PanicInfo) -> ! {
161+
unsafe {
162+
_exit(1);
163+
}
164+
}
165+
166+
```
167+
168+
Next, save the script below as `build.sh` and edit it to suit your
169+
environment.
170+
171+
* `hex_toolchain` below refers to the [hexagon toolchain using exclusively
172+
public open source repos](https://github.com/quic/toolchain_for_hexagon/releases).
173+
* `cc` below refers to clang. You can use `clang` from your distribution, as
174+
long as it's at least `clang-17`. Or you can use
175+
`hexagon-unknown-none-elf-clang` from one of the [hexagon open source toolchain
176+
releases](https://github.com/quic/toolchain_for_hexagon/releases).
177+
178+
```sh
179+
# Hexagon SDK, required for target libraries:
180+
hex_sdk_root=/local/mnt/workspace/Qualcomm/Hexagon_SDK/5.3.0.0
181+
hex_sdk_toolchain=${hex_sdk_root}/tools/HEXAGON_Tools/8.6.06
182+
183+
sdk_libs=${hex_sdk_toolchain}/Tools/target/hexagon/lib
184+
q6_arch=v65
185+
g0_lib_path=${sdk_libs}/${q6_arch}/G0
186+
pic_lib_path=${sdk_libs}/${q6_arch}/G0/pic
187+
188+
cargo build --target=hexagon-unknown-none-elf -Zbuild-std
189+
190+
# Builds an executable against "hexagon standalone OS" suitable for emulation:
191+
${cc} --target=hexagon-unknown-none-elf -o testit \
192+
-fuse-ld=lld \
193+
-m${q6_arch} \
194+
-nodefaultlibs \
195+
-nostartfiles \
196+
${g0_lib_path}/crt0_standalone.o \
197+
${g0_lib_path}/crt0.o \
198+
${g0_lib_path}/init.o \
199+
-L${sdk_libs}/${q6_arch}/ \
200+
-L${sdk_libs}/ \
201+
testit.c \
202+
target/hexagon-unknown-none-elf/debug/libmin_ex_lib_lin.rlib \
203+
target/hexagon-unknown-none-elf/debug/deps/libcore-*.rlib \
204+
target/hexagon-unknown-none-elf/debug/deps/libcompiler_builtins-*.rlib \
205+
-Wl,--start-group \
206+
-Wl,--defsym,_SDA_BASE_=0,--defsym,__sbss_start=0,--defsym,__sbss_end=0 \
207+
-lstandalone \
208+
${g0_lib_path}/libc.a \
209+
-lgcc \
210+
-lc_eh \
211+
-Wl,--end-group \
212+
${g0_lib_path}/fini.o \
213+
214+
${hex_toolchain}/x86_64-linux-gnu/bin/qemu-system-hexagon -monitor none -display none -kernel ./testit
215+
```
216+
217+
# QuRT OS
218+
219+
First, run `cargo new --lib demo2_hexagon` then add the source below as
220+
`src/lib.rs`. This program demonstrates inline assembly and console output
221+
via semihosting.
222+
223+
```rust
224+
#![no_std]
225+
#![no_main]
226+
#![feature(lang_items)]
227+
#![feature(asm_experimental_arch)]
228+
229+
use core::arch::asm;
230+
231+
extern "C" {
232+
fn putchar(ch: i32);
233+
fn _exit(code: i32) -> !;
234+
}
235+
236+
fn hexagon_specific() {
237+
let mut buffer = [0_u8; 128];
238+
239+
unsafe {
240+
let mut x = &buffer;
241+
asm!(
242+
"{{\n\t",
243+
" v0=vmem({addr}+#0)\n\t",
244+
" {tmp} = and({tmp}, #1)\n\t",
245+
"}}\n\t",
246+
addr = in(reg) x,
247+
tmp = out(reg) _,
248+
);
249+
}
250+
}
251+
252+
#[no_mangle]
253+
extern "C" fn hello() -> i32 {
254+
let message = "Hello, this is Rust!\n";
255+
for b in message.bytes() {
256+
unsafe {
257+
putchar(b as i32);
258+
}
259+
}
260+
hexagon_specific();
261+
0
262+
}
263+
264+
#[panic_handler]
265+
fn panic(_panic: &core::panic::PanicInfo) -> ! {
266+
unsafe {
267+
_exit(1);
268+
}
269+
}
270+
271+
#[lang = "eh_personality"]
272+
fn rust_eh_personality() {}
273+
274+
```
275+
276+
Next, save the script below as `build.sh` and edit it to suit your
277+
environment. The script below will build a shared object against the QuRT
278+
RTOS which is suitable for emulation or on-device testing when loaded via
279+
the fastrpc-shell.
280+
281+
282+
```sh
283+
# Hexagon SDK, required for target libraries:
284+
hex_sdk_root=/local/mnt/workspace/Qualcomm/Hexagon_SDK/5.3.0.0
285+
hex_sdk_toolchain=${hex_sdk_root}/tools/HEXAGON_Tools/8.6.06
286+
287+
sdk_libs=${hex_sdk_toolchain}/Tools/target/hexagon/lib
288+
q6_arch=v65
289+
g0_lib_path=${sdk_libs}/${q6_arch}/G0
290+
pic_lib_path=${sdk_libs}/${q6_arch}/G0/pic
291+
runelf=${hex_sdk_root}/rtos/qurt/computev65/sdksim_bin/runelf.pbn
292+
rmohs=${hex_sdk_root}/libs/run_main_on_hexagon/ship/hexagon_toolv86_${q6_arch}/run_main_on_hexagon_sim
293+
294+
# Builds a library suitable for loading into "run_main_on_hexagon_sim" for
295+
# emulation or frpc shell on real target:
296+
${cc} --target=hexagon-unknown-none-elf -o testit.so \
297+
-fuse-ld=lld \
298+
-fPIC -shared \
299+
-nostdlib \
300+
-Wl,-Bsymbolic \
301+
-Wl,--wrap=malloc \
302+
-Wl,--wrap=calloc \
303+
-Wl,--wrap=free \
304+
-Wl,--wrap=realloc \
305+
-Wl,--wrap=memalign \
306+
-m${q6_arch} \
307+
testit.c \
308+
target/hexagon-unknown-none-elf/debug/libmin_ex_lib_lin.rlib \
309+
target/hexagon-unknown-none-elf/debug/deps/libcore-*.rlib \
310+
target/hexagon-unknown-none-elf/debug/deps/libcompiler_builtins-*.rlib \
311+
-Wl,-soname=testit \
312+
${pic_lib_path}/libc.so
313+
314+
# -Bsymbolic above for memory alloc funcs is necessary to access the heap on
315+
# target, but otherwise not required.
316+
317+
# multi-stage loader: runelf => run_main_on_hexagon_sim => testit.so{`main`}
318+
${hex_toolchain}/x86_64-linux-gnu/bin/qemu-system-hexagon \
319+
-monitor none \
320+
-display none \
321+
-kernel ${runelf} \
322+
-append "${rmohs} -- ./testit.so"
323+
```

0 commit comments

Comments
 (0)