Merge branch 'master' of https://github.com/rust-lang/rust into gen
# Conflicts: # src/librustc_mir/build/scope.rs
This commit is contained in:
commit
d020ff0c68
33 changed files with 529 additions and 321 deletions
19
src/Cargo.lock
generated
19
src/Cargo.lock
generated
|
|
@ -65,6 +65,11 @@ name = "ansi_term"
|
|||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "ar"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "arena"
|
||||
version = "0.0.0"
|
||||
|
|
@ -1333,10 +1338,12 @@ dependencies = [
|
|||
name = "rustc_driver"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"ar 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"arena 0.0.0",
|
||||
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"graphviz 0.0.0",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc 0.0.0",
|
||||
"rustc_allocator 0.0.0",
|
||||
"rustc_back 0.0.0",
|
||||
|
|
@ -1354,6 +1361,7 @@ dependencies = [
|
|||
"rustc_resolve 0.0.0",
|
||||
"rustc_save_analysis 0.0.0",
|
||||
"rustc_trans 0.0.0",
|
||||
"rustc_trans_utils 0.0.0",
|
||||
"rustc_typeck 0.0.0",
|
||||
"serialize 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
|
|
@ -1545,11 +1553,21 @@ dependencies = [
|
|||
"rustc_incremental 0.0.0",
|
||||
"rustc_llvm 0.0.0",
|
||||
"rustc_platform_intrinsics 0.0.0",
|
||||
"rustc_trans_utils 0.0.0",
|
||||
"serialize 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
"syntax_pos 0.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_trans_utils"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"rustc 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
"syntax_pos 0.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_tsan"
|
||||
version = "0.0.0"
|
||||
|
|
@ -2141,6 +2159,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66"
|
||||
"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699"
|
||||
"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"
|
||||
"checksum ar 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b24e4eef8e3fa7e2ca75b157e6039cdf8d9d3a68213ddc19d0fd9d576b9717c9"
|
||||
"checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159"
|
||||
"checksum backtrace 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "72f9b4182546f4b04ebc4ab7f84948953a118bd6021a1b6a6c909e3e94f6be76"
|
||||
"checksum backtrace-sys 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "afccc5772ba333abccdf60d55200fa3406f8c59dcf54d5f7998c9107d3799c7c"
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ pub struct Config {
|
|||
pub profiler: bool,
|
||||
|
||||
// llvm codegen options
|
||||
pub llvm_enabled: bool,
|
||||
pub llvm_assertions: bool,
|
||||
pub llvm_optimize: bool,
|
||||
pub llvm_release_debuginfo: bool,
|
||||
|
|
@ -192,6 +193,7 @@ struct Install {
|
|||
#[derive(Deserialize, Default)]
|
||||
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
||||
struct Llvm {
|
||||
enabled: Option<bool>,
|
||||
ccache: Option<StringOrBool>,
|
||||
ninja: Option<bool>,
|
||||
assertions: Option<bool>,
|
||||
|
|
@ -265,6 +267,7 @@ struct TomlTarget {
|
|||
impl Config {
|
||||
pub fn parse(build: &str, file: Option<PathBuf>) -> Config {
|
||||
let mut config = Config::default();
|
||||
config.llvm_enabled = true;
|
||||
config.llvm_optimize = true;
|
||||
config.use_jemalloc = true;
|
||||
config.backtrace = true;
|
||||
|
|
@ -345,6 +348,7 @@ impl Config {
|
|||
Some(StringOrBool::Bool(false)) | None => {}
|
||||
}
|
||||
set(&mut config.ninja, llvm.ninja);
|
||||
set(&mut config.llvm_enabled, llvm.enabled);
|
||||
set(&mut config.llvm_assertions, llvm.assertions);
|
||||
set(&mut config.llvm_optimize, llvm.optimize);
|
||||
set(&mut config.llvm_release_debuginfo, llvm.release_debuginfo);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,10 @@
|
|||
# =============================================================================
|
||||
[llvm]
|
||||
|
||||
# Indicates whether rustc will support compilation with LLVM
|
||||
# note: rustc does not compile without LLVM at the moment
|
||||
#enabled = true
|
||||
|
||||
# Indicates whether the LLVM build is a Release or Debug build
|
||||
#optimize = true
|
||||
|
||||
|
|
|
|||
|
|
@ -429,6 +429,9 @@ impl Build {
|
|||
if self.config.use_jemalloc {
|
||||
features.push_str(" jemalloc");
|
||||
}
|
||||
if self.config.llvm_enabled {
|
||||
features.push_str(" llvm");
|
||||
}
|
||||
features
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,12 @@ impl Step for Llvm {
|
|||
fn run(self, builder: &Builder) {
|
||||
let build = builder.build;
|
||||
let target = self.target;
|
||||
|
||||
// If we're not compiling for LLVM bail out here.
|
||||
if !build.config.llvm_enabled {
|
||||
return;
|
||||
}
|
||||
|
||||
// If we're using a custom LLVM bail out here, but we can only use a
|
||||
// custom LLVM for the build triple.
|
||||
if let Some(config) = build.config.target_config.get(&target) {
|
||||
|
|
|
|||
|
|
@ -629,10 +629,12 @@ extern "rust-intrinsic" {
|
|||
/// Aborts the execution of the process.
|
||||
pub fn abort() -> !;
|
||||
|
||||
/// Tells LLVM that this point in the code is not reachable,
|
||||
/// enabling further optimizations.
|
||||
/// Tells LLVM that this point in the code is not reachable, enabling
|
||||
/// further optimizations.
|
||||
///
|
||||
/// NB: This is very different from the `unreachable!()` macro!
|
||||
/// NB: This is very different from the `unreachable!()` macro: Unlike the
|
||||
/// macro, which panics when it is executed, it is *undefined behavior* to
|
||||
/// reach code marked with this function.
|
||||
pub fn unreachable() -> !;
|
||||
|
||||
/// Informs the optimizer that a condition is always true.
|
||||
|
|
|
|||
|
|
@ -942,3 +942,15 @@ impl<T: ::fmt::Debug> ::fmt::Debug for ManuallyDrop<T> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Tells LLVM that this point in the code is not reachable, enabling further
|
||||
/// optimizations.
|
||||
///
|
||||
/// NB: This is very different from the `unreachable!()` macro: Unlike the
|
||||
/// macro, which panics when it is executed, it is *undefined behavior* to
|
||||
/// reach code marked with this function.
|
||||
#[inline]
|
||||
#[unstable(feature = "unreachable", issue = "43751")]
|
||||
pub unsafe fn unreachable() -> ! {
|
||||
intrinsics::unreachable()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -135,6 +135,11 @@ impl<'tcx> Lvalue<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub enum RvalueInitializationState {
|
||||
Shallow,
|
||||
Deep
|
||||
}
|
||||
|
||||
impl<'tcx> Rvalue<'tcx> {
|
||||
pub fn ty<'a, 'gcx, D>(&self, local_decls: &D, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx>
|
||||
where D: HasLocalDecls<'tcx>
|
||||
|
|
@ -209,6 +214,16 @@ impl<'tcx> Rvalue<'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
/// Returns whether this rvalue is deeply initialized (most rvalues) or
|
||||
/// whether its only shallowly initialized (`Rvalue::Box`).
|
||||
pub fn initialization_state(&self) -> RvalueInitializationState {
|
||||
match *self {
|
||||
Rvalue::NullaryOp(NullOp::Box, _) => RvalueInitializationState::Shallow,
|
||||
_ => RvalueInitializationState::Deep
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Operand<'tcx> {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ crate-type = ["dylib"]
|
|||
arena = { path = "../libarena" }
|
||||
graphviz = { path = "../libgraphviz" }
|
||||
log = { version = "0.3", features = ["release_max_level_info"] }
|
||||
owning_ref = "0.3.3"
|
||||
env_logger = { version = "0.4", default-features = false }
|
||||
rustc = { path = "../librustc" }
|
||||
rustc_allocator = { path = "../librustc_allocator" }
|
||||
|
|
@ -29,9 +30,15 @@ rustc_plugin = { path = "../librustc_plugin" }
|
|||
rustc_privacy = { path = "../librustc_privacy" }
|
||||
rustc_resolve = { path = "../librustc_resolve" }
|
||||
rustc_save_analysis = { path = "../librustc_save_analysis" }
|
||||
rustc_trans = { path = "../librustc_trans" }
|
||||
rustc_trans = { path = "../librustc_trans", optional = true }
|
||||
rustc_trans_utils = { path = "../librustc_trans_utils" }
|
||||
rustc_typeck = { path = "../librustc_typeck" }
|
||||
serialize = { path = "../libserialize" }
|
||||
syntax = { path = "../libsyntax" }
|
||||
syntax_ext = { path = "../libsyntax_ext" }
|
||||
syntax_pos = { path = "../libsyntax_pos" }
|
||||
|
||||
ar = "0.3.0"
|
||||
|
||||
[features]
|
||||
llvm = ["rustc_trans"]
|
||||
|
|
|
|||
|
|
@ -18,7 +18,9 @@ use rustc::session::CompileIncomplete;
|
|||
use rustc::session::config::{self, Input, OutputFilenames, OutputType};
|
||||
use rustc::session::search_paths::PathKind;
|
||||
use rustc::lint;
|
||||
use rustc::middle::{self, dependency_format, stability, reachable};
|
||||
use rustc::middle::{self, stability, reachable};
|
||||
#[cfg(feature="llvm")]
|
||||
use rustc::middle::dependency_format;
|
||||
use rustc::middle::privacy::AccessLevels;
|
||||
use rustc::mir::transform::{MIR_CONST, MIR_VALIDATED, MIR_OPTIMIZED, Passes};
|
||||
use rustc::ty::{self, TyCtxt, Resolutions, GlobalArenas};
|
||||
|
|
@ -31,7 +33,9 @@ use rustc_incremental::{self, IncrementalHashesMap};
|
|||
use rustc_resolve::{MakeGlobMap, Resolver};
|
||||
use rustc_metadata::creader::CrateLoader;
|
||||
use rustc_metadata::cstore::{self, CStore};
|
||||
#[cfg(feature="llvm")]
|
||||
use rustc_trans::back::{link, write};
|
||||
#[cfg(feature="llvm")]
|
||||
use rustc_trans as trans;
|
||||
use rustc_typeck as typeck;
|
||||
use rustc_privacy;
|
||||
|
|
@ -69,6 +73,11 @@ pub fn compile_input(sess: &Session,
|
|||
output: &Option<PathBuf>,
|
||||
addl_plugins: Option<Vec<String>>,
|
||||
control: &CompileController) -> CompileResult {
|
||||
#[cfg(feature="llvm")]
|
||||
use rustc_trans::back::write::OngoingCrateTranslation;
|
||||
#[cfg(not(feature="llvm"))]
|
||||
type OngoingCrateTranslation = ();
|
||||
|
||||
macro_rules! controller_entry_point {
|
||||
($point: ident, $tsess: expr, $make_state: expr, $phase_result: expr) => {{
|
||||
let state = &mut $make_state;
|
||||
|
|
@ -88,7 +97,7 @@ pub fn compile_input(sess: &Session,
|
|||
// We need nested scopes here, because the intermediate results can keep
|
||||
// large chunks of memory alive and we want to free them as soon as
|
||||
// possible to keep the peak memory usage low
|
||||
let (outputs, trans) = {
|
||||
let (outputs, trans): (OutputFilenames, OngoingCrateTranslation) = {
|
||||
let krate = match phase_1_parse_input(control, sess, input) {
|
||||
Ok(krate) => krate,
|
||||
Err(mut parse_error) => {
|
||||
|
|
@ -113,7 +122,8 @@ pub fn compile_input(sess: &Session,
|
|||
};
|
||||
|
||||
let outputs = build_output_filenames(input, outdir, output, &krate.attrs, sess);
|
||||
let crate_name = link::find_crate_name(Some(sess), &krate.attrs, input);
|
||||
let crate_name =
|
||||
::rustc_trans_utils::link::find_crate_name(Some(sess), &krate.attrs, input);
|
||||
let ExpansionResult { expanded_crate, defs, analysis, resolutions, mut hir_forest } = {
|
||||
phase_2_configure_and_expand(
|
||||
sess, &cstore, krate, registry, &crate_name, addl_plugins, control.make_glob_map,
|
||||
|
|
@ -206,6 +216,8 @@ pub fn compile_input(sess: &Session,
|
|||
println!("Pre-trans");
|
||||
tcx.print_debug_stats();
|
||||
}
|
||||
|
||||
#[cfg(feature="llvm")]
|
||||
let trans = phase_4_translate_to_llvm(tcx, analysis, incremental_hashes_map,
|
||||
&outputs);
|
||||
|
||||
|
|
@ -221,38 +233,59 @@ pub fn compile_input(sess: &Session,
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature="llvm"))]
|
||||
{
|
||||
let _ = incremental_hashes_map;
|
||||
sess.err(&format!("LLVM is not supported by this rustc"));
|
||||
sess.abort_if_errors();
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
#[cfg(feature="llvm")]
|
||||
Ok((outputs, trans))
|
||||
})??
|
||||
};
|
||||
|
||||
if sess.opts.debugging_opts.print_type_sizes {
|
||||
sess.code_stats.borrow().print_type_sizes();
|
||||
#[cfg(not(feature="llvm"))]
|
||||
{
|
||||
let _ = outputs;
|
||||
let _ = trans;
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
let (phase5_result, trans) = phase_5_run_llvm_passes(sess, trans);
|
||||
#[cfg(feature="llvm")]
|
||||
{
|
||||
if sess.opts.debugging_opts.print_type_sizes {
|
||||
sess.code_stats.borrow().print_type_sizes();
|
||||
}
|
||||
|
||||
controller_entry_point!(after_llvm,
|
||||
sess,
|
||||
CompileState::state_after_llvm(input, sess, outdir, output, &trans),
|
||||
phase5_result);
|
||||
phase5_result?;
|
||||
let (phase5_result, trans) = phase_5_run_llvm_passes(sess, trans);
|
||||
|
||||
phase_6_link_output(sess, &trans, &outputs);
|
||||
controller_entry_point!(after_llvm,
|
||||
sess,
|
||||
CompileState::state_after_llvm(input, sess, outdir, output, &trans),
|
||||
phase5_result);
|
||||
phase5_result?;
|
||||
|
||||
// Now that we won't touch anything in the incremental compilation directory
|
||||
// any more, we can finalize it (which involves renaming it)
|
||||
rustc_incremental::finalize_session_directory(sess, trans.link.crate_hash);
|
||||
phase_6_link_output(sess, &trans, &outputs);
|
||||
|
||||
if sess.opts.debugging_opts.perf_stats {
|
||||
sess.print_perf_stats();
|
||||
// Now that we won't touch anything in the incremental compilation directory
|
||||
// any more, we can finalize it (which involves renaming it)
|
||||
rustc_incremental::finalize_session_directory(sess, trans.link.crate_hash);
|
||||
|
||||
if sess.opts.debugging_opts.perf_stats {
|
||||
sess.print_perf_stats();
|
||||
}
|
||||
|
||||
controller_entry_point!(
|
||||
compilation_done,
|
||||
sess,
|
||||
CompileState::state_when_compilation_done(input, sess, outdir, output),
|
||||
Ok(())
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
controller_entry_point!(compilation_done,
|
||||
sess,
|
||||
CompileState::state_when_compilation_done(input, sess, outdir, output),
|
||||
Ok(()));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn keep_hygiene_data(sess: &Session) -> bool {
|
||||
|
|
@ -360,6 +393,7 @@ pub struct CompileState<'a, 'tcx: 'a> {
|
|||
pub resolutions: Option<&'a Resolutions>,
|
||||
pub analysis: Option<&'a ty::CrateAnalysis>,
|
||||
pub tcx: Option<TyCtxt<'a, 'tcx, 'tcx>>,
|
||||
#[cfg(feature="llvm")]
|
||||
pub trans: Option<&'a trans::CrateTranslation>,
|
||||
}
|
||||
|
||||
|
|
@ -386,6 +420,7 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> {
|
|||
resolutions: None,
|
||||
analysis: None,
|
||||
tcx: None,
|
||||
#[cfg(feature="llvm")]
|
||||
trans: None,
|
||||
}
|
||||
}
|
||||
|
|
@ -474,7 +509,7 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(feature="llvm")]
|
||||
fn state_after_llvm(input: &'a Input,
|
||||
session: &'tcx Session,
|
||||
out_dir: &'a Option<PathBuf>,
|
||||
|
|
@ -488,6 +523,7 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature="llvm")]
|
||||
fn state_when_compilation_done(input: &'a Input,
|
||||
session: &'tcx Session,
|
||||
out_dir: &'a Option<PathBuf>,
|
||||
|
|
@ -906,6 +942,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|
|||
mir::provide(&mut local_providers);
|
||||
reachable::provide(&mut local_providers);
|
||||
rustc_privacy::provide(&mut local_providers);
|
||||
#[cfg(feature="llvm")]
|
||||
trans::provide(&mut local_providers);
|
||||
typeck::provide(&mut local_providers);
|
||||
ty::provide(&mut local_providers);
|
||||
|
|
@ -918,6 +955,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|
|||
|
||||
let mut extern_providers = ty::maps::Providers::default();
|
||||
cstore::provide(&mut extern_providers);
|
||||
#[cfg(feature="llvm")]
|
||||
trans::provide(&mut extern_providers);
|
||||
ty::provide_extern(&mut extern_providers);
|
||||
traits::provide_extern(&mut extern_providers);
|
||||
|
|
@ -1066,6 +1104,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|
|||
|
||||
/// Run the translation phase to LLVM, after which the AST and analysis can
|
||||
/// be discarded.
|
||||
#[cfg(feature="llvm")]
|
||||
pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
analysis: ty::CrateAnalysis,
|
||||
incremental_hashes_map: IncrementalHashesMap,
|
||||
|
|
@ -1087,6 +1126,7 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
|
||||
/// Run LLVM itself, producing a bitcode file, assembly file or object file
|
||||
/// as a side effect.
|
||||
#[cfg(feature="llvm")]
|
||||
pub fn phase_5_run_llvm_passes(sess: &Session,
|
||||
trans: write::OngoingCrateTranslation)
|
||||
-> (CompileResult, trans::CrateTranslation) {
|
||||
|
|
@ -1105,6 +1145,7 @@ pub fn phase_5_run_llvm_passes(sess: &Session,
|
|||
|
||||
/// Run the linker on any artifacts that resulted from the LLVM run.
|
||||
/// This should produce either a finished executable or library.
|
||||
#[cfg(feature="llvm")]
|
||||
pub fn phase_6_link_output(sess: &Session,
|
||||
trans: &trans::CrateTranslation,
|
||||
outputs: &OutputFilenames) {
|
||||
|
|
@ -1126,7 +1167,12 @@ fn write_out_deps(sess: &Session, outputs: &OutputFilenames, crate_name: &str) {
|
|||
match *output_type {
|
||||
OutputType::Exe => {
|
||||
for output in sess.crate_types.borrow().iter() {
|
||||
let p = link::filename_for_input(sess, *output, crate_name, outputs);
|
||||
let p = ::rustc_trans_utils::link::filename_for_input(
|
||||
sess,
|
||||
*output,
|
||||
crate_name,
|
||||
outputs
|
||||
);
|
||||
out_filenames.push(p);
|
||||
}
|
||||
}
|
||||
|
|
@ -1236,7 +1282,7 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<c
|
|||
if base.is_empty() {
|
||||
base.extend(attr_types);
|
||||
if base.is_empty() {
|
||||
base.push(link::default_output_for_target(session));
|
||||
base.push(::rustc_trans_utils::link::default_output_for_target(session));
|
||||
}
|
||||
base.sort();
|
||||
base.dedup();
|
||||
|
|
@ -1244,7 +1290,7 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<c
|
|||
|
||||
base.into_iter()
|
||||
.filter(|crate_type| {
|
||||
let res = !link::invalid_output_for_target(session, *crate_type);
|
||||
let res = !::rustc_trans_utils::link::invalid_output_for_target(session, *crate_type);
|
||||
|
||||
if !res {
|
||||
session.warn(&format!("dropping unsupported crate type `{}` for target `{}`",
|
||||
|
|
|
|||
|
|
@ -28,10 +28,15 @@
|
|||
#![feature(rustc_diagnostic_macros)]
|
||||
#![feature(set_stdio)]
|
||||
|
||||
#[cfg(not(feature="llvm"))]
|
||||
extern crate ar;
|
||||
|
||||
extern crate arena;
|
||||
extern crate getopts;
|
||||
extern crate graphviz;
|
||||
extern crate env_logger;
|
||||
#[cfg(not(feature="llvm"))]
|
||||
extern crate owning_ref;
|
||||
extern crate libc;
|
||||
extern crate rustc;
|
||||
extern crate rustc_allocator;
|
||||
|
|
@ -49,7 +54,9 @@ extern crate rustc_metadata;
|
|||
extern crate rustc_mir;
|
||||
extern crate rustc_resolve;
|
||||
extern crate rustc_save_analysis;
|
||||
#[cfg(feature="llvm")]
|
||||
extern crate rustc_trans;
|
||||
extern crate rustc_trans_utils;
|
||||
extern crate rustc_typeck;
|
||||
extern crate serialize;
|
||||
#[macro_use]
|
||||
|
|
@ -64,7 +71,7 @@ use pretty::{PpMode, UserIdentifiedItem};
|
|||
use rustc_resolve as resolve;
|
||||
use rustc_save_analysis as save;
|
||||
use rustc_save_analysis::DumpHandler;
|
||||
use rustc_trans::back::link;
|
||||
#[cfg(feature="llvm")]
|
||||
use rustc_trans::back::write::{RELOC_MODEL_ARGS, CODE_GEN_MODEL_ARGS};
|
||||
use rustc::dep_graph::DepGraph;
|
||||
use rustc::session::{self, config, Session, build_session, CompileResult};
|
||||
|
|
@ -74,9 +81,13 @@ use rustc::session::config::nightly_options;
|
|||
use rustc::session::{early_error, early_warn};
|
||||
use rustc::lint::Lint;
|
||||
use rustc::lint;
|
||||
#[cfg(not(feature="llvm"))]
|
||||
use rustc::middle::cstore::MetadataLoader as MetadataLoaderTrait;
|
||||
use rustc_metadata::locator;
|
||||
use rustc_metadata::cstore::CStore;
|
||||
use rustc::util::common::{time, ErrorReported};
|
||||
#[cfg(not(feature="llvm"))]
|
||||
use rustc_back::target::Target;
|
||||
|
||||
use serialize::json::ToJson;
|
||||
|
||||
|
|
@ -89,6 +100,8 @@ use std::ffi::OsString;
|
|||
use std::io::{self, Read, Write};
|
||||
use std::iter::repeat;
|
||||
use std::path::PathBuf;
|
||||
#[cfg(not(feature="llvm"))]
|
||||
use std::path::Path;
|
||||
use std::process::{self, Command, Stdio};
|
||||
use std::rc::Rc;
|
||||
use std::str;
|
||||
|
|
@ -101,11 +114,15 @@ use syntax::feature_gate::{GatedCfg, UnstableFeatures};
|
|||
use syntax::parse::{self, PResult};
|
||||
use syntax_pos::{DUMMY_SP, MultiSpan};
|
||||
|
||||
#[cfg(not(feature="llvm"))]
|
||||
use owning_ref::{OwningRef, ErasedBoxRef};
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test;
|
||||
|
||||
pub mod driver;
|
||||
pub mod pretty;
|
||||
#[cfg(feature="llvm")]
|
||||
pub mod target_features;
|
||||
mod derive_registrar;
|
||||
|
||||
|
|
@ -151,9 +168,49 @@ pub fn run<F>(run_compiler: F) -> isize
|
|||
0
|
||||
}
|
||||
|
||||
#[cfg(not(feature="llvm"))]
|
||||
pub struct NoLLvmMetadataLoader;
|
||||
|
||||
#[cfg(not(feature="llvm"))]
|
||||
pub use NoLLvmMetadataLoader as MetadataLoader;
|
||||
#[cfg(feature="llvm")]
|
||||
pub use rustc_trans::LlvmMetadataLoader as MetadataLoader;
|
||||
|
||||
#[cfg(not(feature="llvm"))]
|
||||
impl MetadataLoaderTrait for NoLLvmMetadataLoader {
|
||||
fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<ErasedBoxRef<[u8]>, String> {
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use self::ar::Archive;
|
||||
|
||||
let file = File::open(filename).map_err(|e|format!("metadata file open err: {:?}", e))?;
|
||||
let mut archive = Archive::new(file);
|
||||
|
||||
while let Some(entry_result) = archive.next_entry() {
|
||||
let mut entry = entry_result.map_err(|e|format!("metadata section read err: {:?}", e))?;
|
||||
if entry.header().identifier() == "rust.metadata.bin" {
|
||||
let mut buf = Vec::new();
|
||||
io::copy(&mut entry, &mut buf).unwrap();
|
||||
let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(buf).into();
|
||||
return Ok(buf.map_owner_box().erase_owner());
|
||||
}
|
||||
}
|
||||
|
||||
Err("Couldnt find metadata section".to_string())
|
||||
}
|
||||
|
||||
fn get_dylib_metadata(&self,
|
||||
_target: &Target,
|
||||
_filename: &Path)
|
||||
-> Result<ErasedBoxRef<[u8]>, String> {
|
||||
panic!("Dylib metadata loading not supported without LLVM")
|
||||
}
|
||||
}
|
||||
|
||||
// Parse args and run the compiler. This is the primary entry point for rustc.
|
||||
// See comments on CompilerCalls below for details about the callbacks argument.
|
||||
// The FileLoader provides a way to load files from sources other than the file system.
|
||||
#[cfg_attr(not(feature="llvm"), allow(unused_mut))]
|
||||
pub fn run_compiler<'a>(args: &[String],
|
||||
callbacks: &mut CompilerCalls<'a>,
|
||||
file_loader: Option<Box<FileLoader + 'static>>,
|
||||
|
|
@ -175,6 +232,7 @@ pub fn run_compiler<'a>(args: &[String],
|
|||
let (sopts, cfg) = config::build_session_options_and_crate_config(&matches);
|
||||
|
||||
if sopts.debugging_opts.debug_llvm {
|
||||
#[cfg(feature="llvm")]
|
||||
rustc_trans::enable_llvm_debug();
|
||||
}
|
||||
|
||||
|
|
@ -197,17 +255,19 @@ pub fn run_compiler<'a>(args: &[String],
|
|||
};
|
||||
|
||||
let dep_graph = DepGraph::new(sopts.build_dep_graph());
|
||||
let cstore = Rc::new(CStore::new(&dep_graph, box rustc_trans::LlvmMetadataLoader));
|
||||
let cstore = Rc::new(CStore::new(&dep_graph, box ::MetadataLoader));
|
||||
|
||||
let loader = file_loader.unwrap_or(box RealFileLoader);
|
||||
let codemap = Rc::new(CodeMap::with_file_loader(loader, sopts.file_path_mapping()));
|
||||
let mut sess = session::build_session_with_codemap(
|
||||
sopts, &dep_graph, input_file_path, descriptions, cstore.clone(), codemap, emitter_dest,
|
||||
);
|
||||
#[cfg(feature="llvm")]
|
||||
rustc_trans::init(&sess);
|
||||
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
|
||||
|
||||
let mut cfg = config::build_configuration(&sess, cfg);
|
||||
#[cfg(feature="llvm")]
|
||||
target_features::add_configuration(&mut cfg, &sess);
|
||||
sess.parse_sess.config = cfg;
|
||||
|
||||
|
|
@ -460,6 +520,7 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
|
|||
Compilation::Continue
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature="llvm"), allow(unused_mut))]
|
||||
fn no_input(&mut self,
|
||||
matches: &getopts::Matches,
|
||||
sopts: &config::Options,
|
||||
|
|
@ -477,15 +538,17 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
|
|||
return None;
|
||||
}
|
||||
let dep_graph = DepGraph::new(sopts.build_dep_graph());
|
||||
let cstore = Rc::new(CStore::new(&dep_graph, box rustc_trans::LlvmMetadataLoader));
|
||||
let cstore = Rc::new(CStore::new(&dep_graph, box ::MetadataLoader));
|
||||
let mut sess = build_session(sopts.clone(),
|
||||
&dep_graph,
|
||||
None,
|
||||
descriptions.clone(),
|
||||
cstore.clone());
|
||||
#[cfg(feature="llvm")]
|
||||
rustc_trans::init(&sess);
|
||||
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
|
||||
let mut cfg = config::build_configuration(&sess, cfg.clone());
|
||||
#[cfg(feature="llvm")]
|
||||
target_features::add_configuration(&mut cfg, &sess);
|
||||
sess.parse_sess.config = cfg;
|
||||
let should_stop =
|
||||
|
|
@ -678,14 +741,19 @@ impl RustcDefaultCalls {
|
|||
};
|
||||
let attrs = attrs.as_ref().unwrap();
|
||||
let t_outputs = driver::build_output_filenames(input, odir, ofile, attrs, sess);
|
||||
let id = link::find_crate_name(Some(sess), attrs, input);
|
||||
let id = rustc_trans_utils::link::find_crate_name(Some(sess), attrs, input);
|
||||
if *req == PrintRequest::CrateName {
|
||||
println!("{}", id);
|
||||
continue;
|
||||
}
|
||||
let crate_types = driver::collect_crate_types(sess, attrs);
|
||||
for &style in &crate_types {
|
||||
let fname = link::filename_for_input(sess, style, &id, &t_outputs);
|
||||
let fname = rustc_trans_utils::link::filename_for_input(
|
||||
sess,
|
||||
style,
|
||||
&id,
|
||||
&t_outputs
|
||||
);
|
||||
println!("{}",
|
||||
fname.file_name()
|
||||
.unwrap()
|
||||
|
|
@ -734,6 +802,7 @@ impl RustcDefaultCalls {
|
|||
}
|
||||
PrintRequest::RelocationModels => {
|
||||
println!("Available relocation models:");
|
||||
#[cfg(feature="llvm")]
|
||||
for &(name, _) in RELOC_MODEL_ARGS.iter() {
|
||||
println!(" {}", name);
|
||||
}
|
||||
|
|
@ -741,13 +810,17 @@ impl RustcDefaultCalls {
|
|||
}
|
||||
PrintRequest::CodeModels => {
|
||||
println!("Available code models:");
|
||||
#[cfg(feature="llvm")]
|
||||
for &(name, _) in CODE_GEN_MODEL_ARGS.iter(){
|
||||
println!(" {}", name);
|
||||
}
|
||||
println!("");
|
||||
}
|
||||
PrintRequest::TargetCPUs | PrintRequest::TargetFeatures => {
|
||||
#[cfg(feature="llvm")]
|
||||
rustc_trans::print(*req, sess);
|
||||
#[cfg(not(feature="llvm"))]
|
||||
panic!("LLVM not supported by this rustc")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -786,6 +859,7 @@ pub fn version(binary: &str, matches: &getopts::Matches) {
|
|||
println!("commit-date: {}", unw(commit_date_str()));
|
||||
println!("host: {}", config::host_triple());
|
||||
println!("release: {}", unw(release_str()));
|
||||
#[cfg(feature="llvm")]
|
||||
rustc_trans::print_version();
|
||||
}
|
||||
}
|
||||
|
|
@ -1083,6 +1157,7 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
|
|||
}
|
||||
|
||||
if cg_flags.contains(&"passes=list".to_string()) {
|
||||
#[cfg(feature="llvm")]
|
||||
rustc_trans::print_passes();
|
||||
return None;
|
||||
}
|
||||
|
|
@ -1210,6 +1285,7 @@ pub fn diagnostics_registry() -> errors::registry::Registry {
|
|||
all_errors.extend_from_slice(&rustc_borrowck::DIAGNOSTICS);
|
||||
all_errors.extend_from_slice(&rustc_resolve::DIAGNOSTICS);
|
||||
all_errors.extend_from_slice(&rustc_privacy::DIAGNOSTICS);
|
||||
#[cfg(feature="llvm")]
|
||||
all_errors.extend_from_slice(&rustc_trans::DIAGNOSTICS);
|
||||
all_errors.extend_from_slice(&rustc_const_eval::DIAGNOSTICS);
|
||||
all_errors.extend_from_slice(&rustc_metadata::DIAGNOSTICS);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ use driver;
|
|||
use rustc::dep_graph::DepGraph;
|
||||
use rustc_lint;
|
||||
use rustc_resolve::MakeGlobMap;
|
||||
#[cfg(feature="llvm")]
|
||||
use rustc_trans;
|
||||
use rustc::middle::lang_items;
|
||||
use rustc::middle::free_region::FreeRegionMap;
|
||||
|
|
@ -106,13 +107,14 @@ fn test_env<F>(source_string: &str,
|
|||
|
||||
let dep_graph = DepGraph::new(false);
|
||||
let _ignore = dep_graph.in_ignore();
|
||||
let cstore = Rc::new(CStore::new(&dep_graph, box rustc_trans::LlvmMetadataLoader));
|
||||
let cstore = Rc::new(CStore::new(&dep_graph, box ::MetadataLoader));
|
||||
let sess = session::build_session_(options,
|
||||
&dep_graph,
|
||||
None,
|
||||
diagnostic_handler,
|
||||
Rc::new(CodeMap::new(FilePathMapping::empty())),
|
||||
cstore.clone());
|
||||
#[cfg(feature="llvm")]
|
||||
rustc_trans::init(&sess);
|
||||
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
|
||||
let input = config::Input::Str {
|
||||
|
|
|
|||
|
|
@ -94,19 +94,19 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
block.and(Rvalue::UnaryOp(op, arg))
|
||||
}
|
||||
ExprKind::Box { value, value_extents } => {
|
||||
ExprKind::Box { value } => {
|
||||
let value = this.hir.mirror(value);
|
||||
let result = this.temp(expr.ty, expr_span);
|
||||
// to start, malloc some memory of suitable type (thus far, uninitialized):
|
||||
let box_ = Rvalue::NullaryOp(NullOp::Box, value.ty);
|
||||
this.cfg.push_assign(block, source_info, &result, box_);
|
||||
this.in_scope((value_extents, source_info), block, |this| {
|
||||
if let Some(scope) = scope {
|
||||
// schedule a shallow free of that memory, lest we unwind:
|
||||
this.schedule_box_free(expr_span, value_extents, &result, value.ty);
|
||||
// initialize the box contents:
|
||||
unpack!(block = this.into(&result.clone().deref(), block, value));
|
||||
block.and(Rvalue::Use(Operand::Consume(result)))
|
||||
})
|
||||
this.schedule_drop(expr_span, scope, &result, value.ty);
|
||||
}
|
||||
// initialize the box contents:
|
||||
unpack!(block = this.into(&result.clone().deref(), block, value));
|
||||
block.and(Rvalue::Use(Operand::Consume(result)))
|
||||
}
|
||||
ExprKind::Cast { source } => {
|
||||
let source = this.hir.mirror(source);
|
||||
|
|
|
|||
|
|
@ -89,9 +89,6 @@ should go to.
|
|||
|
||||
use build::{BlockAnd, BlockAndExtension, Builder, CFG};
|
||||
use rustc::middle::region::CodeExtent;
|
||||
use rustc::middle::lang_items;
|
||||
use rustc::middle::const_val::ConstVal;
|
||||
use rustc::ty::subst::{Kind, Subst};
|
||||
use rustc::ty::{Ty, TyCtxt};
|
||||
use rustc::mir::*;
|
||||
use rustc::mir::transform::MirSource;
|
||||
|
|
@ -127,21 +124,6 @@ pub struct Scope<'tcx> {
|
|||
/// end of the vector (top of the stack) first.
|
||||
drops: Vec<DropData<'tcx>>,
|
||||
|
||||
/// A scope may only have one associated free, because:
|
||||
///
|
||||
/// 1. We require a `free` to only be scheduled in the scope of
|
||||
/// `EXPR` in `box EXPR`;
|
||||
/// 2. It only makes sense to have it translated into the diverge-path.
|
||||
///
|
||||
/// This kind of drop will be run *after* all the regular drops
|
||||
/// scheduled onto this scope, because drops may have dependencies
|
||||
/// on the allocated memory.
|
||||
///
|
||||
/// This is expected to go away once `box EXPR` becomes a sugar
|
||||
/// for placement protocol and gets desugared in some earlier
|
||||
/// stage.
|
||||
free: Option<FreeData<'tcx>>,
|
||||
|
||||
/// The cache for drop chain on “normal” exit into a particular BasicBlock.
|
||||
cached_exits: FxHashMap<(BasicBlock, CodeExtent), BasicBlock>,
|
||||
|
||||
|
|
@ -181,22 +163,6 @@ enum DropKind {
|
|||
Storage
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct FreeData<'tcx> {
|
||||
/// span where free obligation was incurred
|
||||
span: Span,
|
||||
|
||||
/// Lvalue containing the allocated box.
|
||||
value: Lvalue<'tcx>,
|
||||
|
||||
/// type of item for which the box was allocated for (i.e. the T in Box<T>).
|
||||
item_ty: Ty<'tcx>,
|
||||
|
||||
/// The cached block containing code to run the free. The block will also execute all the drops
|
||||
/// in the scope.
|
||||
cached_block: CachedBlock,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct BreakableScope<'tcx> {
|
||||
/// Extent of the loop
|
||||
|
|
@ -258,9 +224,6 @@ impl<'tcx> Scope<'tcx> {
|
|||
cached_block.invalidate();
|
||||
}
|
||||
}
|
||||
if let Some(ref mut freedata) = self.free {
|
||||
freedata.cached_block.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the cached entrypoint for diverging exit from this scope.
|
||||
|
|
@ -278,8 +241,6 @@ impl<'tcx> Scope<'tcx> {
|
|||
});
|
||||
if let Some(cached_block) = drops.next() {
|
||||
Some(cached_block.expect("drop cache is not filled"))
|
||||
} else if let Some(ref data) = self.free {
|
||||
Some(data.cached_block.get(generator_drop).expect("free cache is not filled"))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
@ -369,7 +330,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
extent_span: extent.1.span,
|
||||
needs_cleanup: false,
|
||||
drops: vec![],
|
||||
free: None,
|
||||
cached_generator_drop: None,
|
||||
cached_exits: FxHashMap()
|
||||
});
|
||||
|
|
@ -420,7 +380,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
});
|
||||
let len = self.scopes.len();
|
||||
assert!(scope_count < len, "should not use `exit_scope` to pop ALL scopes");
|
||||
let tmp = self.get_unit_temp();
|
||||
|
||||
// If we are emitting a `drop` statement, we need to have the cached
|
||||
// diverge cleanup pads ready in case that drop panics.
|
||||
|
|
@ -454,13 +413,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
|
||||
// End all regions for scopes out of which we are breaking.
|
||||
self.cfg.push_end_region(block, extent.1, scope.extent);
|
||||
|
||||
if let Some(ref free_data) = scope.free {
|
||||
let next = self.cfg.start_new_block();
|
||||
let free = build_free(self.hir.tcx(), &tmp, free_data, next);
|
||||
self.cfg.terminate(block, scope.source_info(free_data.span), free);
|
||||
block = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
let scope = &self.scopes[len - scope_count];
|
||||
|
|
@ -704,36 +656,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
span_bug!(span, "extent {:?} not in scope to drop {:?}", extent, lvalue);
|
||||
}
|
||||
|
||||
/// Schedule dropping of a not-yet-fully-initialised box.
|
||||
///
|
||||
/// This cleanup will only be translated into unwind branch.
|
||||
/// The extent should be for the `EXPR` inside `box EXPR`.
|
||||
/// There may only be one “free” scheduled in any given scope.
|
||||
pub fn schedule_box_free(&mut self,
|
||||
span: Span,
|
||||
extent: CodeExtent,
|
||||
value: &Lvalue<'tcx>,
|
||||
item_ty: Ty<'tcx>) {
|
||||
for scope in self.scopes.iter_mut().rev() {
|
||||
// See the comment in schedule_drop above. The primary difference is that we invalidate
|
||||
// the unwind blocks unconditionally. That’s because the box free may be considered
|
||||
// outer-most cleanup within the scope.
|
||||
scope.invalidate_cache(true);
|
||||
if scope.extent == extent {
|
||||
assert!(scope.free.is_none(), "scope already has a scheduled free!");
|
||||
scope.needs_cleanup = true;
|
||||
scope.free = Some(FreeData {
|
||||
span: span,
|
||||
value: value.clone(),
|
||||
item_ty: item_ty,
|
||||
cached_block: CachedBlock::default(),
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
span_bug!(span, "extent {:?} not in scope to free {:?}", extent, value);
|
||||
}
|
||||
|
||||
// Other
|
||||
// =====
|
||||
/// Creates a path that performs all required cleanup for unwinding.
|
||||
|
|
@ -751,7 +673,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
assert!(!self.scopes.is_empty()); // or `any` above would be false
|
||||
|
||||
let unit_temp = self.get_unit_temp();
|
||||
let Builder { ref mut hir, ref mut cfg, ref mut scopes,
|
||||
ref mut cached_resume_block, .. } = *self;
|
||||
|
||||
|
|
@ -779,13 +700,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
};
|
||||
|
||||
for scope in scopes.iter_mut() {
|
||||
target = build_diverge_scope(hir.tcx(),
|
||||
cfg,
|
||||
&unit_temp,
|
||||
scope.extent_span,
|
||||
scope,
|
||||
target,
|
||||
generator_drop);
|
||||
target = build_diverge_scope(
|
||||
hir.tcx(), cfg, scope.extent_span, scope, target, generator_drop);
|
||||
}
|
||||
Some(target)
|
||||
}
|
||||
|
|
@ -921,9 +837,8 @@ fn build_scope_drops<'tcx>(cfg: &mut CFG<'tcx>,
|
|||
block.unit()
|
||||
}
|
||||
|
||||
fn build_diverge_scope<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
fn build_diverge_scope<'a, 'gcx, 'tcx>(_tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
cfg: &mut CFG<'tcx>,
|
||||
unit_temp: &Lvalue<'tcx>,
|
||||
span: Span,
|
||||
scope: &mut Scope<'tcx>,
|
||||
mut target: BasicBlock,
|
||||
|
|
@ -949,19 +864,6 @@ fn build_diverge_scope<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
|||
scope: visibility_scope
|
||||
};
|
||||
|
||||
// Next, build up any free.
|
||||
if let Some(ref mut free_data) = scope.free {
|
||||
target = if let Some(cached_block) = free_data.cached_block.get(generator_drop) {
|
||||
cached_block
|
||||
} else {
|
||||
let into = cfg.start_new_cleanup_block();
|
||||
cfg.terminate(into, source_info(free_data.span),
|
||||
build_free(tcx, unit_temp, free_data, target));
|
||||
*free_data.cached_block.ref_mut(generator_drop) = Some(into);
|
||||
into
|
||||
};
|
||||
}
|
||||
|
||||
// Next, build up the drops. Here we iterate the vector in
|
||||
// *forward* order, so that we generate drops[0] first (right to
|
||||
// left in diagram above).
|
||||
|
|
@ -1005,24 +907,3 @@ fn build_diverge_scope<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
|||
|
||||
target
|
||||
}
|
||||
|
||||
fn build_free<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
unit_temp: &Lvalue<'tcx>,
|
||||
data: &FreeData<'tcx>,
|
||||
target: BasicBlock)
|
||||
-> TerminatorKind<'tcx> {
|
||||
let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem);
|
||||
let substs = tcx.intern_substs(&[Kind::from(data.item_ty)]);
|
||||
TerminatorKind::Call {
|
||||
func: Operand::Constant(box Constant {
|
||||
span: data.span,
|
||||
ty: tcx.type_of(free_func).subst(tcx, substs),
|
||||
literal: Literal::Value {
|
||||
value: ConstVal::Function(free_func, substs),
|
||||
}
|
||||
}),
|
||||
args: vec![Operand::Consume(data.value.clone())],
|
||||
destination: Some((unit_temp.clone(), target)),
|
||||
cleanup: None
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -240,7 +240,7 @@ pub(crate) fn drop_flag_effects_for_function_entry<'a, 'tcx, F>(
|
|||
let lookup_result = move_data.rev_lookup.find(&lvalue);
|
||||
on_lookup_result_bits(tcx, mir, move_data,
|
||||
lookup_result,
|
||||
|moi| callback(moi, DropFlagState::Present));
|
||||
|mpi| callback(mpi, DropFlagState::Present));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -270,7 +270,7 @@ pub(crate) fn drop_flag_effects_for_location<'a, 'tcx, F>(
|
|||
|
||||
on_all_children_bits(tcx, mir, move_data,
|
||||
path,
|
||||
|moi| callback(moi, DropFlagState::Absent))
|
||||
|mpi| callback(mpi, DropFlagState::Absent))
|
||||
}
|
||||
|
||||
let block = &mir[loc.block];
|
||||
|
|
@ -279,11 +279,21 @@ pub(crate) fn drop_flag_effects_for_location<'a, 'tcx, F>(
|
|||
mir::StatementKind::SetDiscriminant{ .. } => {
|
||||
span_bug!(stmt.source_info.span, "SetDiscrimant should not exist during borrowck");
|
||||
}
|
||||
mir::StatementKind::Assign(ref lvalue, _) => {
|
||||
debug!("drop_flag_effects: assignment {:?}", stmt);
|
||||
on_lookup_result_bits(tcx, mir, move_data,
|
||||
move_data.rev_lookup.find(lvalue),
|
||||
|moi| callback(moi, DropFlagState::Present))
|
||||
mir::StatementKind::Assign(ref lvalue, ref rvalue) => {
|
||||
match rvalue.initialization_state() {
|
||||
mir::tcx::RvalueInitializationState::Shallow => {
|
||||
debug!("drop_flag_effects: box assignment {:?}", stmt);
|
||||
if let LookupResult::Exact(mpi) = move_data.rev_lookup.find(lvalue) {
|
||||
callback(mpi, DropFlagState::Present);
|
||||
}
|
||||
}
|
||||
mir::tcx::RvalueInitializationState::Deep => {
|
||||
debug!("drop_flag_effects: assignment {:?}", stmt);
|
||||
on_lookup_result_bits(tcx, mir, move_data,
|
||||
move_data.rev_lookup.find(lvalue),
|
||||
|mpi| callback(mpi, DropFlagState::Present))
|
||||
}
|
||||
}
|
||||
}
|
||||
mir::StatementKind::StorageLive(_) |
|
||||
mir::StatementKind::StorageDead(_) |
|
||||
|
|
@ -298,7 +308,7 @@ pub(crate) fn drop_flag_effects_for_location<'a, 'tcx, F>(
|
|||
mir::TerminatorKind::DropAndReplace { ref location, .. } => {
|
||||
on_lookup_result_bits(tcx, mir, move_data,
|
||||
move_data.rev_lookup.find(location),
|
||||
|moi| callback(moi, DropFlagState::Present))
|
||||
|mpi| callback(mpi, DropFlagState::Present))
|
||||
}
|
||||
_ => {
|
||||
// other terminators do not contain move-ins
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ use super::MoveDataParamEnv;
|
|||
use util::elaborate_drops::DropFlagState;
|
||||
|
||||
use super::move_paths::{HasMoveData, MoveData, MoveOutIndex, MovePathIndex};
|
||||
use super::move_paths::LookupResult;
|
||||
use super::{BitDenotation, BlockSets, DataflowOperator};
|
||||
|
||||
use super::drop_flag_effects_for_function_entry;
|
||||
|
|
@ -469,18 +470,30 @@ impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> {
|
|||
mir::StatementKind::SetDiscriminant { .. } => {
|
||||
span_bug!(stmt.source_info.span, "SetDiscriminant should not exist in borrowck");
|
||||
}
|
||||
mir::StatementKind::Assign(ref lvalue, _) => {
|
||||
mir::StatementKind::Assign(ref lvalue, ref rvalue) => {
|
||||
// assigning into this `lvalue` kills all
|
||||
// MoveOuts from it, and *also* all MoveOuts
|
||||
// for children and associated fragment sets.
|
||||
on_lookup_result_bits(tcx,
|
||||
mir,
|
||||
move_data,
|
||||
rev_lookup.find(lvalue),
|
||||
|mpi| for moi in &path_map[mpi] {
|
||||
assert!(moi.index() < bits_per_block);
|
||||
sets.kill_set.add(&moi);
|
||||
});
|
||||
match rvalue.initialization_state() {
|
||||
mir::tcx::RvalueInitializationState::Shallow => {
|
||||
if let LookupResult::Exact(mpi) = rev_lookup.find(lvalue) {
|
||||
for moi in &path_map[mpi] {
|
||||
assert!(moi.index() < bits_per_block);
|
||||
sets.kill_set.add(&moi);
|
||||
}
|
||||
}
|
||||
}
|
||||
mir::tcx::RvalueInitializationState::Deep => {
|
||||
on_lookup_result_bits(tcx,
|
||||
mir,
|
||||
move_data,
|
||||
rev_lookup.find(lvalue),
|
||||
|mpi| for moi in &path_map[mpi] {
|
||||
assert!(moi.index() < bits_per_block);
|
||||
sets.kill_set.add(&moi);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
mir::StatementKind::StorageLive(_) |
|
||||
mir::StatementKind::StorageDead(_) |
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
use rustc::ty::{self, TyCtxt};
|
||||
use rustc::mir::*;
|
||||
use rustc::mir::tcx::RvalueInitializationState;
|
||||
use rustc::util::nodemap::FxHashMap;
|
||||
use rustc_data_structures::indexed_vec::{IndexVec};
|
||||
|
||||
|
|
@ -406,6 +407,12 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
|
|||
match stmt.kind {
|
||||
StatementKind::Assign(ref lval, ref rval) => {
|
||||
self.create_move_path(lval);
|
||||
if let RvalueInitializationState::Shallow = rval.initialization_state() {
|
||||
// Box starts out uninitialized - need to create a separate
|
||||
// move-path for the interior so it will be separate from
|
||||
// the exterior.
|
||||
self.create_move_path(&lval.clone().deref());
|
||||
}
|
||||
self.gather_rvalue(loc, rval);
|
||||
}
|
||||
StatementKind::StorageLive(_) |
|
||||
|
|
|
|||
|
|
@ -561,7 +561,6 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
|||
hir::ExprBox(ref value) => {
|
||||
ExprKind::Box {
|
||||
value: value.to_ref(),
|
||||
value_extents: CodeExtent::Misc(value.id),
|
||||
}
|
||||
}
|
||||
hir::ExprArray(ref fields) => ExprKind::Array { fields: fields.to_ref() },
|
||||
|
|
|
|||
|
|
@ -116,7 +116,6 @@ pub enum ExprKind<'tcx> {
|
|||
},
|
||||
Box {
|
||||
value: ExprRef<'tcx>,
|
||||
value_extents: CodeExtent,
|
||||
},
|
||||
Call {
|
||||
ty: ty::Ty<'tcx>,
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ rustc_errors = { path = "../librustc_errors" }
|
|||
rustc_incremental = { path = "../librustc_incremental" }
|
||||
rustc_llvm = { path = "../librustc_llvm" }
|
||||
rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" }
|
||||
rustc_trans_utils = { path = "../librustc_trans_utils" }
|
||||
serialize = { path = "../libserialize" }
|
||||
syntax = { path = "../libsyntax" }
|
||||
syntax_pos = { path = "../libsyntax_pos" }
|
||||
|
|
|
|||
|
|
@ -8,16 +8,18 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
extern crate rustc_trans_utils;
|
||||
|
||||
use super::archive::{ArchiveBuilder, ArchiveConfig};
|
||||
use super::linker::Linker;
|
||||
use super::rpath::RPathConfig;
|
||||
use super::rpath;
|
||||
use metadata::METADATA_FILENAME;
|
||||
use rustc::session::config::{self, NoDebugInfo, OutputFilenames, Input, OutputType};
|
||||
use rustc::session::config::{self, NoDebugInfo, OutputFilenames, OutputType};
|
||||
use rustc::session::filesearch;
|
||||
use rustc::session::search_paths::PathKind;
|
||||
use rustc::session::Session;
|
||||
use rustc::middle::cstore::{self, LinkMeta, NativeLibrary, LibSource, LinkagePreference,
|
||||
use rustc::middle::cstore::{LinkMeta, NativeLibrary, LibSource, LinkagePreference,
|
||||
NativeLibraryKind};
|
||||
use rustc::middle::dependency_format::Linkage;
|
||||
use CrateTranslation;
|
||||
|
|
@ -44,9 +46,7 @@ use std::process::Command;
|
|||
use std::str;
|
||||
use flate2::Compression;
|
||||
use flate2::write::DeflateEncoder;
|
||||
use syntax::ast;
|
||||
use syntax::attr;
|
||||
use syntax_pos::Span;
|
||||
|
||||
/// The LLVM module name containing crate-metadata. This includes a `.` on
|
||||
/// purpose, so it cannot clash with the name of a user-defined module.
|
||||
|
|
@ -88,55 +88,8 @@ pub const RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET: usize =
|
|||
pub const RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET: usize =
|
||||
RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET + 8;
|
||||
|
||||
|
||||
pub fn find_crate_name(sess: Option<&Session>,
|
||||
attrs: &[ast::Attribute],
|
||||
input: &Input) -> String {
|
||||
let validate = |s: String, span: Option<Span>| {
|
||||
cstore::validate_crate_name(sess, &s, span);
|
||||
s
|
||||
};
|
||||
|
||||
// Look in attributes 100% of the time to make sure the attribute is marked
|
||||
// as used. After doing this, however, we still prioritize a crate name from
|
||||
// the command line over one found in the #[crate_name] attribute. If we
|
||||
// find both we ensure that they're the same later on as well.
|
||||
let attr_crate_name = attrs.iter().find(|at| at.check_name("crate_name"))
|
||||
.and_then(|at| at.value_str().map(|s| (at, s)));
|
||||
|
||||
if let Some(sess) = sess {
|
||||
if let Some(ref s) = sess.opts.crate_name {
|
||||
if let Some((attr, name)) = attr_crate_name {
|
||||
if name != &**s {
|
||||
let msg = format!("--crate-name and #[crate_name] are \
|
||||
required to match, but `{}` != `{}`",
|
||||
s, name);
|
||||
sess.span_err(attr.span, &msg);
|
||||
}
|
||||
}
|
||||
return validate(s.clone(), None);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some((attr, s)) = attr_crate_name {
|
||||
return validate(s.to_string(), Some(attr.span));
|
||||
}
|
||||
if let Input::File(ref path) = *input {
|
||||
if let Some(s) = path.file_stem().and_then(|s| s.to_str()) {
|
||||
if s.starts_with("-") {
|
||||
let msg = format!("crate names cannot start with a `-`, but \
|
||||
`{}` has a leading hyphen", s);
|
||||
if let Some(sess) = sess {
|
||||
sess.err(&msg);
|
||||
}
|
||||
} else {
|
||||
return validate(s.replace("-", "_"), None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"rust_out".to_string()
|
||||
}
|
||||
pub use self::rustc_trans_utils::link::{find_crate_name, filename_for_input,
|
||||
default_output_for_target, invalid_output_for_target};
|
||||
|
||||
pub fn build_link_meta(incremental_hashes_map: &IncrementalHashesMap) -> LinkMeta {
|
||||
let krate_dep_node = &DepNode::new_no_params(DepKind::Krate);
|
||||
|
|
@ -252,37 +205,6 @@ pub fn link_binary(sess: &Session,
|
|||
out_filenames
|
||||
}
|
||||
|
||||
|
||||
/// Returns default crate type for target
|
||||
///
|
||||
/// Default crate type is used when crate type isn't provided neither
|
||||
/// through cmd line arguments nor through crate attributes
|
||||
///
|
||||
/// It is CrateTypeExecutable for all platforms but iOS as there is no
|
||||
/// way to run iOS binaries anyway without jailbreaking and
|
||||
/// interaction with Rust code through static library is the only
|
||||
/// option for now
|
||||
pub fn default_output_for_target(sess: &Session) -> config::CrateType {
|
||||
if !sess.target.target.options.executables {
|
||||
config::CrateTypeStaticlib
|
||||
} else {
|
||||
config::CrateTypeExecutable
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if target supports crate_type as output
|
||||
pub fn invalid_output_for_target(sess: &Session,
|
||||
crate_type: config::CrateType) -> bool {
|
||||
match (sess.target.target.options.dynamic_linking,
|
||||
sess.target.target.options.executables, crate_type) {
|
||||
(false, _, config::CrateTypeCdylib) |
|
||||
(false, _, config::CrateTypeProcMacro) |
|
||||
(false, _, config::CrateTypeDylib) => true,
|
||||
(_, false, config::CrateTypeExecutable) => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
fn is_writeable(p: &Path) -> bool {
|
||||
match p.metadata() {
|
||||
Err(..) => true,
|
||||
|
|
@ -299,42 +221,6 @@ fn filename_for_metadata(sess: &Session, crate_name: &str, outputs: &OutputFilen
|
|||
out_filename
|
||||
}
|
||||
|
||||
pub fn filename_for_input(sess: &Session,
|
||||
crate_type: config::CrateType,
|
||||
crate_name: &str,
|
||||
outputs: &OutputFilenames) -> PathBuf {
|
||||
let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename);
|
||||
|
||||
match crate_type {
|
||||
config::CrateTypeRlib => {
|
||||
outputs.out_directory.join(&format!("lib{}.rlib", libname))
|
||||
}
|
||||
config::CrateTypeCdylib |
|
||||
config::CrateTypeProcMacro |
|
||||
config::CrateTypeDylib => {
|
||||
let (prefix, suffix) = (&sess.target.target.options.dll_prefix,
|
||||
&sess.target.target.options.dll_suffix);
|
||||
outputs.out_directory.join(&format!("{}{}{}", prefix, libname,
|
||||
suffix))
|
||||
}
|
||||
config::CrateTypeStaticlib => {
|
||||
let (prefix, suffix) = (&sess.target.target.options.staticlib_prefix,
|
||||
&sess.target.target.options.staticlib_suffix);
|
||||
outputs.out_directory.join(&format!("{}{}{}", prefix, libname,
|
||||
suffix))
|
||||
}
|
||||
config::CrateTypeExecutable => {
|
||||
let suffix = &sess.target.target.options.exe_suffix;
|
||||
let out_filename = outputs.path(OutputType::Exe);
|
||||
if suffix.is_empty() {
|
||||
out_filename.to_path_buf()
|
||||
} else {
|
||||
out_filename.with_extension(&suffix[1..])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn each_linked_rlib(sess: &Session,
|
||||
f: &mut FnMut(CrateNum, &Path)) -> Result<(), String> {
|
||||
let crates = sess.cstore.used_crates(LinkagePreference::RequireStatic).into_iter();
|
||||
|
|
|
|||
|
|
@ -1356,6 +1356,16 @@ fn start_executing_work(sess: &Session,
|
|||
maybe_start_llvm_timer(&item, &mut llvm_start_time);
|
||||
main_thread_worker_state = MainThreadWorkerState::LLVMing;
|
||||
spawn_work(cgcx, item);
|
||||
} else {
|
||||
// There is no unstarted work, so let the main thread
|
||||
// take over for a running worker. Otherwise the
|
||||
// implicit token would just go to waste.
|
||||
// We reduce the `running` counter by one. The
|
||||
// `tokens.truncate()` below will take care of
|
||||
// giving the Token back.
|
||||
debug_assert!(running > 0);
|
||||
running -= 1;
|
||||
main_thread_worker_state = MainThreadWorkerState::LLVMing;
|
||||
}
|
||||
}
|
||||
MainThreadWorkerState::Translating => {
|
||||
|
|
|
|||
15
src/librustc_trans_utils/Cargo.toml
Normal file
15
src/librustc_trans_utils/Cargo.toml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
[package]
|
||||
authors = ["The Rust Project Developers"]
|
||||
name = "rustc_trans_utils"
|
||||
version = "0.0.0"
|
||||
|
||||
[lib]
|
||||
name = "rustc_trans_utils"
|
||||
path = "lib.rs"
|
||||
crate-type = ["dylib"]
|
||||
test = false
|
||||
|
||||
[dependencies]
|
||||
rustc = { path = "../librustc" }
|
||||
syntax = { path = "../libsyntax" }
|
||||
syntax_pos = { path = "../libsyntax_pos" }
|
||||
38
src/librustc_trans_utils/lib.rs
Normal file
38
src/librustc_trans_utils/lib.rs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright 2017 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! # Note
|
||||
//!
|
||||
//! This API is completely unstable and subject to change.
|
||||
|
||||
#![crate_name = "rustc_trans_utils"]
|
||||
#![crate_type = "dylib"]
|
||||
#![crate_type = "rlib"]
|
||||
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
|
||||
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
|
||||
html_root_url = "https://doc.rust-lang.org/nightly/")]
|
||||
#![deny(warnings)]
|
||||
|
||||
#![feature(box_patterns)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(const_fn)]
|
||||
#![feature(custom_attribute)]
|
||||
#![allow(unused_attributes)]
|
||||
#![feature(i128_type)]
|
||||
#![feature(quote)]
|
||||
#![feature(rustc_diagnostic_macros)]
|
||||
#![feature(slice_patterns)]
|
||||
#![feature(conservative_impl_trait)]
|
||||
|
||||
extern crate rustc;
|
||||
extern crate syntax;
|
||||
extern crate syntax_pos;
|
||||
|
||||
pub mod link;
|
||||
154
src/librustc_trans_utils/link.rs
Normal file
154
src/librustc_trans_utils/link.rs
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
// Copyright 2017 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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use rustc::session::config::{self, /*NoDebugInfo,*/ OutputFilenames, Input, OutputType};
|
||||
/*use rustc::session::filesearch;
|
||||
use rustc::session::search_paths::PathKind;
|
||||
*/use rustc::session::Session;
|
||||
use rustc::middle::cstore;/*::{self, LinkMeta, NativeLibrary, LibSource, LinkagePreference,
|
||||
NativeLibraryKind};*/
|
||||
/*use rustc::middle::dependency_format::Linkage;
|
||||
use rustc::util::common::time;
|
||||
use rustc::util::fs::fix_windows_verbatim_for_gcc;
|
||||
use rustc::dep_graph::{DepKind, DepNode};
|
||||
use rustc::hir::def_id::CrateNum;
|
||||
use rustc::hir::svh::Svh;
|
||||
use rustc_back::tempdir::TempDir;
|
||||
use rustc_back::{PanicStrategy, RelroLevel};
|
||||
use rustc_incremental::IncrementalHashesMap;*/
|
||||
|
||||
/*use std::ascii;
|
||||
use std::char;
|
||||
use std::env;
|
||||
use std::ffi::OsString;
|
||||
use std::fs;
|
||||
use std::io::{self, Read, Write};
|
||||
use std::mem;
|
||||
*/use std::path::PathBuf;/*{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
use std::str;*/
|
||||
use syntax::ast;
|
||||
//use syntax::attr;
|
||||
use syntax_pos::Span;
|
||||
|
||||
pub fn find_crate_name(sess: Option<&Session>,
|
||||
attrs: &[ast::Attribute],
|
||||
input: &Input) -> String {
|
||||
let validate = |s: String, span: Option<Span>| {
|
||||
cstore::validate_crate_name(sess, &s, span);
|
||||
s
|
||||
};
|
||||
|
||||
// Look in attributes 100% of the time to make sure the attribute is marked
|
||||
// as used. After doing this, however, we still prioritize a crate name from
|
||||
// the command line over one found in the #[crate_name] attribute. If we
|
||||
// find both we ensure that they're the same later on as well.
|
||||
let attr_crate_name = attrs.iter().find(|at| at.check_name("crate_name"))
|
||||
.and_then(|at| at.value_str().map(|s| (at, s)));
|
||||
|
||||
if let Some(sess) = sess {
|
||||
if let Some(ref s) = sess.opts.crate_name {
|
||||
if let Some((attr, name)) = attr_crate_name {
|
||||
if name != &**s {
|
||||
let msg = format!("--crate-name and #[crate_name] are \
|
||||
required to match, but `{}` != `{}`",
|
||||
s, name);
|
||||
sess.span_err(attr.span, &msg);
|
||||
}
|
||||
}
|
||||
return validate(s.clone(), None);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some((attr, s)) = attr_crate_name {
|
||||
return validate(s.to_string(), Some(attr.span));
|
||||
}
|
||||
if let Input::File(ref path) = *input {
|
||||
if let Some(s) = path.file_stem().and_then(|s| s.to_str()) {
|
||||
if s.starts_with("-") {
|
||||
let msg = format!("crate names cannot start with a `-`, but \
|
||||
`{}` has a leading hyphen", s);
|
||||
if let Some(sess) = sess {
|
||||
sess.err(&msg);
|
||||
}
|
||||
} else {
|
||||
return validate(s.replace("-", "_"), None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"rust_out".to_string()
|
||||
}
|
||||
|
||||
pub fn filename_for_input(sess: &Session,
|
||||
crate_type: config::CrateType,
|
||||
crate_name: &str,
|
||||
outputs: &OutputFilenames) -> PathBuf {
|
||||
let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename);
|
||||
|
||||
match crate_type {
|
||||
config::CrateTypeRlib => {
|
||||
outputs.out_directory.join(&format!("lib{}.rlib", libname))
|
||||
}
|
||||
config::CrateTypeCdylib |
|
||||
config::CrateTypeProcMacro |
|
||||
config::CrateTypeDylib => {
|
||||
let (prefix, suffix) = (&sess.target.target.options.dll_prefix,
|
||||
&sess.target.target.options.dll_suffix);
|
||||
outputs.out_directory.join(&format!("{}{}{}", prefix, libname,
|
||||
suffix))
|
||||
}
|
||||
config::CrateTypeStaticlib => {
|
||||
let (prefix, suffix) = (&sess.target.target.options.staticlib_prefix,
|
||||
&sess.target.target.options.staticlib_suffix);
|
||||
outputs.out_directory.join(&format!("{}{}{}", prefix, libname,
|
||||
suffix))
|
||||
}
|
||||
config::CrateTypeExecutable => {
|
||||
let suffix = &sess.target.target.options.exe_suffix;
|
||||
let out_filename = outputs.path(OutputType::Exe);
|
||||
if suffix.is_empty() {
|
||||
out_filename.to_path_buf()
|
||||
} else {
|
||||
out_filename.with_extension(&suffix[1..])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns default crate type for target
|
||||
///
|
||||
/// Default crate type is used when crate type isn't provided neither
|
||||
/// through cmd line arguments nor through crate attributes
|
||||
///
|
||||
/// It is CrateTypeExecutable for all platforms but iOS as there is no
|
||||
/// way to run iOS binaries anyway without jailbreaking and
|
||||
/// interaction with Rust code through static library is the only
|
||||
/// option for now
|
||||
pub fn default_output_for_target(sess: &Session) -> config::CrateType {
|
||||
if !sess.target.target.options.executables {
|
||||
config::CrateTypeStaticlib
|
||||
} else {
|
||||
config::CrateTypeExecutable
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if target supports crate_type as output
|
||||
pub fn invalid_output_for_target(sess: &Session,
|
||||
crate_type: config::CrateType) -> bool {
|
||||
match (sess.target.target.options.dynamic_linking,
|
||||
sess.target.target.options.executables, crate_type) {
|
||||
(false, _, config::CrateTypeCdylib) |
|
||||
(false, _, config::CrateTypeProcMacro) |
|
||||
(false, _, config::CrateTypeDylib) => true,
|
||||
(_, false, config::CrateTypeExecutable) => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
|
@ -15,3 +15,4 @@ rustc_driver = { path = "../librustc_driver" }
|
|||
|
||||
[features]
|
||||
jemalloc = ["rustc_back/jemalloc"]
|
||||
llvm = ["rustc_driver/llvm"]
|
||||
|
|
|
|||
|
|
@ -34,10 +34,9 @@ fn foo(i: i32) {
|
|||
// let _1: D;
|
||||
// let _2: i32;
|
||||
// let _3: &'6_2rce i32;
|
||||
// let _7: &'6_4rce i32;
|
||||
// let _6: &'6_4rce i32;
|
||||
// let mut _4: ();
|
||||
// let mut _5: i32;
|
||||
// let mut _6: ();
|
||||
// bb0: {
|
||||
// StorageLive(_1);
|
||||
// _1 = D::{{constructor}}(const 0i32,);
|
||||
|
|
@ -51,10 +50,10 @@ fn foo(i: i32) {
|
|||
// }
|
||||
// bb1: {
|
||||
// StorageDead(_5);
|
||||
// StorageLive(_7);
|
||||
// _7 = &'6_4rce _2;
|
||||
// StorageLive(_6);
|
||||
// _6 = &'6_4rce _2;
|
||||
// _0 = ();
|
||||
// StorageDead(_7);
|
||||
// StorageDead(_6);
|
||||
// EndRegion('6_4rce);
|
||||
// StorageDead(_3);
|
||||
// EndRegion('6_2rce);
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
|
|||
// let mut _2: ();
|
||||
// let mut _3: [closure@NodeId(18) d:&'19mce D];
|
||||
// let mut _4: &'19mce D;
|
||||
// let mut _5: ();
|
||||
// bb0: {
|
||||
// StorageLive(_1);
|
||||
// _1 = D::{{constructor}}(const 0i32,);
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
|
|||
// let mut _2: ();
|
||||
// let mut _3: [closure@NodeId(22) d:&'23mce D];
|
||||
// let mut _4: &'23mce D;
|
||||
// let mut _5: ();
|
||||
// bb0: {
|
||||
// StorageLive(_1);
|
||||
// _1 = D::{{constructor}}(const 0i32,);
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
|
|||
// let mut _2: ();
|
||||
// let mut _3: [closure@NodeId(22) d:D];
|
||||
// let mut _4: D;
|
||||
// let mut _5: ();
|
||||
//
|
||||
// bb0: {
|
||||
// StorageLive(_1);
|
||||
|
|
@ -77,7 +76,6 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
|
|||
// let mut _0: i32;
|
||||
// let _2: &'14_0rce D;
|
||||
// let mut _3: i32;
|
||||
// let mut _4: ();
|
||||
//
|
||||
// bb0: {
|
||||
// StorageLive(_2);
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ fn foo<F>(f: F) where F: FnOnce() -> i32 {
|
|||
// let mut _3: ();
|
||||
// let mut _4: [closure@NodeId(22) r:&'6_1rce D];
|
||||
// let mut _5: &'6_1rce D;
|
||||
// let mut _6: ();
|
||||
// bb0: {
|
||||
// StorageLive(_1);
|
||||
// _1 = D::{{constructor}}(const 0i32,);
|
||||
|
|
|
|||
|
|
@ -39,8 +39,7 @@ impl S {
|
|||
// let mut _2: S;
|
||||
// let mut _3: S;
|
||||
// let mut _4: S;
|
||||
// let mut _5: ();
|
||||
// let mut _6: bool;
|
||||
// let mut _5: bool;
|
||||
//
|
||||
// bb0: {
|
||||
// END rustc.node4.ElaborateDrops.after.mir
|
||||
|
|
@ -50,9 +49,8 @@ impl S {
|
|||
// let mut _2: S;
|
||||
// let mut _3: ();
|
||||
// let mut _4: S;
|
||||
// let mut _5: ();
|
||||
// let mut _6: S;
|
||||
// let mut _7: bool;
|
||||
// let mut _5: S;
|
||||
// let mut _6: bool;
|
||||
//
|
||||
// bb0: {
|
||||
// END rustc.node13.ElaborateDrops.after.mir
|
||||
|
|
|
|||
|
|
@ -161,6 +161,11 @@ fn vec_simple(a: &Allocator) {
|
|||
let _x = vec![a.alloc(), a.alloc(), a.alloc(), a.alloc()];
|
||||
}
|
||||
|
||||
#[allow(unreachable_code)]
|
||||
fn vec_unreachable(a: &Allocator) {
|
||||
let _x = vec![a.alloc(), a.alloc(), a.alloc(), return];
|
||||
}
|
||||
|
||||
fn run_test<F>(mut f: F)
|
||||
where F: FnMut(&Allocator)
|
||||
{
|
||||
|
|
@ -209,6 +214,7 @@ fn main() {
|
|||
|
||||
run_test(|a| array_simple(a));
|
||||
run_test(|a| vec_simple(a));
|
||||
run_test(|a| vec_unreachable(a));
|
||||
|
||||
run_test(|a| struct_dynamic_drop(a, false, false, false));
|
||||
run_test(|a| struct_dynamic_drop(a, false, false, true));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue