1
Fork 0

Represent function pointers in mir-constants as a Value instead of Item

This commit is contained in:
Oliver Schneider 2017-03-07 16:09:01 +01:00
parent 366386c46d
commit b0d9afbc04
No known key found for this signature in database
GPG key ID: A69F8D225B3AD7D9
10 changed files with 55 additions and 46 deletions

View file

@ -983,16 +983,16 @@ impl<'tcx> Debug for Operand<'tcx> {
} }
impl<'tcx> Operand<'tcx> { impl<'tcx> Operand<'tcx> {
pub fn item<'a>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>, pub fn function_handle<'a>(
def_id: DefId, tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
substs: &'tcx Substs<'tcx>, def_id: DefId,
span: Span) substs: &'tcx Substs<'tcx>,
-> Self span: Span,
{ ) -> Self {
Operand::Constant(Constant { Operand::Constant(Constant {
span: span, span: span,
ty: tcx.item_type(def_id).subst(tcx, substs), ty: tcx.item_type(def_id).subst(tcx, substs),
literal: Literal::Item { def_id, substs } literal: Literal::Value { value: ConstVal::Function(def_id, substs) },
}) })
} }

View file

@ -89,6 +89,7 @@ should go to.
use build::{BlockAnd, BlockAndExtension, Builder, CFG}; use build::{BlockAnd, BlockAndExtension, Builder, CFG};
use rustc::middle::region::{CodeExtent, CodeExtentData}; use rustc::middle::region::{CodeExtent, CodeExtentData};
use rustc::middle::lang_items; use rustc::middle::lang_items;
use rustc::middle::const_val::ConstVal;
use rustc::ty::subst::{Kind, Subst}; use rustc::ty::subst::{Kind, Subst};
use rustc::ty::{Ty, TyCtxt}; use rustc::ty::{Ty, TyCtxt};
use rustc::mir::*; use rustc::mir::*;
@ -784,9 +785,8 @@ fn build_free<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
func: Operand::Constant(Constant { func: Operand::Constant(Constant {
span: data.span, span: data.span,
ty: tcx.item_type(free_func).subst(tcx, substs), ty: tcx.item_type(free_func).subst(tcx, substs),
literal: Literal::Item { literal: Literal::Value {
def_id: free_func, value: ConstVal::Function(free_func, substs),
substs: substs
} }
}), }),
args: vec![Operand::Consume(data.value.clone())], args: vec![Operand::Consume(data.value.clone())],

View file

@ -714,9 +714,8 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
ty: callee.ty, ty: callee.ty,
span: expr.span, span: expr.span,
kind: ExprKind::Literal { kind: ExprKind::Literal {
literal: Literal::Item { literal: Literal::Value {
def_id: callee.def_id, value: ConstVal::Function(callee.def_id, callee.substs),
substs: callee.substs,
}, },
}, },
} }
@ -743,14 +742,24 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
-> ExprKind<'tcx> { -> ExprKind<'tcx> {
let substs = cx.tables().node_id_item_substs(expr.id) let substs = cx.tables().node_id_item_substs(expr.id)
.unwrap_or_else(|| cx.tcx.intern_substs(&[])); .unwrap_or_else(|| cx.tcx.intern_substs(&[]));
let def_id = match def { match def {
// A regular function, constructor function or a constant. // A regular function, constructor function or a constant.
Def::Fn(def_id) | Def::Fn(def_id) |
Def::Method(def_id) | Def::Method(def_id) |
Def::StructCtor(def_id, CtorKind::Fn) | Def::StructCtor(def_id, CtorKind::Fn) |
Def::VariantCtor(def_id, CtorKind::Fn) | Def::VariantCtor(def_id, CtorKind::Fn) => ExprKind::Literal {
literal: Literal::Value {
value: ConstVal::Function(def_id, substs),
},
},
Def::Const(def_id) | Def::Const(def_id) |
Def::AssociatedConst(def_id) => def_id, Def::AssociatedConst(def_id) => ExprKind::Literal {
literal: Literal::Item {
def_id: def_id,
substs: substs,
},
},
Def::StructCtor(def_id, CtorKind::Const) | Def::StructCtor(def_id, CtorKind::Const) |
Def::VariantCtor(def_id, CtorKind::Const) => { Def::VariantCtor(def_id, CtorKind::Const) => {
@ -758,7 +767,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
// A unit struct/variant which is used as a value. // A unit struct/variant which is used as a value.
// We return a completely different ExprKind here to account for this special case. // We return a completely different ExprKind here to account for this special case.
ty::TyAdt(adt_def, substs) => { ty::TyAdt(adt_def, substs) => {
return ExprKind::Adt { ExprKind::Adt {
adt_def: adt_def, adt_def: adt_def,
variant_index: adt_def.variant_index_with_id(def_id), variant_index: adt_def.variant_index_with_id(def_id),
substs: substs, substs: substs,
@ -770,17 +779,11 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
} }
} }
Def::Static(node_id, _) => return ExprKind::StaticRef { id: node_id }, Def::Static(node_id, _) => ExprKind::StaticRef { id: node_id },
Def::Local(..) | Def::Upvar(..) => return convert_var(cx, expr, def), Def::Local(..) | Def::Upvar(..) => convert_var(cx, expr, def),
_ => span_bug!(expr.span, "def `{:?}` not yet implemented", def), _ => span_bug!(expr.span, "def `{:?}` not yet implemented", def),
};
ExprKind::Literal {
literal: Literal::Item {
def_id: def_id,
substs: substs,
},
} }
} }

View file

@ -132,9 +132,8 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
let method_ty = self.tcx.item_type(item.def_id); let method_ty = self.tcx.item_type(item.def_id);
let method_ty = method_ty.subst(self.tcx, substs); let method_ty = method_ty.subst(self.tcx, substs);
return (method_ty, return (method_ty,
Literal::Item { Literal::Value {
def_id: item.def_id, value: ConstVal::Function(item.def_id, substs),
substs: substs,
}); });
} }
} }

