Skip to main content

rustc_target/spec/base/
qnx_sdp.rs

1use crate::spec::{
2    Cc, LinkArgs, LinkerFlavor, Lld, Os, RelroLevel, Target, TargetMetadata, TargetOptions, cvs,
3};
4
5pub(crate) fn opts() -> TargetOptions {
6    TargetOptions {
7        crt_static_respected: true,
8        dynamic_linking: true,
9        executables: true,
10        families: ::std::borrow::Cow::Borrowed(&[::std::borrow::Cow::Borrowed("unix")])cvs!["unix"],
11        has_rpath: true,
12        has_thread_local: false,
13        linker: Some("qcc".into()),
14        os: Os::Nto,
15        // We want backtraces to work by default and they rely on unwind tables
16        // (regardless of `-C panic` strategy).
17        default_uwtable: true,
18        position_independent_executables: true,
19        static_position_independent_executables: true,
20        relro_level: RelroLevel::Full,
21        ..Default::default()
22    }
23}
24
25pub(crate) fn meta() -> TargetMetadata {
26    TargetMetadata { description: None, tier: Some(3), host_tools: Some(false), std: Some(true) }
27}
28
29pub(crate) fn aarch64() -> Target {
30    Target {
31        llvm_target: "aarch64-unknown-unknown".into(),
32        metadata: meta(),
33        pointer_width: 64,
34        // from: https://llvm.org/docs/LangRef.html#data-layout
35        // e         = little endian
36        // m:e       = ELF mangling: Private symbols get a .L prefix
37        // i8:8:32   = 8-bit-integer, minimum_alignment=8, preferred_alignment=32
38        // i16:16:32 = 16-bit-integer, minimum_alignment=16, preferred_alignment=32
39        // i64:64    = 64-bit-integer, minimum_alignment=64, preferred_alignment=64
40        // i128:128  = 128-bit-integer, minimum_alignment=128, preferred_alignment=128
41        // n32:64    = 32 and 64 are native integer widths; Elements of this set are considered to support most general arithmetic operations efficiently.
42        // S128      = 128 bits are the natural alignment of the stack in bits.
43        data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
44        arch: crate::spec::Arch::AArch64,
45        options: TargetOptions {
46            features: "+v8a".into(),
47            max_atomic_width: Some(128),
48            ..opts()
49        }
50    }
51}
52
53pub(crate) fn x86_64() -> Target {
54    Target {
55        llvm_target: "x86_64-pc-unknown".into(),
56        metadata: meta(),
57        pointer_width: 64,
58        data_layout:
59            "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
60        arch: crate::spec::Arch::X86_64,
61        options: TargetOptions {
62            cpu: "x86-64".into(),
63            plt_by_default: false,
64            max_atomic_width: Some(64),
65            vendor: "pc".into(),
66            ..opts()
67        },
68    }
69}
70
71pub(crate) fn pre_link_args(api_var: ApiVariant, arch: Arch) -> LinkArgs {
72    let (qcc_arg, arch_lib_dir): (&[_], _) = match arch {
73        Arch::Aarch64 => (
74            &[
75                "-Vgcc_ntoaarch64le_cxx",
76                "-Wl,--fix-cortex-a53-843419", // ferrocene addition
77            ],
78            "aarch64le",
79        ),
80        Arch::I586 => (
81            &["-Vgcc_ntox86_cxx"],
82            "notSupportedByQnx_compiler/rustc_target/src/spec/base/nto_qnx.rs",
83        ),
84        Arch::X86_64 => (&["-Vgcc_ntox86_64_cxx"], "x86_64"),
85    };
86    match api_var {
87        ApiVariant::Default => {
88            TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), qcc_arg)
89        }
90        ApiVariant::IoSock => {
91            let mut qcc_arg = qcc_arg.to_vec();
92            qcc_arg.push(get_iosock_param(arch_lib_dir));
93
94            TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &qcc_arg)
95        }
96    }
97}
98
99pub(crate) enum ApiVariant {
100    Default,
101    IoSock,
102}
103
104pub(crate) enum Arch {
105    Aarch64,
106    I586,
107    X86_64,
108}
109
110// When using `io-sock` on QNX, we must add a search path for the linker so
111// that it prefers the io-sock version.
112// The path depends on the host, i.e. we cannot hard-code it here, but have
113// to determine it when the compiler runs.
114// When using the QNX toolchain, the environment variable QNX_TARGET is always set.
115// More information:
116// https://www.qnx.com/developers/docs/7.1/index.html#com.qnx.doc.neutrino.io_sock/topic/migrate_app.html
117fn get_iosock_param(arch_lib_dir: &str) -> &'static str {
118    let target_dir = std::env::var("QNX_TARGET")
119        .unwrap_or_else(|_| "QNX_TARGET_not_set_please_source_qnxsdp-env.sh".into());
120    let linker_param = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("-L{0}/{1}/io-sock/lib", target_dir,
                arch_lib_dir))
    })format!("-L{target_dir}/{arch_lib_dir}/io-sock/lib");
121
122    // FIXME: leaking this is kind of weird: we're feeding these into something that expects an
123    // `AsRef<OsStr>`, but often converts to `OsString` anyways, so shouldn't we just demand an `OsString`?
124    linker_param.leak()
125}