Skip to content

Commit

Permalink
Auto merge of #29217 - nikomatsakis:mir-trans, r=dotdash
Browse files Browse the repository at this point in the history
This branch implements a variant of trans that is based on MIR. It is very incomplete (intentionally), and had only the goal of laying out enough work to enable more incremental follow-on patches. Currently, only fns tagged with `#[rustc_mir]` use the new trans code. I plan to build up a meta-issue as well that tracks the various "not-yet-implemented" points. The only fn that has been tested so far is this amazingly complex "spike" fn:

```rust
#[rustc_mir]
fn sum(x: i32, y: i32) -> i32 {
    x + y
}
```

In general, the most interesting commit is the last one. There are some points on which I would like feedback from @rust-lang/compiler:

- I did not use `Datum`. Originally, I thought that maybe just a `ValueRef` would be enough but I wound up with two very simple structures, `LvalueRef` and `OperandRef`, that just package up a `ValueRef` and a type. Because of MIR's structure, you don't wind up mixing by-ref and by-value so much, and I tend to think that a thinner abstraction layer is better here, but I'm not sure.
- Related to the above, I expect that sooner or later we will analyze temps (and maybe variables too) to find those whose address is never taken and which are word-sized and which perhaps meet a few other criteria. For those, we'll probably want to avoid the alloca, just because it means prettier code.
- I generally tried to re-use data structures from elsewhere in trans, though I'm sure we can trim these down.
- I didn't do any debuginfo primarily because it seems to want node-ids and we have only spans. I haven't really read into that code so I don't know what's going on there.

r? @nrc
  • Loading branch information
bors committed Nov 4, 2015
2 parents c340ea1 + e787863 commit a216e84
Show file tree
Hide file tree
Showing 43 changed files with 2,023 additions and 388 deletions.
2 changes: 1 addition & 1 deletion mk/crates.mk
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ DEPS_rustc_mir := rustc rustc_front syntax
DEPS_rustc_resolve := rustc rustc_front log syntax
DEPS_rustc_platform_intrinsics := rustc rustc_llvm
DEPS_rustc_privacy := rustc rustc_front log syntax
DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \
DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back rustc_mir \
log syntax serialize rustc_llvm rustc_front rustc_platform_intrinsics
DEPS_rustc_typeck := rustc syntax rustc_front rustc_platform_intrinsics

Expand Down
8 changes: 8 additions & 0 deletions src/librustc/middle/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,13 @@ pub struct Tables<'tcx> {
/// Records the type of each closure. The def ID is the ID of the
/// expression defining the closure.
pub closure_kinds: DefIdMap<ty::ClosureKind>,

/// For each fn, records the "liberated" types of its arguments
/// and return type. Liberated means that all bound regions
/// (including late-bound regions) are replaced with free
/// equivalents. This table is not used in trans (since regions
/// are erased there) and hence is not serialized to metadata.
pub liberated_fn_sigs: NodeMap<ty::FnSig<'tcx>>,
}

impl<'tcx> Tables<'tcx> {
Expand All @@ -133,6 +140,7 @@ impl<'tcx> Tables<'tcx> {
upvar_capture_map: FnvHashMap(),
closure_tys: DefIdMap(),
closure_kinds: DefIdMap(),
liberated_fn_sigs: NodeMap(),
}
}

Expand Down
7 changes: 7 additions & 0 deletions src/librustc/middle/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1731,6 +1731,13 @@ impl<'tcx, 'container> VariantDefData<'tcx, 'container> {
self.fields.iter().find(|f| f.name == name)
}

#[inline]
pub fn index_of_field_named(&self,
name: ast::Name)
-> Option<usize> {
self.fields.iter().position(|f| f.name == name)
}