View file

@ -12,6 +12,7 @@ use rustc::hir;
use rustc::hir::def_id::DefId; use rustc::hir::def_id::DefId;
use rustc::infer; use rustc::infer;
use rustc::middle::region::ROOT_CODE_EXTENT; use rustc::middle::region::ROOT_CODE_EXTENT;
use rustc::middle::const_val::ConstVal;
use rustc::mir::*; use rustc::mir::*;
use rustc::mir::transform::MirSource; use rustc::mir::transform::MirSource;
use rustc::ty::{self, Ty}; use rustc::ty::{self, Ty};
@ -335,7 +336,9 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
Operand::Constant(Constant { Operand::Constant(Constant {
span: span, span: span,
ty: tcx.item_type(def_id).subst(tcx, param_env.free_substs), ty: tcx.item_type(def_id).subst(tcx, param_env.free_substs),
literal: Literal::Item { def_id, substs: param_env.free_substs }, literal: Literal::Value {
value: ConstVal::Function(def_id, param_env.free_substs),
},
}), }),
vec![rcvr] vec![rcvr]
) )

View file

@ -568,11 +568,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
}); });
} }
Operand::Constant(ref constant) => { Operand::Constant(ref constant) => {
// Only functions and methods can have these types.
if let ty::TyFnDef(..) = constant.ty.sty {
return;
}
if let Literal::Item { def_id, substs } = constant.literal { if let Literal::Item { def_id, substs } = constant.literal {
// Don't peek inside generic (associated) constants. // Don't peek inside generic (associated) constants.
if substs.types().next().is_some() { if substs.types().next().is_some() {

View file

@ -15,6 +15,7 @@ use rustc::infer::{self, InferCtxt, InferOk};
use rustc::traits::{self, Reveal}; use rustc::traits::{self, Reveal};
use rustc::ty::fold::TypeFoldable; use rustc::ty::fold::TypeFoldable;
use rustc::ty::{self, Ty, TyCtxt, TypeVariants}; use rustc::ty::{self, Ty, TyCtxt, TypeVariants};
use rustc::middle::const_val::ConstVal;
use rustc::mir::*; use rustc::mir::*;
use rustc::mir::tcx::LvalueTy; use rustc::mir::tcx::LvalueTy;
use rustc::mir::transform::{MirPass, MirSource, Pass}; use rustc::mir::transform::{MirPass, MirSource, Pass};
@ -526,7 +527,9 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
fn is_box_free(&self, operand: &Operand<'tcx>) -> bool { fn is_box_free(&self, operand: &Operand<'tcx>) -> bool {
match operand { match operand {
&Operand::Constant(Constant { &Operand::Constant(Constant {
literal: Literal::Item { def_id, .. }, .. literal: Literal::Value {
value: ConstVal::Function(def_id, _), ..
}, ..
}) => { }) => {
Some(def_id) == self.tcx().lang_items.box_free_fn() Some(def_id) == self.tcx().lang_items.box_free_fn()
} }

View file

@ -525,8 +525,8 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
}], }],
terminator: Some(Terminator { terminator: Some(Terminator {
kind: TerminatorKind::Call { kind: TerminatorKind::Call {
func: Operand::item(tcx, drop_fn.def_id, substs, func: Operand::function_handle(tcx, drop_fn.def_id, substs,
self.source_info.span), self.source_info.span),
args: vec![Operand::Consume(Lvalue::Local(ref_lvalue))], args: vec![Operand::Consume(Lvalue::Local(ref_lvalue))],
destination: Some((unit_temp, succ)), destination: Some((unit_temp, succ)),
cleanup: unwind, cleanup: unwind,
@ -629,7 +629,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
let substs = tcx.mk_substs(iter::once(Kind::from(ty))); let substs = tcx.mk_substs(iter::once(Kind::from(ty)));
let call = TerminatorKind::Call { let call = TerminatorKind::Call {
func: Operand::item(tcx, free_func, substs, self.source_info.span), func: Operand::function_handle(tcx, free_func, substs, self.source_info.span),
args: vec![Operand::Consume(self.lvalue.clone())], args: vec![Operand::Consume(self.lvalue.clone())],
destination: Some((unit_temp, target)), destination: Some((unit_temp, target)),
cleanup: None cleanup: None

View file

@ -13,7 +13,8 @@
use rustc_data_structures::bitvec::BitVector; use rustc_data_structures::bitvec::BitVector;
use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use rustc::mir::{self, Location, TerminatorKind}; use rustc::middle::const_val::ConstVal;
use rustc::mir::{self, Location, TerminatorKind, Literal};
use rustc::mir::visit::{Visitor, LvalueContext}; use rustc::mir::visit::{Visitor, LvalueContext};
use rustc::mir::traversal; use rustc::mir::traversal;
use common; use common;
@ -109,7 +110,9 @@ impl<'mir, 'a, 'tcx> Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'tcx> {
match *kind { match *kind {
mir::TerminatorKind::Call { mir::TerminatorKind::Call {
func: mir::Operand::Constant(mir::Constant { func: mir::Operand::Constant(mir::Constant {
literal: mir::Literal::Item { def_id, .. }, .. literal: Literal::Value {
value: ConstVal::Function(def_id, _), ..
}, ..
}), }),
ref args, .. ref args, ..
} if Some(def_id) == self.cx.ccx.tcx().lang_items.box_free_fn() => { } if Some(def_id) == self.cx.ccx.tcx().lang_items.box_free_fn() => {

View file

@ -101,9 +101,12 @@ impl<'tcx> Const<'tcx> {
ConstVal::Str(ref v) => C_str_slice(ccx, v.clone()), ConstVal::Str(ref v) => C_str_slice(ccx, v.clone()),
ConstVal::ByteStr(ref v) => consts::addr_of(ccx, C_bytes(ccx, v), 1, "byte_str"), ConstVal::ByteStr(ref v) => consts::addr_of(ccx, C_bytes(ccx, v), 1, "byte_str"),
ConstVal::Struct(_) | ConstVal::Tuple(_) | ConstVal::Struct(_) | ConstVal::Tuple(_) |
ConstVal::Array(..) | ConstVal::Repeat(..) | ConstVal::Array(..) | ConstVal::Repeat(..) => {
bug!("MIR must not use `{:?}` (aggregates are expanded to MIR rvalues)", cv)
}
ConstVal::Function(..) => { ConstVal::Function(..) => {
bug!("MIR must not use `{:?}` (which refers to a local ID)", cv) let llty = type_of::type_of(ccx, ty);
return Const::new(C_null(llty), ty);
} }
ConstVal::Char(c) => C_integral(Type::char(ccx), c as u64, false), ConstVal::Char(c) => C_integral(Type::char(ccx), c as u64, false),
}; };
@ -476,8 +479,8 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
let ty = self.monomorphize(&constant.ty); let ty = self.monomorphize(&constant.ty);
match constant.literal.clone() { match constant.literal.clone() {
mir::Literal::Item { def_id, substs } => { mir::Literal::Item { def_id, substs } => {
// Shortcut for zero-sized types, including function item // Shortcut for zero-sized types
// types, which would not work with MirConstContext. // which would not work with MirConstContext.
if common::type_is_zero_size(self.ccx, ty) { if common::type_is_zero_size(self.ccx, ty) {
let llty = type_of::type_of(self.ccx, ty); let llty = type_of::type_of(self.ccx, ty);
return Ok(Const::new(C_null(llty), ty)); return Ok(Const::new(C_null(llty), ty));
@ -924,8 +927,8 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
let ty = self.monomorphize(&constant.ty); let ty = self.monomorphize(&constant.ty);
let result = match constant.literal.clone() { let result = match constant.literal.clone() {
mir::Literal::Item { def_id, substs } => { mir::Literal::Item { def_id, substs } => {
// Shortcut for zero-sized types, including function item // Shortcut for zero-sized types
// types, which would not work with MirConstContext. // which would not work with MirConstContext.
if common::type_is_zero_size(bcx.ccx, ty) { if common::type_is_zero_size(bcx.ccx, ty) {
let llty = type_of::type_of(bcx.ccx, ty); let llty = type_of::type_of(bcx.ccx, ty);
return Const::new(C_null(llty), ty); return Const::new(C_null(llty), ty);