Skip to content

Commit 0a34928

Browse files
authored
Rollup merge of #145973 - vexide:vex-std, r=tgross35
Add `std` support for `armv7a-vex-v5` This PR adds standard library support for the VEX V5 Brain (`armv7a-vex-v5` target). It is more-or-less an updated version of the library-side work done in #131530. This was a joint effort between me, `@lewisfm,` `@max-niederman,` `@Gavin-Niederman` and several other members of the [`vexide` project](https://github.com/vexide/). ## Background VEXos is a fairly unconventional operating system, with user code running in a restricted enviornment with regards to I/O capabilities and whatnot. As such, several OS-dependent APIs are unsupported or have partial support (such as `std::net`, `std::process`, and most of `std::thread`). A more comprehensive list of what does or doesn't work is outlined in the [updated target documentation](https://github.com/vexide/rust/blob/vex-std/src/doc/rustc/src/platform-support/armv7a-vex-v5.md). Despite these limitations, we believe that `libstd` support on this target still has value to users, especially given the popular use of this hardware for educational purposes. For some previous discussion on this matter, see [this comment](#131530 (comment)). ## SDK Linkage VEXos doesn't really ship with an official `libc` or POSIX-style platform API (and though it does port newlib, these are stubbed on top of the underlying SDK). Instead, VEX provides their own SDK for calling platform APIs. Their official SDK is kept proprietary (with public headers), though open-source implementations exist. Following the precedent of the `armv6k-nintendo-3ds` team's work in #95897, we've opted not to directly link `libstd` to any SDK with the expectation that users will provide their own with one of the following options: - [`vex-sdk-download`](https://github.com/vexide/vex-sdk/tree/main/packages/vex-sdk-download), which downloads an official proprietary SDK from VEX using a build script. - [`vex-sdk-jumptable`](https://crates.io/crates/vex-sdk-jumptable), which is a compatible, open-source reimplementation of the SDK using firmware jumps. - [`vex-sdk-pros`](https://github.com/vexide/vex-sdk/tree/main/packages/vex-sdk-pros), which uses the [PROS kernel](https://github.com/purduesigbots/pros) as a provider for SDK functions. - Linking their own implementation or stubbing the functions required by libstd. The `vex-sdk` crate used in the VEXos PAL provides `libc`-style FFI bindings for any compatible system library, so any of these options *should* work fine. A functional demo project using `vex-sdk-download` can be found [here](https://github.com/vexide/armv7a-vex-v5-demo/tree/main). ## Future Work This PR implements virtually everything we are currently able to implement given the current capabilities of the platform. The exception to this is file directory enumeration, though the implementation of that is sufficiently [gross enough](https://github.com/vexide/vexide/blob/c6c5bad11e035cf4e51d429dca7e427210185ed4/packages/vexide-core/src/fs/mod.rs#L987) to drive us away from supporting this officially. Additionally, I have a working branch implementing the `panic_unwind` runtime for this target, which is something that would be nice to see in the future, though given the volume of compiler changes i've deemed it out-of-scope for this PR.
2 parents 21b0e12 + b2634e3 commit 0a34928

File tree

21 files changed

+1012
-10
lines changed

21 files changed

+1012
-10
lines changed

compiler/rustc_target/src/spec/targets/armv7a_vex_v5.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ pub(crate) fn target() -> Target {
3434
description: Some("ARMv7-A Cortex-A9 VEX V5 Brain".into()),
3535
tier: Some(3),
3636
host_tools: Some(false),
37-
std: Some(false),
37+
std: Some(true),
3838
},
3939
pointer_width: 32,
4040
data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),

