mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-05 19:58:32 +00:00
mir: build MIR for constants and static initializers.
This commit is contained in:
parent
cde2f5f116
commit
d434688516
@ -97,6 +97,31 @@ impl<'ast> DefCollector<'ast> {
|
|||||||
f(self);
|
f(self);
|
||||||
self.parent_def = parent;
|
self.parent_def = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_ast_const_integer(&mut self, expr: &'ast Expr) {
|
||||||
|
// Find the node which will be used after lowering.
|
||||||
|
if let ExprKind::Paren(ref inner) = expr.node {
|
||||||
|
return self.visit_ast_const_integer(inner);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME(eddyb) Closures should have separate
|
||||||
|
// function definition IDs and expression IDs.
|
||||||
|
if let ExprKind::Closure(..) = expr.node {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.create_def(expr.id, DefPathData::Initializer);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_hir_const_integer(&mut self, expr: &'ast hir::Expr) {
|
||||||
|
// FIXME(eddyb) Closures should have separate
|
||||||
|
// function definition IDs and expression IDs.
|
||||||
|
if let hir::ExprClosure(..) = expr.node {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.create_def(expr.id, DefPathData::Initializer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ast> visit::Visitor<'ast> for DefCollector<'ast> {
|
impl<'ast> visit::Visitor<'ast> for DefCollector<'ast> {
|
||||||
@ -126,14 +151,17 @@ impl<'ast> visit::Visitor<'ast> for DefCollector<'ast> {
|
|||||||
let variant_def_index =
|
let variant_def_index =
|
||||||
this.create_def(v.node.data.id(),
|
this.create_def(v.node.data.id(),
|
||||||
DefPathData::EnumVariant(v.node.name.name));
|
DefPathData::EnumVariant(v.node.name.name));
|
||||||
|
this.with_parent(variant_def_index, |this| {
|
||||||
|
for (index, field) in v.node.data.fields().iter().enumerate() {
|
||||||
|
let name = field.ident.map(|ident| ident.name)
|
||||||
|
.unwrap_or_else(|| token::intern(&index.to_string()));
|
||||||
|
this.create_def(field.id, DefPathData::Field(name));
|
||||||
|
}
|
||||||
|
|
||||||
for (index, field) in v.node.data.fields().iter().enumerate() {
|
if let Some(ref expr) = v.node.disr_expr {
|
||||||
let name = field.ident.map(|ident| ident.name)
|
this.visit_ast_const_integer(expr);
|
||||||
.unwrap_or(token::intern(&index.to_string()));
|
}
|
||||||
this.create_def_with_parent(Some(variant_def_index),
|
});
|
||||||
field.id,
|
|
||||||
DefPathData::Field(name));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ItemKind::Struct(ref struct_def, _) => {
|
ItemKind::Struct(ref struct_def, _) => {
|
||||||
@ -221,6 +249,10 @@ impl<'ast> visit::Visitor<'ast> for DefCollector<'ast> {
|
|||||||
fn visit_expr(&mut self, expr: &'ast Expr) {
|
fn visit_expr(&mut self, expr: &'ast Expr) {
|
||||||
let parent_def = self.parent_def;
|
let parent_def = self.parent_def;
|
||||||
|
|
||||||
|
if let ExprKind::Repeat(_, ref count) = expr.node {
|
||||||
|
self.visit_ast_const_integer(count);
|
||||||
|
}
|
||||||
|
|
||||||
if let ExprKind::Closure(..) = expr.node {
|
if let ExprKind::Closure(..) = expr.node {
|
||||||
let def = self.create_def(expr.id, DefPathData::ClosureExpr);
|
let def = self.create_def(expr.id, DefPathData::ClosureExpr);
|
||||||
self.parent_def = Some(def);
|
self.parent_def = Some(def);
|
||||||
@ -230,6 +262,13 @@ impl<'ast> visit::Visitor<'ast> for DefCollector<'ast> {
|
|||||||
self.parent_def = parent_def;
|
self.parent_def = parent_def;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_ty(&mut self, ty: &'ast Ty) {
|
||||||
|
if let TyKind::FixedLengthVec(_, ref length) = ty.node {
|
||||||
|
self.visit_ast_const_integer(length);
|
||||||
|
}
|
||||||
|
visit::walk_ty(self, ty);
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_lifetime_def(&mut self, def: &'ast LifetimeDef) {
|
fn visit_lifetime_def(&mut self, def: &'ast LifetimeDef) {
|
||||||
self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name));
|
self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name));
|
||||||
}
|
}
|
||||||
@ -276,11 +315,15 @@ impl<'ast> intravisit::Visitor<'ast> for DefCollector<'ast> {
|
|||||||
this.create_def(v.node.data.id(),
|
this.create_def(v.node.data.id(),
|
||||||
DefPathData::EnumVariant(v.node.name));
|
DefPathData::EnumVariant(v.node.name));
|
||||||
|
|
||||||
for field in v.node.data.fields() {
|
this.with_parent(variant_def_index, |this| {
|
||||||
this.create_def_with_parent(Some(variant_def_index),
|
for field in v.node.data.fields() {
|
||||||
field.id,
|
this.create_def(field.id,
|
||||||
DefPathData::Field(field.name));
|
DefPathData::Field(field.name));
|
||||||
}
|
}
|
||||||
|
if let Some(ref expr) = v.node.disr_expr {
|
||||||
|
this.visit_hir_const_integer(expr);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ItemStruct(ref struct_def, _) => {
|
hir::ItemStruct(ref struct_def, _) => {
|
||||||
@ -365,6 +408,10 @@ impl<'ast> intravisit::Visitor<'ast> for DefCollector<'ast> {
|
|||||||
fn visit_expr(&mut self, expr: &'ast hir::Expr) {
|
fn visit_expr(&mut self, expr: &'ast hir::Expr) {
|
||||||
let parent_def = self.parent_def;
|
let parent_def = self.parent_def;
|
||||||
|
|
||||||
|
if let hir::ExprRepeat(_, ref count) = expr.node {
|
||||||
|
self.visit_hir_const_integer(count);
|
||||||
|
}
|
||||||
|
|
||||||
if let hir::ExprClosure(..) = expr.node {
|
if let hir::ExprClosure(..) = expr.node {
|
||||||
let def = self.create_def(expr.id, DefPathData::ClosureExpr);
|
let def = self.create_def(expr.id, DefPathData::ClosureExpr);
|
||||||
self.parent_def = Some(def);
|
self.parent_def = Some(def);
|
||||||
@ -374,6 +421,13 @@ impl<'ast> intravisit::Visitor<'ast> for DefCollector<'ast> {
|
|||||||
self.parent_def = parent_def;
|
self.parent_def = parent_def;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_ty(&mut self, ty: &'ast hir::Ty) {
|
||||||
|
if let hir::TyFixedLengthVec(_, ref length) = ty.node {
|
||||||
|
self.visit_hir_const_integer(length);
|
||||||
|
}
|
||||||
|
intravisit::walk_ty(self, ty);
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_lifetime_def(&mut self, def: &'ast hir::LifetimeDef) {
|
fn visit_lifetime_def(&mut self, def: &'ast hir::LifetimeDef) {
|
||||||
self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name));
|
self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name));
|
||||||
}
|
}
|
||||||
@ -381,4 +435,4 @@ impl<'ast> intravisit::Visitor<'ast> for DefCollector<'ast> {
|
|||||||
fn visit_macro_def(&mut self, macro_def: &'ast hir::MacroDef) {
|
fn visit_macro_def(&mut self, macro_def: &'ast hir::MacroDef) {
|
||||||
self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.name));
|
self.create_def(macro_def.id, DefPathData::MacroDef(macro_def.name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ use middle::cstore::{self, LOCAL_CRATE};
|
|||||||
use hir::def::{self, Def, ExportMap};
|
use hir::def::{self, Def, ExportMap};
|
||||||
use hir::def_id::DefId;
|
use hir::def_id::DefId;
|
||||||
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
|
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
|
||||||
use middle::region::{CodeExtent};
|
use middle::region::{CodeExtent, ROOT_CODE_EXTENT};
|
||||||
use traits;
|
use traits;
|
||||||
use ty;
|
use ty;
|
||||||
use ty::subst::{Subst, Substs, VecPerParamSpace};
|
use ty::subst::{Subst, Substs, VecPerParamSpace};
|
||||||
@ -1376,6 +1376,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
hir::ItemEnum(..) |
|
hir::ItemEnum(..) |
|
||||||
hir::ItemStruct(..) |
|
hir::ItemStruct(..) |
|
||||||
|
hir::ItemTy(..) |
|
||||||
hir::ItemImpl(..) |
|
hir::ItemImpl(..) |
|
||||||
hir::ItemConst(..) |
|
hir::ItemConst(..) |
|
||||||
hir::ItemStatic(..) => {
|
hir::ItemStatic(..) => {
|
||||||
@ -1408,6 +1409,15 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
|
|||||||
// This is a convenience to allow closures to work.
|
// This is a convenience to allow closures to work.
|
||||||
ParameterEnvironment::for_item(cx, cx.map.get_parent(id))
|
ParameterEnvironment::for_item(cx, cx.map.get_parent(id))
|
||||||
}
|
}
|
||||||
|
Some(ast_map::NodeForeignItem(item)) => {
|
||||||
|
let def_id = cx.map.local_def_id(id);
|
||||||
|
let scheme = cx.lookup_item_type(def_id);
|
||||||
|
let predicates = cx.lookup_predicates(def_id);
|
||||||
|
cx.construct_parameter_environment(item.span,
|
||||||
|
&scheme.generics,
|
||||||
|
&predicates,
|
||||||
|
ROOT_CODE_EXTENT)
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
bug!("ParameterEnvironment::from_item(): \
|
bug!("ParameterEnvironment::from_item(): \
|
||||||
`{}` is not an item",
|
`{}` is not an item",
|
||||||
|
@ -35,13 +35,12 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
|||||||
|
|
||||||
let expr_ty = expr.ty.clone();
|
let expr_ty = expr.ty.clone();
|
||||||
let temp = this.temp(expr_ty.clone());
|
let temp = this.temp(expr_ty.clone());
|
||||||
let temp_lifetime = match expr.temp_lifetime {
|
// In constants, temp_lifetime is None. We should not need to drop
|
||||||
Some(t) => t,
|
// anything because no values with a destructor can be created in
|
||||||
None => {
|
// a constant at this time, even if the type may need dropping.
|
||||||
span_bug!(expr.span, "no temp_lifetime for expr");
|
if let Some(temp_lifetime) = expr.temp_lifetime {
|
||||||
}
|
this.schedule_drop(expr.span, temp_lifetime, &temp, expr_ty);
|
||||||
};
|
}
|
||||||
this.schedule_drop(expr.span, temp_lifetime, &temp, expr_ty);
|
|
||||||
|
|
||||||
// Careful here not to cause an infinite cycle. If we always
|
// Careful here not to cause an infinite cycle. If we always
|
||||||
// called `into`, then for lvalues like `x.f`, it would
|
// called `into`, then for lvalues like `x.f`, it would
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use hair::cx::Cx;
|
use hair::cx::Cx;
|
||||||
use rustc::middle::region::{CodeExtent, CodeExtentData};
|
use rustc::middle::region::{CodeExtent, CodeExtentData, ROOT_CODE_EXTENT};
|
||||||
use rustc::ty::{self, Ty};
|
use rustc::ty::{self, Ty};
|
||||||
use rustc::mir::repr::*;
|
use rustc::mir::repr::*;
|
||||||
use rustc_data_structures::fnv::FnvHashMap;
|
use rustc_data_structures::fnv::FnvHashMap;
|
||||||
@ -232,6 +232,33 @@ pub fn construct_fn<'a, 'tcx, A>(hir: Cx<'a,'tcx>,
|
|||||||
builder.finish(upvar_decls, arg_decls, return_ty)
|
builder.finish(upvar_decls, arg_decls, return_ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn construct_const<'a, 'tcx>(hir: Cx<'a,'tcx>,
|
||||||
|
item_id: ast::NodeId,
|
||||||
|
ast_expr: &'tcx hir::Expr)
|
||||||
|
-> (Mir<'tcx>, ScopeAuxiliaryVec) {
|
||||||
|
let tcx = hir.tcx();
|
||||||
|
let span = tcx.map.span(item_id);
|
||||||
|
let mut builder = Builder::new(hir, span);
|
||||||
|
|
||||||
|
let extent = ROOT_CODE_EXTENT;
|
||||||
|
let mut block = START_BLOCK;
|
||||||
|
let _ = builder.in_scope(extent, block, |builder, call_site_scope_id| {
|
||||||
|
let expr = builder.hir.mirror(ast_expr);
|
||||||
|
unpack!(block = builder.into(&Lvalue::ReturnPointer, block, expr));
|
||||||
|
|
||||||
|
let return_block = builder.return_block();
|
||||||
|
builder.cfg.terminate(block, call_site_scope_id, span,
|
||||||
|
TerminatorKind::Goto { target: return_block });
|
||||||
|
builder.cfg.terminate(return_block, call_site_scope_id, span,
|
||||||
|
TerminatorKind::Return);
|
||||||
|
|
||||||
|
return_block.unit()
|
||||||
|
});
|
||||||
|
|
||||||
|
let ty = tcx.expr_ty_adjusted(ast_expr);
|
||||||
|
builder.finish(vec![], vec![], ty::FnConverging(ty))
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a,'tcx> Builder<'a,'tcx> {
|
impl<'a,'tcx> Builder<'a,'tcx> {
|
||||||
fn new(hir: Cx<'a, 'tcx>, span: Span) -> Builder<'a, 'tcx> {
|
fn new(hir: Cx<'a, 'tcx>, span: Span) -> Builder<'a, 'tcx> {
|
||||||
let mut builder = Builder {
|
let mut builder = Builder {
|
||||||
|
@ -16,8 +16,6 @@
|
|||||||
//! - `#[rustc_mir(graphviz="file.gv")]`
|
//! - `#[rustc_mir(graphviz="file.gv")]`
|
||||||
//! - `#[rustc_mir(pretty="file.mir")]`
|
//! - `#[rustc_mir(pretty="file.mir")]`
|
||||||
|
|
||||||
extern crate syntax;
|
|
||||||
|
|
||||||
use build;
|
use build;
|
||||||
use rustc::dep_graph::DepNode;
|
use rustc::dep_graph::DepNode;
|
||||||
use rustc::mir::repr::Mir;
|
use rustc::mir::repr::Mir;
|
||||||
@ -72,9 +70,73 @@ impl<'a, 'tcx> BuildMir<'a, 'tcx> {
|
|||||||
|
|
||||||
assert!(self.map.map.insert(id, mir).is_none())
|
assert!(self.map.map.insert(id, mir).is_none())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn build_const_integer(&mut self, expr: &'tcx hir::Expr) {
|
||||||
|
// FIXME(eddyb) Closures should have separate
|
||||||
|
// function definition IDs and expression IDs.
|
||||||
|
// Type-checking should not let closures get
|
||||||
|
// this far in an integer constant position.
|
||||||
|
if let hir::ExprClosure(..) = expr.node {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.build(expr.id, |cx| build::construct_const(cx, expr.id, expr));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> {
|
impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> {
|
||||||
|
// Const and static items.
|
||||||
|
fn visit_item(&mut self, item: &'tcx hir::Item) {
|
||||||
|
match item.node {
|
||||||
|
hir::ItemConst(_, ref expr) |
|
||||||
|
hir::ItemStatic(_, _, ref expr) => {
|
||||||
|
self.build(item.id, |cx| build::construct_const(cx, item.id, expr));
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
intravisit::walk_item(self, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trait associated const defaults.
|
||||||
|
fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) {
|
||||||
|
if let hir::ConstTraitItem(_, Some(ref expr)) = item.node {
|
||||||
|
self.build(item.id, |cx| build::construct_const(cx, item.id, expr));
|
||||||
|
}
|
||||||
|
intravisit::walk_trait_item(self, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Impl associated const.
|
||||||
|
fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) {
|
||||||
|
if let hir::ImplItemKind::Const(_, ref expr) = item.node {
|
||||||
|
self.build(item.id, |cx| build::construct_const(cx, item.id, expr));
|
||||||
|
}
|
||||||
|
intravisit::walk_impl_item(self, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Repeat counts, i.e. [expr; constant].
|
||||||
|
fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
|
||||||
|
if let hir::ExprRepeat(_, ref count) = expr.node {
|
||||||
|
self.build_const_integer(count);
|
||||||
|
}
|
||||||
|
intravisit::walk_expr(self, expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Array lengths, i.e. [T; constant].
|
||||||
|
fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
|
||||||
|
if let hir::TyFixedLengthVec(_, ref length) = ty.node {
|
||||||
|
self.build_const_integer(length);
|
||||||
|
}
|
||||||
|
intravisit::walk_ty(self, ty);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enum variant discriminant values.
|
||||||
|
fn visit_variant(&mut self, v: &'tcx hir::Variant,
|
||||||
|
g: &'tcx hir::Generics, item_id: ast::NodeId) {
|
||||||
|
if let Some(ref expr) = v.node.disr_expr {
|
||||||
|
self.build_const_integer(expr);
|
||||||
|
}
|
||||||
|
intravisit::walk_variant(self, v, g, item_id);
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_fn(&mut self,
|
fn visit_fn(&mut self,
|
||||||
fk: intravisit::FnKind<'tcx>,
|
fk: intravisit::FnKind<'tcx>,
|
||||||
decl: &'tcx hir::FnDecl,
|
decl: &'tcx hir::FnDecl,
|
||||||
|
Loading…
Reference in New Issue
Block a user