Skip to content

Commit

Permalink
Link with wasm-ld instead of binaryen
Browse files Browse the repository at this point in the history
  • Loading branch information
alexcrichton committed Jan 30, 2018
1 parent 8261bff commit 106657e
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 20 deletions.
2 changes: 1 addition & 1 deletion src/bootstrap/bin/rustc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ fn main() {
// flesh out rpath support more fully in the future.
cmd.arg("-Z").arg("osx-rpath-install-name");
Some("-Wl,-rpath,@loader_path/../lib")
} else if !target.contains("windows") {
} else if !target.contains("windows") && !target.contains("wasm32") {
Some("-Wl,-rpath,$ORIGIN/../lib")
} else {
None
Expand Down
4 changes: 3 additions & 1 deletion src/bootstrap/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,9 @@ impl Build {
.and_then(|c| c.linker.as_ref()) {
Some(linker)
} else if target != self.config.build &&
!target.contains("msvc") && !target.contains("emscripten") {
!target.contains("msvc") &&
!target.contains("emscripten") &&
!target.contains("wasm32") {
Some(self.cc(target))
} else {
None
Expand Down
2 changes: 1 addition & 1 deletion src/bootstrap/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -838,7 +838,7 @@ impl Step for Compiletest {
}

if build.config.llvm_enabled {
let llvm_config = build.llvm_config(target);
let llvm_config = build.llvm_config(build.config.build);
let llvm_version = output(Command::new(&llvm_config).arg("--version"));
cmd.arg("--llvm-version").arg(llvm_version);
if !build.is_rust_llvm(target) {
Expand Down
3 changes: 3 additions & 0 deletions src/etc/wasm32-shim.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,6 @@ for (var i = 0; i < module_imports.length; i++) {
}

let instance = new WebAssembly.Instance(m, imports);
if (instance.exports.memory)
memory = instance.exports.memory;
instance.exports.main();
1 change: 1 addition & 0 deletions src/librustc_back/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ linker_flavor! {
(Gcc, "gcc"),
(Ld, "ld"),
(Msvc, "msvc"),
(WasmLd, "wasm-ld"),
}

#[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
Expand Down
20 changes: 3 additions & 17 deletions src/librustc_back/target/wasm32_unknown_unknown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ use super::{Target, TargetOptions, PanicStrategy};

pub fn target() -> Result<Target, String> {
let opts = TargetOptions {
linker: "not-used".to_string(),
linker: "wasm-ld".to_string(),

// we allow dynamic linking, but only cdylibs. Basically we allow a
// final library artifact that exports some symbols (a wasm module) but
Expand All @@ -58,9 +58,6 @@ pub fn target() -> Result<Target, String> {
dll_suffix: ".wasm".to_string(),
linker_is_gnu: false,

// We're storing bitcode for now in all the rlibs
obj_is_bitcode: true,

// A bit of a lie, but "eh"
max_atomic_width: Some(32),

Expand All @@ -69,27 +66,17 @@ pub fn target() -> Result<Target, String> {
// the future once unwinding is implemented. Don't rely on this.
panic_strategy: PanicStrategy::Abort,

// There's no linker yet so we're forced to use LLVM as a linker. This
// means that we must always enable LTO for final artifacts.
requires_lto: true,

// Wasm doesn't have atomics yet, so tell LLVM that we're in a single
// threaded model which will legalize atomics to normal operations.
singlethread: true,

// Because we're always enabling LTO we can't enable builtin lowering as
// otherwise we'll lower the definition of the `memcpy` function to
// memcpy itself. Note that this is specifically because we're
// performing LTO with compiler-builtins.
no_builtins: true,

// no dynamic linking, no need for default visibility!
default_hidden_visibility: true,

.. Default::default()
};
Ok(Target {
llvm_target: "wasm32-unknown-unknown".to_string(),
llvm_target: "wasm32-unknown-unknown-wasm".to_string(),
target_endian: "little".to_string(),
target_pointer_width: "32".to_string(),
target_c_int_width: "32".to_string(),
Expand All @@ -100,8 +87,7 @@ pub fn target() -> Result<Target, String> {
target_vendor: "unknown".to_string(),
data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128".to_string(),
arch: "wasm32".to_string(),
// A bit of a lie, but it gets the job done
linker_flavor: LinkerFlavor::Binaryen,
linker_flavor: LinkerFlavor::WasmLd,
options: opts,
})
}
118 changes: 118 additions & 0 deletions src/librustc_trans/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,17 @@ impl LinkerInfo {
is_ld: true,
}) as Box<Linker>
}

LinkerFlavor::Binaryen => {
panic!("can't instantiate binaryen linker")
}

LinkerFlavor::WasmLd => {
Box::new(WasmLd {
cmd,
exe: true,
}) as Box<Linker>
}
}
}
}
Expand Down Expand Up @@ -775,3 +783,113 @@ fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec<String> {

symbols
}

pub struct WasmLd {
cmd: Command,
exe: bool,
}

impl Linker for WasmLd {
fn link_dylib(&mut self, lib: &str) {
self.cmd.arg("-l").arg(lib);
}

fn link_staticlib(&mut self, lib: &str) {
self.cmd.arg("-l").arg(lib);
}

fn link_rlib(&mut self, lib: &Path) {
self.cmd.arg(lib);
}

fn include_path(&mut self, path: &Path) {
self.cmd.arg("-L").arg(path);
}

fn framework_path(&mut self, _path: &Path) {
panic!("frameworks not supported")
}

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 position_independent_executable(&mut self) {
}

fn partial_relro(&mut self) {
}

fn full_relro(&mut self) {
}

fn build_static_executable(&mut self) {
}

fn args(&mut self, args: &[String]) {
self.cmd.args(args);
}

fn link_rust_dylib(&mut self, lib: &str, _path: &Path) {
self.cmd.arg("-l").arg(lib);
}

fn link_framework(&mut self, _framework: &str) {
panic!("frameworks not supported")
}

fn link_whole_staticlib(&mut self, lib: &str, _search_path: &[PathBuf]) {
self.cmd.arg("-l").arg(lib);
}

fn link_whole_rlib(&mut self, lib: &Path) {
self.cmd.arg(lib);
}

fn gc_sections(&mut self, _keep_metadata: bool) {
}

fn optimize(&mut self) {
}

fn debuginfo(&mut self) {
}

fn no_default_libraries(&mut self) {
}

fn build_dylib(&mut self, _out_filename: &Path) {
self.cmd.arg("--no-entry");
self.exe = false;
}

fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType) {
}

fn subsystem(&mut self, _subsystem: &str) {
}

fn finalize(&mut self) -> Command {
self.cmd.arg("--threads");
self.cmd.arg("--fatal-warnings");

// FIXME we probably shouldn't pass this but instead pass an explicit
// whitelist of symbols we'll allow to be undefined. Unfortunately
// though we can't handle symbols like `log10` that LLVM injects at a
// super late date without actually parsing object files. For now let's
// stick to this and hopefully fix it before stabilization happens.
self.cmd.arg("--allow-undefined");

if self.exe {
self.cmd.arg("--entry").arg("main");
}
let mut cmd = Command::new("");
::std::mem::swap(&mut cmd, &mut self.cmd);
cmd
}
}

0 comments on commit 106657e

Please sign in to comment.