Auto merge of #23376 - eddyb:die-tydesc-die, r=nikomatsakis

Final remnant of reflection is gone. Also, virtual `Trait` destructors are no longer tied to `Box`.
That means they can be used to drop any instance of the type (used in libarena to replace TyDesc).

This is [breaking-change] for direct users of intrinsics:
* use `intrinsics::type_name::<T>()` instead of `(*intrinsics::get_tydesc::<T>()).name`
* the only way to get the destructor is from a trait object's vtable (see libarena changes)

r? @pcwalton f? @dotdash
This commit is contained in:
bors 2015-03-17 21:23:02 +00:00
commit ea8b82e90c
20 changed files with 178 additions and 529 deletions

View File

@ -42,8 +42,9 @@ extern crate alloc;
use std::cell::{Cell, RefCell};
use std::cmp;
use std::intrinsics::{TyDesc, get_tydesc};
use std::intrinsics;
#[cfg(stage0)] // SNAP 270a677
use std::intrinsics::{get_tydesc, TyDesc};
use std::marker;
use std::mem;
#[cfg(stage0)]
@ -186,6 +187,27 @@ fn un_bitpack_tydesc_ptr(p: usize) -> (*const TyDesc, bool) {
((p & !1) as *const TyDesc, p & 1 == 1)
}
// HACK(eddyb) TyDesc replacement using a trait object vtable.
// This could be replaced in the future with a custom DST layout,
// or `&'static (drop_glue, size, align)` created by a `const fn`.
#[cfg(not(stage0))] // SNAP 270a677
struct TyDesc {
drop_glue: fn(*const i8),
size: usize,
align: usize
}
#[cfg(not(stage0))] // SNAP 270a677
unsafe fn get_tydesc<T>() -> *const TyDesc {
use std::raw::TraitObject;
let ptr = &*(1 as *const T);
// Can use any trait that is implemented for all types.
let obj = mem::transmute::<&marker::MarkerTrait, TraitObject>(ptr);
obj.vtable as *const TyDesc
}
impl<'longer_than_self> Arena<'longer_than_self> {
fn chunk_size(&self) -> usize {
self.copy_head.borrow().capacity()

View File

@ -44,10 +44,12 @@
use marker::Sized;
#[cfg(stage0)] // SNAP 270a677
pub type GlueFn = extern "Rust" fn(*const i8);
#[lang="ty_desc"]
#[derive(Copy)]
#[cfg(stage0)] // SNAP 270a677
pub struct TyDesc {
// sizeof(T)
pub size: usize,
@ -197,8 +199,13 @@ extern "rust-intrinsic" {
pub fn pref_align_of<T>() -> usize;
/// Get a static pointer to a type descriptor.
#[cfg(stage0)] // SNAP 270a677
pub fn get_tydesc<T: ?Sized>() -> *const TyDesc;
/// Gets a static string slice containing the name of a type.
#[cfg(not(stage0))] // SNAP 270a677
pub fn type_name<T: ?Sized>() -> &'static str;
/// Gets an identifier which is globally unique to the specified type. This
/// function will return the same value for a type regardless of whichever
/// crate it is invoked in.

View File

@ -316,9 +316,6 @@ lets_do_this! {
StartFnLangItem, "start", start_fn;
TyDescStructLangItem, "ty_desc", ty_desc;
OpaqueStructLangItem, "opaque", opaque;
EhPersonalityLangItem, "eh_personality", eh_personality;
ExchangeHeapLangItem, "exchange_heap", exchange_heap;

View File

@ -47,8 +47,7 @@ use middle::check_const;
use middle::const_eval;
use middle::def::{self, DefMap, ExportMap};
use middle::dependency_format;
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem};
use middle::lang_items::{FnOnceTraitLangItem, TyDescStructLangItem};
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
use middle::mem_categorization as mc;
use middle::region;
use middle::resolve_lifetime;
@ -723,7 +722,6 @@ pub struct ctxt<'tcx> {
pub object_cast_map: ObjectCastMap<'tcx>,
pub map: ast_map::Map<'tcx>,
pub intrinsic_defs: RefCell<DefIdMap<Ty<'tcx>>>,
pub freevars: RefCell<FreevarMap>,
pub tcache: RefCell<DefIdMap<TypeScheme<'tcx>>>,
pub rcache: RefCell<FnvHashMap<creader_cache_key, Ty<'tcx>>>,
@ -2575,7 +2573,6 @@ pub fn mk_ctxt<'tcx>(s: Session,
super_predicates: RefCell::new(DefIdMap()),
object_cast_map: RefCell::new(NodeMap()),
map: map,
intrinsic_defs: RefCell::new(DefIdMap()),
freevars: freevars,
tcache: RefCell::new(DefIdMap()),
rcache: RefCell::new(FnvHashMap()),
@ -5951,13 +5948,6 @@ pub fn required_region_bounds<'tcx>(tcx: &ctxt<'tcx>,
.collect()
}
pub fn get_tydesc_ty<'tcx>(tcx: &ctxt<'tcx>) -> Result<Ty<'tcx>, String> {
tcx.lang_items.require(TyDescStructLangItem).map(|tydesc_lang_item| {
tcx.intrinsic_defs.borrow().get(&tydesc_lang_item).cloned()
.expect("Failed to resolve TyDesc")
})
}
pub fn item_variances(tcx: &ctxt, item_id: ast::DefId) -> Rc<ItemVariances> {
lookup_locally_or_in_crate_store(
"item_variance_map", item_id, &mut *tcx.item_variance_map.borrow_mut(),

View File

@ -660,7 +660,7 @@ fn bind_subslice_pat(bcx: Block,
offset_right: uint) -> ValueRef {
let _icx = push_ctxt("match::bind_subslice_pat");
let vec_ty = node_id_type(bcx, pat_id);
let vt = tvec::vec_types(bcx, ty::sequence_element_type(bcx.tcx(), ty::type_content(vec_ty)));
let unit_ty = ty::sequence_element_type(bcx.tcx(), ty::type_content(vec_ty));
let vec_datum = match_datum(val, vec_ty);
let (base, len) = vec_datum.get_vec_base_and_len(bcx);
@ -669,7 +669,7 @@ fn bind_subslice_pat(bcx: Block,
let slice_len = Sub(bcx, len, slice_len_offset, DebugLoc::None);
let slice_ty = ty::mk_slice(bcx.tcx(),
bcx.tcx().mk_region(ty::ReStatic),
ty::mt {ty: vt.unit_ty, mutbl: ast::MutImmutable});
ty::mt {ty: unit_ty, mutbl: ast::MutImmutable});
let scratch = rvalue_scratch_datum(bcx, slice_ty, "");
Store(bcx, slice_begin,
GEPi(bcx, scratch.val, &[0, abi::FAT_PTR_ADDR]));

View File

@ -57,8 +57,7 @@ use trans::common::{C_null, C_struct_in_context, C_u64, C_u8, C_undef};
use trans::common::{CrateContext, ExternMap, FunctionContext};
use trans::common::{Result, NodeIdAndSpan};
use trans::common::{node_id_type, return_type_is_void};
use trans::common::{tydesc_info, type_is_immediate};
use trans::common::{type_is_zero_size, val_ty};
use trans::common::{type_is_immediate, type_is_zero_size, val_ty};
use trans::common;
use trans::consts;
use trans::context::SharedCrateContext;
@ -90,7 +89,6 @@ use std::ffi::{CStr, CString};
use std::cell::{Cell, RefCell};
use std::collections::HashSet;
use std::mem;
use std::rc::Rc;
use std::str;
use std::{i8, i16, i32, i64};
use syntax::abi::{Rust, RustCall, RustIntrinsic, Abi};
@ -392,22 +390,6 @@ pub fn malloc_raw_dyn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
Result::new(r.bcx, PointerCast(r.bcx, r.val, llty_ptr))
}
// Type descriptor and type glue stuff
pub fn get_tydesc<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
t: Ty<'tcx>) -> Rc<tydesc_info<'tcx>> {
match ccx.tydescs().borrow().get(&t) {
Some(inf) => return inf.clone(),
_ => { }
}
ccx.stats().n_static_tydescs.set(ccx.stats().n_static_tydescs.get() + 1);
let inf = Rc::new(glue::declare_tydesc(ccx, t));
ccx.tydescs().borrow_mut().insert(t, inf.clone());
inf
}
#[allow(dead_code)] // useful
pub fn set_optimize_for_size(f: ValueRef) {
llvm::SetFunctionAttribute(f, llvm::OptimizeForSizeAttribute)
@ -702,6 +684,10 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
let unit_ty = ty::sequence_element_type(cx.tcx(), t);
cx = tvec::iter_vec_raw(cx, base, unit_ty, len, f);
}
ty::ty_vec(_, None) | ty::ty_str => {
let unit_ty = ty::sequence_element_type(cx.tcx(), t);
cx = tvec::iter_vec_raw(cx, data_ptr, unit_ty, info.unwrap(), f);
}
ty::ty_tup(ref args) => {
let repr = adt::represent_type(cx.ccx(), t);
for (i, arg) in args.iter().enumerate() {
@ -3133,7 +3119,6 @@ pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>)
}
for ccx in shared_ccx.iter() {
glue::emit_tydescs(&ccx);
if ccx.sess().opts.debuginfo != NoDebugInfo {
debuginfo::finalize(&ccx);
}
@ -3145,7 +3130,6 @@ pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>)
if shared_ccx.sess().trans_stats() {
let stats = shared_ccx.stats();
println!("--- trans stats ---");
println!("n_static_tydescs: {}", stats.n_static_tydescs.get());
println!("n_glues_created: {}", stats.n_glues_created.get());
println!("n_null_glues: {}", stats.n_null_glues.get());
println!("n_real_glues: {}", stats.n_real_glues.get());

View File

@ -316,15 +316,6 @@ pub fn gensym_name(name: &str) -> PathElem {
PathName(token::gensym(&format!("{}:{}", name, num)))
}
#[derive(Copy)]
pub struct tydesc_info<'tcx> {
pub ty: Ty<'tcx>,
pub tydesc: ValueRef,
pub size: ValueRef,
pub align: ValueRef,
pub name: ValueRef,
}
/*
* A note on nomenclature of linking: "extern", "foreign", and "upcall".
*

View File

@ -314,7 +314,6 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
let info =
expr::unsized_info(
cx, k, e.id, ty, param_substs,
|t| ty::mk_imm_rptr(cx.tcx(), cx.tcx().mk_region(ty::ReStatic), t),
|| const_get_elt(cx, llconst, &[abi::FAT_PTR_EXTRA as u32]));
let unsized_ty = ty::unsize_ty(cx.tcx(), ty, k, e.span);

View File

@ -18,7 +18,7 @@ use middle::traits;
use trans::adt;
use trans::base;
use trans::builder::Builder;
use trans::common::{ExternMap,tydesc_info,BuilderRef_res};
use trans::common::{ExternMap,BuilderRef_res};
use trans::debuginfo;
use trans::monomorphize::MonoId;
use trans::type_::{Type, TypeNames};
@ -38,7 +38,6 @@ use syntax::ast;
use syntax::parse::token::InternedString;
pub struct Stats {
pub n_static_tydescs: Cell<uint>,
pub n_glues_created: Cell<uint>,
pub n_null_glues: Cell<uint>,
pub n_real_glues: Cell<uint>,
@ -89,10 +88,6 @@ pub struct LocalCrateContext<'tcx> {
needs_unwind_cleanup_cache: RefCell<FnvHashMap<Ty<'tcx>, bool>>,
fn_pointer_shims: RefCell<FnvHashMap<Ty<'tcx>, ValueRef>>,
drop_glues: RefCell<FnvHashMap<Ty<'tcx>, ValueRef>>,
tydescs: RefCell<FnvHashMap<Ty<'tcx>, Rc<tydesc_info<'tcx>>>>,
/// Set when running emit_tydescs to enforce that no more tydescs are
/// created.
finished_tydescs: Cell<bool>,
/// Track mapping of external ids to local items imported for inlining
external: RefCell<DefIdMap<Option<ast::NodeId>>>,
/// Backwards version of the `external` map (inlined items to where they
@ -102,7 +97,7 @@ pub struct LocalCrateContext<'tcx> {
monomorphized: RefCell<FnvHashMap<MonoId<'tcx>, ValueRef>>,
monomorphizing: RefCell<DefIdMap<uint>>,
/// Cache generated vtables
vtables: RefCell<FnvHashMap<(Ty<'tcx>, ty::PolyTraitRef<'tcx>), ValueRef>>,
vtables: RefCell<FnvHashMap<ty::PolyTraitRef<'tcx>, ValueRef>>,
/// Cache of constant strings,
const_cstr_cache: RefCell<FnvHashMap<InternedString, ValueRef>>,
@ -264,7 +259,6 @@ impl<'tcx> SharedCrateContext<'tcx> {
symbol_hasher: RefCell::new(symbol_hasher),
tcx: tcx,
stats: Stats {
n_static_tydescs: Cell::new(0),
n_glues_created: Cell::new(0),
n_null_glues: Cell::new(0),
n_real_glues: Cell::new(0),
@ -399,8 +393,6 @@ impl<'tcx> LocalCrateContext<'tcx> {
needs_unwind_cleanup_cache: RefCell::new(FnvHashMap()),
fn_pointer_shims: RefCell::new(FnvHashMap()),
drop_glues: RefCell::new(FnvHashMap()),
tydescs: RefCell::new(FnvHashMap()),
finished_tydescs: Cell::new(false),
external: RefCell::new(DefIdMap()),
external_srcs: RefCell::new(NodeMap()),
monomorphized: RefCell::new(FnvHashMap()),
@ -442,8 +434,6 @@ impl<'tcx> LocalCrateContext<'tcx> {
str_slice_ty.set_struct_body(&[Type::i8p(&ccx), ccx.int_type()], false);
ccx.tn().associate_type("str_slice", &str_slice_ty);
ccx.tn().associate_type("tydesc", &Type::tydesc(&ccx, str_slice_ty));
if ccx.sess().count_llvm_insns() {
base::init_insn_ctxt()
}
@ -519,10 +509,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
self.local.builder.b
}
pub fn tydesc_type(&self) -> Type {
self.local.tn.find_type("tydesc").unwrap()
}
pub fn get_intrinsic(&self, key: & &'static str) -> ValueRef {
if let Some(v) = self.intrinsics().borrow().get(key).cloned() {
return v;
@ -590,14 +576,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
&self.local.drop_glues
}
pub fn tydescs<'a>(&'a self) -> &'a RefCell<FnvHashMap<Ty<'tcx>, Rc<tydesc_info<'tcx>>>> {
&self.local.tydescs
}
pub fn finished_tydescs<'a>(&'a self) -> &'a Cell<bool> {
&self.local.finished_tydescs
}
pub fn external<'a>(&'a self) -> &'a RefCell<DefIdMap<Option<ast::NodeId>>> {
&self.local.external
}
@ -614,8 +592,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
&self.local.monomorphizing
}
pub fn vtables<'a>(&'a self) -> &'a RefCell<FnvHashMap<(Ty<'tcx>, ty::PolyTraitRef<'tcx>),
ValueRef>> {
pub fn vtables<'a>(&'a self) -> &'a RefCell<FnvHashMap<ty::PolyTraitRef<'tcx>, ValueRef>> {
&self.local.vtables
}

View File

@ -288,53 +288,38 @@ pub fn get_dataptr(bcx: Block, fat_ptr: ValueRef) -> ValueRef {
// Retrieve the information we are losing (making dynamic) in an unsizing
// adjustment.
//
// When making a dtor, we need to do different things depending on the
// ownership of the object.. mk_ty is a function for turning `unadjusted_ty`
// into a type to be destructed. If we want to end up with a Box pointer,
// then mk_ty should make a Box pointer (T -> Box<T>), if we want a
// borrowed reference then it should be T -> &T.
//
// The `unadjusted_val` argument is a bit funny. It is intended
// for use in an upcast, where the new vtable for an object will
// be drived from the old one. Hence it is a pointer to the fat
// pointer.
pub fn unsized_info_bcx<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
kind: &ty::UnsizeKind<'tcx>,
id: ast::NodeId,
unadjusted_ty: Ty<'tcx>,
unadjusted_val: ValueRef, // see above (*)
param_substs: &'tcx subst::Substs<'tcx>,
mk_ty: F)
-> ValueRef
where F: FnOnce(Ty<'tcx>) -> Ty<'tcx>
{
pub fn unsized_info_bcx<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
kind: &ty::UnsizeKind<'tcx>,
id: ast::NodeId,
unadjusted_ty: Ty<'tcx>,
unadjusted_val: ValueRef, // see above (*)
param_substs: &'tcx subst::Substs<'tcx>)
-> ValueRef {
unsized_info(
bcx.ccx(),
kind,
id,
unadjusted_ty,
param_substs,
mk_ty,
|| Load(bcx, GEPi(bcx, unadjusted_val, &[0, abi::FAT_PTR_EXTRA])))
}
// Same as `unsize_info_bcx`, but does not require a bcx -- instead it
// takes an extra closure to compute the upcast vtable.
pub fn unsized_info<'ccx, 'tcx, MK_TY, MK_UPCAST_VTABLE>(
pub fn unsized_info<'ccx, 'tcx, MK_UPCAST_VTABLE>(
ccx: &CrateContext<'ccx, 'tcx>,
kind: &ty::UnsizeKind<'tcx>,
id: ast::NodeId,
unadjusted_ty: Ty<'tcx>,
param_substs: &'tcx subst::Substs<'tcx>,
mk_ty: MK_TY,
mk_upcast_vtable: MK_UPCAST_VTABLE) // see notes above
-> ValueRef
where MK_TY: FnOnce(Ty<'tcx>) -> Ty<'tcx>,
MK_UPCAST_VTABLE: FnOnce() -> ValueRef,
where MK_UPCAST_VTABLE: FnOnce() -> ValueRef
{
// FIXME(#19596) workaround: `|t| t` causes monomorphization recursion
fn identity<T>(t: T) -> T { t }
debug!("unsized_info(kind={:?}, id={}, unadjusted_ty={})",
kind, id, unadjusted_ty.repr(ccx.tcx()));
match kind {
@ -342,10 +327,8 @@ pub fn unsized_info<'ccx, 'tcx, MK_TY, MK_UPCAST_VTABLE>(
&ty::UnsizeStruct(box ref k, tp_index) => match unadjusted_ty.sty {
ty::ty_struct(_, ref substs) => {
let ty_substs = substs.types.get_slice(subst::TypeSpace);
// The dtor for a field treats it like a value, so mk_ty
// should just be the identity function.
unsized_info(ccx, k, id, ty_substs[tp_index], param_substs,
identity, mk_upcast_vtable)
mk_upcast_vtable)
}
_ => ccx.sess().bug(&format!("UnsizeStruct with bad sty: {}",
unadjusted_ty.repr(ccx.tcx())))
@ -359,8 +342,7 @@ pub fn unsized_info<'ccx, 'tcx, MK_TY, MK_UPCAST_VTABLE>(
let trait_ref = monomorphize::apply_param_substs(ccx.tcx(),
param_substs,
&trait_ref);
let box_ty = mk_ty(unadjusted_ty);
consts::ptrcast(meth::get_vtable(ccx, box_ty, trait_ref, param_substs),
consts::ptrcast(meth::get_vtable(ccx, trait_ref, param_substs),
Type::vtable_ptr(ccx))
}
&ty::UnsizeUpcast(_) => {
@ -498,8 +480,7 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let unsized_ty = ty::unsize_ty(tcx, datum_ty, k, expr.span);
debug!("unsized_ty={}", unsized_ty.repr(bcx.tcx()));
let info = unsized_info_bcx(bcx, k, expr.id, datum_ty, datum.val, bcx.fcx.param_substs,
|t| ty::mk_imm_rptr(tcx, tcx.mk_region(ty::ReStatic), t));
let info = unsized_info_bcx(bcx, k, expr.id, datum_ty, datum.val, bcx.fcx.param_substs);
// Arrange cleanup
let lval = unpack_datum!(bcx, datum.to_lvalue_datum(bcx, "into_fat_ptr", expr.id));
@ -590,8 +571,7 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let base = PointerCast(bcx, get_dataptr(bcx, scratch.val), llbox_ty.ptr_to());
bcx = datum.store_to(bcx, base);
let info = unsized_info_bcx(bcx, k, expr.id, unboxed_ty, base, bcx.fcx.param_substs,
|t| ty::mk_uniq(tcx, t));
let info = unsized_info_bcx(bcx, k, expr.id, unboxed_ty, base, bcx.fcx.param_substs);
Store(bcx, info, get_len(bcx, scratch.val));
DatumBlock::new(bcx, scratch.to_expr_datum())
@ -888,10 +868,7 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
}
};
let vt =
tvec::vec_types(bcx,
ty::sequence_element_type(bcx.tcx(),
base_datum.ty));
let unit_ty = ty::sequence_element_type(bcx.tcx(), base_datum.ty);
let (base, len) = base_datum.get_vec_base_and_len(bcx);
@ -916,8 +893,8 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
len)
});
let elt = InBoundsGEP(bcx, base, &[ix_val]);
let elt = PointerCast(bcx, elt, vt.llunit_ty.ptr_to());
Datum::new(elt, vt.unit_ty, LvalueExpr)
let elt = PointerCast(bcx, elt, type_of::type_of(ccx, unit_ty).ptr_to());
Datum::new(elt, unit_ty, LvalueExpr)
}
};

View File

@ -10,12 +10,12 @@
//!
//
// Code relating to taking, dropping, etc as well as type descriptors.
// Code relating to drop glue.
use back::abi;
use back::link::*;
use llvm::{ValueRef, True, get_param};
use llvm::{ValueRef, get_param};
use llvm;
use middle::lang_items::ExchangeFreeFnLangItem;
use middle::subst;
@ -26,24 +26,20 @@ use trans::build::*;
use trans::callee;
use trans::cleanup;
use trans::cleanup::CleanupMethods;
use trans::consts;
use trans::common::*;
use trans::datum;
use trans::debuginfo::DebugLoc;
use trans::expr;
use trans::machine::*;
use trans::tvec;
use trans::type_::Type;
use trans::type_of::{self, type_of, sizing_type_of, align_of};
use trans::type_of::{type_of, sizing_type_of, align_of};
use middle::ty::{self, Ty};
use util::ppaux::{ty_to_short_str, Repr};
use util::ppaux;
use arena::TypedArena;
use libc::c_uint;
use std::ffi::CString;
use syntax::ast;
use syntax::parse::token;
pub fn trans_exchange_free_dyn<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
v: ValueRef,
@ -178,31 +174,46 @@ pub fn get_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Val
let llfnty = Type::glue_fn(ccx, llty);
let (glue, new_sym) = match ccx.available_drop_glues().borrow().get(&t) {
Some(old_sym) => {
let glue = decl_cdecl_fn(ccx, &old_sym[..], llfnty, ty::mk_nil(ccx.tcx()));
(glue, None)
},
None => {
let (sym, glue) = declare_generic_glue(ccx, t, llfnty, "drop");
(glue, Some(sym))
},
};
ccx.drop_glues().borrow_mut().insert(t, glue);
// To avoid infinite recursion, don't `make_drop_glue` until after we've
// added the entry to the `drop_glues` cache.
match new_sym {
Some(sym) => {
ccx.available_drop_glues().borrow_mut().insert(t, sym);
// We're creating a new drop glue, so also generate a body.
make_generic_glue(ccx, t, glue, make_drop_glue, "drop");
},
None => {},
}
if let Some(old_sym) = ccx.available_drop_glues().borrow().get(&t) {
let llfn = decl_cdecl_fn(ccx, &old_sym, llfnty, ty::mk_nil(ccx.tcx()));
ccx.drop_glues().borrow_mut().insert(t, llfn);
return llfn;
};
glue
let fn_nm = mangle_internal_name_by_type_and_seq(ccx, t, "drop");
let llfn = decl_cdecl_fn(ccx, &fn_nm, llfnty, ty::mk_nil(ccx.tcx()));
note_unique_llvm_symbol(ccx, fn_nm.clone());
ccx.available_drop_glues().borrow_mut().insert(t, fn_nm);
let _s = StatRecorder::new(ccx, format!("drop {}", ty_to_short_str(ccx.tcx(), t)));
let empty_substs = ccx.tcx().mk_substs(Substs::trans_empty());
let (arena, fcx): (TypedArena<_>, FunctionContext);
arena = TypedArena::new();
fcx = new_fn_ctxt(ccx, llfn, ast::DUMMY_NODE_ID, false,
ty::FnConverging(ty::mk_nil(ccx.tcx())),
empty_substs, None, &arena);
let bcx = init_function(&fcx, false, ty::FnConverging(ty::mk_nil(ccx.tcx())));
update_linkage(ccx, llfn, None, OriginalTranslation);
ccx.stats().n_glues_created.set(ccx.stats().n_glues_created.get() + 1);
// All glue functions take values passed *by alias*; this is a
// requirement since in many contexts glue is invoked indirectly and
// the caller has no idea if it's dealing with something that can be
// passed by value.
//
// llfn is expected be declared to take a parameter of the appropriate
// type, so we don't need to explicitly cast the function parameter.
let llrawptr0 = get_param(llfn, fcx.arg_pos(0) as c_uint);
let bcx = make_drop_glue(bcx, llrawptr0, t);
finish_fn(&fcx, bcx, ty::FnConverging(ty::mk_nil(ccx.tcx())), DebugLoc::None);
llfn
}
fn trans_struct_drop_flag<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
@ -386,51 +397,34 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>)
let _icx = push_ctxt("make_drop_glue");
match t.sty {
ty::ty_uniq(content_ty) => {
match content_ty.sty {
ty::ty_vec(ty, None) => {
tvec::make_drop_glue_unboxed(bcx, v0, ty, true)
}
ty::ty_str => {
let unit_ty = ty::sequence_element_type(bcx.tcx(), content_ty);
tvec::make_drop_glue_unboxed(bcx, v0, unit_ty, true)
}
ty::ty_trait(..) => {
let lluniquevalue = GEPi(bcx, v0, &[0, abi::FAT_PTR_ADDR]);
// Only drop the value when it is non-null
let concrete_ptr = Load(bcx, lluniquevalue);
with_cond(bcx, IsNotNull(bcx, concrete_ptr), |bcx| {
let dtor_ptr = Load(bcx, GEPi(bcx, v0, &[0, abi::FAT_PTR_EXTRA]));
let dtor = Load(bcx, dtor_ptr);
Call(bcx,
dtor,
&[PointerCast(bcx, lluniquevalue, Type::i8p(bcx.ccx()))],
None,
DebugLoc::None);
bcx
})
}
ty::ty_struct(..) if !type_is_sized(bcx.tcx(), content_ty) => {
let llval = GEPi(bcx, v0, &[0, abi::FAT_PTR_ADDR]);
let llbox = Load(bcx, llval);
let not_null = IsNotNull(bcx, llbox);
with_cond(bcx, not_null, |bcx| {
let bcx = drop_ty(bcx, v0, content_ty, DebugLoc::None);
let info = GEPi(bcx, v0, &[0, abi::FAT_PTR_EXTRA]);
let info = Load(bcx, info);
let (llsize, llalign) = size_and_align_of_dst(bcx, content_ty, info);
if !type_is_sized(bcx.tcx(), content_ty) {
let llval = GEPi(bcx, v0, &[0, abi::FAT_PTR_ADDR]);
let llbox = Load(bcx, llval);
let not_null = IsNotNull(bcx, llbox);
with_cond(bcx, not_null, |bcx| {
let bcx = drop_ty(bcx, v0, content_ty, DebugLoc::None);
let info = GEPi(bcx, v0, &[0, abi::FAT_PTR_EXTRA]);
let info = Load(bcx, info);
let (llsize, llalign) = size_and_align_of_dst(bcx, content_ty, info);
// `Box<ZeroSizeType>` does not allocate.
let needs_free = ICmp(bcx,
llvm::IntNE,
llsize,
C_uint(bcx.ccx(), 0u64),
DebugLoc::None);
with_cond(bcx, needs_free, |bcx| {
trans_exchange_free_dyn(bcx, llbox, llsize, llalign, DebugLoc::None)
})
}
_ => {
assert!(type_is_sized(bcx.tcx(), content_ty));
let llval = v0;
let llbox = Load(bcx, llval);
let not_null = IsNotNull(bcx, llbox);
with_cond(bcx, not_null, |bcx| {
let bcx = drop_ty(bcx, llbox, content_ty, DebugLoc::None);
trans_exchange_free_ty(bcx, llbox, content_ty, DebugLoc::None)
})
}
})
} else {
let llval = v0;
let llbox = Load(bcx, llval);
let not_null = IsNotNull(bcx, llbox);
with_cond(bcx, not_null, |bcx| {
let bcx = drop_ty(bcx, llbox, content_ty, DebugLoc::None);
trans_exchange_free_ty(bcx, llbox, content_ty, DebugLoc::None)
})
}
}
ty::ty_struct(did, substs) | ty::ty_enum(did, substs) => {
@ -462,34 +456,19 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>)
}
}
}
ty::ty_closure(..) => {
iter_structural_ty(bcx,
v0,
t,
|bb, vv, tt| drop_ty(bb, vv, tt, DebugLoc::None))
}
ty::ty_trait(..) => {
// No need to do a null check here (as opposed to the Box<trait case
// above), because this happens for a trait field in an unsized
// struct. If anything is null, it is the whole struct and we won't
// get here.
let lluniquevalue = GEPi(bcx, v0, &[0, abi::FAT_PTR_ADDR]);
let dtor_ptr = Load(bcx, GEPi(bcx, v0, &[0, abi::FAT_PTR_EXTRA]));
let dtor = Load(bcx, dtor_ptr);
let data_ptr = GEPi(bcx, v0, &[0, abi::FAT_PTR_ADDR]);
let vtable_ptr = Load(bcx, GEPi(bcx, v0, &[0, abi::FAT_PTR_EXTRA]));
let dtor = Load(bcx, vtable_ptr);
Call(bcx,
dtor,
&[PointerCast(bcx, Load(bcx, lluniquevalue), Type::i8p(bcx.ccx()))],
&[PointerCast(bcx, Load(bcx, data_ptr), Type::i8p(bcx.ccx()))],
None,
DebugLoc::None);
bcx
},
ty::ty_vec(_, None) | ty::ty_str => {
let unit_ty = ty::sequence_element_type(bcx.tcx(), t);
tvec::make_drop_glue_unboxed(bcx, v0, unit_ty, false)
},
}
_ => {
assert!(type_is_sized(bcx.tcx(), t));
if bcx.fcx.type_needs_drop(t) && ty::type_is_structural(t) {
if bcx.fcx.type_needs_drop(t) {
iter_structural_ty(bcx,
v0,
t,
@ -500,124 +479,3 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>)
}
}
}
// Generates the declaration for (but doesn't emit) a type descriptor.
pub fn declare_tydesc<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>)
-> tydesc_info<'tcx> {
// If emit_tydescs already ran, then we shouldn't be creating any new
// tydescs.
assert!(!ccx.finished_tydescs().get());
// This really shouldn't be like this, size/align will be wrong for
// unsized types (i.e. [T] will have the size/align of T).
// But we need it until we split this out into a "type name" intrinsic.
let llty = type_of::in_memory_type_of(ccx, t);
if ccx.sess().count_type_sizes() {
println!("{}\t{}", llsize_of_real(ccx, llty),
ppaux::ty_to_string(ccx.tcx(), t));
}
let llsize = llsize_of(ccx, llty);
let llalign = llalign_of(ccx, llty);
let name = mangle_internal_name_by_type_and_seq(ccx, t, "tydesc");
debug!("+++ declare_tydesc {} {}", ppaux::ty_to_string(ccx.tcx(), t), name);
let buf = CString::new(name.clone()).unwrap();
let gvar = unsafe {
llvm::LLVMAddGlobal(ccx.llmod(), ccx.tydesc_type().to_ref(),
buf.as_ptr())
};
note_unique_llvm_symbol(ccx, name);
let ty_name = token::intern_and_get_ident(
&ppaux::ty_to_string(ccx.tcx(), t));
let ty_name = C_str_slice(ccx, ty_name);
debug!("--- declare_tydesc {}", ppaux::ty_to_string(ccx.tcx(), t));
tydesc_info {
ty: t,
tydesc: gvar,
size: llsize,
align: llalign,
name: ty_name,
}
}
fn declare_generic_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>,
llfnty: Type, name: &str) -> (String, ValueRef) {
let _icx = push_ctxt("declare_generic_glue");
let fn_nm = mangle_internal_name_by_type_and_seq(
ccx,
t,
&format!("glue_{}", name));
let llfn = decl_cdecl_fn(ccx, &fn_nm[..], llfnty, ty::mk_nil(ccx.tcx()));
note_unique_llvm_symbol(ccx, fn_nm.clone());
return (fn_nm, llfn);
}
fn make_generic_glue<'a, 'tcx, F>(ccx: &CrateContext<'a, 'tcx>,
t: Ty<'tcx>,
llfn: ValueRef,
helper: F,
name: &str)
-> ValueRef where
F: for<'blk> FnOnce(Block<'blk, 'tcx>, ValueRef, Ty<'tcx>) -> Block<'blk, 'tcx>,
{
let _icx = push_ctxt("make_generic_glue");
let glue_name = format!("glue {} {}", name, ty_to_short_str(ccx.tcx(), t));
let _s = StatRecorder::new(ccx, glue_name);
let empty_substs = ccx.tcx().mk_substs(Substs::trans_empty());
let (arena, fcx): (TypedArena<_>, FunctionContext);
arena = TypedArena::new();
fcx = new_fn_ctxt(ccx, llfn, ast::DUMMY_NODE_ID, false,
ty::FnConverging(ty::mk_nil(ccx.tcx())),
empty_substs, None, &arena);
let bcx = init_function(&fcx, false, ty::FnConverging(ty::mk_nil(ccx.tcx())));
update_linkage(ccx, llfn, None, OriginalTranslation);
ccx.stats().n_glues_created.set(ccx.stats().n_glues_created.get() + 1);
// All glue functions take values passed *by alias*; this is a
// requirement since in many contexts glue is invoked indirectly and
// the caller has no idea if it's dealing with something that can be
// passed by value.
//
// llfn is expected be declared to take a parameter of the appropriate
// type, so we don't need to explicitly cast the function parameter.
let llrawptr0 = get_param(llfn, fcx.arg_pos(0) as c_uint);
let bcx = helper(bcx, llrawptr0, t);
finish_fn(&fcx, bcx, ty::FnConverging(ty::mk_nil(ccx.tcx())), DebugLoc::None);
llfn
}
pub fn emit_tydescs(ccx: &CrateContext) {
let _icx = push_ctxt("emit_tydescs");
// As of this point, allow no more tydescs to be created.
ccx.finished_tydescs().set(true);
let glue_fn_ty = Type::generic_glue_fn(ccx).ptr_to();
for (_, ti) in &*ccx.tydescs().borrow() {
// Each of the glue functions needs to be cast to a generic type
// before being put into the tydesc because we only have a singleton
// tydesc type. Then we'll recast each function to its real type when
// calling it.
let drop_glue = consts::ptrcast(get_drop_glue(ccx, ti.ty), glue_fn_ty);
ccx.stats().n_real_glues.set(ccx.stats().n_real_glues.get() + 1);
let tydesc = C_named_struct(ccx.tydesc_type(),
&[ti.size, // size
ti.align, // align
drop_glue, // drop_glue
ti.name]); // name
unsafe {
let gvar = ti.tydesc;
llvm::LLVMSetInitializer(gvar, tydesc);
llvm::LLVMSetGlobalConstant(gvar, True);
llvm::SetLinkage(gvar, llvm::InternalLinkage);
}
};
}

View File

@ -347,15 +347,10 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
bcx = src.store_to(bcx, llargs[0]);
C_nil(ccx)
}
(_, "get_tydesc") => {
(_, "type_name") => {
let tp_ty = *substs.types.get(FnSpace, 0);
let static_ti = get_tydesc(ccx, tp_ty);
// FIXME (#3730): ideally this shouldn't need a cast,
// but there's a circularity between translating rust types to llvm
// types and having a tydesc type available. So I can't directly access
// the llvm type of intrinsic::TyDesc struct.
PointerCast(bcx, static_ti.tydesc, llret_ty)
let ty_name = token::intern_and_get_ident(&ty_to_string(ccx.tcx(), tp_ty));
C_str_slice(ccx, ty_name)
}
(_, "type_id") => {
let hash = ty::hash_crate_independent(

View File

@ -12,9 +12,7 @@
#![allow(non_camel_case_types)]
use llvm;
use llvm::{ValueRef};
use llvm::False;
use llvm::{self, ValueRef};
use trans::common::*;
use trans::type_::Type;
@ -101,16 +99,6 @@ pub fn llalign_of_min(cx: &CrateContext, ty: Type) -> llalign {
}
}
// Returns the "default" alignment of t, which is calculated by casting
// null to a record containing a single-bit followed by a t value, then
// doing gep(0,1) to get at the trailing (and presumably padded) t cell.
pub fn llalign_of(cx: &CrateContext, ty: Type) -> ValueRef {
unsafe {
return llvm::LLVMConstIntCast(
llvm::LLVMAlignOf(ty.to_ref()), cx.int_type().to_ref(), False);
}
}
pub fn llelement_offset(cx: &CrateContext, struct_ty: Type, element: uint) -> u64 {
unsafe {
return llvm::LLVMOffsetOfElement(cx.td().lltd, struct_ty.to_ref(),

View File

@ -680,11 +680,8 @@ pub fn trans_object_shim<'a, 'tcx>(
///
/// The `trait_ref` encodes the erased self type. Hence if we are
/// making an object `Foo<Trait>` from a value of type `Foo<T>`, then
/// `trait_ref` would map `T:Trait`, but `box_ty` would be
/// `Foo<T>`. This `box_ty` is primarily used to encode the destructor.
/// This will hopefully change now that DST is underway.
/// `trait_ref` would map `T:Trait`.
pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
box_ty: Ty<'tcx>,
trait_ref: ty::PolyTraitRef<'tcx>,
param_substs: &'tcx subst::Substs<'tcx>)
-> ValueRef
@ -692,13 +689,10 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
let tcx = ccx.tcx();
let _icx = push_ctxt("meth::get_vtable");
debug!("get_vtable(box_ty={}, trait_ref={})",
box_ty.repr(tcx),
trait_ref.repr(tcx));
debug!("get_vtable(trait_ref={})", trait_ref.repr(tcx));
// Check the cache.
let cache_key = (box_ty, trait_ref.clone());
match ccx.vtables().borrow().get(&cache_key) {
match ccx.vtables().borrow().get(&trait_ref) {
Some(&val) => { return val }
None => { }
}
@ -755,7 +749,7 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
let components: Vec<_> = vec![
// Generate a destructor for the vtable.
glue::get_drop_glue(ccx, box_ty),
glue::get_drop_glue(ccx, trait_ref.self_ty()),
C_uint(ccx, size),
C_uint(ccx, align)
].into_iter().chain(methods).collect();
@ -763,7 +757,7 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
let vtable = consts::addr_of(ccx, C_struct(ccx, &components, false),
"vtable", trait_ref.def_id().node);
ccx.vtables().borrow_mut().insert(cache_key, vtable);
ccx.vtables().borrow_mut().insert(trait_ref, vtable);
vtable
}
@ -842,16 +836,15 @@ pub fn trans_trait_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
debug!("trans_trait_cast: trait_ref={}",
trait_ref.repr(bcx.tcx()));
let datum_ty = datum.ty;
let llbox_ty = type_of(bcx.ccx(), datum_ty);
let llty = type_of(bcx.ccx(), datum.ty);
// Store the pointer into the first half of pair.
let llboxdest = GEPi(bcx, lldest, &[0, abi::FAT_PTR_ADDR]);
let llboxdest = PointerCast(bcx, llboxdest, llbox_ty.ptr_to());
let llboxdest = PointerCast(bcx, llboxdest, llty.ptr_to());
bcx = datum.store_to(bcx, llboxdest);
// Store the vtable into the second half of pair.
let vtable = get_vtable(bcx.ccx(), datum_ty, trait_ref, bcx.fcx.param_substs);
let vtable = get_vtable(bcx.ccx(), trait_ref, bcx.fcx.param_substs);
let llvtabledest = GEPi(bcx, lldest, &[0, abi::FAT_PTR_EXTRA]);
let llvtabledest = PointerCast(bcx, llvtabledest, val_ty(vtable).ptr_to());
Store(bcx, vtable, llvtabledest);

View File

@ -24,8 +24,6 @@ use trans::datum::*;
use trans::debuginfo::DebugLoc;
use trans::expr::{Dest, Ignore, SaveIn};
use trans::expr;
use trans::glue;
use trans::machine;
use trans::machine::llsize_of_alloc;
use trans::type_::Type;
use trans::type_of;
@ -35,79 +33,17 @@ use util::ppaux::ty_to_string;
use syntax::ast;
use syntax::parse::token::InternedString;
fn get_len(bcx: Block, vptr: ValueRef) -> ValueRef {
let _icx = push_ctxt("tvec::get_lenl");
Load(bcx, expr::get_len(bcx, vptr))
}
fn get_dataptr(bcx: Block, vptr: ValueRef) -> ValueRef {
let _icx = push_ctxt("tvec::get_dataptr");
Load(bcx, expr::get_dataptr(bcx, vptr))
}
pub fn make_drop_glue_unboxed<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
vptr: ValueRef,
unit_ty: Ty<'tcx>,
should_deallocate: bool)
-> Block<'blk, 'tcx> {
let not_null = IsNotNull(bcx, vptr);
with_cond(bcx, not_null, |bcx| {
let ccx = bcx.ccx();
let _icx = push_ctxt("tvec::make_drop_glue_unboxed");
let dataptr = get_dataptr(bcx, vptr);
let bcx = if bcx.fcx.type_needs_drop(unit_ty) {
let len = get_len(bcx, vptr);
iter_vec_raw(bcx,
dataptr,
unit_ty,
len,
|bb, vv, tt| glue::drop_ty(bb, vv, tt, DebugLoc::None))
} else {
bcx
};
if should_deallocate {
let llty = type_of::type_of(ccx, unit_ty);
let unit_size = llsize_of_alloc(ccx, llty);
if unit_size != 0 {
let len = get_len(bcx, vptr);
let not_empty = ICmp(bcx,
llvm::IntNE,
len,
C_uint(ccx, 0_u32),
DebugLoc::None);
with_cond(bcx, not_empty, |bcx| {
let llalign = C_uint(ccx, machine::llalign_of_min(ccx, llty));
let size = Mul(bcx, C_uint(ccx, unit_size), len, DebugLoc::None);
glue::trans_exchange_free_dyn(bcx,
dataptr,
size,
llalign,
DebugLoc::None)
})
} else {
bcx
}
} else {
bcx
}
})
}
#[derive(Copy)]
pub struct VecTypes<'tcx> {
pub unit_ty: Ty<'tcx>,
pub llunit_ty: Type,
pub llunit_alloc_size: u64
struct VecTypes<'tcx> {
unit_ty: Ty<'tcx>,
llunit_ty: Type
}
impl<'tcx> VecTypes<'tcx> {
pub fn to_string<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> String {
format!("VecTypes {{unit_ty={}, llunit_ty={}, llunit_alloc_size={}}}",
format!("VecTypes {{unit_ty={}, llunit_ty={}}}",
ty_to_string(ccx.tcx(), self.unit_ty),
ccx.tn().type_to_string(self.llunit_ty),
self.llunit_alloc_size)
ccx.tn().type_to_string(self.llunit_ty))
}
}
@ -221,12 +157,12 @@ pub fn trans_lit_str<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
}
}
pub fn write_content<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
vt: &VecTypes<'tcx>,
vstore_expr: &ast::Expr,
content_expr: &ast::Expr,
dest: Dest)
-> Block<'blk, 'tcx> {
fn write_content<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
vt: &VecTypes<'tcx>,
vstore_expr: &ast::Expr,
content_expr: &ast::Expr,
dest: Dest)
-> Block<'blk, 'tcx> {
let _icx = push_ctxt("tvec::write_content");
let fcx = bcx.fcx;
let mut bcx = bcx;
@ -315,28 +251,21 @@ pub fn write_content<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
}
}
pub fn vec_types_from_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
vec_expr: &ast::Expr)
-> VecTypes<'tcx> {
fn vec_types_from_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, vec_expr: &ast::Expr)
-> VecTypes<'tcx> {
let vec_ty = node_id_type(bcx, vec_expr.id);
vec_types(bcx, ty::sequence_element_type(bcx.tcx(), vec_ty))
}
pub fn vec_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
unit_ty: Ty<'tcx>)
-> VecTypes<'tcx> {
let ccx = bcx.ccx();
let llunit_ty = type_of::type_of(ccx, unit_ty);
let llunit_alloc_size = llsize_of_alloc(ccx, llunit_ty);
fn vec_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, unit_ty: Ty<'tcx>)
-> VecTypes<'tcx> {
VecTypes {
unit_ty: unit_ty,
llunit_ty: llunit_ty,
llunit_alloc_size: llunit_alloc_size
llunit_ty: type_of::type_of(bcx.ccx(), unit_ty)
}
}
pub fn elements_required(bcx: Block, content_expr: &ast::Expr) -> uint {
fn elements_required(bcx: Block, content_expr: &ast::Expr) -> uint {
//! Figure out the number of elements we need to store this content
match content_expr.node {
@ -401,12 +330,12 @@ pub fn get_base_and_len<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
}
}
pub fn iter_vec_loop<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
data_ptr: ValueRef,
vt: &VecTypes<'tcx>,
count: ValueRef,
f: F)
-> Block<'blk, 'tcx> where
fn iter_vec_loop<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
data_ptr: ValueRef,
vt: &VecTypes<'tcx>,
count: ValueRef,
f: F)
-> Block<'blk, 'tcx> where
F: FnOnce(Block<'blk, 'tcx>, ValueRef, Ty<'tcx>) -> Block<'blk, 'tcx>,
{
let _icx = push_ctxt("tvec::iter_vec_loop");
@ -426,7 +355,7 @@ pub fn iter_vec_loop<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
let bcx = loop_bcx;
let lleltptr = if vt.llunit_alloc_size == 0 {
let lleltptr = if llsize_of_alloc(bcx.ccx(), vt.llunit_ty) == 0 {
data_ptr
} else {
InBoundsGEP(bcx, data_ptr, &[loop_counter])
@ -454,7 +383,7 @@ pub fn iter_vec_raw<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
let vt = vec_types(bcx, unit_ty);
if vt.llunit_alloc_size == 0 {
if llsize_of_alloc(bcx.ccx(), vt.llunit_ty) == 0 {
// Special-case vectors with elements of size 0 so they don't go out of bounds (#9890)
iter_vec_loop(bcx, data_ptr, &vt, len, f)
} else {
@ -471,7 +400,7 @@ pub fn iter_vec_raw<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
let body_bcx = fcx.new_temp_block("iter_vec_loop_body");
let next_bcx = fcx.new_temp_block("iter_vec_next");
CondBr(header_bcx, not_yet_at_end, body_bcx.llbb, next_bcx.llbb, DebugLoc::None);
let body_bcx = f(body_bcx, data_ptr, vt.unit_ty);
let body_bcx = f(body_bcx, data_ptr, unit_ty);
AddIncomingToPhi(data_ptr, InBoundsGEP(body_bcx, data_ptr,
&[C_int(bcx.ccx(), 1)]),
body_bcx.llbb);

View File

@ -175,41 +175,10 @@ impl Type {
Type::array(&Type::i8p(ccx).ptr_to(), 1)
}
pub fn generic_glue_fn(cx: &CrateContext) -> Type {
match cx.tn().find_type("glue_fn") {
Some(ty) => return ty,
None => ()
}
let ty = Type::glue_fn(cx, Type::i8p(cx));
cx.tn().associate_type("glue_fn", &ty);
ty
}
pub fn glue_fn(ccx: &CrateContext, t: Type) -> Type {
Type::func(&[t], &Type::void(ccx))
}
pub fn tydesc(ccx: &CrateContext, str_slice_ty: Type) -> Type {
let mut tydesc = Type::named_struct(ccx, "tydesc");
let glue_fn_ty = Type::glue_fn(ccx, Type::i8p(ccx)).ptr_to();
let int_ty = Type::int(ccx);
// Must mirror:
//
// std::unstable::intrinsics::TyDesc
let elems = [int_ty, // size
int_ty, // align
glue_fn_ty, // drop
str_slice_ty]; // name
tydesc.set_struct_body(&elems, false);
tydesc
}
pub fn array(ty: &Type, len: u64) -> Type {
ty!(llvm::LLVMRustArrayType(ty.to_ref(), len))
}

View File

@ -5347,17 +5347,8 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
"needs_drop" => (1, Vec::new(), ccx.tcx.types.bool),
"owns_managed" => (1, Vec::new(), ccx.tcx.types.bool),
"get_tydesc" => {
let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
Ok(t) => t,
Err(s) => { span_fatal!(tcx.sess, it.span, E0240, "{}", &s[..]); }
};
let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
ty: tydesc_ty,
mutbl: ast::MutImmutable
});
(1, Vec::new(), td_ptr)
}
"type_name" => (1, Vec::new(), ty::mk_str_slice(tcx, tcx.mk_region(ty::ReStatic),
ast::MutImmutable)),
"type_id" => (1, Vec::new(), ccx.tcx.types.u64),
"offset" => {
(1,

View File

@ -102,15 +102,6 @@ use syntax::visit;
pub fn collect_item_types(tcx: &ty::ctxt) {
let ccx = &CrateCtxt { tcx: tcx, stack: RefCell::new(Vec::new()) };
match ccx.tcx.lang_items.ty_desc() {
Some(id) => { collect_intrinsic_type(ccx, id); }
None => {}
}
match ccx.tcx.lang_items.opaque() {
Some(id) => { collect_intrinsic_type(ccx, id); }
None => {}
}
let mut visitor = CollectTraitDefVisitor{ ccx: ccx };
visit::walk_crate(&mut visitor, ccx.tcx.map.krate());
@ -152,15 +143,6 @@ enum AstConvRequest {
GetTypeParameterBounds(ast::NodeId),
}
///////////////////////////////////////////////////////////////////////////
// Zeroth phase: collect types of intrinsics
fn collect_intrinsic_type(ccx: &CrateCtxt,
lang_item: ast::DefId) {
let ty::TypeScheme { ty, .. } = type_scheme_of_def_id(ccx, lang_item);
ccx.tcx.intrinsic_defs.borrow_mut().insert(lang_item, ty);
}
///////////////////////////////////////////////////////////////////////////
// First phase: just collect *trait definitions* -- basically, the set
// of type parameters and supertraits. This is information we need to

View File

@ -13,17 +13,17 @@ struct NT(str);
struct DST { a: u32, b: str }
fn main() {
// get_tydesc should support unsized types
// type_name should support unsized types
assert_eq!(unsafe {(
// Slice
(*std::intrinsics::get_tydesc::<[u8]>()).name,
std::intrinsics::type_name::<[u8]>(),
// str
(*std::intrinsics::get_tydesc::<str>()).name,
std::intrinsics::type_name::<str>(),
// Trait
(*std::intrinsics::get_tydesc::<Copy>()).name,
std::intrinsics::type_name::<Copy>(),
// Newtype
(*std::intrinsics::get_tydesc::<NT>()).name,
std::intrinsics::type_name::<NT>(),
// DST
(*std::intrinsics::get_tydesc::<DST>()).name
std::intrinsics::type_name::<DST>()
)}, ("[u8]", "str", "core::marker::Copy", "NT", "DST"));
}

View File

@ -9,7 +9,7 @@
// except according to those terms.
use std::intrinsics::get_tydesc;
use std::intrinsics::type_name;
struct Foo<T> {
x: T
@ -17,7 +17,7 @@ struct Foo<T> {
pub fn main() {
unsafe {
assert_eq!((*get_tydesc::<int>()).name, "isize");
assert_eq!((*get_tydesc::<Foo<uint>>()).name, "Foo<usize>");
assert_eq!(type_name::<int>(), "isize");
assert_eq!(type_name::<Foo<uint>>(), "Foo<usize>");
}
}