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

Add tier 3 no_std AArch64/x86_64 support for the QNX Neutrino RTOS #102701

Merged
merged 4 commits into from
Nov 12, 2022
Merged
Show file tree
Hide file tree
Changes from 3 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
28 changes: 28 additions & 0 deletions compiler/rustc_target/src/spec/aarch64_unknown_nto_qnx_710.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use super::nto_qnx_base;
use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions};

pub fn target() -> Target {
Target {
llvm_target: "aarch64-unknown-unknown".into(),
pointer_width: 64,
// from: https://llvm.org/docs/LangRef.html#data-layout
// e = little endian
// m:e = ELF mangling: Private symbols get a .L prefix
// i8:8:32 = 8-bit-integer, minimum_alignment=8, preferred_alignment=32
// i16:16:32 = 16-bit-integer, minimum_alignment=16, preferred_alignment=32
// i64:64 = 64-bit-integer, minimum_alignment=64, preferred_alignment=64
// i128:128 = 128-bit-integer, minimum_alignment=128, preferred_alignment=128
// n32:64 = 32 and 64 are native integer widths; Elements of this set are considered to support most general arithmetic operations efficiently.
// S128 = 128 bits are the natural alignment of the stack in bits.
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
arch: "aarch64".into(),
options: TargetOptions {
max_atomic_width: Some(128),
pre_link_args: TargetOptions::link_args(
LinkerFlavor::Gnu(Cc::Yes, Lld::No),
&["-Vgcc_ntoaarch64le_cxx"],
),
..nto_qnx_base::opts()
},
}
}
4 changes: 4 additions & 0 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ mod linux_musl_base;
mod linux_uclibc_base;
mod msvc_base;
mod netbsd_base;
mod nto_qnx_base;
mod openbsd_base;
mod redox_base;
mod solaris_base;
Expand Down Expand Up @@ -1242,6 +1243,9 @@ supported_targets! {
("x86_64-unknown-none", x86_64_unknown_none),

("mips64-openwrt-linux-musl", mips64_openwrt_linux_musl),

("aarch64-unknown-nto-qnx7.1.0", aarch64_unknown_nto_qnx_710),
("x86_64-pc-nto-qnx7.1.0", x86_64_pc_nto_qnx710),
}

/// Cow-Vec-Str: Cow<'static, [Cow<'static, str>]>
Expand Down
19 changes: 19 additions & 0 deletions compiler/rustc_target/src/spec/nto_qnx_base.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use crate::spec::{cvs, RelroLevel, TargetOptions};

pub fn opts() -> TargetOptions {
flba-eb marked this conversation as resolved.
Show resolved Hide resolved
TargetOptions {
crt_static_respected: true,
dynamic_linking: true,
env: "nto71".into(),
executables: true,
families: cvs!["unix"],
has_rpath: true,
has_thread_local: false,
flba-eb marked this conversation as resolved.
Show resolved Hide resolved
linker: Some("qcc".into()),
os: "nto".into(),
position_independent_executables: true,
static_position_independent_executables: true,
relro_level: RelroLevel::Full,
..Default::default()
}
}
21 changes: 21 additions & 0 deletions compiler/rustc_target/src/spec/x86_64_pc_nto_qnx710.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use super::nto_qnx_base;
use crate::spec::{Cc, LinkerFlavor, Lld, Target, TargetOptions};

