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"
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",
"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",
"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"
"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"
pub profiler: bool,
// llvm codegen options
+ pub llvm_enabled: bool,
pub llvm_assertions: bool,
pub llvm_optimize: bool,
pub llvm_release_debuginfo: bool,
#[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>,
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;
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);
# =============================================================================
[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
if self.config.use_jemalloc {
features.push_str(" jemalloc");
}
+ if self.config.llvm_enabled {
+ features.push_str(" llvm");
+ }
features
}
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) {
/// 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.
}
}
}
+
+/// 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()
+}
}
}
+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>
}
}
}
+
+ #[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> {
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" }
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"]
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};
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;
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;
// 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) => {
};
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,
println!("Pre-trans");
tcx.print_debug_stats();
}
+
+ #[cfg(feature="llvm")]
let trans = phase_4_translate_to_llvm(tcx, analysis, incremental_hashes_map,
&outputs);
}
}
+ #[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);
- controller_entry_point!(compilation_done,
- sess,
- CompileState::state_when_compilation_done(input, sess, outdir, output),
- Ok(()));
+ 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(())
+ Ok(())
+ }
}
fn keep_hygiene_data(sess: &Session) -> bool {
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>,
}
resolutions: None,
analysis: None,
tcx: None,
+ #[cfg(feature="llvm")]
trans: None,
}
}
}
}
-
+ #[cfg(feature="llvm")]
fn state_after_llvm(input: &'a Input,
session: &'tcx Session,
out_dir: &'a Option<PathBuf>,
}
}
+ #[cfg(feature="llvm")]
fn state_when_compilation_done(input: &'a Input,
session: &'tcx Session,
out_dir: &'a Option<PathBuf>,
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);
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);
/// 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,
/// 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) {
/// 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) {
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);
}
}
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();
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 `{}`",
#![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;
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]
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};
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;
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;
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;
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>>,
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();
}
};
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;
Compilation::Continue
}
+ #[cfg_attr(not(feature="llvm"), allow(unused_mut))]
fn no_input(&mut self,
matches: &getopts::Matches,
sopts: &config::Options,
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 =
};
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()
}
PrintRequest::RelocationModels => {
println!("Available relocation models:");
+ #[cfg(feature="llvm")]
for &(name, _) in RELOC_MODEL_ARGS.iter() {
println!(" {}", name);
}
}
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")
}
}
}
println!("commit-date: {}", unw(commit_date_str()));
println!("host: {}", config::host_triple());
println!("release: {}", unw(release_str()));
+ #[cfg(feature="llvm")]
rustc_trans::print_version();
}
}
}
if cg_flags.contains(&"passes=list".to_string()) {
+ #[cfg(feature="llvm")]
rustc_trans::print_passes();
return None;
}
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);
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;
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 {
}
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);
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;
/// 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>,
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
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.
});
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
}
extent_span: extent.1.span,
needs_cleanup: false,
drops: vec![],
- free: None,
cached_generator_drop: None,
cached_exits: FxHashMap()
});
});
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.
// 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];
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.
}
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;
};
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)
}
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,
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).
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
- }
-}
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));
}
}
on_all_children_bits(tcx, mir, move_data,
path,
- |moi| callback(moi, DropFlagState::Absent))
+ |mpi| callback(mpi, DropFlagState::Absent))
}
let block = &mir[loc.block];
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(_) |
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
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;
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(_) |
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};
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(_) |
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() },
},
Box {
value: ExprRef<'tcx>,
- value_extents: CodeExtent,
},
Call {
ty: ty::Ty<'tcx>,
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" }
// 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;
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.
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);
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,
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();
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 => {
--- /dev/null
+[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" }
--- /dev/null
+// 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;
--- /dev/null
+// 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
+ }
+}
[features]
jemalloc = ["rustc_back/jemalloc"]
+llvm = ["rustc_driver/llvm"]
// 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,);
// }
// 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);
// 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,);
// 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,);
// let mut _2: ();
// let mut _3: [closure@NodeId(22) d:D];
// let mut _4: D;
-// let mut _5: ();
//
// bb0: {
// StorageLive(_1);
// let mut _0: i32;
// let _2: &'14_0rce D;
// let mut _3: i32;
-// let mut _4: ();
//
// bb0: {
// StorageLive(_2);
// 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,);
// 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
// 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
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)
{
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));