StructGEP(bcx, fat_ptr, abi::FAT_PTR_ADDR)
}
+pub fn get_meta_builder(b: &Builder, fat_ptr: ValueRef) -> ValueRef {
+ b.struct_gep(fat_ptr, abi::FAT_PTR_EXTRA)
+}
+
+pub fn get_dataptr_builder(b: &Builder, fat_ptr: ValueRef) -> ValueRef {
+ b.struct_gep(fat_ptr, abi::FAT_PTR_ADDR)
+}
+
fn require_alloc_fn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, info_ty: Ty<'tcx>, it: LangItem) -> DefId {
match bcx.tcx().lang_items.require(it) {
Ok(id) => id,
pub fn load_fat_ptr<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
src: ValueRef,
- _ty: Ty<'tcx>)
- -> (ValueRef, ValueRef) {
- // FIXME: emit metadata
- (Load(cx, get_dataptr(cx, src)),
- Load(cx, get_meta(cx, src)))
+ ty: Ty<'tcx>)
+ -> (ValueRef, ValueRef)
+{
+ if cx.unreachable.get() {
+ // FIXME: remove me
+ return (Load(cx, get_dataptr(cx, src)),
+ Load(cx, get_meta(cx, src)));
+ }
+
+ load_fat_ptr_builder(&B(cx), src, ty)
+}
+
+pub fn load_fat_ptr_builder<'a, 'tcx>(
+ b: &Builder<'a, 'tcx>,
+ src: ValueRef,
+ t: Ty<'tcx>)
+ -> (ValueRef, ValueRef)
+{
+
+ let ptr = get_dataptr_builder(b, src);
+ let ptr = if t.is_region_ptr() || t.is_unique() {
+ b.load_nonnull(ptr)
+ } else {
+ b.load(ptr)
+ };
+
+ // FIXME: emit metadata on `meta`.
+ let meta = b.load(get_meta_builder(b, src));
+
+ (ptr, meta)
}
pub fn from_immediate(bcx: Block, val: ValueRef) -> ValueRef {
use super::{MirContext, LocalRef};
use super::analyze::CleanupKind;
use super::constant::Const;
-use super::lvalue::{LvalueRef, load_fat_ptr};
+use super::lvalue::{LvalueRef};
use super::operand::OperandRef;
use super::operand::OperandValue::*;
for (n, &ty) in arg_types.iter().enumerate() {
let ptr = adt::trans_field_ptr_builder(bcx, tuple.ty, base, Disr(0), n);
let val = if common::type_is_fat_ptr(bcx.tcx(), ty) {
- let (lldata, llextra) = load_fat_ptr(bcx, ptr);
+ let (lldata, llextra) = base::load_fat_ptr_builder(bcx, ptr, ty);
Pair(lldata, llextra)
} else {
// trans_argument will load this if it needs to
use rustc::mir::repr as mir;
use rustc::mir::tcx::LvalueTy;
use rustc_data_structures::indexed_vec::Idx;
-use abi;
use adt;
use base;
-use builder::Builder;
use common::{self, BlockAndBuilder, CrateContext, C_uint, C_undef};
use consts;
use machine;
}
}
-pub fn get_meta(b: &Builder, fat_ptr: ValueRef) -> ValueRef {
- b.struct_gep(fat_ptr, abi::FAT_PTR_EXTRA)
-}
-
-pub fn get_dataptr(b: &Builder, fat_ptr: ValueRef) -> ValueRef {
- b.struct_gep(fat_ptr, abi::FAT_PTR_ADDR)
-}
-
-pub fn load_fat_ptr(b: &Builder, fat_ptr: ValueRef) -> (ValueRef, ValueRef) {
- (b.load(get_dataptr(b, fat_ptr)), b.load(get_meta(b, fat_ptr)))
-}
-
impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
pub fn trans_lvalue(&mut self,
bcx: &BlockAndBuilder<'bcx, 'tcx>,
pub use self::constant::trans_static_initializer;
-use self::lvalue::{LvalueRef, get_dataptr, get_meta};
+use self::lvalue::{LvalueRef};
use rustc::mir::traversal;
use self::operand::{OperandRef, OperandValue};
// they are the two sub-fields of a single aggregate field.
let meta = &fcx.fn_ty.args[idx];
idx += 1;
- arg.store_fn_arg(bcx, &mut llarg_idx, get_dataptr(bcx, dst));
- meta.store_fn_arg(bcx, &mut llarg_idx, get_meta(bcx, dst));
+ arg.store_fn_arg(bcx, &mut llarg_idx,
+ base::get_dataptr_builder(bcx, dst));
+ meta.store_fn_arg(bcx, &mut llarg_idx,
+ base::get_meta_builder(bcx, dst));
} else {
arg.store_fn_arg(bcx, &mut llarg_idx, dst);
}
// so make an alloca to store them in.
let meta = &fcx.fn_ty.args[idx];
idx += 1;
- arg.store_fn_arg(bcx, &mut llarg_idx, get_dataptr(bcx, lltemp));
- meta.store_fn_arg(bcx, &mut llarg_idx, get_meta(bcx, lltemp));
+ arg.store_fn_arg(bcx, &mut llarg_idx,
+ base::get_dataptr_builder(bcx, lltemp));
+ meta.store_fn_arg(bcx, &mut llarg_idx,
+ base::get_meta_builder(bcx, lltemp));
} else {
// otherwise, arg is passed by value, so make a
// temporary and store it there
{
debug!("trans_load: {:?} @ {:?}", Value(llval), ty);
- let val = if common::type_is_imm_pair(bcx.ccx(), ty) {
+ let val = if common::type_is_fat_ptr(bcx.tcx(), ty) {
+ let (lldata, llextra) = base::load_fat_ptr_builder(bcx, llval, ty);
+ OperandValue::Pair(lldata, llextra)
+ } else if common::type_is_imm_pair(bcx.ccx(), ty) {
+ let [a_ty, b_ty] = common::type_pair_fields(bcx.ccx(), ty).unwrap();
let a_ptr = bcx.struct_gep(llval, 0);
let b_ptr = bcx.struct_gep(llval, 1);
- // This is None only for fat pointers, which don't
- // need any special load-time behavior anyway.
- let pair_fields = common::type_pair_fields(bcx.ccx(), ty);
- let (a, b) = if let Some([a_ty, b_ty]) = pair_fields {
- (base::load_ty_builder(bcx, a_ptr, a_ty),
- base::load_ty_builder(bcx, b_ptr, b_ty))
- } else {
- (bcx.load(a_ptr), bcx.load(b_ptr))
- };
- OperandValue::Pair(a, b)
+ OperandValue::Pair(
+ base::load_ty_builder(bcx, a_ptr, a_ty),
+ base::load_ty_builder(bcx, b_ptr, b_ty)
+ )
} else if common::type_is_immediate(bcx.ccx(), ty) {
OperandValue::Immediate(base::load_ty_builder(bcx, llval, ty))
} else {
use super::MirContext;
use super::constant::const_scalar_checked_binop;
use super::operand::{OperandRef, OperandValue};
-use super::lvalue::{LvalueRef, get_dataptr};
+use super::lvalue::{LvalueRef};
impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
pub fn trans_rvalue(&mut self,
let tr_elem = self.trans_operand(&bcx, elem);
let size = count.value.as_u64(bcx.tcx().sess.target.uint_type);
let size = C_uint(bcx.ccx(), size);
- let base = get_dataptr(&bcx, dest.llval);
+ let base = base::get_dataptr_builder(&bcx, dest.llval);
let bcx = bcx.map_block(|block| {
tvec::slice_for_each(block, base, tr_elem.ty, size, |block, llslot| {
self.store_operand_direct(block, llslot, tr_elem);