library/Cargo.lock

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ dependencies = [
326326
"rustc-demangle",
327327
"std_detect",
328328
"unwind",
329+
"vex-sdk",
329330
"wasi 0.11.1+wasi-snapshot-preview1",
330331
"wasi 0.14.4+wasi-0.2.4",
331332
"windows-targets 0.0.0",
@@ -379,6 +380,15 @@ dependencies = [
379380
"rustc-std-workspace-core",
380381
]
381382

383+
[[package]]
384+
name = "vex-sdk"
385+
version = "0.27.0"
386+
source = "registry+https://github.com/rust-lang/crates.io-index"
387+
checksum = "89f74fce61d7a7ba1589da9634c6305a72befb7cc9150c1f872d87d8060f32b9"
388+
dependencies = [
389+
"rustc-std-workspace-core",
390+
]
391+
382392
[[package]]
383393
name = "wasi"
384394
version = "0.11.1+wasi-snapshot-preview1"

library/std/Cargo.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ path = "../windows_targets"
6262
rand = { version = "0.9.0", default-features = false, features = ["alloc"] }
6363
rand_xorshift = "0.4.0"
6464

65-
[target.'cfg(any(all(target_family = "wasm", target_os = "unknown"), target_os = "xous", all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies]
65+
[target.'cfg(any(all(target_family = "wasm", target_os = "unknown"), target_os = "xous", target_os = "vexos", all(target_vendor = "fortanix", target_env = "sgx")))'.dependencies]
6666
dlmalloc = { version = "0.2.10", features = ['rustc-dep-of-std'] }
6767

6868
[target.x86_64-fortanix-unknown-sgx.dependencies]
@@ -89,6 +89,11 @@ wasip2 = { version = '0.14.4', features = [
8989
r-efi = { version = "5.2.0", features = ['rustc-dep-of-std'] }
9090
r-efi-alloc = { version = "2.0.0", features = ['rustc-dep-of-std'] }
9191

92+
[target.'cfg(target_os = "vexos")'.dependencies]
93+
vex-sdk = { version = "0.27.0", features = [
94+
'rustc-dep-of-std',
95+
], default-features = false }
96+
9297
[features]
9398
backtrace = [
9499
'addr2line/rustc-dep-of-std',

library/std/build.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ fn main() {
5252
|| target_os == "rtems"
5353
|| target_os == "nuttx"
5454
|| target_os == "cygwin"
55+
|| target_os == "vexos"
5556

5657
// See src/bootstrap/src/core/build_steps/synthetic_targets.rs
5758
|| env::var("RUSTC_BOOTSTRAP_SYNTHETIC_TARGET").is_ok()

library/std/src/env.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,6 +1098,7 @@ pub mod consts {
10981098
/// * `"redox"`
10991099
/// * `"solaris"`
11001100
/// * `"solid_asp3`
1101+
/// * `"vexos"`
11011102
/// * `"vita"`
11021103
/// * `"vxworks"`
11031104
/// * `"xous"`
@@ -1148,6 +1149,7 @@ pub mod consts {
11481149
///
11491150
/// <details><summary>Full list of possible values</summary>
11501151
///
1152+
/// * `"bin"`
11511153
/// * `"exe"`
11521154
/// * `"efi"`
11531155
/// * `"js"`

library/std/src/sys/alloc/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ cfg_select! {
9292
target_os = "uefi" => {
9393
mod uefi;
9494
}
95+
target_os = "vexos" => {
96+
mod vexos;
97+
}
9598
target_family = "wasm" => {
9699
mod wasm;
97100
}

library/std/src/sys/alloc/vexos.rs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
2+
#![allow(static_mut_refs)]
3+
4+
use crate::alloc::{GlobalAlloc, Layout, System};
5+
use crate::ptr;
6+
use crate::sync::atomic::{AtomicBool, Ordering};
7+
8+
// Symbols for heap section boundaries defined in the target's linkerscript
9+
unsafe extern "C" {
10+
static mut __heap_start: u8;
11+
static mut __heap_end: u8;
12+
}
13+
14+
static mut DLMALLOC: dlmalloc::Dlmalloc<Vexos> = dlmalloc::Dlmalloc::new_with_allocator(Vexos);
15+
16+
struct Vexos;
17+
18+
unsafe impl dlmalloc::Allocator for Vexos {
19+
/// Allocs system resources
20+
fn alloc(&self, _size: usize) -> (*mut u8, usize, u32) {
21+
static INIT: AtomicBool = AtomicBool::new(false);
22+
23+
if !INIT.swap(true, Ordering::Relaxed) {
24+
// This target has no growable heap, as user memory has a fixed
25+
// size/location and VEXos does not manage allocation for us.
26+
unsafe {
27+
(
28+
(&raw mut __heap_start).cast::<u8>(),
29+
(&raw const __heap_end).offset_from_unsigned(&raw const __heap_start),
30+
0,
31+
)
32+
}
33+
} else {
34+
(ptr::null_mut(), 0, 0)
35+
}
36+
}
37+
38+
fn remap(&self, _ptr: *mut u8, _oldsize: usize, _newsize: usize, _can_move: bool) -> *mut u8 {
39+
ptr::null_mut()
40+
}
41+
42+
fn free_part(&self, _ptr: *mut u8, _oldsize: usize, _newsize: usize) -> bool {
43+
false
44+
}
45+
46+
fn free(&self, _ptr: *mut u8, _size: usize) -> bool {
47+
return false;
48+
}
49+
50+
fn can_release_part(&self, _flags: u32) -> bool {
51+
false
52+
}
53+
54+
fn allocates_zeros(&self) -> bool {
55+
false
56+
}
57+
58+
fn page_size(&self) -> usize {
59+
0x1000
60+
}
61+
}
62+
63+
#[stable(feature = "alloc_system_type", since = "1.28.0")]
64+
unsafe impl GlobalAlloc for System {
65+
#[inline]
66+
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
67+
// SAFETY: DLMALLOC access is guaranteed to be safe because we are a single-threaded target, which
68+
// guarantees unique and non-reentrant access to the allocator. As such, no allocator lock is used.
69+
// Calling malloc() is safe because preconditions on this function match the trait method preconditions.
70+
unsafe { DLMALLOC.malloc(layout.size(), layout.align()) }
71+
}
72+
73+
#[inline]
74+
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
75+
// SAFETY: DLMALLOC access is guaranteed to be safe because we are a single-threaded target, which
76+
// guarantees unique and non-reentrant access to the allocator. As such, no allocator lock is used.
77+
// Calling calloc() is safe because preconditions on this function match the trait method preconditions.
78+
unsafe { DLMALLOC.calloc(layout.size(), layout.align()) }
79+
}
80+
81+
#[inline]
82+
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
83+
// SAFETY: DLMALLOC access is guaranteed to be safe because we are a single-threaded target, which
84+
// guarantees unique and non-reentrant access to the allocator. As such, no allocator lock is used.
85+
// Calling free() is safe because preconditions on this function match the trait method preconditions.
86+
unsafe { DLMALLOC.free(ptr, layout.size(), layout.align()) }
87+
}
88+
89+
#[inline]
90+
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
91+
// SAFETY: DLMALLOC access is guaranteed to be safe because we are a single-threaded target, which
92+
// guarantees unique and non-reentrant access to the allocator. As such, no allocator lock is used.
93+
// Calling realloc() is safe because preconditions on this function match the trait method preconditions.
94+
unsafe { DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size) }
95+
}
96+
}

library/std/src/sys/env_consts.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,17 @@ pub mod os {
323323
pub const EXE_EXTENSION: &str = "efi";
324324
}
325325

326+
#[cfg(target_os = "vexos")]
327+
pub mod os {
328+
pub const FAMILY: &str = "";
329+
pub const OS: &str = "vexos";
330+
pub const DLL_PREFIX: &str = "";
331+
pub const DLL_SUFFIX: &str = "";
332+
pub const DLL_EXTENSION: &str = "";
333+
pub const EXE_SUFFIX: &str = ".bin";
334+
pub const EXE_EXTENSION: &str = "bin";
335+
}
336+
326337
#[cfg(target_os = "visionos")]
327338
pub mod os {
328339
pub const FAMILY: &str = "unix";

library/std/src/sys/fs/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ cfg_select! {
3535
mod uefi;
3636
use uefi as imp;
3737
}
38+
target_os = "vexos" => {
39+
mod vexos;
40+
use vexos as imp;
41+
}
3842
target_os = "wasi" => {
3943
mod wasi;
4044
use wasi as imp;

0 commit comments

Comments
 (0)