Skip to content

Commit a216e84

Browse files
committed
Auto merge of #29217 - nikomatsakis:mir-trans, r=dotdash
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
2 parents c340ea1 + e787863 commit a216e84

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+2023
-388
lines changed

mk/crates.mk

+1-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ DEPS_rustc_mir := rustc rustc_front syntax
103103
DEPS_rustc_resolve := rustc rustc_front log syntax
104104
DEPS_rustc_platform_intrinsics := rustc rustc_llvm
105105
DEPS_rustc_privacy := rustc rustc_front log syntax
106-
DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \
106+
DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back rustc_mir \
107107
log syntax serialize rustc_llvm rustc_front rustc_platform_intrinsics
108108
DEPS_rustc_typeck := rustc syntax rustc_front rustc_platform_intrinsics
109109

src/librustc/middle/ty/context.rs

+8
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,13 @@ pub struct Tables<'tcx> {
121121
/// Records the type of each closure. The def ID is the ID of the
122122
/// expression defining the closure.
123123
pub closure_kinds: DefIdMap<ty::ClosureKind>,
124+
125+
/// For each fn, records the "liberated" types of its arguments
126+
/// and return type. Liberated means that all bound regions
127+
/// (including late-bound regions) are replaced with free
128+
/// equivalents. This table is not used in trans (since regions
129+
/// are erased there) and hence is not serialized to metadata.
130+
pub liberated_fn_sigs: NodeMap<ty::FnSig<'tcx>>,
124131
}
125132

126133
impl<'tcx> Tables<'tcx> {
@@ -133,6 +140,7 @@ impl<'tcx> Tables<'tcx> {
133140
upvar_capture_map: FnvHashMap(),
134141
closure_tys: DefIdMap(),
135142
closure_kinds: DefIdMap(),
143+
liberated_fn_sigs: NodeMap(),
136144
}
137145
}
138146

src/librustc/middle/ty/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -1731,6 +1731,13 @@ impl<'tcx, 'container> VariantDefData<'tcx, 'container> {
17311731
self.fields.iter().find(|f| f.name == name)
17321732
}
17331733

