diff options
Diffstat (limited to 'src/librustc_trans/trans')
| -rw-r--r-- | src/librustc_trans/trans/_match.rs | 2 | ||||
| -rw-r--r-- | src/librustc_trans/trans/adt.rs | 2 | ||||
| -rw-r--r-- | src/librustc_trans/trans/base.rs | 5 | ||||
| -rw-r--r-- | src/librustc_trans/trans/common.rs | 20 | ||||
| -rw-r--r-- | src/librustc_trans/trans/consts.rs | 57 | ||||
| -rw-r--r-- | src/librustc_trans/trans/datum.rs | 18 | ||||
| -rw-r--r-- | src/librustc_trans/trans/debuginfo.rs | 1 | ||||
| -rw-r--r-- | src/librustc_trans/trans/expr.rs | 66 | ||||
| -rw-r--r-- | src/librustc_trans/trans/glue.rs | 20 | ||||
| -rw-r--r-- | src/librustc_trans/trans/meth.rs | 3 | ||||
| -rw-r--r-- | src/librustc_trans/trans/tvec.rs | 39 | ||||
| -rw-r--r-- | src/librustc_trans/trans/type_.rs | 8 | ||||
| -rw-r--r-- | src/librustc_trans/trans/type_of.rs | 164 |
13 files changed, 166 insertions, 239 deletions
diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs index 1a24b3fabf8..26e1a981f1b 100644 --- a/src/librustc_trans/trans/_match.rs +++ b/src/librustc_trans/trans/_match.rs @@ -678,7 +678,7 @@ fn bind_subslice_pat(bcx: Block, } fn extract_vec_elems<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - left_ty: Ty, + left_ty: Ty<'tcx>, before: uint, after: uint, val: ValueRef) diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs index 903de940207..3ea14d3c589 100644 --- a/src/librustc_trans/trans/adt.rs +++ b/src/librustc_trans/trans/adt.rs @@ -699,7 +699,7 @@ fn struct_llfields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, st: &Struct<'tcx>, st.fields.iter().filter(|&ty| !dst || type_is_sized(cx.tcx(), *ty)) .map(|&ty| type_of::sizing_type_of(cx, ty)).collect() } else { - st.fields.iter().map(|&ty| type_of::type_of(cx, ty)).collect() + st.fields.iter().map(|&ty| type_of::in_memory_type_of(cx, ty)).collect() } } diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 35b6ca7f0f5..b18b7b75d32 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -676,8 +676,7 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>, let val = if common::type_is_sized(cx.tcx(), field_ty) { llfld_a } else { - let boxed_ty = ty::mk_open(cx.tcx(), field_ty); - let scratch = datum::rvalue_scratch_datum(cx, boxed_ty, "__fat_ptr_iter"); + let scratch = datum::rvalue_scratch_datum(cx, field_ty, "__fat_ptr_iter"); Store(cx, llfld_a, GEPi(cx, scratch.val, &[0, abi::FAT_PTR_ADDR])); Store(cx, info.unwrap(), GEPi(cx, scratch.val, &[0, abi::FAT_PTR_EXTRA])); scratch.val @@ -1353,7 +1352,7 @@ fn build_cfg(tcx: &ty::ctxt, id: ast::NodeId) -> (ast::NodeId, Option<cfg::CFG>) // the clobbering of the existing value in the return slot. fn has_nested_returns(tcx: &ty::ctxt, cfg: &cfg::CFG, blk_id: ast::NodeId) -> bool { for n in cfg.graph.depth_traverse(cfg.entry) { - match tcx.map.find(n.id) { + match tcx.map.find(n.id()) { Some(ast_map::NodeExpr(ex)) => { if let ast::ExprRet(Some(ref ret_expr)) = ex.node { let mut visitor = FindNestedReturn::new(); diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index e92960ec7cd..a3ba506fc46 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -120,14 +120,16 @@ pub fn erase_regions<'tcx,T>(cx: &ty::ctxt<'tcx>, value: &T) -> T // Is the type's representation size known at compile time? pub fn type_is_sized<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool { let param_env = ty::empty_parameter_environment(tcx); - ty::type_is_sized(¶m_env, DUMMY_SP, ty) -} - -pub fn lltype_is_sized<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool { - match ty.sty { - ty::ty_open(_) => true, - _ => type_is_sized(cx, ty), + // FIXME(#4287) This can cause errors due to polymorphic recursion, + // a better span should be provided, if available. + let err_count = tcx.sess.err_count(); + let is_sized = ty::type_is_sized(¶m_env, DUMMY_SP, ty); + // Those errors aren't fatal, but an incorrect result can later + // trip over asserts in both rustc's trans and LLVM. + if err_count < tcx.sess.err_count() { + tcx.sess.abort_if_errors(); } + is_sized } pub fn type_is_fat_ptr<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool { @@ -211,9 +213,7 @@ pub fn type_needs_unwind_cleanup<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty< } } -pub fn type_needs_drop<'tcx>(cx: &ty::ctxt<'tcx>, - ty: Ty<'tcx>) - -> bool { +pub fn type_needs_drop<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool { ty::type_contents(cx, ty).needs_drop(cx) } diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index 3c0024712b2..5cbe9dd71fb 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -146,8 +146,8 @@ fn const_deref<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, (const_deref_ptr(cx, v), mt.ty) } else { // Derefing a fat pointer does not change the representation, - // just the type to ty_open. - (v, ty::mk_open(cx.tcx(), mt.ty)) + // just the type to the unsized contents. + (v, mt.ty) } } None => { @@ -290,15 +290,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // an optimisation, it is necessary for mutable vectors to // work properly. ty = match ty::deref(ty, true) { - Some(mt) => { - if type_is_sized(cx.tcx(), mt.ty) { - mt.ty - } else { - // Derefing a fat pointer does not change the representation, - // just the type to ty_open. - ty::mk_open(cx.tcx(), mt.ty) - } - } + Some(mt) => mt.ty, None => { cx.sess().bug(&format!("unexpected dereferenceable type {}", ty_to_string(cx.tcx(), ty))) @@ -319,11 +311,12 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, llconst = addr_of(cx, llconst, "autoref", e.id); } Some(box ty::AutoUnsize(ref k)) => { - let unsized_ty = ty::unsize_ty(cx.tcx(), ty, k, e.span); 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)); - let base = ptrcast(llconst, type_of::type_of(cx, unsized_ty).ptr_to()); + let unsized_ty = ty::unsize_ty(cx.tcx(), ty, k, e.span); + let ptr_ty = type_of::in_memory_type_of(cx, unsized_ty).ptr_to(); + let base = ptrcast(llconst, ptr_ty); let prev_const = cx.const_unsized().borrow_mut() .insert(base, llconst); assert!(prev_const.is_none() || prev_const == Some(llconst)); @@ -366,7 +359,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, }; unsafe { let _icx = push_ctxt("const_expr"); - return match e.node { + match e.node { ast::ExprLit(ref lit) => { const_lit(cx, e, &**lit) } @@ -386,7 +379,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let (te2, _) = const_expr(cx, &**e2, param_substs); let te2 = base::cast_shift_const_rhs(b, te1, te2); - return match b.node { + match b.node { ast::BiAdd => { if is_float { llvm::LLVMConstFAdd(te1, te2) } else { llvm::LLVMConstAdd(te1, te2) } @@ -440,7 +433,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ast::ExprUnary(u, ref e) => { let (te, ty) = const_expr(cx, &**e, param_substs); let is_float = ty::type_is_fp(ty); - return match u { + match u { ast::UnUniq | ast::UnDeref => { const_deref(cx, te, ty).0 } @@ -477,16 +470,10 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, }; let (arr, len) = match bt.sty { ty::ty_vec(_, Some(u)) => (bv, C_uint(cx, u)), - ty::ty_open(ty) => match ty.sty { - ty::ty_vec(_, None) | ty::ty_str => { - let e1 = const_get_elt(cx, bv, &[0]); - (const_deref_ptr(cx, e1), const_get_elt(cx, bv, &[1])) - }, - _ => cx.sess().span_bug(base.span, - &format!("index-expr base must be a vector \ - or string type, found {}", - ty_to_string(cx.tcx(), bt))) - }, + ty::ty_vec(_, None) | ty::ty_str => { + let e1 = const_get_elt(cx, bv, &[0]); + (const_deref_ptr(cx, e1), const_get_elt(cx, bv, &[1])) + } ty::ty_rptr(_, mt) => match mt.ty.sty { ty::ty_vec(_, Some(u)) => { (const_deref_ptr(cx, bv), C_uint(cx, u)) @@ -527,8 +514,8 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, if expr::cast_is_noop(basety, ety) { return v; } - return match (expr::cast_type_kind(cx.tcx(), basety), - expr::cast_type_kind(cx.tcx(), ety)) { + match (expr::cast_type_kind(cx.tcx(), basety), + expr::cast_type_kind(cx.tcx(), ety)) { (expr::cast_integral, expr::cast_integral) => { let s = ty::type_is_signed(basety) as Bool; @@ -597,13 +584,13 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } let opt_def = cx.tcx().def_map.borrow().get(&cur.id).cloned(); if let Some(def::DefStatic(def_id, _)) = opt_def { - return get_static_val(cx, def_id, ety); + get_static_val(cx, def_id, ety) + } else { + // If this isn't the address of a static, then keep going through + // normal constant evaluation. + let (v, _) = const_expr(cx, &**sub, param_substs); + addr_of(cx, v, "ref", e.id) } - - // If this isn't the address of a static, then keep going through - // normal constant evaluation. - let (v, _) = const_expr(cx, &**sub, param_substs); - addr_of(cx, v, "ref", e.id) } ast::ExprAddrOf(ast::MutMutable, ref sub) => { let (v, _) = const_expr(cx, &**sub, param_substs); @@ -753,7 +740,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } _ => cx.sess().span_bug(e.span, "bad constant expression type in consts::const_expr") - }; + } } } diff --git a/src/librustc_trans/trans/datum.rs b/src/librustc_trans/trans/datum.rs index e0598583a19..8262dbf55dd 100644 --- a/src/librustc_trans/trans/datum.rs +++ b/src/librustc_trans/trans/datum.rs @@ -492,8 +492,6 @@ impl<'tcx> Datum<'tcx, Expr> { -> DatumBlock<'blk, 'tcx, Lvalue> { debug!("to_lvalue_datum self: {}", self.to_string(bcx.ccx())); - assert!(lltype_is_sized(bcx.tcx(), self.ty), - "Trying to convert unsized value to lval"); self.match_kind( |l| DatumBlock::new(bcx, l), |r| { @@ -549,15 +547,10 @@ impl<'tcx> Datum<'tcx, Lvalue> { -> Datum<'tcx, Lvalue> where F: FnOnce(ValueRef) -> ValueRef, { - let val = match self.ty.sty { - _ if type_is_sized(bcx.tcx(), self.ty) => gep(self.val), - ty::ty_open(_) => { - let base = Load(bcx, expr::get_dataptr(bcx, self.val)); - gep(base) - } - _ => bcx.tcx().sess.bug( - &format!("Unexpected unsized type in get_element: {}", - bcx.ty_to_string(self.ty))) + let val = if type_is_sized(bcx.tcx(), self.ty) { + gep(self.val) + } else { + gep(Load(bcx, expr::get_dataptr(bcx, self.val))) }; Datum { val: val, @@ -566,7 +559,8 @@ impl<'tcx> Datum<'tcx, Lvalue> { } } - pub fn get_vec_base_and_len(&self, bcx: Block) -> (ValueRef, ValueRef) { + pub fn get_vec_base_and_len<'blk>(&self, bcx: Block<'blk, 'tcx>) + -> (ValueRef, ValueRef) { //! Converts a vector into the slice pair. tvec::get_base_and_len(bcx, self.val, self.ty) diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index b5cba9b6740..162881f58c7 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -3828,7 +3828,6 @@ fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } ty::ty_err | ty::ty_infer(_) | - ty::ty_open(_) | ty::ty_projection(..) | ty::ty_param(_) => { cx.sess().bug(&format!("debuginfo: Trying to create type name for \ diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index 78992959a6f..9e9ee453752 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -451,8 +451,6 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let datum_ty = datum.ty; let unsized_ty = ty::unsize_ty(tcx, datum_ty, k, expr.span); debug!("unsized_ty={}", unsized_ty.repr(bcx.tcx())); - let dest_ty = ty::mk_open(tcx, unsized_ty); - debug!("dest_ty={}", unsized_ty.repr(bcx.tcx())); let info = unsized_info(bcx.ccx(), k, expr.id, datum_ty, bcx.fcx.param_substs, |t| ty::mk_imm_rptr(tcx, tcx.mk_region(ty::ReStatic), t)); @@ -462,20 +460,16 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, datum.to_lvalue_datum(bcx, "into_fat_ptr", expr.id)); // Compute the base pointer. This doesn't change the pointer value, // but merely its type. - let base = match *k { - ty::UnsizeStruct(..) | ty::UnsizeVtable(..) => { - PointerCast(bcx, lval.val, type_of::type_of(bcx.ccx(), unsized_ty).ptr_to()) - } - ty::UnsizeLength(..) => { - GEPi(bcx, lval.val, &[0, 0]) - } - }; + let ptr_ty = type_of::in_memory_type_of(bcx.ccx(), unsized_ty).ptr_to(); + let base = PointerCast(bcx, lval.val, ptr_ty); - let scratch = rvalue_scratch_datum(bcx, dest_ty, "__fat_ptr"); - Store(bcx, base, get_dataptr(bcx, scratch.val)); - Store(bcx, info, get_len(bcx, scratch.val)); + let llty = type_of::type_of(bcx.ccx(), unsized_ty); + // HACK(eddyb) get around issues with lifetime intrinsics. + let scratch = alloca_no_lifetime(bcx, llty, "__fat_ptr"); + Store(bcx, base, get_dataptr(bcx, scratch)); + Store(bcx, info, get_len(bcx, scratch)); - DatumBlock::new(bcx, scratch.to_expr_datum()) + DatumBlock::new(bcx, Datum::new(scratch, unsized_ty, LvalueExpr)) } fn unsize_unique_vec<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, @@ -711,7 +705,7 @@ fn trans_field<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, let _icx = push_ctxt("trans_rec_field"); let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, base, "field")); - let bare_ty = ty::unopen_type(base_datum.ty); + let bare_ty = base_datum.ty; let repr = adt::represent_type(bcx.ccx(), bare_ty); with_field_tys(bcx.tcx(), bare_ty, None, move |discr, field_tys| { let ix = get_idx(bcx.tcx(), field_tys); @@ -723,7 +717,7 @@ fn trans_field<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, if type_is_sized(bcx.tcx(), d.ty) { DatumBlock { datum: d.to_expr_datum(), bcx: bcx } } else { - let scratch = rvalue_scratch_datum(bcx, ty::mk_open(bcx.tcx(), d.ty), ""); + let scratch = rvalue_scratch_datum(bcx, d.ty, ""); Store(bcx, d.val, get_dataptr(bcx, scratch.val)); let info = Load(bcx, get_len(bcx, base_datum.val)); Store(bcx, info, get_len(bcx, scratch.val)); @@ -809,7 +803,7 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, if type_is_sized(bcx.tcx(), elt_ty) { Datum::new(datum.to_llscalarish(bcx), elt_ty, LvalueExpr) } else { - Datum::new(datum.val, ty::mk_open(bcx.tcx(), elt_ty), LvalueExpr) + Datum::new(datum.val, elt_ty, LvalueExpr) } } None => { @@ -1671,7 +1665,7 @@ fn trans_uniq_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, fn ref_fat_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, lval: Datum<'tcx, Lvalue>) -> DatumBlock<'blk, 'tcx, Expr> { - let dest_ty = ty::close_type(bcx.tcx(), lval.ty); + let dest_ty = ty::mk_imm_rptr(bcx.tcx(), bcx.tcx().mk_region(ty::ReStatic), lval.ty); let scratch = rvalue_scratch_datum(bcx, dest_ty, "__fat_ptr"); memcpy_ty(bcx, scratch.val, lval.val, scratch.ty); @@ -1685,16 +1679,13 @@ fn trans_addr_of<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let _icx = push_ctxt("trans_addr_of"); let mut bcx = bcx; let sub_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, subexpr, "addr_of")); - match sub_datum.ty.sty { - ty::ty_open(_) => { - // Opened DST value, close to a fat pointer - ref_fat_ptr(bcx, sub_datum) - } - _ => { - // Sized value, ref to a thin pointer - let ty = expr_ty(bcx, expr); - immediate_rvalue_bcx(bcx, sub_datum.val, ty).to_expr_datumblock() - } + if !type_is_sized(bcx.tcx(), sub_datum.ty) { + // DST lvalue, close to a fat pointer + ref_fat_ptr(bcx, sub_datum) + } else { + // Sized value, ref to a thin pointer + let ty = expr_ty(bcx, expr); + immediate_rvalue_bcx(bcx, sub_datum.val, ty).to_expr_datumblock() } } @@ -2234,16 +2225,15 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, if type_is_sized(bcx.tcx(), content_ty) { deref_owned_pointer(bcx, expr, datum, content_ty) } else { - // A fat pointer and an opened DST value have the same - // representation just different types. Since there is no - // temporary for `*e` here (because it is unsized), we cannot - // emulate the sized object code path for running drop glue and - // free. Instead, we schedule cleanup for `e`, turning it into - // an lvalue. + // A fat pointer and a DST lvalue have the same representation + // just different types. Since there is no temporary for `*e` + // here (because it is unsized), we cannot emulate the sized + // object code path for running drop glue and free. Instead, + // we schedule cleanup for `e`, turning it into an lvalue. let datum = unpack_datum!( bcx, datum.to_lvalue_datum(bcx, "deref", expr.id)); - let datum = Datum::new(datum.val, ty::mk_open(bcx.tcx(), content_ty), LvalueExpr); + let datum = Datum::new(datum.val, content_ty, LvalueExpr); DatumBlock::new(bcx, datum) } } @@ -2260,11 +2250,9 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // owner (or, in the case of *T, by the user). DatumBlock::new(bcx, Datum::new(ptr, content_ty, LvalueExpr)) } else { - // A fat pointer and an opened DST value have the same representation + // A fat pointer and a DST lvalue have the same representation // just different types. - DatumBlock::new(bcx, Datum::new(datum.val, - ty::mk_open(bcx.tcx(), content_ty), - LvalueExpr)) + DatumBlock::new(bcx, Datum::new(datum.val, content_ty, LvalueExpr)) } } diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs index 20956bf795b..c14683aeade 100644 --- a/src/librustc_trans/trans/glue.rs +++ b/src/librustc_trans/trans/glue.rs @@ -34,7 +34,7 @@ use trans::expr; use trans::machine::*; use trans::tvec; use trans::type_::Type; -use trans::type_of::{type_of, sizing_type_of, align_of}; +use trans::type_of::{self, type_of, sizing_type_of, align_of}; use middle::ty::{self, Ty}; use util::ppaux::{ty_to_short_str, Repr}; use util::ppaux; @@ -265,8 +265,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, assert_eq!(params.len(), 1); let self_arg = if type_is_fat_ptr(bcx.tcx(), self_ty) { // The dtor expects a fat pointer, so make one, even if we have to fake it. - let boxed_ty = ty::mk_open(bcx.tcx(), t); - let scratch = datum::rvalue_scratch_datum(bcx, boxed_ty, "__fat_ptr_drop_self"); + let scratch = datum::rvalue_scratch_datum(bcx, t, "__fat_ptr_drop_self"); Store(bcx, value, GEPi(bcx, scratch.val, &[0, abi::FAT_PTR_ADDR])); Store(bcx, // If we just had a thin pointer, make a fat pointer by sticking @@ -284,20 +283,18 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, // Add all the fields as a value which needs to be cleaned at the end of // this scope. Iterate in reverse order so a Drop impl doesn't reverse // the order in which fields get dropped. - for (i, ty) in st.fields.iter().enumerate().rev() { + for (i, &ty) in st.fields.iter().enumerate().rev() { let llfld_a = adt::struct_field_ptr(variant_cx, &*st, value, i, false); - let val = if type_is_sized(bcx.tcx(), *ty) { + let val = if type_is_sized(bcx.tcx(), ty) { llfld_a } else { - let boxed_ty = ty::mk_open(bcx.tcx(), *ty); - let scratch = datum::rvalue_scratch_datum(bcx, boxed_ty, "__fat_ptr_drop_field"); + let scratch = datum::rvalue_scratch_datum(bcx, ty, "__fat_ptr_drop_field"); Store(bcx, llfld_a, GEPi(bcx, scratch.val, &[0, abi::FAT_PTR_ADDR])); Store(bcx, info.unwrap(), GEPi(bcx, scratch.val, &[0, abi::FAT_PTR_EXTRA])); scratch.val }; - variant_cx.fcx.schedule_drop_mem(cleanup::CustomScope(field_scope), - val, *ty); + variant_cx.fcx.schedule_drop_mem(cleanup::CustomScope(field_scope), val, ty); } let dtor_ty = ty::mk_ctor_fn(bcx.tcx(), @@ -502,7 +499,10 @@ pub fn declare_tydesc<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) // tydescs. assert!(!ccx.finished_tydescs().get()); - let llty = type_of(ccx, t); + // 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), diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 7644ecf2cfd..3411f12886d 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -818,9 +818,6 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, param_substs, substs.clone()).val; - // currently, at least, by-value self is not object safe - assert!(m.explicit_self != ty::ByValueExplicitSelfCategory); - Some(fn_ref).into_iter() } } diff --git a/src/librustc_trans/trans/tvec.rs b/src/librustc_trans/trans/tvec.rs index 7b59e0258ee..d3acd23e641 100644 --- a/src/librustc_trans/trans/tvec.rs +++ b/src/librustc_trans/trans/tvec.rs @@ -372,38 +372,31 @@ pub fn get_fixed_base_and_len(bcx: Block, (base, len) } -fn get_slice_base_and_len(bcx: Block, - llval: ValueRef) - -> (ValueRef, ValueRef) { - let base = Load(bcx, GEPi(bcx, llval, &[0, abi::FAT_PTR_ADDR])); - let len = Load(bcx, GEPi(bcx, llval, &[0, abi::FAT_PTR_EXTRA])); - (base, len) -} - /// Converts a vector into the slice pair. The vector should be stored in `llval` which should be /// by-reference. If you have a datum, you would probably prefer to call /// `Datum::get_base_and_len()` which will handle any conversions for you. -pub fn get_base_and_len(bcx: Block, - llval: ValueRef, - vec_ty: Ty) - -> (ValueRef, ValueRef) { +pub fn get_base_and_len<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, + llval: ValueRef, + vec_ty: Ty<'tcx>) + -> (ValueRef, ValueRef) { let ccx = bcx.ccx(); match vec_ty.sty { ty::ty_vec(_, Some(n)) => get_fixed_base_and_len(bcx, llval, n), - ty::ty_open(ty) => match ty.sty { - ty::ty_vec(_, None) | ty::ty_str => get_slice_base_and_len(bcx, llval), - _ => ccx.sess().bug("unexpected type in get_base_and_len") - }, + ty::ty_vec(_, None) | ty::ty_str => { + let base = Load(bcx, expr::get_dataptr(bcx, llval)); + let len = Load(bcx, expr::get_len(bcx, llval)); + (base, len) + } // Only used for pattern matching. - ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => match ty.sty { - ty::ty_vec(_, None) | ty::ty_str => get_slice_base_and_len(bcx, llval), - ty::ty_vec(_, Some(n)) => { - let base = GEPi(bcx, Load(bcx, llval), &[0, 0]); - (base, C_uint(ccx, n)) - } - _ => ccx.sess().bug("unexpected type in get_base_and_len"), + ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => { + let inner = if type_is_sized(bcx.tcx(), ty) { + Load(bcx, llval) + } else { + llval + }; + get_base_and_len(bcx, inner, ty) }, _ => ccx.sess().bug("unexpected type in get_base_and_len"), } diff --git a/src/librustc_trans/trans/type_.rs b/src/librustc_trans/trans/type_.rs index 0c69a7132a7..d5ec18e641b 100644 --- a/src/librustc_trans/trans/type_.rs +++ b/src/librustc_trans/trans/type_.rs @@ -232,14 +232,6 @@ impl Type { Type::glue_fn(ccx, Type::i8p(ccx)).ptr_to().ptr_to() } - pub fn opaque_trait(ccx: &CrateContext) -> Type { - Type::struct_(ccx, &[Type::opaque_trait_data(ccx).ptr_to(), Type::vtable_ptr(ccx)], false) - } - - pub fn opaque_trait_data(ccx: &CrateContext) -> Type { - Type::i8(ccx) - } - pub fn kind(&self) -> TypeKind { unsafe { llvm::LLVMGetTypeKind(self.to_ref()) diff --git a/src/librustc_trans/trans/type_of.rs b/src/librustc_trans/trans/type_of.rs index b53ea79804c..97278eb0512 100644 --- a/src/librustc_trans/trans/type_of.rs +++ b/src/librustc_trans/trans/type_of.rs @@ -10,8 +10,6 @@ #![allow(non_camel_case_types)] -pub use self::named_ty::*; - use middle::subst; use trans::adt; use trans::common::*; @@ -183,9 +181,8 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ } let llsizingty = match t.sty { - _ if !lltype_is_sized(cx.tcx(), t) => { - cx.sess().bug(&format!("trying to take the sizing type of {}, an unsized type", - ppaux::ty_to_string(cx.tcx(), t))) + _ if !type_is_sized(cx.tcx(), t) => { + Type::struct_(cx, &[Type::i8p(cx), Type::i8p(cx)], false) } ty::ty_bool => Type::bool(cx), @@ -232,15 +229,11 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ } } - ty::ty_open(_) => { - Type::struct_(cx, &[Type::i8p(cx), Type::i8p(cx)], false) - } - ty::ty_projection(..) | ty::ty_infer(..) | ty::ty_param(..) | ty::ty_err(..) => { cx.sess().bug(&format!("fictitious type {} in sizing_type_of()", ppaux::ty_to_string(cx.tcx(), t))) } - ty::ty_vec(_, None) | ty::ty_trait(..) | ty::ty_str => panic!("unreachable") + ty::ty_vec(_, None) | ty::ty_trait(..) | ty::ty_str => unreachable!() }; cx.llsizingtypes().borrow_mut().insert(t, llsizingty); @@ -270,25 +263,37 @@ pub fn arg_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type { } } -// NB: If you update this, be sure to update `sizing_type_of()` as well. -pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type { - fn type_of_unsize_info<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type { - // It is possible to end up here with a sized type. This happens with a - // struct which might be unsized, but is monomorphised to a sized type. - // In this case we'll fake a fat pointer with no unsize info (we use 0). - // However, its still a fat pointer, so we need some type use. - if type_is_sized(cx.tcx(), t) { - return Type::i8p(cx); - } - - match unsized_part_of_type(cx.tcx(), t).sty { - ty::ty_str | ty::ty_vec(..) => Type::uint_from_ty(cx, ast::TyUs(false)), - ty::ty_trait(_) => Type::vtable_ptr(cx), - _ => panic!("Unexpected type returned from unsized_part_of_type : {}", - t.repr(cx.tcx())) - } - } +/// Get the LLVM type corresponding to a Rust type, i.e. `middle::ty::Ty`. +/// This is the right LLVM type for an alloca containg a value of that type, +/// and the pointee of an Lvalue Datum (which is always a LLVM pointer). +/// For unsized types, the returned type is a fat pointer, thus the resulting +/// LLVM type for a `Trait` Lvalue is `{ i8*, void(i8*)** }*`, which is a double +/// indirection to the actual data, unlike a `i8` Lvalue, which is just `i8*`. +/// This is needed due to the treatment of immediate values, as a fat pointer +/// is too large for it to be placed in SSA value (by our rules). +/// For the raw type without far pointer indirection, see `in_memory_type_of`. +pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Type { + let ty = if !type_is_sized(cx.tcx(), ty) { + ty::mk_imm_ptr(cx.tcx(), ty) + } else { + ty + }; + in_memory_type_of(cx, ty) +} +/// Get the LLVM type corresponding to a Rust type, i.e. `middle::ty::Ty`. +/// This is the right LLVM type for a field/array element of that type, +/// and is the same as `type_of` for all Sized types. +/// Unsized types, however, are represented by a "minimal unit", e.g. +/// `[T]` becomes `T`, while `str` and `Trait` turn into `i8` - this +/// is useful for indexing slices, as `&[T]`'s data pointer is `T*`. +/// If the type is an unsized struct, the regular layout is generated, +/// with the inner-most trailing unsized field using the "minimal unit" +/// of that field's type - this is useful for taking the address of +/// that field and ensuring the struct has the right alignment. +/// For the LLVM type of a value as a whole, see `type_of`. +/// NB: If you update this, be sure to update `sizing_type_of()` as well. +pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type { // Check the cache. match cx.lltypes().borrow().get(&t) { Some(&llty) => return llty, @@ -307,7 +312,7 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type { let t_norm = erase_regions(cx.tcx(), &t); if t != t_norm { - let llty = type_of(cx, t_norm); + let llty = in_memory_type_of(cx, t_norm); debug!("--> normalized {} {:?} to {} {:?} llty={}", t.repr(cx.tcx()), t, @@ -331,10 +336,10 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type { // of the enum's variants refers to the enum itself. let repr = adt::represent_type(cx, t); let tps = substs.types.get_slice(subst::TypeSpace); - let name = llvm_type_name(cx, an_enum, did, tps); + let name = llvm_type_name(cx, did, tps); adt::incomplete_type_of(cx, &*repr, &name[..]) } - ty::ty_closure(did, _, ref substs) => { + ty::ty_closure(..) => { // Only create the named struct, but don't fill it in. We // fill it in *after* placing it into the type cache. let repr = adt::represent_type(cx, t); @@ -342,41 +347,47 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type { // inherited from their environment, so we use entire // contents of the VecPerParamSpace to to construct the llvm // name - let name = llvm_type_name(cx, a_closure, did, substs.types.as_slice()); - adt::incomplete_type_of(cx, &*repr, &name[..]) + adt::incomplete_type_of(cx, &*repr, "closure") } ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) | ty::ty_ptr(ty::mt{ty, ..}) => { - match ty.sty { - ty::ty_str => { + if !type_is_sized(cx.tcx(), ty) { + if let ty::ty_str = ty.sty { // This means we get a nicer name in the output (str is always // unsized). cx.tn().find_type("str_slice").unwrap() + } else { + let ptr_ty = in_memory_type_of(cx, ty).ptr_to(); + let unsized_part = unsized_part_of_type(cx.tcx(), ty); + let info_ty = match unsized_part.sty { + ty::ty_str | ty::ty_vec(..) => { + Type::uint_from_ty(cx, ast::TyUs(false)) + } + ty::ty_trait(_) => Type::vtable_ptr(cx), + _ => panic!("Unexpected type returned from \ + unsized_part_of_type: {} for ty={}", + unsized_part.repr(cx.tcx()), ty.repr(cx.tcx())) + }; + Type::struct_(cx, &[ptr_ty, info_ty], false) } - ty::ty_trait(..) => Type::opaque_trait(cx), - _ if !type_is_sized(cx.tcx(), ty) => { - let p_ty = type_of(cx, ty).ptr_to(); - Type::struct_(cx, &[p_ty, type_of_unsize_info(cx, ty)], false) - } - _ => type_of(cx, ty).ptr_to(), + } else { + in_memory_type_of(cx, ty).ptr_to() } } ty::ty_vec(ty, Some(size)) => { let size = size as u64; - let llty = type_of(cx, ty); + let llty = in_memory_type_of(cx, ty); ensure_array_fits_in_address_space(cx, llty, size, t); Type::array(&llty, size) } - ty::ty_vec(ty, None) => { - type_of(cx, ty) - } - ty::ty_trait(..) => { - Type::opaque_trait_data(cx) - } - - ty::ty_str => Type::i8(cx), + // Unsized slice types (and str) have the type of their element, and + // traits have the type of u8. This is so that the data pointer inside + // fat pointers is of the right type (e.g. for array accesses), even + // when taking the address of an unsized field in a struct. + ty::ty_vec(ty, None) => in_memory_type_of(cx, ty), + ty::ty_str | ty::ty_trait(..) => Type::i8(cx), ty::ty_bare_fn(..) => { type_of_fn_from_ty(cx, t).ptr_to() @@ -388,7 +399,7 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type { } ty::ty_struct(did, ref substs) => { if ty::type_is_simd(cx.tcx(), t) { - let llet = type_of(cx, ty::simd_type(cx.tcx(), t)); + let llet = in_memory_type_of(cx, ty::simd_type(cx.tcx(), t)); let n = ty::simd_size(cx.tcx(), t) as u64; ensure_array_fits_in_address_space(cx, llet, n, t); Type::vector(&llet, n) @@ -398,29 +409,11 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type { // infinite recursion with recursive struct types. let repr = adt::represent_type(cx, t); let tps = substs.types.get_slice(subst::TypeSpace); - let name = llvm_type_name(cx, a_struct, did, tps); + let name = llvm_type_name(cx, did, tps); adt::incomplete_type_of(cx, &*repr, &name[..]) } } - ty::ty_open(t) => match t.sty { - ty::ty_struct(..) => { - let p_ty = type_of(cx, t).ptr_to(); - Type::struct_(cx, &[p_ty, type_of_unsize_info(cx, t)], false) - } - ty::ty_vec(ty, None) => { - let p_ty = type_of(cx, ty).ptr_to(); - Type::struct_(cx, &[p_ty, type_of_unsize_info(cx, t)], false) - } - ty::ty_str => { - let p_ty = Type::i8p(cx); - Type::struct_(cx, &[p_ty, type_of_unsize_info(cx, t)], false) - } - ty::ty_trait(..) => Type::opaque_trait(cx), - _ => cx.sess().bug(&format!("ty_open with sized type: {}", - ppaux::ty_to_string(cx.tcx(), t))) - }, - ty::ty_infer(..) => cx.sess().bug("type_of with ty_infer"), ty::ty_projection(..) => cx.sess().bug("type_of with ty_projection"), ty::ty_param(..) => cx.sess().bug("type_of with ty_param"), @@ -444,7 +437,7 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type { _ => () } - return llty; + llty } pub fn align_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) @@ -453,37 +446,22 @@ pub fn align_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) machine::llalign_of_min(cx, llty) } -// Want refinements! (Or case classes, I guess -#[derive(Copy)] -pub enum named_ty { - a_struct, - an_enum, - a_closure, -} - -pub fn llvm_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, - what: named_ty, - did: ast::DefId, - tps: &[Ty<'tcx>]) - -> String { - let name = match what { - a_struct => "struct", - an_enum => "enum", - a_closure => return "closure".to_string(), - }; - +fn llvm_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, + did: ast::DefId, + tps: &[Ty<'tcx>]) + -> String { let base = ty::item_path_str(cx.tcx(), did); let strings: Vec<String> = tps.iter().map(|t| t.repr(cx.tcx())).collect(); let tstr = if strings.is_empty() { base } else { - format!("{}<{:?}>", base, strings) + format!("{}<{}>", base, strings.connect(", ")) }; if did.krate == 0 { - format!("{}.{}", name, tstr) + tstr } else { - format!("{}.{}[{}{}]", name, tstr, "#", did.krate) + format!("{}.{}", did.krate, tstr) } } |
