From 315de9c58f15612ffacac6f264e50f8f57181080 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Wed, 9 Aug 2017 00:47:38 +0200 Subject: [PATCH 01/10] Put `intrinsics::unreachable` on a possible path to stabilization Mark it with the `unreachable` feature and put it into the `mem` module. This is a pretty straight-forward API that can already be simulated in stable Rust by using `transmute` to create an uninhabited enum that can be matched. --- src/libcore/intrinsics.rs | 8 +++++--- src/libcore/mem.rs | 11 +++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 65c18d6d7772..fdca8d00d7a7 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -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. diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 866296a56703..55b34fe81ed5 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -942,3 +942,14 @@ impl ::fmt::Debug for ManuallyDrop { } } } + +/// 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. +#[unstable(feature = "unreachable", issue = "0")] +pub unsafe fn unreachable() -> ! { + intrinsics::unreachable() +} From 5704b07667fddb415a1df202885f5ffabe386ff2 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Wed, 9 Aug 2017 01:03:50 +0200 Subject: [PATCH 02/10] `mem::unreachable`: Add tracking issue --- src/libcore/mem.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 55b34fe81ed5..045720b0268a 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -949,7 +949,7 @@ impl ::fmt::Debug for ManuallyDrop { /// 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. -#[unstable(feature = "unreachable", issue = "0")] +#[unstable(feature = "unreachable", issue = "43751")] pub unsafe fn unreachable() -> ! { intrinsics::unreachable() } From 07149e03f45194a8fdb12c616c1f221d5186e1e5 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 9 Aug 2017 18:18:48 +0200 Subject: [PATCH 03/10] trans-scheduler: Let main thread take over for other worker. --- src/librustc_trans/back/write.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 0d5fe6c0ae95..94cae37761fe 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -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 => { From 17d2bcd162e59f35c9252f6822fe7045e59ac1b9 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Wed, 9 Aug 2017 22:23:27 +0300 Subject: [PATCH 04/10] For box expressions, use NZ drop instead of a free block This falls naturally out of making drop elaboration work with `box` expressions, which is probably required for sane MIR borrow-checking. This is a pure refactoring with no intentional functional effects. --- src/librustc/mir/tcx.rs | 15 +++ src/librustc_mir/build/expr/as_rvalue.rs | 14 +-- src/librustc_mir/build/scope.rs | 118 +----------------- .../dataflow/drop_flag_effects.rs | 26 ++-- src/librustc_mir/dataflow/impls/mod.rs | 31 +++-- src/librustc_mir/dataflow/move_paths/mod.rs | 7 ++ src/librustc_mir/hair/cx/expr.rs | 1 - src/librustc_mir/hair/mod.rs | 1 - src/test/mir-opt/end_region_4.rs | 9 +- src/test/mir-opt/end_region_5.rs | 1 - src/test/mir-opt/end_region_6.rs | 1 - src/test/mir-opt/end_region_7.rs | 2 - src/test/mir-opt/end_region_8.rs | 1 - src/test/mir-opt/issue-41110.rs | 8 +- src/test/run-pass/dynamic-drop.rs | 6 + 15 files changed, 84 insertions(+), 157 deletions(-) diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index 1af80771fb95..a801804d502a 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -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> @@ -206,6 +211,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> { diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 2512291f1a44..8974c4ec1fbf 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -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); diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index ccba87a4d26a..a4a89a7f8185 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -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>, - /// 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>, - /// The cache for drop chain on “normal” exit into a particular BasicBlock. cached_exits: FxHashMap<(BasicBlock, CodeExtent), BasicBlock>, } @@ -170,22 +152,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). - 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: Option -} - #[derive(Clone, Debug)] pub struct BreakableScope<'tcx> { /// Extent of the loop @@ -224,9 +190,6 @@ impl<'tcx> Scope<'tcx> { *cached_block = None; } } - if let Some(ref mut freedata) = self.free { - freedata.cached_block = None; - } } /// Returns the cached entrypoint for diverging exit from this scope. @@ -242,8 +205,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.expect("free cache is not filled")) } else { None } @@ -333,7 +294,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { extent_span: extent.1.span, needs_cleanup: false, drops: vec![], - free: None, cached_exits: FxHashMap() }); } @@ -382,7 +342,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. @@ -415,13 +374,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(span), free); - block = next; - } } } let scope = &self.scopes[len - scope_count]; @@ -607,36 +559,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: None - }); - return; - } - } - span_bug!(span, "extent {:?} not in scope to free {:?}", extent, value); - } - // Other // ===== /// Creates a path that performs all required cleanup for unwinding. @@ -650,7 +572,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; @@ -679,7 +600,7 @@ 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); + hir.tcx(), cfg, scope.extent_span, scope, target); } Some(target) } @@ -805,9 +726,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) @@ -832,19 +752,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 { - 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 = 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). @@ -888,24 +795,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 - } -} diff --git a/src/librustc_mir/dataflow/drop_flag_effects.rs b/src/librustc_mir/dataflow/drop_flag_effects.rs index 24d5aa9e46bf..890fe3c091ab 100644 --- a/src/librustc_mir/dataflow/drop_flag_effects.rs +++ b/src/librustc_mir/dataflow/drop_flag_effects.rs @@ -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 diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs index d5bdc71a705c..d68e64abe4f2 100644 --- a/src/librustc_mir/dataflow/impls/mod.rs +++ b/src/librustc_mir/dataflow/impls/mod.rs @@ -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(_) | diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs index c2945d465927..20a61418d85a 100644 --- a/src/librustc_mir/dataflow/move_paths/mod.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -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(_) | diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 06a0c4ff213d..b7fc37675e29 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -559,7 +559,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() }, diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index bb11cce74875..e46c18b2dcfe 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -116,7 +116,6 @@ pub enum ExprKind<'tcx> { }, Box { value: ExprRef<'tcx>, - value_extents: CodeExtent, }, Call { ty: ty::Ty<'tcx>, diff --git a/src/test/mir-opt/end_region_4.rs b/src/test/mir-opt/end_region_4.rs index bfb1b3b65289..0b34231b4eec 100644 --- a/src/test/mir-opt/end_region_4.rs +++ b/src/test/mir-opt/end_region_4.rs @@ -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); diff --git a/src/test/mir-opt/end_region_5.rs b/src/test/mir-opt/end_region_5.rs index 773a348a9397..e51bb9350db6 100644 --- a/src/test/mir-opt/end_region_5.rs +++ b/src/test/mir-opt/end_region_5.rs @@ -33,7 +33,6 @@ fn foo(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,); diff --git a/src/test/mir-opt/end_region_6.rs b/src/test/mir-opt/end_region_6.rs index 112c93843e04..c55e6d105cbd 100644 --- a/src/test/mir-opt/end_region_6.rs +++ b/src/test/mir-opt/end_region_6.rs @@ -33,7 +33,6 @@ fn foo(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,); diff --git a/src/test/mir-opt/end_region_7.rs b/src/test/mir-opt/end_region_7.rs index 913986ae816a..9c8e3ec08d49 100644 --- a/src/test/mir-opt/end_region_7.rs +++ b/src/test/mir-opt/end_region_7.rs @@ -33,7 +33,6 @@ fn foo(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) where F: FnOnce() -> i32 { // let mut _0: i32; // let _2: &'14_0rce D; // let mut _3: i32; -// let mut _4: (); // // bb0: { // StorageLive(_2); diff --git a/src/test/mir-opt/end_region_8.rs b/src/test/mir-opt/end_region_8.rs index dc8f8ea11f51..b4dbec5cd2dd 100644 --- a/src/test/mir-opt/end_region_8.rs +++ b/src/test/mir-opt/end_region_8.rs @@ -35,7 +35,6 @@ fn foo(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,); diff --git a/src/test/mir-opt/issue-41110.rs b/src/test/mir-opt/issue-41110.rs index 1daa18256dce..3a8b5c449c22 100644 --- a/src/test/mir-opt/issue-41110.rs +++ b/src/test/mir-opt/issue-41110.rs @@ -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 diff --git a/src/test/run-pass/dynamic-drop.rs b/src/test/run-pass/dynamic-drop.rs index bdcd3eecc696..1aba47af1e9d 100644 --- a/src/test/run-pass/dynamic-drop.rs +++ b/src/test/run-pass/dynamic-drop.rs @@ -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(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)); From faadd35ee5074aa85fa6e2078650b3e6f1fd4662 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Fri, 11 Aug 2017 03:42:36 +0200 Subject: [PATCH 05/10] Add `#[inline]` to `mem::unreachable` --- src/libcore/mem.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 045720b0268a..6f7adbe1e7a0 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -949,6 +949,7 @@ impl ::fmt::Debug for ManuallyDrop { /// 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() From e152a1620b9fb91a70c629059df482872c687522 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sun, 18 Jun 2017 16:00:10 +0200 Subject: [PATCH 06/10] Build support for no llvm --- src/bootstrap/config.rs | 4 ++++ src/bootstrap/config.toml.example | 4 ++++ src/bootstrap/lib.rs | 3 +++ src/bootstrap/native.rs | 6 ++++++ 4 files changed, 17 insertions(+) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 5d898cb716dc..ec57bb069e0a 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -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, ccache: Option, ninja: Option, assertions: Option, @@ -265,6 +267,7 @@ struct TomlTarget { impl Config { pub fn parse(build: &str, file: Option) -> 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); diff --git a/src/bootstrap/config.toml.example b/src/bootstrap/config.toml.example index 9314135050f0..19678dc77937 100644 --- a/src/bootstrap/config.toml.example +++ b/src/bootstrap/config.toml.example @@ -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 diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 5b5ef3f07f98..a8485d1d152d 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -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 } diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index ee0eca5d4824..59efbd5c4d20 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -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) { From b43c02b0aad08fe8ffef702423bc60e2fa869eee Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Thu, 20 Jul 2017 14:56:53 +0200 Subject: [PATCH 07/10] Make librustc_driver work without librustc_trans --- src/Cargo.lock | 7 +++++ src/librustc_driver/Cargo.toml | 7 ++++- src/librustc_driver/lib.rs | 49 ++++++++++++++++++++++++++++++++-- src/librustc_driver/test.rs | 2 +- src/rustc/Cargo.toml | 1 + 5 files changed, 62 insertions(+), 4 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 38897993d435..2e3b54f00bc1 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -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,6 +1338,7 @@ 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", @@ -2141,6 +2147,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" diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index f1bdf0b2c3d3..c8ea09f4687b 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -29,9 +29,14 @@ 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_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"] diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 6f0a50180d79..2a3da956468e 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -28,6 +28,9 @@ #![feature(rustc_diagnostic_macros)] #![feature(set_stdio)] +#[cfg(not(feature="llvm"))] +extern crate ar; + extern crate arena; extern crate getopts; extern crate graphviz; @@ -49,6 +52,7 @@ 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_typeck; extern crate serialize; @@ -74,6 +78,8 @@ 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; use rustc_metadata::locator; use rustc_metadata::cstore::CStore; use rustc::util::common::{time, ErrorReported}; @@ -151,6 +157,45 @@ pub fn run(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 MetadataLoader for NoLLvmMetadataLoader { + fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result, 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() == METADATA_FILENAME { + let mut buf = Vec::new(); + io::copy(&mut entry, &mut buf).unwrap(); + let buf: OwningRef, [u8]> = OwningRef::new(buf).into(); + return Ok(buf.erase_owner()); + } + } + + Err("Couldnt find metadata section".to_string()) + } + + fn get_dylib_metadata(&self, + target: &Target, + filename: &Path) + -> Result, 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. @@ -197,7 +242,7 @@ 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())); @@ -477,7 +522,7 @@ 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, diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 8668ab301543..b187cdaa480e 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -106,7 +106,7 @@ fn test_env(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, diff --git a/src/rustc/Cargo.toml b/src/rustc/Cargo.toml index 4452f4a2f446..d185c061d5bd 100644 --- a/src/rustc/Cargo.toml +++ b/src/rustc/Cargo.toml @@ -15,3 +15,4 @@ rustc_driver = { path = "../librustc_driver" } [features] jemalloc = ["rustc_back/jemalloc"] +llvm = ["rustc_driver/llvm"] From b7314c7cafc657afa6b98eb9c4958e56a82129bb Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 5 Aug 2017 16:55:23 +0200 Subject: [PATCH 08/10] Actually make rustc_driver compile without llvm --- src/Cargo.lock | 21 ++++ src/librustc_driver/Cargo.toml | 1 + src/librustc_driver/driver.rs | 86 ++++++++++------ src/librustc_driver/lib.rs | 25 ++++- src/librustc_driver/test.rs | 2 + src/librustc_trans/Cargo.toml | 1 + src/librustc_trans/back/link.rs | 125 +--------------------- src/librustc_trans_utils/Cargo.toml | 25 +++++ src/librustc_trans_utils/lib.rs | 38 +++++++ src/librustc_trans_utils/link.rs | 154 ++++++++++++++++++++++++++++ 10 files changed, 324 insertions(+), 154 deletions(-) create mode 100644 src/librustc_trans_utils/Cargo.toml create mode 100644 src/librustc_trans_utils/lib.rs create mode 100644 src/librustc_trans_utils/link.rs diff --git a/src/Cargo.lock b/src/Cargo.lock index 2e3b54f00bc1..4940dfd0e655 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1360,6 +1360,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", @@ -1551,6 +1552,26 @@ 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", + "rustc_allocator 0.0.0", + "rustc_back 0.0.0", + "rustc_bitflags 0.0.0", + "rustc_const_math 0.0.0", + "rustc_data_structures 0.0.0", + "rustc_errors 0.0.0", + "rustc_incremental 0.0.0", + "rustc_llvm 0.0.0", + "rustc_platform_intrinsics 0.0.0", "serialize 0.0.0", "syntax 0.0.0", "syntax_pos 0.0.0", diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index c8ea09f4687b..04c0f9b35184 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -30,6 +30,7 @@ rustc_privacy = { path = "../librustc_privacy" } rustc_resolve = { path = "../librustc_resolve" } rustc_save_analysis = { path = "../librustc_save_analysis" } 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" } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index c689b3d241c1..be257c8524b6 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -31,7 +31,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; @@ -113,7 +115,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,8 +209,12 @@ 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); + #[cfg(not(feature="llvm"))] + let trans = { panic!("LLVM not supported by this rustc."); () }; if log_enabled!(::log::LogLevel::Info) { println!("Post-trans"); @@ -225,34 +232,42 @@ pub fn compile_input(sess: &Session, })?? }; - if sess.opts.debugging_opts.print_type_sizes { - sess.code_stats.borrow().print_type_sizes(); + #[cfg(not(feature="llvm"))] + unreachable!(); + + #[cfg(feature="llvm")] + { + if sess.opts.debugging_opts.print_type_sizes { + sess.code_stats.borrow().print_type_sizes(); + } + + let (phase5_result, trans) = phase_5_run_llvm_passes(sess, trans); + + controller_entry_point!(after_llvm, + sess, + CompileState::state_after_llvm(input, sess, outdir, output, &trans), + phase5_result); + phase5_result?; + + phase_6_link_output(sess, &trans, &outputs); + + // 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(()) } - - let (phase5_result, trans) = phase_5_run_llvm_passes(sess, trans); - - controller_entry_point!(after_llvm, - sess, - CompileState::state_after_llvm(input, sess, outdir, output, &trans), - phase5_result); - phase5_result?; - - phase_6_link_output(sess, &trans, &outputs); - - // 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(()) } fn keep_hygiene_data(sess: &Session) -> bool { @@ -360,6 +375,7 @@ pub struct CompileState<'a, 'tcx: 'a> { pub resolutions: Option<&'a Resolutions>, pub analysis: Option<&'a ty::CrateAnalysis>, pub tcx: Option>, + #[cfg(feature="llvm")] pub trans: Option<&'a trans::CrateTranslation>, } @@ -386,6 +402,7 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> { resolutions: None, analysis: None, tcx: None, + #[cfg(feature="llvm")] trans: None, } } @@ -474,7 +491,7 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> { } } - + #[cfg(feature="llvm")] fn state_after_llvm(input: &'a Input, session: &'tcx Session, out_dir: &'a Option, @@ -906,6 +923,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 +936,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); @@ -1063,6 +1082,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, @@ -1084,6 +1104,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) { @@ -1102,6 +1123,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) { @@ -1123,7 +1145,7 @@ 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); } } @@ -1233,7 +1255,7 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec Vec(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(); } @@ -249,10 +258,12 @@ pub fn run_compiler<'a>(args: &[String], 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; @@ -528,9 +539,11 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { 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 = @@ -723,14 +736,14 @@ 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() @@ -779,6 +792,7 @@ impl RustcDefaultCalls { } PrintRequest::RelocationModels => { println!("Available relocation models:"); + #[cfg(features="llvm")] for &(name, _) in RELOC_MODEL_ARGS.iter() { println!(" {}", name); } @@ -786,13 +800,17 @@ impl RustcDefaultCalls { } PrintRequest::CodeModels => { println!("Available code models:"); + #[cfg(features="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") } } } @@ -831,6 +849,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(); } } @@ -1128,6 +1147,7 @@ pub fn handle_options(args: &[String]) -> Option { } if cg_flags.contains(&"passes=list".to_string()) { + #[cfg(feature="llvm")] rustc_trans::print_passes(); return None; } @@ -1255,6 +1275,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); diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index b187cdaa480e..7f65a8b97cd6 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -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; @@ -113,6 +114,7 @@ fn test_env(source_string: &str, 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 { diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml index ed9321cc3f3a..4a92a5798604 100644 --- a/src/librustc_trans/Cargo.toml +++ b/src/librustc_trans/Cargo.toml @@ -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" } diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 5e85771217b9..e2db1721b262 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -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,7 @@ 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| { - 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 +204,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 +220,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(); diff --git a/src/librustc_trans_utils/Cargo.toml b/src/librustc_trans_utils/Cargo.toml new file mode 100644 index 000000000000..4fa32389b710 --- /dev/null +++ b/src/librustc_trans_utils/Cargo.toml @@ -0,0 +1,25 @@ +[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" } +rustc_allocator = { path = "../librustc_allocator" } +rustc_back = { path = "../librustc_back" } +rustc_bitflags = { path = "../librustc_bitflags" } +rustc_const_math = { path = "../librustc_const_math" } +rustc_data_structures = { path = "../librustc_data_structures" } +rustc_errors = { path = "../librustc_errors" } +rustc_incremental = { path = "../librustc_incremental" } +rustc_llvm = { path = "../librustc_llvm" } +rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" } +serialize = { path = "../libserialize" } +syntax = { path = "../libsyntax" } +syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_trans_utils/lib.rs b/src/librustc_trans_utils/lib.rs new file mode 100644 index 000000000000..81e83076f8c0 --- /dev/null +++ b/src/librustc_trans_utils/lib.rs @@ -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 or the MIT license +// , 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; diff --git a/src/librustc_trans_utils/link.rs b/src/librustc_trans_utils/link.rs new file mode 100644 index 000000000000..29bb062d34cf --- /dev/null +++ b/src/librustc_trans_utils/link.rs @@ -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 or the MIT license +// , 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| { + 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 + } +} From b8d5c74c9902e06fc27a362d28c5832b707931f8 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Fri, 11 Aug 2017 10:35:01 +0200 Subject: [PATCH 09/10] It now completely compiles without LLVM!!! --- src/Cargo.lock | 1 + src/librustc_driver/Cargo.toml | 1 + src/librustc_driver/driver.rs | 38 +++++++++++++++++++++++++++------ src/librustc_driver/lib.rs | 32 +++++++++++++++++---------- src/librustc_trans/back/link.rs | 3 ++- 5 files changed, 56 insertions(+), 19 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 4940dfd0e655..6cb46c5c4000 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1343,6 +1343,7 @@ dependencies = [ "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", diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index 04c0f9b35184..d6155f53485e 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -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" } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index be257c8524b6..0e92499e1e1f 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -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}; @@ -71,6 +73,11 @@ pub fn compile_input(sess: &Session, output: &Option, addl_plugins: Option>, 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; @@ -90,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) => { @@ -213,8 +220,6 @@ pub fn compile_input(sess: &Session, #[cfg(feature="llvm")] let trans = phase_4_translate_to_llvm(tcx, analysis, incremental_hashes_map, &outputs); - #[cfg(not(feature="llvm"))] - let trans = { panic!("LLVM not supported by this rustc."); () }; if log_enabled!(::log::LogLevel::Info) { println!("Post-trans"); @@ -228,12 +233,25 @@ 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)) })?? }; #[cfg(not(feature="llvm"))] - unreachable!(); + { + let _ = outputs; + let _ = trans; + unreachable!(); + } #[cfg(feature="llvm")] { @@ -505,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, @@ -1145,7 +1164,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 = ::rustc_trans_utils::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); } } @@ -1263,7 +1287,7 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec Result, String> { use std::fs::File; use std::io; @@ -185,11 +188,11 @@ impl MetadataLoader for NoLLvmMetadataLoader { 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() == METADATA_FILENAME { + if entry.header().identifier() == "rust.metadata.bin" { let mut buf = Vec::new(); io::copy(&mut entry, &mut buf).unwrap(); let buf: OwningRef, [u8]> = OwningRef::new(buf).into(); - return Ok(buf.erase_owner()); + return Ok(buf.map_owner_box().erase_owner()); } } @@ -197,8 +200,8 @@ impl MetadataLoader for NoLLvmMetadataLoader { } fn get_dylib_metadata(&self, - target: &Target, - filename: &Path) + _target: &Target, + _filename: &Path) -> Result, String> { panic!("Dylib metadata loading not supported without LLVM") } @@ -207,6 +210,7 @@ impl MetadataLoader for NoLLvmMetadataLoader { // 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>, @@ -516,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, @@ -743,7 +748,12 @@ impl RustcDefaultCalls { } let crate_types = driver::collect_crate_types(sess, attrs); for &style in &crate_types { - let fname = rustc_trans_utils::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() @@ -792,7 +802,7 @@ impl RustcDefaultCalls { } PrintRequest::RelocationModels => { println!("Available relocation models:"); - #[cfg(features="llvm")] + #[cfg(feature="llvm")] for &(name, _) in RELOC_MODEL_ARGS.iter() { println!(" {}", name); } @@ -800,7 +810,7 @@ impl RustcDefaultCalls { } PrintRequest::CodeModels => { println!("Available code models:"); - #[cfg(features="llvm")] + #[cfg(feature="llvm")] for &(name, _) in CODE_GEN_MODEL_ARGS.iter(){ println!(" {}", name); } diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index e2db1721b262..a9bd8ea90109 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -88,7 +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 use self::rustc_trans_utils::link::{find_crate_name, filename_for_input, default_output_for_target, invalid_output_for_target}; +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); From e5399961c69ac2a64bdbed8af8b34698c3039db0 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Fri, 11 Aug 2017 11:08:01 +0200 Subject: [PATCH 10/10] Remove some unused dependencies from rustc_trans_utils --- src/Cargo.lock | 10 ---------- src/librustc_trans_utils/Cargo.toml | 10 ---------- 2 files changed, 20 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 6cb46c5c4000..c175198c227a 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1564,16 +1564,6 @@ name = "rustc_trans_utils" version = "0.0.0" dependencies = [ "rustc 0.0.0", - "rustc_allocator 0.0.0", - "rustc_back 0.0.0", - "rustc_bitflags 0.0.0", - "rustc_const_math 0.0.0", - "rustc_data_structures 0.0.0", - "rustc_errors 0.0.0", - "rustc_incremental 0.0.0", - "rustc_llvm 0.0.0", - "rustc_platform_intrinsics 0.0.0", - "serialize 0.0.0", "syntax 0.0.0", "syntax_pos 0.0.0", ] diff --git a/src/librustc_trans_utils/Cargo.toml b/src/librustc_trans_utils/Cargo.toml index 4fa32389b710..f026d4fcbc28 100644 --- a/src/librustc_trans_utils/Cargo.toml +++ b/src/librustc_trans_utils/Cargo.toml @@ -11,15 +11,5 @@ test = false [dependencies] rustc = { path = "../librustc" } -rustc_allocator = { path = "../librustc_allocator" } -rustc_back = { path = "../librustc_back" } -rustc_bitflags = { path = "../librustc_bitflags" } -rustc_const_math = { path = "../librustc_const_math" } -rustc_data_structures = { path = "../librustc_data_structures" } -rustc_errors = { path = "../librustc_errors" } -rustc_incremental = { path = "../librustc_incremental" } -rustc_llvm = { path = "../librustc_llvm" } -rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" } -serialize = { path = "../libserialize" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" }