translate tuple-variant constructors using MIR
This commit is contained in:
parent
a559452b05
commit
0af3775dd2
@ -1264,10 +1264,17 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> {
|
||||
def_id,
|
||||
ROOT_CODE_EXTENT)
|
||||
}
|
||||
_ => {
|
||||
Some(hir_map::NodeStructCtor(..)) |
|
||||
Some(hir_map::NodeVariant(..)) => {
|
||||
let def_id = tcx.hir.local_def_id(id);
|
||||
tcx.construct_parameter_environment(tcx.hir.span(id),
|
||||
def_id,
|
||||
ROOT_CODE_EXTENT)
|
||||
}
|
||||
it => {
|
||||
bug!("ParameterEnvironment::from_item(): \
|
||||
`{}` is not an item",
|
||||
tcx.hir.node_to_string(id))
|
||||
`{}` = {:?} is unsupported",
|
||||
tcx.hir.node_to_string(id), it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -293,7 +293,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
predicates: Some(self.encode_predicates(def_id)),
|
||||
|
||||
ast: None,
|
||||
mir: None,
|
||||
mir: self.encode_mir(def_id),
|
||||
}
|
||||
}
|
||||
|
||||
@ -426,7 +426,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
|
||||
predicates: Some(self.encode_predicates(def_id)),
|
||||
|
||||
ast: None,
|
||||
mir: None,
|
||||
mir: self.encode_mir(def_id),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
|
||||
|
||||
#![feature(associated_consts)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(i128_type)]
|
||||
#![feature(rustc_diagnostic_macros)]
|
||||
#![feature(rustc_private)]
|
||||
@ -50,6 +51,7 @@ pub mod callgraph;
|
||||
pub mod def_use;
|
||||
pub mod graphviz;
|
||||
mod hair;
|
||||
mod shim;
|
||||
pub mod mir_map;
|
||||
pub mod pretty;
|
||||
pub mod transform;
|
||||
|
@ -22,6 +22,7 @@ use rustc::dep_graph::DepNode;
|
||||
use rustc::mir::Mir;
|
||||
use rustc::mir::transform::MirSource;
|
||||
use rustc::mir::visit::MutVisitor;
|
||||
use shim;
|
||||
use pretty;
|
||||
use hair::cx::Cx;
|
||||
|
||||
@ -30,6 +31,7 @@ use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::maps::Providers;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::hir;
|
||||
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||
use syntax::abi::Abi;
|
||||
use syntax::ast;
|
||||
use syntax_pos::Span;
|
||||
@ -44,6 +46,31 @@ pub fn build_mir_for_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
||||
tcx.visit_all_bodies_in_krate(|body_owner_def_id, _body_id| {
|
||||
tcx.item_mir(body_owner_def_id);
|
||||
});
|
||||
|
||||
// Tuple struct/variant constructors don't have a BodyId, so we need
|
||||
// to build them separately.
|
||||
struct GatherCtors<'a, 'tcx: 'a> {
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>
|
||||
}
|
||||
impl<'a, 'tcx> Visitor<'tcx> for GatherCtors<'a, 'tcx> {
|
||||
fn visit_variant_data(&mut self,
|
||||
v: &'tcx hir::VariantData,
|
||||
_: ast::Name,
|
||||
_: &'tcx hir::Generics,
|
||||
_: ast::NodeId,
|
||||
_: Span) {
|
||||
if let hir::VariantData::Tuple(_, node_id) = *v {
|
||||
self.tcx.item_mir(self.tcx.hir.local_def_id(node_id));
|
||||
}
|
||||
intravisit::walk_struct_def(self, v)
|
||||
}
|
||||
fn nested_visit_map<'b>(&'b mut self) -> NestedVisitorMap<'b, 'tcx> {
|
||||
NestedVisitorMap::None
|
||||
}
|
||||
}
|
||||
tcx.visit_all_item_likes_in_krate(DepNode::Mir, &mut GatherCtors {
|
||||
tcx: tcx
|
||||
}.as_deep_visitor());
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,6 +122,10 @@ fn build_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
|
||||
_ => hir::BodyId { node_id: expr.id }
|
||||
}
|
||||
}
|
||||
hir::map::NodeVariant(variant) =>
|
||||
return create_constructor_shim(tcx, id, &variant.node.data),
|
||||
hir::map::NodeStructCtor(ctor) =>
|
||||
return create_constructor_shim(tcx, id, ctor),
|
||||
_ => unsupported()
|
||||
};
|
||||
|
||||
@ -180,6 +211,38 @@ impl<'a, 'gcx: 'tcx, 'tcx> MutVisitor<'tcx> for GlobalizeMir<'a, 'gcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn create_constructor_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
ctor_id: ast::NodeId,
|
||||
v: &'tcx hir::VariantData)
|
||||
-> &'tcx RefCell<Mir<'tcx>>
|
||||
{
|
||||
let span = tcx.hir.span(ctor_id);
|
||||
if let hir::VariantData::Tuple(ref fields, ctor_id) = *v {
|
||||
let pe = ty::ParameterEnvironment::for_item(tcx, ctor_id);
|
||||
tcx.infer_ctxt(pe, Reveal::UserFacing).enter(|infcx| {
|
||||
let (mut mir, src) =
|
||||
shim::build_adt_ctor(&infcx, ctor_id, fields, span);
|
||||
|
||||
// Convert the Mir to global types.
|
||||
let tcx = infcx.tcx.global_tcx();
|
||||
let mut globalizer = GlobalizeMir {
|
||||
tcx: tcx,
|
||||
span: mir.span
|
||||
};
|
||||
globalizer.visit_mir(&mut mir);
|
||||
let mir = unsafe {
|
||||
mem::transmute::<Mir, Mir<'tcx>>(mir)
|
||||
};
|
||||
|
||||
pretty::dump_mir(tcx, "mir_map", &0, src, &mir);
|
||||
|
||||
tcx.alloc_mir(mir)
|
||||
})
|
||||
} else {
|
||||
span_bug!(span, "attempting to create MIR for non-tuple variant {:?}", v);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// BuildMir -- walks a crate, looking for fn items and methods to build MIR from
|
||||
|
||||
|
109
src/librustc_mir/shim.rs
Normal file
109
src/librustc_mir/shim.rs
Normal file
@ -0,0 +1,109 @@
|
||||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use rustc::hir;
|
||||
use rustc::infer;
|
||||
use rustc::mir::*;
|
||||
use rustc::mir::transform::MirSource;
|
||||
use rustc::ty;
|
||||
|
||||
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
|
||||
|
||||
use syntax::ast;
|
||||
use syntax_pos::Span;
|
||||
|
||||
use std::iter;
|
||||
|
||||
fn local_decls_for_sig<'tcx>(sig: &ty::FnSig<'tcx>)
|
||||
-> IndexVec<Local, LocalDecl<'tcx>>
|
||||
{
|
||||
iter::once(LocalDecl {
|
||||
mutability: Mutability::Mut,
|
||||
ty: sig.output(),
|
||||
name: None,
|
||||
source_info: None
|
||||
}).chain(sig.inputs().iter().map(|ity| LocalDecl {
|
||||
mutability: Mutability::Not,
|
||||
ty: *ity,
|
||||
name: None,
|
||||
source_info: None,
|
||||
})).collect()
|
||||
}
|
||||
|
||||
pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>,
|
||||
ctor_id: ast::NodeId,
|
||||
fields: &[hir::StructField],
|
||||
span: Span)
|
||||
-> (Mir<'tcx>, MirSource)
|
||||
{
|
||||
let tcx = infcx.tcx;
|
||||
let def_id = tcx.hir.local_def_id(ctor_id);
|
||||
let sig = match tcx.item_type(def_id).sty {
|
||||
ty::TyFnDef(_, _, fty) => tcx.no_late_bound_regions(&fty)
|
||||
.expect("LBR in ADT constructor signature"),
|
||||
_ => bug!("unexpected type for ctor {:?}", def_id)
|
||||
};
|
||||
let sig = tcx.erase_regions(&sig);
|
||||
|
||||
let (adt_def, substs) = match sig.output().sty {
|
||||
ty::TyAdt(adt_def, substs) => (adt_def, substs),
|
||||
_ => bug!("unexpected type for ADT ctor {:?}", sig.output())
|
||||
};
|
||||
|
||||
debug!("build_ctor: def_id={:?} sig={:?} fields={:?}", def_id, sig, fields);
|
||||
|
||||
let local_decls = local_decls_for_sig(&sig);
|
||||
|
||||
let source_info = SourceInfo {
|
||||
span: span,
|
||||
scope: ARGUMENT_VISIBILITY_SCOPE
|
||||
};
|
||||
|
||||
let variant_no = if adt_def.is_enum() {
|
||||
adt_def.variant_index_with_id(def_id)
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
// return = ADT(arg0, arg1, ...); return
|
||||
let start_block = BasicBlockData {
|
||||
statements: vec![Statement {
|
||||
source_info: source_info,
|
||||
kind: StatementKind::Assign(
|
||||
Lvalue::Local(RETURN_POINTER),
|
||||
Rvalue::Aggregate(
|
||||
AggregateKind::Adt(adt_def, variant_no, substs, None),
|
||||
(1..sig.inputs().len()+1).map(|i| {
|
||||
Operand::Consume(Lvalue::Local(Local::new(i)))
|
||||
}).collect()
|
||||
)
|
||||
)
|
||||
}],
|
||||
terminator: Some(Terminator {
|
||||
source_info: source_info,
|
||||
kind: TerminatorKind::Return,
|
||||
}),
|
||||
is_cleanup: false
|
||||
};
|
||||
|
||||
let mir = Mir::new(
|
||||
IndexVec::from_elem_n(start_block, 1),
|
||||
IndexVec::from_elem_n(
|
||||
VisibilityScopeData { span: span, parent_scope: None }, 1
|
||||
),
|
||||
IndexVec::new(),
|
||||
sig.output(),
|
||||
local_decls,
|
||||
sig.inputs().len(),
|
||||
vec![],
|
||||
span
|
||||
);
|
||||
(mir, MirSource::Fn(ctor_id))
|
||||
}
|
@ -34,10 +34,8 @@ use back::linker::LinkerInfo;
|
||||
use back::symbol_export::{self, ExportedSymbols};
|
||||
use llvm::{Linkage, ValueRef, Vector, get_param};
|
||||
use llvm;
|
||||
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
|
||||
use rustc::hir::def_id::LOCAL_CRATE;
|
||||
use middle::lang_items::StartFnLangItem;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::mir::tcx::LvalueTy;
|
||||
use rustc::traits;
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::adjustment::CustomCoerceUnsized;
|
||||
@ -47,9 +45,8 @@ use rustc::util::common::time;
|
||||
use session::config::{self, NoDebugInfo};
|
||||
use rustc_incremental::IncrementalHashesMap;
|
||||
use session::{self, DataTypeKind, Session};
|
||||
use abi::{self, FnType};
|
||||
use abi;
|
||||
use mir::lvalue::LvalueRef;
|
||||
use adt;
|
||||
use attributes;
|
||||
use builder::Builder;
|
||||
use callee::{Callee};
|
||||
@ -65,7 +62,7 @@ use context::{SharedCrateContext, CrateContextList};
|
||||
use debuginfo;
|
||||
use declare;
|
||||
use machine;
|
||||
use machine::{llalign_of_min, llsize_of};
|
||||
use machine::llsize_of;
|
||||
use meth;
|
||||
use mir;
|
||||
use monomorphize::{self, Instance};
|
||||
@ -76,7 +73,6 @@ use trans_item::{TransItem, DefPathBasedNames};
|
||||
use type_::Type;
|
||||
use type_of;
|
||||
use value::Value;
|
||||
use Disr;
|
||||
use util::nodemap::{NodeSet, FxHashMap, FxHashSet};
|
||||
|
||||
use libc::c_uint;
|
||||
@ -615,72 +611,6 @@ pub fn trans_instance<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, instance: Instance
|
||||
mir::trans_mir(ccx, lldecl, &mir, instance, sig);
|
||||
}
|
||||
|
||||
pub fn trans_ctor_shim<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
def_id: DefId,
|
||||
substs: &'tcx Substs<'tcx>,
|
||||
disr: Disr,
|
||||
llfn: ValueRef) {
|
||||
attributes::inline(llfn, attributes::InlineAttr::Hint);
|
||||
attributes::set_frame_pointer_elimination(ccx, llfn);
|
||||
|
||||
let ctor_ty = common::def_ty(ccx.shared(), def_id, substs);
|
||||
let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&ctor_ty.fn_sig());
|
||||
let fn_ty = FnType::new(ccx, sig, &[]);
|
||||
|
||||
let bcx = Builder::new_block(ccx, llfn, "entry-block");
|
||||
if !fn_ty.ret.is_ignore() {
|
||||
// But if there are no nested returns, we skip the indirection
|
||||
// and have a single retslot
|
||||
let dest = if fn_ty.ret.is_indirect() {
|
||||
get_param(llfn, 0)
|
||||
} else {
|
||||
// We create an alloca to hold a pointer of type `ret.original_ty`
|
||||
// which will hold the pointer to the right alloca which has the
|
||||
// final ret value
|
||||
bcx.alloca(fn_ty.ret.memory_ty(ccx), "sret_slot")
|
||||
};
|
||||
// Can return unsized value
|
||||
let mut dest_val = LvalueRef::new_sized_ty(dest, sig.output(), Alignment::AbiAligned);
|
||||
dest_val.ty = LvalueTy::Downcast {
|
||||
adt_def: sig.output().ty_adt_def().unwrap(),
|
||||
substs: substs,
|
||||
variant_index: disr.0 as usize,
|
||||
};
|
||||
let mut llarg_idx = fn_ty.ret.is_indirect() as usize;
|
||||
let mut arg_idx = 0;
|
||||
for (i, arg_ty) in sig.inputs().iter().enumerate() {
|
||||
let (lldestptr, _) = dest_val.trans_field_ptr(&bcx, i);
|
||||
let arg = &fn_ty.args[arg_idx];
|
||||
arg_idx += 1;
|
||||
if common::type_is_fat_ptr(bcx.ccx, arg_ty) {
|
||||
let meta = &fn_ty.args[arg_idx];
|
||||
arg_idx += 1;
|
||||
arg.store_fn_arg(&bcx, &mut llarg_idx, get_dataptr(&bcx, lldestptr));
|
||||
meta.store_fn_arg(&bcx, &mut llarg_idx, get_meta(&bcx, lldestptr));
|
||||
} else {
|
||||
arg.store_fn_arg(&bcx, &mut llarg_idx, lldestptr);
|
||||
}
|
||||
}
|
||||
adt::trans_set_discr(&bcx, sig.output(), dest, disr);
|
||||
|
||||
if fn_ty.ret.is_indirect() {
|
||||
bcx.ret_void();
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(cast_ty) = fn_ty.ret.cast {
|
||||
bcx.ret(bcx.load(
|
||||
bcx.pointercast(dest, cast_ty.ptr_to()),
|
||||
Some(llalign_of_min(ccx, fn_ty.ret.ty))
|
||||
));
|
||||
} else {
|
||||
bcx.ret(bcx.load(dest, None))
|
||||
}
|
||||
} else {
|
||||
bcx.ret_void();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn llvm_linkage_by_name(name: &str) -> Option<Linkage> {
|
||||
// Use the names from src/llvm/docs/LangRef.rst here. Most types are only
|
||||
// applicable to variable declarations and may not really make sense for
|
||||
@ -721,7 +651,7 @@ pub fn set_link_section(ccx: &CrateContext,
|
||||
}
|
||||
|
||||
/// Create the `main` function which will initialise the rust runtime and call
|
||||
/// users’ main function.
|
||||
/// users main function.
|
||||
pub fn maybe_create_entry_wrapper(ccx: &CrateContext) {
|
||||
let (main_def_id, span) = match *ccx.sess().entry_fn.borrow() {
|
||||
Some((id, span)) => {
|
||||
|
@ -22,7 +22,6 @@ use rustc::ty::subst::{Substs, Subst};
|
||||
use rustc::traits;
|
||||
use abi::{Abi, FnType};
|
||||
use attributes;
|
||||
use base;
|
||||
use builder::Builder;
|
||||
use common::{self, CrateContext};
|
||||
use cleanup::CleanupScope;
|
||||
@ -35,7 +34,6 @@ use meth;
|
||||
use monomorphize::Instance;
|
||||
use trans_item::TransItem;
|
||||
use type_of;
|
||||
use Disr;
|
||||
use rustc::ty::{self, Ty, TypeFoldable};
|
||||
use rustc::hir;
|
||||
use std::iter;
|
||||
@ -46,9 +44,6 @@ use mir::lvalue::Alignment;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum CalleeData {
|
||||
/// Constructor for enum variant/tuple-like-struct.
|
||||
NamedTupleConstructor(Disr),
|
||||
|
||||
/// Function pointer.
|
||||
Fn(ValueRef),
|
||||
|
||||
@ -92,16 +87,6 @@ impl<'tcx> Callee<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(eddyb) Detect ADT constructors more efficiently.
|
||||
if let Some(adt_def) = fn_ty.fn_ret().skip_binder().ty_adt_def() {
|
||||
if let Some(i) = adt_def.variants.iter().position(|v| def_id == v.did) {
|
||||
return Callee {
|
||||
data: NamedTupleConstructor(Disr::for_variant(tcx, adt_def, i)),
|
||||
ty: fn_ty
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
let (llfn, ty) = get_fn(ccx, def_id, substs);
|
||||
Callee::ptr(llfn, ty)
|
||||
}
|
||||
@ -185,24 +170,6 @@ impl<'tcx> Callee<'tcx> {
|
||||
match self.data {
|
||||
Fn(llfn) => llfn,
|
||||
Virtual(_) => meth::trans_object_shim(ccx, self),
|
||||
NamedTupleConstructor(disr) => match self.ty.sty {
|
||||
ty::TyFnDef(def_id, substs, _) => {
|
||||
let instance = Instance::new(def_id, substs);
|
||||
if let Some(&llfn) = ccx.instances().borrow().get(&instance) {
|
||||
return llfn;
|
||||
}
|
||||
|
||||
let sym = ccx.symbol_map().get_or_compute(ccx.shared(),
|
||||
TransItem::Fn(instance));
|
||||
assert!(!ccx.codegen_unit().contains_item(&TransItem::Fn(instance)));
|
||||
let lldecl = declare::define_internal_fn(ccx, &sym, self.ty);
|
||||
base::trans_ctor_shim(ccx, def_id, substs, disr, lldecl);
|
||||
ccx.instances().borrow_mut().insert(instance, lldecl);
|
||||
|
||||
lldecl
|
||||
}
|
||||
_ => bug!("expected fn item type, found {}", self.ty)
|
||||
},
|
||||
Intrinsic => bug!("intrinsic {} getting reified", self.ty)
|
||||
}
|
||||
}
|
||||
|
@ -630,14 +630,15 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
||||
-> bool {
|
||||
match tcx.item_type(def_id).sty {
|
||||
ty::TyFnDef(def_id, _, _) => {
|
||||
// Some constructors also have type TyFnDef but they are
|
||||
// always instantiated inline and don't result in a
|
||||
// translation item. Same for FFI functions.
|
||||
// foreign items are linked from another library, not
|
||||
// translated locally.
|
||||
if let Some(hir_map::NodeForeignItem(_)) = tcx.hir.get_if_local(def_id) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ty::TyClosure(..) => {}
|
||||
ty::TyClosure(..) => {
|
||||
// TODO: trans items for closures
|
||||
}
|
||||
_ => return false
|
||||
}
|
||||
|
||||
@ -697,16 +698,6 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
||||
fn should_trans_locally<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
def_id: DefId)
|
||||
-> bool {
|
||||
if let ty::TyFnDef(_, _, sig) = tcx.item_type(def_id).sty {
|
||||
if let Some(adt_def) = sig.output().skip_binder().ty_adt_def() {
|
||||
if adt_def.variants.iter().any(|v| def_id == v.did) {
|
||||
// HACK: ADT constructors are translated in-place and
|
||||
// do not have a trans-item.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if def_id.is_local() {
|
||||
true
|
||||
} else {
|
||||
|
@ -37,6 +37,7 @@ use libc::{c_uint, c_char};
|
||||
use std::iter;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::attr;
|
||||
use syntax::symbol::InternedString;
|
||||
use syntax_pos::Span;
|
||||
|
||||
@ -601,8 +602,13 @@ pub fn ty_fn_sig<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_closure(tcx: TyCtxt, def_id: DefId) -> bool {
|
||||
tcx.def_key(def_id).disambiguated_data.data == DefPathData::ClosureExpr
|
||||
pub fn requests_inline(tcx: TyCtxt, def_id: DefId) -> bool {
|
||||
match tcx.def_key(def_id).disambiguated_data.data {
|
||||
DefPathData::StructCtor |
|
||||
DefPathData::EnumVariant(..) |
|
||||
DefPathData::ClosureExpr => true,
|
||||
_ => attr::requests_inline(&tcx.get_attrs(def_id)[..]),
|
||||
}
|
||||
}
|
||||
|
||||
/// Given a DefId and some Substs, produces the monomorphic item type.
|
||||
|
@ -16,7 +16,7 @@ use rustc::ty::{self, layout, TypeFoldable};
|
||||
use rustc::mir;
|
||||
use abi::{Abi, FnType, ArgType};
|
||||
use base::{self, Lifetime};
|
||||
use callee::{Callee, CalleeData, Fn, Intrinsic, NamedTupleConstructor, Virtual};
|
||||
use callee::{Callee, CalleeData, Fn, Intrinsic, Virtual};
|
||||
use builder::Builder;
|
||||
use common::{self, Funclet};
|
||||
use common::{C_bool, C_str_slice, C_struct, C_u32, C_undef};
|
||||
@ -491,10 +491,6 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||
}
|
||||
|
||||
let fn_ptr = match callee.data {
|
||||
NamedTupleConstructor(_) => {
|
||||
// FIXME translate this like mir::Rvalue::Aggregate.
|
||||
callee.reify(bcx.ccx)
|
||||
}
|
||||
Intrinsic => {
|
||||
use intrinsic::trans_intrinsic_call;
|
||||
|
||||
|
@ -26,6 +26,7 @@ use monomorphize::Instance;
|
||||
use rustc::dep_graph::DepNode;
|
||||
use rustc::hir;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::hir::map::definitions::DefPathData;
|
||||
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc_const_eval::fatal_const_eval_err;
|
||||
@ -178,9 +179,14 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||
llvm::SetUniqueComdat(ccx.llmod(), lldecl);
|
||||
}
|
||||
|
||||
if let ty::TyClosure(..) = mono_ty.sty {
|
||||
// set an inline hint for all closures
|
||||
attributes::inline(lldecl, attributes::InlineAttr::Hint);
|
||||
debug!("predefine_fn: mono_ty = {:?} instance = {:?}", mono_ty, instance);
|
||||
match ccx.tcx().def_key(instance.def).disambiguated_data.data {
|
||||
DefPathData::StructCtor |
|
||||
DefPathData::EnumVariant(..) |
|
||||
DefPathData::ClosureExpr => {
|
||||
attributes::inline(lldecl, attributes::InlineAttr::Hint);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
attributes::from_fn_attrs(ccx, &attrs, lldecl);
|
||||
@ -252,8 +258,8 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||
match *self {
|
||||
TransItem::Fn(ref instance) => {
|
||||
if self.explicit_linkage(tcx).is_none() &&
|
||||
(common::is_closure(tcx, instance.def) ||
|
||||
attr::requests_inline(&tcx.get_attrs(instance.def)[..])) {
|
||||
common::requests_inline(tcx, instance.def)
|
||||
{
|
||||
InstantiationMode::LocalCopy
|
||||
} else {
|
||||
InstantiationMode::GloballyShared
|
||||
|
Loading…
Reference in New Issue
Block a user