From 485aec41affd054cecc70a73d424b6f4c0f59b98 Mon Sep 17 00:00:00 2001 From: Kai Luo Date: Thu, 23 Mar 2023 15:00:46 +0800 Subject: [PATCH] Add AixLinker to support linking on AIX --- compiler/rustc_codegen_ssa/src/back/linker.rs | 173 ++++++++++++++++++ 1 file changed, 173 insertions(+) diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 23e2b272410..9b46e1115e7 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -133,6 +133,9 @@ pub fn get_linker<'a>( LinkerFlavor::Unix(Cc::No) if sess.target.os == "l4re" => { Box::new(L4Bender::new(cmd, sess)) as Box } + LinkerFlavor::Unix(Cc::No) if sess.target.os == "aix" => { + Box::new(AixLinker::new(cmd, sess)) as Box + } LinkerFlavor::WasmLld(Cc::No) => Box::new(WasmLd::new(cmd, sess)) as Box, LinkerFlavor::Gnu(cc, _) | LinkerFlavor::Darwin(cc, _) @@ -1474,6 +1477,176 @@ fn hint_static(&mut self) { } } +/// Linker for AIX. +pub struct AixLinker<'a> { + cmd: Command, + sess: &'a Session, + hinted_static: bool, +} + +impl<'a> AixLinker<'a> { + pub fn new(cmd: Command, sess: &'a Session) -> AixLinker<'a> { + AixLinker { cmd: cmd, sess: sess, hinted_static: false } + } + + fn hint_static(&mut self) { + if !self.hinted_static { + self.cmd.arg("-bstatic"); + self.hinted_static = true; + } + } + + fn hint_dynamic(&mut self) { + if self.hinted_static { + self.cmd.arg("-bdynamic"); + self.hinted_static = false; + } + } + + fn build_dylib(&mut self, _out_filename: &Path) { + self.cmd.arg("-bM:SRE"); + self.cmd.arg("-bnoentry"); + // FIXME: Use CreateExportList utility to create export list + // and remove -bexpfull. + self.cmd.arg("-bexpfull"); + } +} + +impl<'a> Linker for AixLinker<'a> { + fn link_dylib(&mut self, lib: &str, _verbatim: bool, _as_needed: bool) { + self.hint_dynamic(); + self.cmd.arg(format!("-l{}", lib)); + } + + fn link_staticlib(&mut self, lib: &str, _verbatim: bool) { + self.hint_static(); + self.cmd.arg(format!("-l{}", lib)); + } + + fn link_rlib(&mut self, lib: &Path) { + self.hint_static(); + self.cmd.arg(lib); + } + + fn include_path(&mut self, path: &Path) { + self.cmd.arg("-L").arg(path); + } + + fn framework_path(&mut self, _: &Path) { + bug!("frameworks are not supported on L4Re"); + } + + fn output_filename(&mut self, path: &Path) { + self.cmd.arg("-o").arg(path); + } + + fn add_object(&mut self, path: &Path) { + self.cmd.arg(path); + } + + fn full_relro(&mut self) {} + + fn partial_relro(&mut self) {} + + fn no_relro(&mut self) {} + + fn cmd(&mut self) -> &mut Command { + &mut self.cmd + } + + fn set_output_kind(&mut self, output_kind: LinkOutputKind, out_filename: &Path) { + match output_kind { + LinkOutputKind::DynamicDylib => { + self.hint_dynamic(); + self.build_dylib(out_filename); + } + LinkOutputKind::StaticDylib => { + self.hint_static(); + self.build_dylib(out_filename); + } + _ => {} + } + } + + fn link_rust_dylib(&mut self, lib: &str, _: &Path) { + self.hint_dynamic(); + self.cmd.arg(format!("-l{}", lib)); + } + + fn link_framework(&mut self, _framework: &str, _as_needed: bool) { + bug!("frameworks not supported on AIX"); + } + + fn link_whole_staticlib(&mut self, lib: &str, verbatim: bool, search_path: &[PathBuf]) { + self.hint_static(); + let lib = find_native_static_library(lib, verbatim, search_path, &self.sess); + self.cmd.arg(format!("-bkeepfile:{}", lib.to_str().unwrap())); + } + + fn link_whole_rlib(&mut self, lib: &Path) { + self.hint_static(); + self.cmd.arg(format!("-bkeepfile:{}", lib.to_str().unwrap())); + } + + fn gc_sections(&mut self, _keep_metadata: bool) { + self.cmd.arg("-bgc"); + } + + fn no_gc_sections(&mut self) { + self.cmd.arg("-bnogc"); + } + + fn optimize(&mut self) {} + + fn pgo_gen(&mut self) {} + + fn control_flow_guard(&mut self) {} + + fn debuginfo(&mut self, strip: Strip, _: &[PathBuf]) { + match strip { + Strip::None => {} + Strip::Debuginfo => {} + Strip::Symbols => { + self.cmd.arg("-s"); + } + } + } + + fn no_crt_objects(&mut self) {} + + fn no_default_libraries(&mut self) {} + + fn export_symbols(&mut self, tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) { + let path = tmpdir.join("list.exp"); + let res: io::Result<()> = try { + let mut f = BufWriter::new(File::create(&path)?); + // TODO: use llvm-nm to generate export list. + for symbol in symbols { + debug!(" _{}", symbol); + writeln!(f, " {}", symbol)?; + } + }; + if let Err(e) = res { + self.sess.fatal(&format!("failed to write export file: {}", e)); + } + self.cmd.arg(format!("-bE:{}", path.to_str().unwrap())); + } + + fn subsystem(&mut self, _subsystem: &str) {} + + fn reset_per_library_state(&mut self) { + self.hint_dynamic(); + } + + fn linker_plugin_lto(&mut self) {} + + fn add_eh_frame_header(&mut self) {} + + fn add_no_exec(&mut self) {} + + fn add_as_needed(&mut self) {} +} + fn for_each_exported_symbols_include_dep<'tcx>( tcx: TyCtxt<'tcx>, crate_type: CrateType,