about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_codegen_ssa/back/link.rs25
-rw-r--r--src/librustc_target/spec/mipsel_sony_psp.rs43
-rw-r--r--src/librustc_target/spec/mipsel_sony_psp_linker_script.ld34
-rw-r--r--src/librustc_target/spec/mod.rs9
m---------src/stdarch0
5 files changed, 111 insertions, 0 deletions
diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs
index d8b38cf3370..a54160cdd71 100644
--- a/src/librustc_codegen_ssa/back/link.rs
+++ b/src/librustc_codegen_ssa/back/link.rs
@@ -1179,6 +1179,28 @@ fn add_pre_link_args(
     cmd.args(&sess.opts.debugging_opts.pre_link_args);
 }
 
+/// Add a link script embedded in the target, if applicable.
+fn add_link_script(cmd: &mut dyn Linker, sess: &Session, tmpdir: &Path, crate_type: CrateType) {
+    match (crate_type, &sess.target.target.options.link_script) {
+        (CrateType::Cdylib | CrateType::Executable, Some(script)) => {
+            if !sess.target.target.options.linker_is_gnu {
+                sess.fatal("can only use link script when linking with GNU-like linker");
+            }
+
+            let file_name = ["rustc", &sess.target.target.llvm_target, "linkfile.ld"].join("-");
+
+            let path = tmpdir.join(file_name);
+            if let Err(e) = fs::write(&path, script) {
+                sess.fatal(&format!("failed to write link script to {}: {}", path.display(), e));
+            }
+
+            cmd.arg("--script");
+            cmd.arg(path);
+        }
+        _ => {}
+    }
+}
+
 /// Add arbitrary "user defined" args defined from command line and by `#[link_args]` attributes.
 /// FIXME: Determine where exactly these args need to be inserted.
 fn add_user_defined_link_args(
@@ -1421,6 +1443,9 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
     // NO-OPT-OUT, OBJECT-FILES-MAYBE, CUSTOMIZATION-POINT
     add_pre_link_args(cmd, sess, flavor, crate_type);
 
+    // NO-OPT-OUT
+    add_link_script(cmd, sess, tmpdir, crate_type);
+
     // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
     if sess.target.target.options.is_like_fuchsia {
         let prefix = match sess.opts.debugging_opts.sanitizer {
diff --git a/src/librustc_target/spec/mipsel_sony_psp.rs b/src/librustc_target/spec/mipsel_sony_psp.rs
new file mode 100644
index 00000000000..0c74454d0c5
--- /dev/null
+++ b/src/librustc_target/spec/mipsel_sony_psp.rs
@@ -0,0 +1,43 @@
+use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, RelocModel};
+use crate::spec::{Target, TargetOptions, TargetResult};
+
+// The PSP has custom linker requirements.
+const LINKER_SCRIPT: &str = include_str!("./mipsel_sony_psp_linker_script.ld");
+
+pub fn target() -> TargetResult {
+    let mut pre_link_args = LinkArgs::new();
+    pre_link_args.insert(
+        LinkerFlavor::Lld(LldFlavor::Ld),
+        vec!["--eh-frame-hdr".to_string(), "--emit-relocs".to_string()],
+    );
+
+    Ok(Target {
+        llvm_target: "mipsel-sony-psp".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "32".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
+        arch: "mips".to_string(),
+        target_os: "psp".to_string(),
+        target_env: "".to_string(),
+        target_vendor: "sony".to_string(),
+        linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
+
+        options: TargetOptions {
+            cpu: "mips2".to_string(),
+            executables: true,
+            linker: Some("rust-lld".to_owned()),
+            linker_is_gnu: true,
+            relocation_model: RelocModel::Static,
+
+            // PSP FPU only supports single precision floats.
+            features: "+single-float".to_string(),
+
+            // PSP does not support trap-on-condition instructions.
+            llvm_args: vec!["-mno-check-zero-division".to_string()],
+            pre_link_args,
+            link_script: Some(LINKER_SCRIPT.to_string()),
+            ..Default::default()
+        },
+    })
+}
diff --git a/src/librustc_target/spec/mipsel_sony_psp_linker_script.ld b/src/librustc_target/spec/mipsel_sony_psp_linker_script.ld
new file mode 100644
index 00000000000..1bd436d6f94
--- /dev/null
+++ b/src/librustc_target/spec/mipsel_sony_psp_linker_script.ld
@@ -0,0 +1,34 @@
+ENTRY(module_start)
+SECTIONS
+{
+  /* PRX format requires text to begin at 0 */
+  .text 0 : { *(.text .text.*) }
+
+  /* Sort stubs for convenient ordering */
+  .sceStub.text : { *(.sceStub.text) *(SORT(.sceStub.text.*)) }
+
+  /* Keep these sections around, even though they may appear unused to the linker */
+  .lib.ent.top :  { KEEP(*(.lib.ent.top)) }
+  .lib.ent :      { KEEP(*(.lib.ent)) }
+  .lib.ent.btm :  { KEEP(*(.lib.ent.btm)) }
+  .lib.stub.top : { KEEP(*(.lib.stub.top)) }
+  .lib.stub :     { KEEP(*(.lib.stub)) }
+  .lib.stub.btm : { KEEP(*(.lib.stub.btm)) }
+  .eh_frame_hdr : { KEEP(*(.eh_frame_hdr)) }
+
+  /* Add symbols for LLVM's libunwind */
+  __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0;
+  __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0;
+  .eh_frame :
+  {
+    __eh_frame_start = .;
+    KEEP(*(.eh_frame))
+    __eh_frame_end = .;
+  }
+
+  /* These are explicitly listed to avoid being merged into .rodata */
+  .rodata.sceResident : { *(.rodata.sceResident) }
+  .rodata.sceModuleInfo : { *(.rodata.sceModuleInfo) }
+  /* Sort NIDs for convenient ordering */
+  .rodata.sceNid : { *(.rodata.sceNid) *(SORT(.rodata.sceNid.*)) }
+}
diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs
index 477161dc658..c7b2023ddca 100644
--- a/src/librustc_target/spec/mod.rs
+++ b/src/librustc_target/spec/mod.rs
@@ -582,6 +582,8 @@ supported_targets! {
     ("powerpc-wrs-vxworks", powerpc_wrs_vxworks),
     ("powerpc-wrs-vxworks-spe", powerpc_wrs_vxworks_spe),
     ("powerpc64-wrs-vxworks", powerpc64_wrs_vxworks),
+
+    ("mipsel-sony-psp", mipsel_sony_psp),
 }
 
 /// Everything `rustc` knows about how to compile for a specific target.
@@ -666,6 +668,10 @@ pub struct TargetOptions {
     /// Linker arguments that are unconditionally passed *after* any
     /// user-defined libraries.
     pub post_link_args: LinkArgs,
+    /// Optional link script applied to `dylib` and `executable` crate types.
+    /// This is a string containing the script, not a path. Can only be applied
+    /// to linkers where `linker_is_gnu` is true.
+    pub link_script: Option<String>,
 
     /// Environment variables to be set for the linker invocation.
     pub link_env: Vec<(String, String)>,
@@ -899,6 +905,7 @@ impl Default for TargetOptions {
             pre_link_args: LinkArgs::new(),
             pre_link_args_crt: LinkArgs::new(),
             post_link_args: LinkArgs::new(),
+            link_script: None,
             asm_args: Vec::new(),
             cpu: "generic".to_string(),
             features: String::new(),
@@ -1249,6 +1256,7 @@ impl Target {
         key!(post_link_objects, list);
         key!(post_link_objects_crt, list);
         key!(post_link_args, link_args);
+        key!(link_script, optional);
         key!(link_env, env);
         key!(link_env_remove, list);
         key!(asm_args, list);
@@ -1479,6 +1487,7 @@ impl ToJson for Target {
         target_option_val!(post_link_objects);
         target_option_val!(post_link_objects_crt);
         target_option_val!(link_args - post_link_args);
+        target_option_val!(link_script);
         target_option_val!(env - link_env);
         target_option_val!(link_env_remove);
         target_option_val!(asm_args);
diff --git a/src/stdarch b/src/stdarch
-Subproject d10eefc62284c40c5a95a2eed19fc1f414a5364
+Subproject ec6fccd34c30003a7ebf4e7a9dfe4e31f5b76e1