1734+
#[inline]
1735+
pub fn index_of_field_named(&self,
1736+
name: ast::Name)
1737+
-> Option<usize> {
1738+
self.fields.iter().position(|f| f.name == name)
1739+
}
1740+
17341741
#[inline]
17351742
pub fn field_named(&self, name: ast::Name) -> &FieldDefData<'tcx, 'container> {
17361743
self.find_field_named(name).unwrap()

src/librustc_driver/driver.rs

+16-11
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use rustc::front;
1212
use rustc::front::map as hir_map;
1313
use rustc_mir as mir;
14+
use rustc_mir::mir_map::MirMap;
1415
use rustc::session::Session;
1516
use rustc::session::config::{self, Input, OutputFilenames, OutputType};
1617
use rustc::session::search_paths::PathKind;
@@ -22,6 +23,7 @@ use rustc::middle::dependency_format;
2223
use rustc::middle;
2324
use rustc::plugin::registry::Registry;
2425
use rustc::plugin;
26+
use rustc::util::nodemap::NodeMap;
2527
use rustc::util::common::time;
2628
use rustc_borrowck as borrowck;
2729
use rustc_resolve as resolve;
@@ -146,7 +148,7 @@ pub fn compile_input(sess: Session,
146148
&arenas,
147149
&id,
148150
control.make_glob_map,
149-
|tcx, analysis| {
151+
|tcx, mir_map, analysis| {
150152

151153
{
152154
let state = CompileState::state_after_analysis(input,
@@ -170,7 +172,7 @@ pub fn compile_input(sess: Session,
170172
println!("Pre-trans");
171173
tcx.print_debug_stats();
172174
}
173-
let trans = phase_4_translate_to_llvm(tcx, analysis);
175+
let trans = phase_4_translate_to_llvm(tcx, &mir_map, analysis);
174176

175177
if log_enabled!(::log::INFO) {
176178
println!("Post-trans");
@@ -670,6 +672,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
670672
f: F)
671673
-> R
672674
where F: for<'a> FnOnce(&'a ty::ctxt<'tcx>,
675+
MirMap<'tcx>,
673676
ty::CrateAnalysis) -> R
674677
{
675678
let time_passes = sess.time_passes();
@@ -751,18 +754,18 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
751754
time(time_passes, "match checking", ||
752755
middle::check_match::check_crate(tcx));
753756

754-
match tcx.sess.opts.unstable_features {
757+
let mir_map = match tcx.sess.opts.unstable_features {
755758
UnstableFeatures::Disallow => {
756759
// use this as a shorthand for beta/stable, and skip
757760
// MIR construction there until known regressions are
758761
// addressed
762+
NodeMap()
759763
}
760764
UnstableFeatures::Allow | UnstableFeatures::Cheat => {
761-
let _mir_map =
762-
time(time_passes, "MIR dump", ||
763-
mir::mir_map::build_mir_for_crate(tcx));
765+
time(time_passes, "MIR dump", ||
766+
mir::mir_map::build_mir_for_crate(tcx))
764767
}
765-
}
768+
};
766769

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

807-
f(tcx, ty::CrateAnalysis {
810+
f(tcx, mir_map, ty::CrateAnalysis {
808811
export_map: export_map,
809812
exported_items: exported_items,
810813
public_items: public_items,
@@ -817,16 +820,18 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
817820

818821
/// Run the translation phase to LLVM, after which the AST and analysis can
819822
/// be discarded.
820-
pub fn phase_4_translate_to_llvm(tcx: &ty::ctxt, analysis: ty::CrateAnalysis)
821-
-> trans::CrateTranslation {
823+
pub fn phase_4_translate_to_llvm<'tcx>(tcx: &ty::ctxt<'tcx>,
824+
mir_map: &MirMap<'tcx>,
825+
analysis: ty::CrateAnalysis)
826+
-> trans::CrateTranslation {
822827
let time_passes = tcx.sess.time_passes();
823828

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

827832
// Option dance to work around the lack of stack once closures.
828833
time(time_passes, "translation", move ||
829-
trans::trans_crate(tcx, analysis))
834+
trans::trans_crate(tcx, mir_map, analysis))
830835
}
831836

832837
/// Run LLVM itself, producing a bitcode file, assembly file or object file

src/librustc_driver/pretty.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ impl PpSourceMode {
182182
arenas,
183183
id,
184184
resolve::MakeGlobMap::No,
185-
|tcx, _| {
185+
|tcx, _, _| {
186186
let annotation = TypedAnnotation { tcx: tcx };
187187
f(&annotation, payload, &ast_map.forest.krate)
188188
})
@@ -782,7 +782,7 @@ pub fn pretty_print_input(sess: Session,
782782
&arenas,
783783
&id,
784784
resolve::MakeGlobMap::No,
785-
|tcx, _| {
785+
|tcx, _, _| {
786786
print_flowgraph(variants, tcx, code, mode, out)
787787
})
788788
}

src/librustc_mir/build/expr/as_rvalue.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
7171

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

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

158-
let field_names = this.hir.fields(adt_def, variant_index);
159-
159+
// if base expression is given, evaluate it now
160160
let base = base.map(|base| unpack!(block = this.as_lvalue(block, base)));
161161

162+
// get list of all fields that we will need
163+
let field_names = this.hir.all_fields(adt_def, variant_index);
164+
162165
// for the actual values we use, take either the
163166
// expr the user specified or, if they didn't
164167
// specify something for this field name, create a

src/librustc_mir/build/expr/into.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -211,10 +211,10 @@ impl<'a,'tcx> Builder<'a,'tcx> {
211211
this.cfg.start_new_block().unit()
212212
}
213213
ExprKind::Call { fun, args } => {
214-
let fun = unpack!(block = this.as_lvalue(block, fun));
214+
let fun = unpack!(block = this.as_operand(block, fun));
215215
let args: Vec<_> =
216216
args.into_iter()
217-
.map(|arg| unpack!(block = this.as_lvalue(block, arg)))
217+
.map(|arg| unpack!(block = this.as_operand(block, arg)))
218218
.collect();
219219
let success = this.cfg.start_new_block();
220220
let panic = this.diverge_cleanup();

src/librustc_mir/build/matches/test.rs

+11-9
Original file line numberDiff line numberDiff line change
@@ -92,34 +92,36 @@ impl<'a,'tcx> Builder<'a,'tcx> {
9292
.collect();
9393
self.cfg.terminate(block, Terminator::Switch {
9494
discr: lvalue.clone(),
95+
adt_def: adt_def,
9596
targets: target_blocks.clone()
9697
});
9798
target_blocks
9899
}
99100

100101
TestKind::Eq { value, ty } => {
101102
// call PartialEq::eq(discrim, constant)
102-
let constant = self.push_literal(block, test.span, ty.clone(), value);
103+
let constant = self.literal_operand(test.span, ty.clone(), value);
103104
let item_ref = self.hir.partial_eq(ty);
104-
self.call_comparison_fn(block, test.span, item_ref, lvalue.clone(), constant)
105+
self.call_comparison_fn(block, test.span, item_ref,
106+
Operand::Consume(lvalue.clone()), constant)
105107
}
106108

107109
TestKind::Range { lo, hi, ty } => {
108110
// Test `v` by computing `PartialOrd::le(lo, v) && PartialOrd::le(v, hi)`.
109-
let lo = self.push_literal(block, test.span, ty.clone(), lo);
110-
let hi = self.push_literal(block, test.span, ty.clone(), hi);
111+
let lo = self.literal_operand(test.span, ty.clone(), lo);
112+
let hi = self.literal_operand(test.span, ty.clone(), hi);
111113
let item_ref = self.hir.partial_le(ty);
112114

113115
let lo_blocks = self.call_comparison_fn(block,
114116
test.span,
115117
item_ref.clone(),
116118
lo,
117-
lvalue.clone());
119+
Operand::Consume(lvalue.clone()));
118120

119121
let hi_blocks = self.call_comparison_fn(lo_blocks[0],
120122
test.span,
121123
item_ref,
122-
lvalue.clone(),
124+
Operand::Consume(lvalue.clone()),
123125
hi);
124126

125127
let failure = self.cfg.start_new_block();
@@ -164,14 +166,14 @@ impl<'a,'tcx> Builder<'a,'tcx> {
164166
block: BasicBlock,
165167
span: Span,
166168
item_ref: ItemRef<'tcx>,
167-
lvalue1: Lvalue<'tcx>,
168-
lvalue2: Lvalue<'tcx>)
169+
lvalue1: Operand<'tcx>,
170+
lvalue2: Operand<'tcx>)
169171
-> Vec<BasicBlock> {
170172
let target_blocks = vec![self.cfg.start_new_block(), self.cfg.start_new_block()];
171173

172174
let bool_ty = self.hir.bool_ty();
173175
let eq_result = self.temp(bool_ty);
174-
let func = self.push_item_ref(block, span, item_ref);
176+
let func = self.item_ref_operand(span, item_ref);
175177
let call_blocks = [self.cfg.start_new_block(), self.diverge_cleanup()];
176178
self.cfg.terminate(block,
177179
Terminator::Call {

src/librustc_mir/build/misc.rs

+11-15
Original file line numberDiff line numberDiff line change
@@ -34,20 +34,17 @@ impl<'a,'tcx> Builder<'a,'tcx> {
3434
lvalue
3535
}
3636

37-
pub fn push_literal(&mut self,
38-
block: BasicBlock,
39-
span: Span,
40-
ty: Ty<'tcx>,
41-
literal: Literal<'tcx>)
42-
-> Lvalue<'tcx> {
43-
let temp = self.temp(ty.clone());
37+
pub fn literal_operand(&mut self,
38+
span: Span,
39+
ty: Ty<'tcx>,
40+
literal: Literal<'tcx>)
41+
-> Operand<'tcx> {
4442
let constant = Constant {
4543
span: span,
4644
ty: ty,
4745
literal: literal,
4846
};
49-
self.cfg.push_assign_constant(block, span, &temp, constant);
50-
temp
47+
Operand::Constant(constant)
5148
}
5249

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

66-
pub fn push_item_ref(&mut self,
67-
block: BasicBlock,
68-
span: Span,
69-
item_ref: ItemRef<'tcx>)
70-
-> Lvalue<'tcx> {
63+
pub fn item_ref_operand(&mut self,
64+
span: Span,
65+
item_ref: ItemRef<'tcx>)
66+
-> Operand<'tcx> {
7167
let literal = Literal::Item {
7268
def_id: item_ref.def_id,
7369
substs: item_ref.substs,
7470
};
75-
self.push_literal(block, span, item_ref.ty, literal)
71+
self.literal_operand(span, item_ref.ty, literal)
7672
}
7773
}

src/librustc_mir/build/mod.rs

+11-9
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@
99
// except according to those terms.
1010

1111
use hair;
12+
use hair::cx::{Cx, PatNode};
1213
use rustc::middle::region::CodeExtent;
13-
use rustc::middle::ty::Ty;
14+
use rustc::middle::ty::{FnOutput, Ty};
1415
use rustc_data_structures::fnv::FnvHashMap;
1516
use rustc_front::hir;
1617
use repr::*;
1718
use syntax::ast;
1819
use syntax::codemap::Span;
19-
use tcx::{Cx, PatNode};
2020

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

78-
pub fn construct<'a, 'tcx>(mut hir: Cx<'a, 'tcx>,
79-
_span: Span,
80-
implicit_arguments: Vec<Ty<'tcx>>,
81-
explicit_arguments: Vec<(Ty<'tcx>, PatNode<'tcx>)>,
82-
argument_extent: CodeExtent,
83-
ast_block: &'tcx hir::Block)
84-
-> Mir<'tcx> {
78+
pub fn construct<'a,'tcx>(mut hir: Cx<'a,'tcx>,
79+
_span: Span,
80+
implicit_arguments: Vec<Ty<'tcx>>,
81+
explicit_arguments: Vec<(Ty<'tcx>, PatNode<'tcx>)>,
82+
argument_extent: CodeExtent,
83+
return_ty: FnOutput<'tcx>,
84+
ast_block: &'tcx hir::Block)
85+
-> Mir<'tcx> {
8586
let cfg = CFG { basic_blocks: vec![] };
8687

8788
// it's handy to have a temporary of type `()` sometimes, so make
@@ -121,6 +122,7 @@ pub fn construct<'a, 'tcx>(mut hir: Cx<'a, 'tcx>,
121122
var_decls: builder.var_decls,
122123
arg_decls: arg_decls,
123124
temp_decls: builder.temp_decls,
125+
return_ty: return_ty,
124126
}
125127
}
126128

0 commit comments

Comments
 (0)