From d3b02f33878c6915d24407c6c747df3168bd244a Mon Sep 17 00:00:00 2001 From: Sebastian Humenda Date: Tue, 3 Apr 2018 14:53:13 +0200 Subject: [PATCH] L4Re WIP --- compiler/rustc_codegen_ssa/src/back/linker.rs | 102 +++++++++++++++--- compiler/rustc_target/src/spec/l4re_base.rs | 18 +--- .../src/spec/x86_64_unknown_l4re_uclibc.rs | 1 + library/panic_unwind/src/lib.rs | 4 + library/std/src/sys/unix/l4re.rs | 10 +- library/std/src/sys/unix/mod.rs | 1 + .../std/src/sys/unix/process/process_unix.rs | 5 +- 7 files changed, 107 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 9e1c6a169f152..d4602afd408c8 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -134,15 +134,13 @@ pub fn get_linker<'a>( } LinkerFlavor::Em => Box::new(EmLinker { cmd, sess }) as Box, LinkerFlavor::Gcc => { - Box::new(GccLinker { cmd, sess, target_cpu, hinted_static: false, is_ld: false }) - as Box + Box::new(GccLinker::new(cmd, sess, target_cpu, false)) as Box } LinkerFlavor::Lld(LldFlavor::Ld) | LinkerFlavor::Lld(LldFlavor::Ld64) | LinkerFlavor::Ld => { - Box::new(GccLinker { cmd, sess, target_cpu, hinted_static: false, is_ld: true }) - as Box + Box::new(GccLinker::new(cmd, sess, target_cpu, true)) as Box } LinkerFlavor::Lld(LldFlavor::Wasm) => Box::new(WasmLd::new(cmd, sess)) as Box, @@ -220,6 +218,17 @@ pub struct GccLinker<'a> { } impl<'a> GccLinker<'a> { + fn new(mut cmd: Command, sess: &'a Session, target_cpu: &'a str, is_ld: bool) -> GccLinker<'a> { + if sess.target.os == "l4re" { + // FIXME: Why is this a rustc's job at all? + // Why can't l4-bender read the `L4_BENDER_ARGS` variable instead? + // If this needs to be done with rustc, then why it cannot be done with existing + // generic tools like `-Clink-arg` or `-Zpre-link-arg` + add_l4bender_args(&mut cmd); + } + GccLinker { cmd, sess, target_cpu, is_ld, hinted_static: false } + } + /// Argument that must be passed *directly* to the linker /// /// These arguments need to be prepended with `-Wl`, when a GCC-style linker is used. @@ -339,6 +348,10 @@ impl<'a> Linker for GccLinker<'a> { } fn set_output_kind(&mut self, output_kind: LinkOutputKind, out_filename: &Path) { + if self.sess.target.os == "l4re" { + // FIXME: Should be unnecessary if the targets correctly specify not supporting dylibs and cdylibs. + return; + } match output_kind { LinkOutputKind::DynamicNoPicExe => { if !self.is_ld && self.sess.target.linker_is_gnu { @@ -433,7 +446,12 @@ impl<'a> Linker for GccLinker<'a> { } fn link_staticlib(&mut self, lib: Symbol, verbatim: bool) { self.hint_static(); - self.cmd.arg(format!("-l{}{}", if verbatim { ":" } else { "" }, lib)); + if self.sess.target.os == "l4re" { + // FIXME: Why is this deliberate difference from gcc necessary? + self.cmd.arg(format!("-PC{}", lib)); + } else { + self.cmd.arg(format!("-l{}{}", if verbatim { ":" } else { "" }, lib)); + } } fn link_rlib(&mut self, lib: &Path) { self.hint_static(); @@ -452,14 +470,33 @@ impl<'a> Linker for GccLinker<'a> { self.cmd.arg(path); } fn full_relro(&mut self) { - self.linker_arg("-zrelro"); - self.linker_arg("-znow"); + if self.sess.target.os == "l4re" { + // FIXME: Why a comma between `-z` and `relro`? + // FIXME: Why a comma between `-z,relro and -z,now`? + // FIXME: Will `-zrelro` without space or comma work? + self.cmd.arg("-z,relro,-z,now"); + } else { + self.linker_arg("-zrelro"); + self.linker_arg("-znow"); + } } fn partial_relro(&mut self) { - self.linker_arg("-zrelro"); + if self.sess.target.os == "l4re" { + // FIXME: Why a comma between `-z` and `relro`? + // FIXME: Will `-zrelro` without space or comma work? + self.cmd.arg("-z,relro"); + } else { + self.linker_arg("-zrelro"); + } } fn no_relro(&mut self) { - self.linker_arg("-znorelro"); + if self.sess.target.os == "l4re" { + // FIXME: Why a comma between `-z` and `norelro`? + // FIXME: Will `-znorelro` without space or comma work? + self.cmd.arg("-z,norelro"); + } else { + self.linker_arg("-znorelro"); + } } fn link_rust_dylib(&mut self, lib: Symbol, _path: &Path) { @@ -537,7 +574,9 @@ impl<'a> Linker for GccLinker<'a> { // eliminate the metadata. If we're building an executable, however, // --gc-sections drops the size of hello world from 1.8MB to 597K, a 67% // reduction. - } else if (self.sess.target.linker_is_gnu || self.sess.target.is_like_wasm) + } else if (self.sess.target.linker_is_gnu + || self.sess.target.is_like_wasm + || self.sess.target.os == "l4re") && !keep_metadata { self.linker_arg("--gc-sections"); @@ -553,7 +592,11 @@ impl<'a> Linker for GccLinker<'a> { } fn optimize(&mut self) { - if !self.sess.target.linker_is_gnu && !self.sess.target.is_like_wasm { + if self.sess.target.os == "l4re" { + // FIXME: Why the difference with the GNU case below? + self.cmd.arg("-O2"); + return; + } else if !self.sess.target.linker_is_gnu && !self.sess.target.is_like_wasm { return; } @@ -713,8 +756,13 @@ impl<'a> Linker for GccLinker<'a> { } fn subsystem(&mut self, subsystem: &str) { - self.linker_arg("--subsystem"); - self.linker_arg(&subsystem); + if self.sess.target.os == "l4re" { + // FIXME: Why the comma between --subsystem and its name? + self.cmd.arg(&format!("--subsystem,{}", subsystem)); + } else { + self.linker_arg("--subsystem"); + self.linker_arg(&subsystem); + } } fn reset_per_library_state(&mut self) { @@ -1597,3 +1645,31 @@ impl<'a> Linker for BpfLinker<'a> { fn linker_plugin_lto(&mut self) {} } + +fn add_l4bender_args(cmd: &mut Command) { + if let Ok(l4bender_args) = env::var("L4_BENDER_ARGS") { + // This parses a shell-escaped string and unquotes the arguments. It doesn't attempt to + // completely understand shell, but should instead allow passing arguments like + // `-Dlinker="ld -m x86_64"`, and a copy without quotes, but spaces preserved, is added + // as an argument to the given Command. This means that constructs as \" are not + // understood, so quote wisely. + let mut arg = String::new(); + let mut quoted = false; + for character in l4bender_args.chars() { + match character { + ' ' if !quoted => { + cmd.arg(&arg); + arg.clear(); + } + '"' | '\'' => quoted = !quoted, + _ => arg.push(character), + }; + } + if arg.len() > 0 { + cmd.arg(&arg); + arg.clear(); + } + } + + cmd.arg("--"); // separate direct l4-bender args from linker args +} diff --git a/compiler/rustc_target/src/spec/l4re_base.rs b/compiler/rustc_target/src/spec/l4re_base.rs index f6e3102f61762..0863c19b68ac9 100644 --- a/compiler/rustc_target/src/spec/l4re_base.rs +++ b/compiler/rustc_target/src/spec/l4re_base.rs @@ -1,27 +1,15 @@ -use crate::spec::{LinkerFlavor, PanicStrategy, TargetOptions}; -//use std::process::Command; - -// Use GCC to locate code for crt* libraries from the host, not from L4Re. Note -// that a few files also come from L4Re, for these, the function shouldn't be -// used. This uses GCC for the location of the file, but GCC is required for L4Re anyway. -//fn get_path_or(filename: &str) -> String { -// let child = Command::new("gcc") -// .arg(format!("-print-file-name={}", filename)).output() -// .expect("Failed to execute GCC"); -// String::from_utf8(child.stdout) -// .expect("Couldn't read path from GCC").trim().into() -//} +use crate::spec::{PanicStrategy, TargetOptions}; pub fn opts() -> TargetOptions { TargetOptions { os: "l4re".to_string(), env: "uclibc".to_string(), - linker_flavor: LinkerFlavor::Ld, executables: true, panic_strategy: PanicStrategy::Abort, - linker: Some("ld".to_string()), + linker: Some("l4-bender".to_string()), linker_is_gnu: false, families: vec!["unix".to_string()], + limit_rdylib_exports: false, ..Default::default() } } diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs b/compiler/rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs index 1fbd0bb4cec25..69e26c95985a6 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs +++ b/compiler/rustc_target/src/spec/x86_64_unknown_l4re_uclibc.rs @@ -4,6 +4,7 @@ pub fn target() -> Target { let mut base = super::l4re_base::opts(); base.cpu = "x86-64".to_string(); base.max_atomic_width = Some(64); + base.crt_static_default = true; Target { llvm_target: "x86_64-unknown-l4re-uclibc".to_string(), diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs index ac7d8c18e3e02..f50f294983ba4 100644 --- a/library/panic_unwind/src/lib.rs +++ b/library/panic_unwind/src/lib.rs @@ -39,6 +39,10 @@ cfg_if::cfg_if! { } else if #[cfg(target_os = "hermit")] { #[path = "hermit.rs"] mod real_imp; + } else if #[cfg(target_os = "l4re")] { + // L4Re is unix family but does not yet support unwinding. + #[path = "dummy.rs"] + mod real_imp; } else if #[cfg(target_env = "msvc")] { #[path = "seh.rs"] mod real_imp; diff --git a/library/std/src/sys/unix/l4re.rs b/library/std/src/sys/unix/l4re.rs index ba63b41534c1a..e91465aa71acb 100644 --- a/library/std/src/sys/unix/l4re.rs +++ b/library/std/src/sys/unix/l4re.rs @@ -59,7 +59,7 @@ pub mod net { } pub fn is_read_vectored(&self) -> bool { - unimpl!(); + false } pub fn peek(&self, _: &mut [u8]) -> io::Result { @@ -83,7 +83,7 @@ pub mod net { } pub fn is_write_vectored(&self) -> bool { - unimpl!(); + false } pub fn set_timeout(&self, _: Option, _: libc::c_int) -> io::Result<()> { @@ -191,7 +191,7 @@ pub mod net { } pub fn is_read_vectored(&self) -> bool { - unimpl!(); + false } pub fn write(&self, _: &[u8]) -> io::Result { @@ -203,7 +203,7 @@ pub mod net { } pub fn is_write_vectored(&self) -> bool { - unimpl!(); + false } pub fn peer_addr(&self) -> io::Result { @@ -497,7 +497,7 @@ pub mod net { impl LookupHost { pub fn port(&self) -> u16 { - unimpl!(); + 0 // unimplemented } } diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs index f5424e3d28214..9e28ffb29b4e2 100644 --- a/library/std/src/sys/unix/mod.rs +++ b/library/std/src/sys/unix/mod.rs @@ -80,6 +80,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) { target_os = "macos", target_os = "ios", target_os = "redox", + target_os = "l4re", )))] { use crate::sys::os::errno; let pfds: &mut [_] = &mut [ diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs index 12edf04a4e2e9..b5cb6a63dbaa0 100644 --- a/library/std/src/sys/unix/process/process_unix.rs +++ b/library/std/src/sys/unix/process/process_unix.rs @@ -26,7 +26,10 @@ use crate::sys::weak::weak; #[cfg(target_os = "vxworks")] use libc::RTP_ID as pid_t; -#[cfg(not(target_os = "vxworks"))] +#[cfg(target_os = "l4re")] +use libc::{c_int, pid_t}; + +#[cfg(not(any(target_os = "vxworks", target_os = "l4re")))] use libc::{c_int, gid_t, pid_t, uid_t}; ////////////////////////////////////////////////////////////////////////////////