diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 5d486c04b427e..84e7c40e4559e 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -48,6 +48,7 @@ impl Step for Std { builder.info(&format!("Checking std artifacts ({} -> {})", &compiler.host, target)); run_cargo(builder, &mut cargo, + vec![], &libstd_stamp(builder, compiler, target), true); @@ -94,6 +95,7 @@ impl Step for Rustc { builder.info(&format!("Checking compiler artifacts ({} -> {})", &compiler.host, target)); run_cargo(builder, &mut cargo, + vec![], &librustc_stamp(builder, compiler, target), true); @@ -144,6 +146,7 @@ impl Step for CodegenBackend { let _folder = builder.fold_output(|| format!("stage{}-rustc_codegen_llvm", compiler.stage)); run_cargo(builder, &mut cargo, + vec![], &codegen_backend_stamp(builder, compiler, target, backend), true); } @@ -181,6 +184,7 @@ impl Step for Test { builder.info(&format!("Checking test artifacts ({} -> {})", &compiler.host, target)); run_cargo(builder, &mut cargo, + vec![], &libtest_stamp(builder, compiler, target), true); @@ -228,6 +232,7 @@ impl Step for Rustdoc { println!("Checking rustdoc artifacts ({} -> {})", &compiler.host, target); run_cargo(builder, &mut cargo, + vec![], &rustdoc_stamp(builder, compiler, target), true); diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 366df4b0ad5cc..61a04b9720602 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -29,7 +29,6 @@ use build_helper::{output, mtime, up_to_date}; use filetime::FileTime; use serde_json; -use crate::dist; use crate::util::{exe, libdir, is_dylib}; use crate::{Compiler, Mode, GitRepo}; use crate::native; @@ -115,6 +114,7 @@ impl Step for Std { &compiler.host, target)); run_cargo(builder, &mut cargo, + vec![], &libstd_stamp(builder, compiler, target), false); @@ -375,6 +375,7 @@ impl Step for Test { &compiler.host, target)); run_cargo(builder, &mut cargo, + vec![], &libtest_stamp(builder, compiler, target), false); @@ -502,6 +503,7 @@ impl Step for Rustc { compiler.stage, &compiler.host, target)); run_cargo(builder, &mut cargo, + vec![], &librustc_stamp(builder, compiler, target), false); @@ -644,18 +646,47 @@ impl Step for CodegenBackend { let out_dir = builder.cargo_out(compiler, Mode::Codegen, target); - let mut cargo = builder.cargo(compiler, Mode::Codegen, target, "build"); + let mut cargo = builder.cargo(compiler, Mode::Codegen, target, "rustc"); cargo.arg("--manifest-path") .arg(builder.src.join("src/librustc_codegen_llvm/Cargo.toml")); rustc_cargo_env(builder, &mut cargo); let features = build_codegen_backend(&builder, &mut cargo, &compiler, target, backend); + let mut cargo_tails_args = vec![]; + + if builder.config.llvm_thin_lto { + cargo_tails_args.push("--".to_string()); + + let num_jobs = builder.jobs(); + + if !target.contains("msvc") { + // Here we assume that the linker is clang. If it's not, there'll + // be linker errors. + cargo_tails_args.push("-Clink-arg=-fuse-ld=lld".to_string()); + cargo_tails_args.push("-Clink-arg=-flto=thin".to_string()); + + if builder.config.llvm_optimize { + cargo_tails_args.push("-Clink-arg=-O2".to_string()); + } + + // Let's make LLD respect the `-j` option. + let num_jobs_arg = format!("-Clink-arg=-Wl,--thinlto-jobs={}", num_jobs); + cargo_tails_args.push(num_jobs_arg); + } else { + // Here we assume that the linker is lld-link.exe. lld-link.exe + // does not need the extra arguments except for num_jobs + let num_jobs_arg = format!("-Clink-arg=/opt:lldltojobs={}", num_jobs); + cargo_tails_args.push(num_jobs_arg); + } + } + let tmp_stamp = out_dir.join(".tmp.stamp"); let _folder = builder.fold_output(|| format!("stage{}-rustc_codegen_llvm", compiler.stage)); let files = run_cargo(builder, cargo.arg("--features").arg(features), + cargo_tails_args, &tmp_stamp, false); if builder.config.dry_run { @@ -728,9 +759,7 @@ pub fn build_codegen_backend(builder: &Builder, "libstdc++.a"); cargo.env("LLVM_STATIC_STDCPP", file); } - if builder.config.llvm_link_shared || - (builder.config.llvm_thin_lto && backend != "emscripten") - { + if builder.config.llvm_link_shared { cargo.env("LLVM_LINK_SHARED", "1"); } } @@ -970,8 +999,6 @@ impl Step for Assemble { copy_lld_to_sysroot(builder, target_compiler, &lld_install); } - dist::maybe_install_llvm_dylib(builder, target_compiler.host, &sysroot); - // Link the compiler binary itself into place let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host); let rustc = out_dir.join(exe("rustc_binary", &*host)); @@ -998,6 +1025,7 @@ pub fn add_to_sysroot(builder: &Builder, sysroot_dst: &Path, stamp: &Path) { pub fn run_cargo(builder: &Builder, cargo: &mut Command, + tail_args: Vec, stamp: &Path, is_check: bool) -> Vec @@ -1020,7 +1048,7 @@ pub fn run_cargo(builder: &Builder, // files we need to probe for later. let mut deps = Vec::new(); let mut toplevel = Vec::new(); - let ok = stream_cargo(builder, cargo, &mut |msg| { + let ok = stream_cargo(builder, cargo, tail_args, &mut |msg| { let filenames = match msg { CargoMessage::CompilerArtifact { filenames, .. } => filenames, _ => return, @@ -1145,6 +1173,7 @@ pub fn run_cargo(builder: &Builder, pub fn stream_cargo( builder: &Builder, cargo: &mut Command, + tail_args: Vec, cb: &mut dyn FnMut(CargoMessage), ) -> bool { if builder.config.dry_run { @@ -1155,6 +1184,10 @@ pub fn stream_cargo( cargo.arg("--message-format").arg("json") .stdout(Stdio::piped()); + for arg in tail_args { + cargo.arg(arg); + } + builder.verbose(&format!("running: {:?}", cargo)); let mut child = match cargo.spawn() { Ok(child) => child, diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index e38a1d295453a..f6f4d60846544 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -1887,13 +1887,13 @@ impl Step for HashSign { // LLVM tools are linked dynamically. // Note: This function does no yet support Windows but we also don't support // linking LLVM tools dynamically on Windows yet. -pub fn maybe_install_llvm_dylib(builder: &Builder, - target: Interned, - sysroot: &Path) { +fn maybe_install_llvm_dylib(builder: &Builder, + target: Interned, + image: &Path) { let src_libdir = builder .llvm_out(target) .join("lib"); - let dst_libdir = sysroot.join("lib/rustlib").join(&*target).join("lib"); + let dst_libdir = image.join("lib/rustlib").join(&*target).join("lib"); t!(fs::create_dir_all(&dst_libdir)); if target.contains("apple-darwin") { diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index d2fc26e5812c2..4335359e11589 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -87,7 +87,7 @@ impl Step for ToolBuild { let _folder = builder.fold_output(|| format!("stage{}-{}", compiler.stage, tool)); builder.info(&format!("Building stage{} tool {} ({})", compiler.stage, tool, target)); let mut duplicates = Vec::new(); - let is_expected = compile::stream_cargo(builder, &mut cargo, &mut |msg| { + let is_expected = compile::stream_cargo(builder, &mut cargo, vec![], &mut |msg| { // Only care about big things like the RLS/Cargo for now match tool { | "rls" diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index b56ae61227c85..6c1417741f252 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -210,7 +210,14 @@ pub fn run(run_compiler: F) -> isize } fn load_backend_from_dylib(path: &Path) -> fn() -> Box { - let lib = DynamicLibrary::open(Some(path)).unwrap_or_else(|err| { + // Note that we're specifically using `open_global_now` here rather than + // `open`, namely we want the behavior on Unix of RTLD_GLOBAL and RTLD_NOW, + // where NOW means "bind everything right now" because we don't want + // surprises later on and RTLD_GLOBAL allows the symbols to be made + // available for future dynamic libraries opened. This is currently used by + // loading LLVM and then making its symbols available for other dynamic + // libraries. + let lib = DynamicLibrary::open_global_now(path).unwrap_or_else(|err| { let err = format!("couldn't load codegen backend {:?}: {:?}", path, err); early_error(ErrorOutputType::default(), &err); }); diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 1b6453893375e..ce482087bbae5 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -142,10 +142,6 @@ fn main() { continue; } - if flag.starts_with("-flto") { - continue; - } - // -Wdate-time is not supported by the netbsd cross compiler if is_crossed && target.contains("netbsd") && flag.contains("date-time") { continue; diff --git a/src/test/run-make-fulldeps/llvm-pass/Makefile b/src/test/run-make-fulldeps/llvm-pass/Makefile new file mode 100644 index 0000000000000..8a18aadf36a8b --- /dev/null +++ b/src/test/run-make-fulldeps/llvm-pass/Makefile @@ -0,0 +1,28 @@ +-include ../tools.mk + +ifeq ($(UNAME),Darwin) +PLUGIN_FLAGS := -C link-args=-Wl,-undefined,dynamic_lookup +endif + +ifeq ($(findstring stage1,$(RUST_BUILD_STAGE)),stage1) +# ignore stage1 +all: + +else +# Windows doesn't correctly handle include statements with escaping paths, +# so this test will not get run on Windows. +ifdef IS_WINDOWS +all: +else +all: $(call NATIVE_STATICLIB,llvm-function-pass) $(call NATIVE_STATICLIB,llvm-module-pass) + $(RUSTC) plugin.rs -C prefer-dynamic $(PLUGIN_FLAGS) + $(RUSTC) main.rs + +$(TMPDIR)/libllvm-function-pass.o: + $(CXX) $(CFLAGS) $(LLVM_CXXFLAGS) -c llvm-function-pass.so.cc -o $(TMPDIR)/libllvm-function-pass.o + +$(TMPDIR)/libllvm-module-pass.o: + $(CXX) $(CFLAGS) $(LLVM_CXXFLAGS) -c llvm-module-pass.so.cc -o $(TMPDIR)/libllvm-module-pass.o +endif + +endif diff --git a/src/test/run-make-fulldeps/llvm-pass/llvm-function-pass.so.cc b/src/test/run-make-fulldeps/llvm-pass/llvm-function-pass.so.cc new file mode 100644 index 0000000000000..c0a17d920cffc --- /dev/null +++ b/src/test/run-make-fulldeps/llvm-pass/llvm-function-pass.so.cc @@ -0,0 +1,56 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#include +#include +#include + +#include "llvm/Pass.h" +#include "llvm/IR/Function.h" + +using namespace llvm; + +namespace { + + class TestLLVMPass : public FunctionPass { + + public: + + static char ID; + TestLLVMPass() : FunctionPass(ID) { } + + bool runOnFunction(Function &F) override; + + StringRef getPassName() const override { + return "Some LLVM pass"; + } + + }; + +} + +bool TestLLVMPass::runOnFunction(Function &F) { + // A couple examples of operations that previously caused segmentation faults + // https://github.com/rust-lang/rust/issues/31067 + + for (auto N = F.begin(); N != F.end(); ++N) { + /* code */ + } + + LLVMContext &C = F.getContext(); + IntegerType *Int8Ty = IntegerType::getInt8Ty(C); + PointerType::get(Int8Ty, 0); + return true; +} + +char TestLLVMPass::ID = 0; + +static RegisterPass RegisterAFLPass( + "some-llvm-function-pass", "Some LLVM pass"); diff --git a/src/test/run-make-fulldeps/llvm-pass/llvm-module-pass.so.cc b/src/test/run-make-fulldeps/llvm-pass/llvm-module-pass.so.cc new file mode 100644 index 0000000000000..70051681ab035 --- /dev/null +++ b/src/test/run-make-fulldeps/llvm-pass/llvm-module-pass.so.cc @@ -0,0 +1,55 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#include +#include +#include + +#include "llvm/IR/Module.h" + +using namespace llvm; + +namespace { + + class TestLLVMPass : public ModulePass { + + public: + + static char ID; + TestLLVMPass() : ModulePass(ID) { } + + bool runOnModule(Module &M) override; + + StringRef getPassName() const override { + return "Some LLVM pass"; + } + + }; + +} + +bool TestLLVMPass::runOnModule(Module &M) { + // A couple examples of operations that previously caused segmentation faults + // https://github.com/rust-lang/rust/issues/31067 + + for (auto F = M.begin(); F != M.end(); ++F) { + /* code */ + } + + LLVMContext &C = M.getContext(); + IntegerType *Int8Ty = IntegerType::getInt8Ty(C); + PointerType::get(Int8Ty, 0); + return true; +} + +char TestLLVMPass::ID = 0; + +static RegisterPass RegisterAFLPass( + "some-llvm-module-pass", "Some LLVM pass"); diff --git a/src/test/run-make-fulldeps/llvm-pass/main.rs b/src/test/run-make-fulldeps/llvm-pass/main.rs new file mode 100644 index 0000000000000..5b5ab94bcef02 --- /dev/null +++ b/src/test/run-make-fulldeps/llvm-pass/main.rs @@ -0,0 +1,14 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(plugin)] +#![plugin(some_plugin)] + +fn main() {} diff --git a/src/test/run-make-fulldeps/llvm-pass/plugin.rs b/src/test/run-make-fulldeps/llvm-pass/plugin.rs new file mode 100644 index 0000000000000..f77b2fca857a6 --- /dev/null +++ b/src/test/run-make-fulldeps/llvm-pass/plugin.rs @@ -0,0 +1,28 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(plugin_registrar, rustc_private)] +#![crate_type = "dylib"] +#![crate_name = "some_plugin"] + +extern crate rustc; +extern crate rustc_plugin; + +#[link(name = "llvm-function-pass", kind = "static")] +#[link(name = "llvm-module-pass", kind = "static")] +extern {} + +use rustc_plugin::registry::Registry; + +#[plugin_registrar] +pub fn plugin_registrar(reg: &mut Registry) { + reg.register_llvm_pass("some-llvm-function-pass"); + reg.register_llvm_pass("some-llvm-module-pass"); +}