From 48996f9e759912140ccc98072e9e55fa6480a9d7 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 20 Nov 2017 06:22:17 -0800 Subject: [PATCH] rustbuild: Enable WebAssembly backend by default This commit alters how we compile LLVM by default enabling the WebAssembly backend. This then also adds the wasm32-unknown-unknown target to get compiled on the `cross` builder and distributed through rustup. Tests are not yet enabled for this target but that should hopefully be coming soon! --- config.toml.example | 7 +- src/bootstrap/config.rs | 5 +- src/bootstrap/native.rs | 5 +- src/ci/docker/cross2/Dockerfile | 1 + src/librustc_driver/driver.rs | 8 +++ src/librustc_driver/lib.rs | 6 +- src/librustc_driver/pretty.rs | 29 ++++---- src/librustdoc/core.rs | 3 - src/librustdoc/test.rs | 3 - src/libstd/os/mod.rs | 72 ++++++++++++-------- src/libstd/sys/mod.rs | 99 ++++++++++++++++------------ src/tools/build-manifest/src/main.rs | 1 + 12 files changed, 140 insertions(+), 99 deletions(-) diff --git a/config.toml.example b/config.toml.example index df0142b8d46..a9281a31b13 100644 --- a/config.toml.example +++ b/config.toml.example @@ -60,10 +60,9 @@ # LLVM experimental targets to build support for. These targets are specified in # the same format as above, but since these targets are experimental, they are # not built by default and the experimental Rust compilation targets that depend -# on them will not work unless the user opts in to building them. Possible -# experimental LLVM targets include WebAssembly for the -# wasm32-experimental-emscripten Rust target. -#experimental-targets = "" +# on them will not work unless the user opts in to building them. By default the +# `WebAssembly` target is enabled when compiling LLVM from scratch. +#experimental-targets = "WebAssembly" # Cap the number of parallel linker invocations when compiling LLVM. # This can be useful when building LLVM with debug info, which significantly diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 35e62f17f2e..d43cd54ddce 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -76,7 +76,7 @@ pub struct Config { pub llvm_static_stdcpp: bool, pub llvm_link_shared: bool, pub llvm_targets: Option, - pub llvm_experimental_targets: Option, + pub llvm_experimental_targets: String, pub llvm_link_jobs: Option, // rust codegen options @@ -447,7 +447,8 @@ impl Config { set(&mut config.llvm_static_stdcpp, llvm.static_libstdcpp); set(&mut config.llvm_link_shared, llvm.link_shared); config.llvm_targets = llvm.targets.clone(); - config.llvm_experimental_targets = llvm.experimental_targets.clone(); + config.llvm_experimental_targets = llvm.experimental_targets.clone() + .unwrap_or("WebAssembly".to_string()); config.llvm_link_jobs = llvm.link_jobs; } diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index fce6755aea9..ac068ebe651 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -110,10 +110,7 @@ impl Step for Llvm { None => "X86;ARM;AArch64;Mips;PowerPC;SystemZ;JSBackend;MSP430;Sparc;NVPTX;Hexagon", }; - let llvm_exp_targets = match build.config.llvm_experimental_targets { - Some(ref s) => s, - None => "", - }; + let llvm_exp_targets = &build.config.llvm_experimental_targets; let assertions = if build.config.llvm_assertions {"ON"} else {"OFF"}; diff --git a/src/ci/docker/cross2/Dockerfile b/src/ci/docker/cross2/Dockerfile index cc260382f49..f16d97d39ef 100644 --- a/src/ci/docker/cross2/Dockerfile +++ b/src/ci/docker/cross2/Dockerfile @@ -47,6 +47,7 @@ ENV \ ENV TARGETS=x86_64-unknown-fuchsia ENV TARGETS=$TARGETS,aarch64-unknown-fuchsia ENV TARGETS=$TARGETS,sparcv9-sun-solaris +ENV TARGETS=$TARGETS,wasm32-unknown-unknown ENV TARGETS=$TARGETS,x86_64-sun-solaris ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnux32 diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 8f2917fed7a..b1e9bc7e47c 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -56,6 +56,7 @@ use std::sync::mpsc; use syntax::{ast, diagnostics, visit}; use syntax::attr; use syntax::ext::base::ExtCtxt; +use syntax::fold::Folder; use syntax::parse::{self, PResult}; use syntax::util::node_count::NodeCounter; use syntax; @@ -63,6 +64,7 @@ use syntax_ext; use arena::DroplessArena; use derive_registrar; +use pretty::ReplaceBodyWithLoop; use profile; @@ -809,6 +811,12 @@ pub fn phase_2_configure_and_expand(sess: &Session, sess.diagnostic()) }); + // If we're actually rustdoc then there's no need to actually compile + // anything, so switch everything to just looping + if sess.opts.actually_rustdoc { + krate = ReplaceBodyWithLoop::new(sess).fold_crate(krate); + } + // If we're in rustdoc we're always compiling as an rlib, but that'll trip a // bunch of checks in the `modify` function below. For now just skip this // step entirely if we're rustdoc as it's not too useful anyway. diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index c5cce70c945..bda721d0783 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -565,7 +565,9 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { control.after_hir_lowering.stop = Compilation::Stop; control.after_parse.callback = box move |state| { - state.krate = Some(pretty::fold_crate(state.krate.take().unwrap(), ppm)); + state.krate = Some(pretty::fold_crate(state.session, + state.krate.take().unwrap(), + ppm)); }; control.after_hir_lowering.callback = box move |state| { pretty::print_after_hir_lowering(state.session, @@ -587,7 +589,7 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { control.after_parse.stop = Compilation::Stop; control.after_parse.callback = box move |state| { - let krate = pretty::fold_crate(state.krate.take().unwrap(), ppm); + let krate = pretty::fold_crate(state.session, state.krate.take().unwrap(), ppm); pretty::print_after_parsing(state.session, state.input, &krate, diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index bf1579acf53..d930739c9f0 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -638,13 +638,14 @@ impl UserIdentifiedItem { // ambitious form of the closed RFC #1637. See also [#34511]. // // [#34511]: https://github.com/rust-lang/rust/issues/34511#issuecomment-322340401 -pub struct ReplaceBodyWithLoop { +pub struct ReplaceBodyWithLoop<'a> { within_static_or_const: bool, + sess: &'a Session, } -impl ReplaceBodyWithLoop { - pub fn new() -> ReplaceBodyWithLoop { - ReplaceBodyWithLoop { within_static_or_const: false } +impl<'a> ReplaceBodyWithLoop<'a> { + pub fn new(sess: &'a Session) -> ReplaceBodyWithLoop<'a> { + ReplaceBodyWithLoop { within_static_or_const: false, sess } } fn run R>(&mut self, is_const: bool, action: F) -> R { @@ -691,7 +692,7 @@ impl ReplaceBodyWithLoop { } } -impl fold::Folder for ReplaceBodyWithLoop { +impl<'a> fold::Folder for ReplaceBodyWithLoop<'a> { fn fold_item_kind(&mut self, i: ast::ItemKind) -> ast::ItemKind { let is_const = match i { ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => true, @@ -723,11 +724,13 @@ impl fold::Folder for ReplaceBodyWithLoop { } fn fold_block(&mut self, b: P) -> P { - fn expr_to_block(rules: ast::BlockCheckMode, e: Option>) -> P { + fn expr_to_block(rules: ast::BlockCheckMode, + e: Option>, + sess: &Session) -> P { P(ast::Block { stmts: e.map(|e| { ast::Stmt { - id: ast::DUMMY_NODE_ID, + id: sess.next_node_id(), span: e.span, node: ast::StmtKind::Expr(e), } @@ -735,22 +738,22 @@ impl fold::Folder for ReplaceBodyWithLoop { .into_iter() .collect(), rules, - id: ast::DUMMY_NODE_ID, + id: sess.next_node_id(), span: syntax_pos::DUMMY_SP, }) } if !self.within_static_or_const { - let empty_block = expr_to_block(BlockCheckMode::Default, None); + let empty_block = expr_to_block(BlockCheckMode::Default, None, self.sess); let loop_expr = P(ast::Expr { node: ast::ExprKind::Loop(empty_block, None), - id: ast::DUMMY_NODE_ID, + id: self.sess.next_node_id(), span: syntax_pos::DUMMY_SP, attrs: ast::ThinVec::new(), }); - expr_to_block(b.rules, Some(loop_expr)) + expr_to_block(b.rules, Some(loop_expr), self.sess) } else { fold::noop_fold_block(b, self) @@ -829,9 +832,9 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec, } } -pub fn fold_crate(krate: ast::Crate, ppm: PpMode) -> ast::Crate { +pub fn fold_crate(sess: &Session, krate: ast::Crate, ppm: PpMode) -> ast::Crate { if let PpmSource(PpmEveryBodyLoops) = ppm { - let mut fold = ReplaceBodyWithLoop::new(); + let mut fold = ReplaceBodyWithLoop::new(sess); fold.fold_crate(krate) } else { krate diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 9172bfcde3f..456a00947ae 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -10,7 +10,6 @@ use rustc_lint; use rustc_driver::{driver, target_features, abort_on_err}; -use rustc_driver::pretty::ReplaceBodyWithLoop; use rustc::session::{self, config}; use rustc::hir::def_id::DefId; use rustc::hir::def::Def; @@ -26,7 +25,6 @@ use rustc_metadata::cstore::CStore; use syntax::codemap; use syntax::feature_gate::UnstableFeatures; -use syntax::fold::Folder; use errors; use errors::emitter::ColorConfig; @@ -157,7 +155,6 @@ pub fn run_core(search_paths: SearchPaths, let control = &driver::CompileController::basic(); let krate = panictry!(driver::phase_1_parse_input(control, &sess, &input)); - let krate = ReplaceBodyWithLoop::new().fold_crate(krate); let name = link::find_crate_name(Some(&sess), &krate.attrs, &input); diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 3aa674415f0..ee0d9a7f3e2 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -31,7 +31,6 @@ use rustc_back::dynamic_lib::DynamicLibrary; use rustc_back::tempdir::TempDir; use rustc_driver::{self, driver, Compilation}; use rustc_driver::driver::phase_2_configure_and_expand; -use rustc_driver::pretty::ReplaceBodyWithLoop; use rustc_metadata::cstore::CStore; use rustc_resolve::MakeGlobMap; use rustc_trans; @@ -39,7 +38,6 @@ use rustc_trans::back::link; use syntax::ast; use syntax::codemap::CodeMap; use syntax::feature_gate::UnstableFeatures; -use syntax::fold::Folder; use syntax_pos::{BytePos, DUMMY_SP, Pos, Span}; use errors; use errors::emitter::ColorConfig; @@ -97,7 +95,6 @@ pub fn run(input: &str, let krate = panictry!(driver::phase_1_parse_input(&driver::CompileController::basic(), &sess, &input)); - let krate = ReplaceBodyWithLoop::new().fold_crate(krate); let driver::ExpansionResult { defs, mut hir_forest, .. } = { phase_2_configure_and_expand( &sess, diff --git a/src/libstd/os/mod.rs b/src/libstd/os/mod.rs index 122f15d1d4c..ac7809451d1 100644 --- a/src/libstd/os/mod.rs +++ b/src/libstd/os/mod.rs @@ -13,35 +13,53 @@ #![stable(feature = "os", since = "1.0.0")] #![allow(missing_docs, bad_style, missing_debug_implementations)] -#[cfg(all(not(dox), any(target_os = "redox", unix)))] -#[stable(feature = "rust1", since = "1.0.0")] -pub use sys::ext as unix; -#[cfg(all(not(dox), windows))] -#[stable(feature = "rust1", since = "1.0.0")] -pub use sys::ext as windows; +cfg_if! { + if #[cfg(dox)] { -#[cfg(dox)] -#[stable(feature = "rust1", since = "1.0.0")] -pub use sys::unix_ext as unix; -#[cfg(dox)] -#[stable(feature = "rust1", since = "1.0.0")] -pub use sys::windows_ext as windows; + // When documenting libstd we want to show unix/windows/linux modules as + // these are the "main modules" that are used across platforms. This + // should help show platform-specific functionality in a hopefully + // cross-platform way in the documentation -#[cfg(any(dox, target_os = "linux", target_os = "l4re"))] -#[doc(cfg(target_os = "linux"))] -pub mod linux; + #[stable(feature = "rust1", since = "1.0.0")] + pub use sys::unix_ext as unix; -#[cfg(all(not(dox), target_os = "android"))] pub mod android; -#[cfg(all(not(dox), target_os = "bitrig"))] pub mod bitrig; -#[cfg(all(not(dox), target_os = "dragonfly"))] pub mod dragonfly; -#[cfg(all(not(dox), target_os = "freebsd"))] pub mod freebsd; -#[cfg(all(not(dox), target_os = "haiku"))] pub mod haiku; -#[cfg(all(not(dox), target_os = "ios"))] pub mod ios; -#[cfg(all(not(dox), target_os = "macos"))] pub mod macos; -#[cfg(all(not(dox), target_os = "netbsd"))] pub mod netbsd; -#[cfg(all(not(dox), target_os = "openbsd"))] pub mod openbsd; -#[cfg(all(not(dox), target_os = "solaris"))] pub mod solaris; -#[cfg(all(not(dox), target_os = "emscripten"))] pub mod emscripten; -#[cfg(all(not(dox), target_os = "fuchsia"))] pub mod fuchsia; + #[stable(feature = "rust1", since = "1.0.0")] + pub use sys::windows_ext as windows; + + #[doc(cfg(target_os = "linux"))] + pub mod linux; + + } else { + + // If we're not documenting libstd then we just expose everything as we + // otherwise would. + + #[cfg(target_os = "android")] pub mod android; + #[cfg(target_os = "bitrig")] pub mod bitrig; + #[cfg(target_os = "dragonfly")] pub mod dragonfly; + #[cfg(target_os = "freebsd")] pub mod freebsd; + #[cfg(target_os = "haiku")] pub mod haiku; + #[cfg(target_os = "ios")] pub mod ios; + #[cfg(target_os = "macos")] pub mod macos; + #[cfg(target_os = "netbsd")] pub mod netbsd; + #[cfg(target_os = "openbsd")] pub mod openbsd; + #[cfg(target_os = "solaris")] pub mod solaris; + #[cfg(target_os = "emscripten")] pub mod emscripten; + #[cfg(target_os = "fuchsia")] pub mod fuchsia; + + #[cfg(any(target_os = "redox", unix))] + #[stable(feature = "rust1", since = "1.0.0")] + pub use sys::ext as unix; + + #[cfg(windows)] + #[stable(feature = "rust1", since = "1.0.0")] + pub use sys::ext as windows; + + #[cfg(any(target_os = "linux", target_os = "l4re"))] + pub mod linux; + + } +} pub mod raw; diff --git a/src/libstd/sys/mod.rs b/src/libstd/sys/mod.rs index 27d6433b329..be8cb88416b 100644 --- a/src/libstd/sys/mod.rs +++ b/src/libstd/sys/mod.rs @@ -32,49 +32,66 @@ #![allow(missing_debug_implementations)] -pub use self::imp::*; +cfg_if! { + if #[cfg(unix)] { + mod unix; + pub use self::unix::*; + } else if #[cfg(windows)] { + mod windows; + pub use self::windows::*; + } else if #[cfg(target_os = "redox")] { + mod redox; + pub use self::redox::*; + } else if #[cfg(target_arch = "wasm32")] { + mod wasm; + pub use self::wasm::*; + } else { + compile_error!("libstd doesn't compile for this platform yet"); + } +} -#[cfg(unix)] -#[path = "unix/mod.rs"] -mod imp; +// Import essential modules from both platforms when documenting. These are +// then later used in the `std::os` module when documenting, for example, +// Windows when we're compiling for Linux. -#[cfg(windows)] -#[path = "windows/mod.rs"] -mod imp; +#[cfg(dox)] +cfg_if! { + if #[cfg(any(unix, target_os = "redox"))] { + // On unix we'll document what's already available + pub use self::ext as unix_ext; + } else if #[cfg(target_arch = "wasm32")] { + // On wasm right now the module below doesn't compile (missing things + // in `libc` which is empty) so just omit everything with an empty module + #[unstable(issue = "0", feature = "std_internals")] + pub mod unix_ext {} + } else { + // On other platforms like Windows document the bare bones of unix + use os::linux as platform; + #[path = "unix/ext/mod.rs"] + pub mod unix_ext; + } +} -#[cfg(target_os = "redox")] -#[path = "redox/mod.rs"] -mod imp; +#[cfg(dox)] +cfg_if! { + if #[cfg(windows)] { + // On windows we'll just be documenting what's already available + pub use self::ext as windows_ext; + } else if #[cfg(target_arch = "wasm32")] { + // On wasm right now the shim below doesn't compile, so just omit it + #[unstable(issue = "0", feature = "std_internals")] + pub mod windows_ext {} + } else { + // On all other platforms (aka linux/osx/etc) then pull in a "minimal" + // amount of windows goop which ends up compiling + #[macro_use] + #[path = "windows/compat.rs"] + mod compat; -#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] -#[path = "wasm/mod.rs"] -mod imp; + #[path = "windows/c.rs"] + mod c; -// Import essential modules from both platforms when documenting. - -#[cfg(all(dox, not(unix)))] -use os::linux as platform; - -#[cfg(all(dox, not(any(unix, target_os = "redox"))))] -#[path = "unix/ext/mod.rs"] -pub mod unix_ext; - -#[cfg(all(dox, any(unix, target_os = "redox")))] -pub use self::ext as unix_ext; - - -#[cfg(all(dox, not(windows)))] -#[macro_use] -#[path = "windows/compat.rs"] -mod compat; - -#[cfg(all(dox, not(windows)))] -#[path = "windows/c.rs"] -mod c; - -#[cfg(all(dox, not(windows)))] -#[path = "windows/ext/mod.rs"] -pub mod windows_ext; - -#[cfg(all(dox, windows))] -pub use self::ext as windows_ext; + #[path = "windows/ext/mod.rs"] + pub mod windows_ext; + } +} diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 524ba7908bd..c4e696e1760 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -84,6 +84,7 @@ static TARGETS: &'static [&'static str] = &[ "sparc64-unknown-linux-gnu", "sparcv9-sun-solaris", "wasm32-unknown-emscripten", + "wasm32-unknown-unknown", "x86_64-linux-android", "x86_64-apple-darwin", "x86_64-apple-ios",