Skip to content

Commit d01ee6f

Browse files
authored
Rollup merge of #72062 - overdrivenpotato:psp, r=jonas-schievink
Add built in PSP target This adds a new target, `mipsel-sony-psp`, corresponding to the Sony PSP. The linker script is necessary to handle special sections, which are required by the target. This has been tested with my [rust-psp] crate and I can confirm it works as intended. The linker script is taken from [here]. It has been slightly adapted to work with rust and LLD. The `stdarch` submodule was also updated in order for `libcore` to build successfully. [rust-psp]: https://github.com/overdrivenpotato/rust-psp [here]: https://github.com/pspdev/pspsdk/blob/master/src/base/linkfile.prx.in
2 parents a264aca + 425723f commit d01ee6f

File tree

5 files changed

+112
-1
lines changed

5 files changed

+112
-1
lines changed

src/librustc_codegen_ssa/back/link.rs

+25
Original file line numberDiff line numberDiff line change
@@ -1179,6 +1179,28 @@ fn add_pre_link_args(
11791179
cmd.args(&sess.opts.debugging_opts.pre_link_args);
11801180
}
11811181

1182+
/// Add a link script embedded in the target, if applicable.
1183+
fn add_link_script(cmd: &mut dyn Linker, sess: &Session, tmpdir: &Path, crate_type: CrateType) {
1184+
match (crate_type, &sess.target.target.options.link_script) {
1185+
(CrateType::Cdylib | CrateType::Executable, Some(script)) => {
1186+
if !sess.target.target.options.linker_is_gnu {
1187+
sess.fatal("can only use link script when linking with GNU-like linker");
1188+
}
1189+
1190+
let file_name = ["rustc", &sess.target.target.llvm_target, "linkfile.ld"].join("-");
1191+
1192+
let path = tmpdir.join(file_name);
1193+
if let Err(e) = fs::write(&path, script) {
1194+
sess.fatal(&format!("failed to write link script to {}: {}", path.display(), e));
1195+
}
1196+
1197+
cmd.arg("--script");
1198+
cmd.arg(path);
1199+
}
1200+
_ => {}
1201+
}
1202+
}
1203+
11821204
/// Add arbitrary "user defined" args defined from command line and by `#[link_args]` attributes.
11831205
/// FIXME: Determine where exactly these args need to be inserted.
11841206
fn add_user_defined_link_args(
@@ -1421,6 +1443,9 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
14211443
// NO-OPT-OUT, OBJECT-FILES-MAYBE, CUSTOMIZATION-POINT
14221444
add_pre_link_args(cmd, sess, flavor, crate_type);
14231445

1446+
// NO-OPT-OUT
1447+
add_link_script(cmd, sess, tmpdir, crate_type);
1448+
14241449
// NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
14251450
if sess.target.target.options.is_like_fuchsia {
14261451
let prefix = match sess.opts.debugging_opts.sanitizer {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, RelocModel};
2+
use crate::spec::{Target, TargetOptions, TargetResult};
3+
4+
// The PSP has custom linker requirements.
5+
const LINKER_SCRIPT: &str = include_str!("./mipsel_sony_psp_linker_script.ld");
6+
7+
pub fn target() -> TargetResult {
8+
let mut pre_link_args = LinkArgs::new();
9+
pre_link_args.insert(
10+
LinkerFlavor::Lld(LldFlavor::Ld),
11+
vec!["--eh-frame-hdr".to_string(), "--emit-relocs".to_string()],
12+
);
13+
14+
Ok(Target {
15+
llvm_target: "mipsel-sony-psp".to_string(),
16+
target_endian: "little".to_string(),
17+
target_pointer_width: "32".to_string(),
18+
target_c_int_width: "32".to_string(),
19+
data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(),
20+
arch: "mips".to_string(),
21+
target_os: "psp".to_string(),
22+
target_env: "".to_string(),
23+
target_vendor: "sony".to_string(),
24+
linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
25+
26+
options: TargetOptions {
27+
cpu: "mips2".to_string(),
28+
executables: true,
29+
linker: Some("rust-lld".to_owned()),
30+
linker_is_gnu: true,
31+
relocation_model: RelocModel::Static,
32+
33+
// PSP FPU only supports single precision floats.
34+
features: "+single-float".to_string(),
35+
36+
// PSP does not support trap-on-condition instructions.
37+
llvm_args: vec!["-mno-check-zero-division".to_string()],
38+
pre_link_args,
39+
link_script: Some(LINKER_SCRIPT.to_string()),
40+
..Default::default()
41+
},
42+
})
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
ENTRY(module_start)
2+
SECTIONS
3+
{
4+
/* PRX format requires text to begin at 0 */
5+
.text 0 : { *(.text .text.*) }
6+
7+
/* Sort stubs for convenient ordering */
8+
.sceStub.text : { *(.sceStub.text) *(SORT(.sceStub.text.*)) }
9+
10+
/* Keep these sections around, even though they may appear unused to the linker */
11+
.lib.ent.top : { KEEP(*(.lib.ent.top)) }
12+
.lib.ent : { KEEP(*(.lib.ent)) }
13+
.lib.ent.btm : { KEEP(*(.lib.ent.btm)) }
14+
.lib.stub.top : { KEEP(*(.lib.stub.top)) }
15+
.lib.stub : { KEEP(*(.lib.stub)) }
16+
.lib.stub.btm : { KEEP(*(.lib.stub.btm)) }
17+
.eh_frame_hdr : { KEEP(*(.eh_frame_hdr)) }
18+
19+
/* Add symbols for LLVM's libunwind */
20+
__eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0;
21+
__eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0;
22+
.eh_frame :
23+
{
24+
__eh_frame_start = .;
25+
KEEP(*(.eh_frame))
26+
__eh_frame_end = .;
27+
}
28+
29+
/* These are explicitly listed to avoid being merged into .rodata */
30+
.rodata.sceResident : { *(.rodata.sceResident) }
31+
.rodata.sceModuleInfo : { *(.rodata.sceModuleInfo) }
32+
/* Sort NIDs for convenient ordering */
33+
.rodata.sceNid : { *(.rodata.sceNid) *(SORT(.rodata.sceNid.*)) }
34+
}

src/librustc_target/spec/mod.rs

+9
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,8 @@ supported_targets! {
582582
("powerpc-wrs-vxworks", powerpc_wrs_vxworks),
583583
("powerpc-wrs-vxworks-spe", powerpc_wrs_vxworks_spe),
584584
("powerpc64-wrs-vxworks", powerpc64_wrs_vxworks),
585+
586+
("mipsel-sony-psp", mipsel_sony_psp),
585587
}
586588

587589
/// Everything `rustc` knows about how to compile for a specific target.
@@ -666,6 +668,10 @@ pub struct TargetOptions {
666668
/// Linker arguments that are unconditionally passed *after* any
667669
/// user-defined libraries.
668670
pub post_link_args: LinkArgs,
671+
/// Optional link script applied to `dylib` and `executable` crate types.
672+
/// This is a string containing the script, not a path. Can only be applied
673+
/// to linkers where `linker_is_gnu` is true.
674+
pub link_script: Option<String>,
669675

670676
/// Environment variables to be set for the linker invocation.
671677
pub link_env: Vec<(String, String)>,
@@ -899,6 +905,7 @@ impl Default for TargetOptions {
899905
pre_link_args: LinkArgs::new(),
900906
pre_link_args_crt: LinkArgs::new(),
901907
post_link_args: LinkArgs::new(),
908+
link_script: None,
902909
asm_args: Vec::new(),
903910
cpu: "generic".to_string(),
904911
features: String::new(),
@@ -1249,6 +1256,7 @@ impl Target {
12491256
key!(post_link_objects, list);
12501257
key!(post_link_objects_crt, list);
12511258
key!(post_link_args, link_args);
1259+
key!(link_script, optional);
12521260
key!(link_env, env);
12531261
key!(link_env_remove, list);
12541262
key!(asm_args, list);
@@ -1479,6 +1487,7 @@ impl ToJson for Target {
14791487
target_option_val!(post_link_objects);
14801488
target_option_val!(post_link_objects_crt);
14811489
target_option_val!(link_args - post_link_args);
1490+
target_option_val!(link_script);
14821491
target_option_val!(env - link_env);
14831492
target_option_val!(link_env_remove);
14841493
target_option_val!(asm_args);

0 commit comments

Comments
 (0)