#[inline]
pub fn field_named(&self, name: ast::Name) -> &FieldDefData<'tcx, 'container> {
self.find_field_named(name).unwrap()
Expand Down
27 changes: 16 additions & 11 deletions src/librustc_driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use rustc::front;
use rustc::front::map as hir_map;
use rustc_mir as mir;
use rustc_mir::mir_map::MirMap;
use rustc::session::Session;
use rustc::session::config::{self, Input, OutputFilenames, OutputType};
use rustc::session::search_paths::PathKind;
Expand All @@ -22,6 +23,7 @@ use rustc::middle::dependency_format;
use rustc::middle;
use rustc::plugin::registry::Registry;
use rustc::plugin;
use rustc::util::nodemap::NodeMap;
use rustc::util::common::time;
use rustc_borrowck as borrowck;
use rustc_resolve as resolve;
Expand Down Expand Up @@ -146,7 +148,7 @@ pub fn compile_input(sess: Session,
&arenas,
&id,
control.make_glob_map,
|tcx, analysis| {
|tcx, mir_map, analysis| {

{
let state = CompileState::state_after_analysis(input,
Expand All @@ -170,7 +172,7 @@ pub fn compile_input(sess: Session,
println!("Pre-trans");
tcx.print_debug_stats();
}
let trans = phase_4_translate_to_llvm(tcx, analysis);
let trans = phase_4_translate_to_llvm(tcx, &mir_map, analysis);

if log_enabled!(::log::INFO) {
println!("Post-trans");
Expand Down Expand Up @@ -670,6 +672,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
f: F)
-> R
where F: for<'a> FnOnce(&'a ty::ctxt<'tcx>,
MirMap<'tcx>,
ty::CrateAnalysis) -> R
{
let time_passes = sess.time_passes();
Expand Down Expand Up @@ -751,18 +754,18 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
time(time_passes, "match checking", ||
middle::check_match::check_crate(tcx));

match tcx.sess.opts.unstable_features {
let mir_map = match tcx.sess.opts.unstable_features {
UnstableFeatures::Disallow => {
// use this as a shorthand for beta/stable, and skip
// MIR construction there until known regressions are
// addressed
NodeMap()
}
UnstableFeatures::Allow | UnstableFeatures::Cheat => {
let _mir_map =
time(time_passes, "MIR dump", ||
mir::mir_map::build_mir_for_crate(tcx));
time(time_passes, "MIR dump", ||
mir::mir_map::build_mir_for_crate(tcx))
}
}
};

time(time_passes, "liveness checking", ||
middle::liveness::check_crate(tcx));
Expand Down Expand Up @@ -804,7 +807,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
// The above three passes generate errors w/o aborting
tcx.sess.abort_if_errors();

f(tcx, ty::CrateAnalysis {
f(tcx, mir_map, ty::CrateAnalysis {
export_map: export_map,
exported_items: exported_items,
public_items: public_items,
Expand All @@ -817,16 +820,18 @@ 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.
pub fn phase_4_translate_to_llvm(tcx: &ty::ctxt, analysis: ty::CrateAnalysis)
-> trans::CrateTranslation {
pub fn phase_4_translate_to_llvm<'tcx>(tcx: &ty::ctxt<'tcx>,
mir_map: &MirMap<'tcx>,
analysis: ty::CrateAnalysis)
-> trans::CrateTranslation {
let time_passes = tcx.sess.time_passes();

time(time_passes, "resolving dependency formats", ||
dependency_format::calculate(&tcx.sess));

// Option dance to work around the lack of stack once closures.
time(time_passes, "translation", move ||
trans::trans_crate(tcx, analysis))
trans::trans_crate(tcx, mir_map, analysis))
}

/// Run LLVM itself, producing a bitcode file, assembly file or object file
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_driver/pretty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ impl PpSourceMode {
arenas,
id,
resolve::MakeGlobMap::No,
|tcx, _| {
|tcx, _, _| {
let annotation = TypedAnnotation { tcx: tcx };
f(&annotation, payload, &ast_map.forest.krate)
})
Expand Down Expand Up @@ -782,7 +782,7 @@ pub fn pretty_print_input(sess: Session,
&arenas,
&id,
resolve::MakeGlobMap::No,
|tcx, _| {
|tcx, _, _| {
print_flowgraph(variants, tcx, code, mode, out)
})
}
Expand Down
11 changes: 7 additions & 4 deletions src/librustc_mir/build/expr/as_rvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {

// schedule a shallow free of that memory, lest we unwind:
let extent = this.extent_of_innermost_scope().unwrap();
this.schedule_drop(expr_span, extent, DropKind::Shallow, &result, value_ty);
this.schedule_drop(expr_span, extent, DropKind::Free, &result, value_ty);

// initialize the box contents:
let contents = result.clone().deref();
Expand Down Expand Up @@ -149,16 +149,19 @@ impl<'a,'tcx> Builder<'a,'tcx> {
block.and(Rvalue::Aggregate(AggregateKind::Closure(closure_id, substs), upvars))
}
ExprKind::Adt { adt_def, variant_index, substs, fields, base } => { // see (*) above
// first process the set of fields
// first process the set of fields that were provided
// (evaluating them in order given by user)
let fields_map: FnvHashMap<_, _> =
fields.into_iter()
.map(|f| (f.name, unpack!(block = this.as_operand(block, f.expr))))
.collect();

let field_names = this.hir.fields(adt_def, variant_index);

// if base expression is given, evaluate it now
let base = base.map(|base| unpack!(block = this.as_lvalue(block, base)));

// get list of all fields that we will need
let field_names = this.hir.all_fields(adt_def, variant_index);

// for the actual values we use, take either the
// expr the user specified or, if they didn't
// specify something for this field name, create a
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_mir/build/expr/into.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,10 +211,10 @@ impl<'a,'tcx> Builder<'a,'tcx> {
this.cfg.start_new_block().unit()
}
ExprKind::Call { fun, args } => {
let fun = unpack!(block = this.as_lvalue(block, fun));
let fun = unpack!(block = this.as_operand(block, fun));
let args: Vec<_> =
args.into_iter()
.map(|arg| unpack!(block = this.as_lvalue(block, arg)))
.map(|arg| unpack!(block = this.as_operand(block, arg)))
.collect();
let success = this.cfg.start_new_block();
let panic = this.diverge_cleanup();
Expand Down
20 changes: 11 additions & 9 deletions src/librustc_mir/build/matches/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,34 +92,36 @@ impl<'a,'tcx> Builder<'a,'tcx> {
.collect();
self.cfg.terminate(block, Terminator::Switch {
discr: lvalue.clone(),
adt_def: adt_def,
targets: target_blocks.clone()
});
target_blocks
}

TestKind::Eq { value, ty } => {
// call PartialEq::eq(discrim, constant)
let constant = self.push_literal(block, test.span, ty.clone(), value);
let constant = self.literal_operand(test.span, ty.clone(), value);
let item_ref = self.hir.partial_eq(ty);
self.call_comparison_fn(block, test.span, item_ref, lvalue.clone(), constant)
self.call_comparison_fn(block, test.span, item_ref,
Operand::Consume(lvalue.clone()), constant)
}

TestKind::Range { lo, hi, ty } => {
// Test `v` by computing `PartialOrd::le(lo, v) && PartialOrd::le(v, hi)`.
let lo = self.push_literal(block, test.span, ty.clone(), lo);
let hi = self.push_literal(block, test.span, ty.clone(), hi);
let lo = self.literal_operand(test.span, ty.clone(), lo);
let hi = self.literal_operand(test.span, ty.clone(), hi);
let item_ref = self.hir.partial_le(ty);

let lo_blocks = self.call_comparison_fn(block,
test.span,
item_ref.clone(),
lo,
lvalue.clone());
Operand::Consume(lvalue.clone()));

let hi_blocks = self.call_comparison_fn(lo_blocks[0],
test.span,
item_ref,
lvalue.clone(),
Operand::Consume(lvalue.clone()),
hi);

let failure = self.cfg.start_new_block();
Expand Down Expand Up @@ -164,14 +166,14 @@ impl<'a,'tcx> Builder<'a,'tcx> {
block: BasicBlock,
span: Span,
item_ref: ItemRef<'tcx>,
lvalue1: Lvalue<'tcx>,
lvalue2: Lvalue<'tcx>)
lvalue1: Operand<'tcx>,
lvalue2: Operand<'tcx>)
-> Vec<BasicBlock> {
let target_blocks = vec![self.cfg.start_new_block(), self.cfg.start_new_block()];

let bool_ty = self.hir.bool_ty();
let eq_result = self.temp(bool_ty);
let func = self.push_item_ref(block, span, item_ref);
let func = self.item_ref_operand(span, item_ref);
let call_blocks = [self.cfg.start_new_block(), self.diverge_cleanup()];
self.cfg.terminate(block,
Terminator::Call {
Expand Down
26 changes: 11 additions & 15 deletions src/librustc_mir/build/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,17 @@ impl<'a,'tcx> Builder<'a,'tcx> {
lvalue
}

pub fn push_literal(&mut self,
block: BasicBlock,
span: Span,
ty: Ty<'tcx>,
literal: Literal<'tcx>)
-> Lvalue<'tcx> {
let temp = self.temp(ty.clone());
pub fn literal_operand(&mut self,
span: Span,
ty: Ty<'tcx>,
literal: Literal<'tcx>)
-> Operand<'tcx> {
let constant = Constant {
span: span,
ty: ty,
literal: literal,
};
self.cfg.push_assign_constant(block, span, &temp, constant);
temp
Operand::Constant(constant)
}

pub fn push_usize(&mut self, block: BasicBlock, span: Span, value: usize) -> Lvalue<'tcx> {
Expand All @@ -63,15 +60,14 @@ impl<'a,'tcx> Builder<'a,'tcx> {
temp
}

pub fn push_item_ref(&mut self,
block: BasicBlock,
span: Span,
item_ref: ItemRef<'tcx>)
-> Lvalue<'tcx> {
pub fn item_ref_operand(&mut self,
span: Span,
item_ref: ItemRef<'tcx>)
-> Operand<'tcx> {
let literal = Literal::Item {
def_id: item_ref.def_id,
substs: item_ref.substs,
};
self.push_literal(block, span, item_ref.ty, literal)
self.literal_operand(span, item_ref.ty, literal)
}
}
20 changes: 11 additions & 9 deletions src/librustc_mir/build/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@
// except according to those terms.

use hair;
use hair::cx::{Cx, PatNode};
use rustc::middle::region::CodeExtent;
use rustc::middle::ty::Ty;
use rustc::middle::ty::{FnOutput, Ty};
use rustc_data_structures::fnv::FnvHashMap;
use rustc_front::hir;
use repr::*;
use syntax::ast;
use syntax::codemap::Span;
use tcx::{Cx, PatNode};

struct Builder<'a, 'tcx: 'a> {
hir: Cx<'a, 'tcx>,
Expand Down Expand Up @@ -75,13 +75,14 @@ macro_rules! unpack {
///////////////////////////////////////////////////////////////////////////
// construct() -- the main entry point for building MIR for a function

pub fn construct<'a, 'tcx>(mut hir: Cx<'a, 'tcx>,
_span: Span,
implicit_arguments: Vec<Ty<'tcx>>,
explicit_arguments: Vec<(Ty<'tcx>, PatNode<'tcx>)>,
argument_extent: CodeExtent,
ast_block: &'tcx hir::Block)
-> Mir<'tcx> {
pub fn construct<'a,'tcx>(mut hir: Cx<'a,'tcx>,
_span: Span,
implicit_arguments: Vec<Ty<'tcx>>,
explicit_arguments: Vec<(Ty<'tcx>, PatNode<'tcx>)>,
argument_extent: CodeExtent,
return_ty: FnOutput<'tcx>,
ast_block: &'tcx hir::Block)
-> Mir<'tcx> {
let cfg = CFG { basic_blocks: vec![] };

// it's handy to have a temporary of type `()` sometimes, so make
Expand Down Expand Up @@ -121,6 +122,7 @@ pub fn construct<'a, 'tcx>(mut hir: Cx<'a, 'tcx>,
var_decls: builder.var_decls,
arg_decls: arg_decls,
temp_decls: builder.temp_decls,
return_ty: return_ty,
}
}

Expand Down
Loading

0 comments on commit a216e84

Please sign in to comment.