pub fn target() -> Target {
Target {
llvm_target: "x86_64-pc-unknown".into(),
pointer_width: 64,
data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
.into(),
arch: "x86_64".into(),
options: TargetOptions {
cpu: "x86-64".into(),
max_atomic_width: Some(64),
pre_link_args: TargetOptions::link_args(
LinkerFlavor::Gnu(Cc::Yes, Lld::No),
&["-Vgcc_ntox86_64_cxx"],
),
..nto_qnx_base::opts()
},
}
}
1 change: 1 addition & 0 deletions src/doc/rustc/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
- [nvptx64-nvidia-cuda](platform-support/nvptx64-nvidia-cuda.md)
- [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md)
- [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md)
- [\*-nto-qnx-\*](platform-support/nto-qnx.md)
- [*-unknown-openbsd](platform-support/openbsd.md)
- [\*-unknown-uefi](platform-support/unknown-uefi.md)
- [wasm64-unknown-unknown](platform-support/wasm64-unknown-unknown.md)
Expand Down
2 changes: 2 additions & 0 deletions src/doc/rustc/src/platform-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ target | std | host | notes
[`aarch64-kmc-solid_asp3`](platform-support/kmc-solid.md) | ✓ | | ARM64 SOLID with TOPPERS/ASP3
[`aarch64-nintendo-switch-freestanding`](platform-support/aarch64-nintendo-switch-freestanding.md) | * | | ARM64 Nintendo Switch, Horizon
[`aarch64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ |
[`aarch64-unknown-nto-qnx7.1.0`](platform-support/nto-qnx.md) | ? | | ARM64 QNX Neutrino 7.1 RTOS |
`aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD
`aarch64-unknown-hermit` | ✓ | | ARM64 HermitCore
`aarch64-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (ILP32 ABI)
Expand Down Expand Up @@ -303,6 +304,7 @@ target | std | host | notes
`x86_64-apple-ios-macabi` | ✓ | | Apple Catalyst on x86_64
`x86_64-apple-tvos` | * | | x86 64-bit tvOS
[`x86_64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ | | x86 64-bit Apple WatchOS simulator
[`x86_64-pc-nto-qnx7.1.0`](platform-support/nto-qnx.md) | ? | | x86 64-bit QNX Neutrino 7.1 RTOS |
[`x86_64-pc-windows-gnullvm`](platform-support/pc-windows-gnullvm.md) | ✓ | ✓ |
`x86_64-pc-windows-msvc` | * | | 64-bit Windows XP support
`x86_64-sun-solaris` | ? | | Deprecated target for 64-bit Solaris 10/11, illumos
Expand Down
118 changes: 118 additions & 0 deletions src/doc/rustc/src/platform-support/nto-qnx.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# nto-qnx

**Tier: 3**

[BlackBerry® QNX®][BlackBerry] Neutrino (nto) Real-time operating system.
The support has been implemented jointly by [Elektrobit Automotive GmbH][Elektrobit]
and [BlackBerry][BlackBerry].

[BlackBerry]: https://blackberry.qnx.com
[Elektrobit]: https://www.elektrobit.com

## Target maintainers

- Florian Bartels, `Florian.Bartels@elektrobit.com`, https://github.com/flba-eb
- Tristan Roach, `TRoach@blackberry.com`, https://github.com/gh-tr

## Requirements

Currently, only cross-compilation for QNX Neutrino on AArch64 and x86_64 are supported (little endian).
Adding other architectures that are supported by QNX Neutrino is possible.

The standard library does not yet support QNX Neutrino. Therefore, only `no_std` code can
be compiled.

`core` and `alloc` (with default allocator) are supported.

Applications must link against `libc.so` (see example). This is required because applications
always link against the `crt` library and `crt` depends on `libc.so`.

The correct version of `qcc` must be available by setting the `$PATH` variable (e.g. by sourcing `qnxsdp-env.sh` of the
QNX Neutrino toolchain).

### Small example application

```rust
#![no_std]
#![no_main]
#![feature(lang_items)]

// We must always link against libc, even if no external functions are used
// "extern C" - Block can be empty but must be present
#[link(name = "c")]
extern "C" {
pub fn printf(format: *const core::ffi::c_char, ...) -> core::ffi::c_int;
}

#[no_mangle]
pub extern "C" fn main(_argc: isize, _argv: *const *const u8) -> isize {
const HELLO: &'static str = "Hello World, the answer is %d\n\0";
unsafe {
printf(HELLO.as_ptr() as *const _, 42);
}
0
}

use core::panic::PanicInfo;

#[panic_handler]
fn panic(_panic: &PanicInfo<'_>) -> ! {
loop {}
}

#[lang = "eh_personality"]
#[no_mangle]
pub extern "C" fn rust_eh_personality() {}
```

The QNX Neutrino support of Rust has been tested with QNX Neutrino 7.1.

There are no further known requirements.

## Conditional compilation

For conditional compilation, following QNX Neutrino specific attributes are defined:

- `target_os` = `"nto"`
- `target_env` = `"nto71"` (for QNX Neutrino 7.1)

## Building the target

1. Create a `config.toml`

Example content:

```toml
profile = "compiler"
changelog-seen = 2
```

2. Compile the Rust toolchain for an `x86_64-unknown-linux-gnu` host (for both `aarch64` and `x86_64` targets)

Run the following:

```bash
env \
CC_aarch64-unknown-nto-qnx7.1.0="qcc" \
CFLAGS_aarch64-unknown-nto-qnx7.1.0="-Vgcc_ntoaarch64le_cxx" \
CXX_aarch64-unknown-nto-qnx7.1.0="qcc" \
AR_aarch64_unknown_nto_qnx7.1.0="ntoaarch64-ar" \
CC_x86_64-pc-nto-qnx7.1.0="qcc" \
CFLAGS_x86_64-pc-nto-qnx7.1.0="-Vgcc_ntox86_64_cxx" \
CXX_x86_64-pc-nto-qnx7.1.0="qcc" \
AR_x86_64_pc_nto_qnx7.1.0="ntox86_64-ar" \
./x.py build --target aarch64-unknown-nto-qnx7.1.0 --target x86_64-pc-nto-qnx7.1.0 --target x86_64-unknown-linux-gnu rustc library/core library/alloc/
```

## Building Rust programs

Rust does not yet ship pre-compiled artifacts for this target. To compile for this target, you must either build Rust with the target enabled (see "Building the target" above), or build your own copy of `core` by using
`build-std` or similar.

## Testing

Compiled executables can directly be run on QNX Neutrino.

## Cross-compilation toolchains and C code

Compiling C code requires the same environment variables to be set as compiling the Rust toolchain (see above), to ensure `qcc` is used with proper arguments. To ensure compatibility, do not specify any further arguments that for example change calling conventions or memory layout.
2 changes: 1 addition & 1 deletion src/test/ui/check-cfg/well-known-values.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ LL | #[cfg(target_os = "linuz")]
| |
| help: did you mean: `"linux"`
|
= note: expected values for `target_os` are: android, cuda, dragonfly, emscripten, espidf, freebsd, fuchsia, haiku, hermit, horizon, illumos, ios, l4re, linux, macos, netbsd, none, openbsd, psp, redox, solaris, solid_asp3, tvos, uefi, unknown, vxworks, wasi, watchos, windows, xous
= note: expected values for `target_os` are: android, cuda, dragonfly, emscripten, espidf, freebsd, fuchsia, haiku, hermit, horizon, illumos, ios, l4re, linux, macos, netbsd, none, nto, openbsd, psp, redox, solaris, solid_asp3, tvos, uefi, unknown, vxworks, wasi, watchos, windows, xous
= note: `#[warn(unexpected_cfgs)]` on by default

warning: unexpected `cfg` condition value
Expand Down