Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preliminary support for MIR in trans #29217

Merged
merged 18 commits into from
Nov 4, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
6d7c66e
Introduce a "liberated fn sigs" map so that we have easy access to this
nikomatsakis Oct 21, 2015
88a9c3e
Build the MIR using the liberated fn sigs, and track the return type
nikomatsakis Oct 21, 2015
1e30f3e
Change ShallowDrop to Free, so that it matches what trans will do
nikomatsakis Oct 21, 2015
15c1da4
Convert from using named fields to always using indices
nikomatsakis Oct 21, 2015
3c07b46
Pass the mir map to trans
nikomatsakis Oct 21, 2015
b5d3580
Move the "HAIR" code that reads the tcx tables etc out of the `tcx`
nikomatsakis Oct 21, 2015
3ab29d3
Add adt_def into Switch, since it's convenient to have in trans
nikomatsakis Oct 21, 2015
044096b
Change Call operands to be, well, Operands
nikomatsakis Oct 21, 2015
0a62158
Add helper methods that require tcx; these compute types of
nikomatsakis Oct 21, 2015
81ff2c2
Change adt case handling fn to be less tied to match
nikomatsakis Oct 21, 2015
877b93a
Move shifting code out of expr and into somewhere more accessible
nikomatsakis Oct 21, 2015
02017b3
New trans codepath that builds fn body from MIR instead.
nikomatsakis Oct 21, 2015
e84829d
Plumbing to omit allocas for temps when possible (currently unused)
nikomatsakis Nov 2, 2015
544b06d
Add a MIR visitor
nikomatsakis Nov 3, 2015
6a5b263
Add (and use) an analysis to determine which temps can forgo an alloca.
nikomatsakis Nov 3, 2015
9c9f4be
correct typos
nikomatsakis Nov 3, 2015
b46c0fc
address nits from dotdash
nikomatsakis Nov 3, 2015
e787863
remove unused import
nikomatsakis Nov 4, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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