trans: generalize OperandValue::FatPtr to all pairs of immediates.
This commit is contained in:
parent
156b1fb9e1
commit
f1f453cf3b
@ -39,6 +39,7 @@ use monomorphize;
|
||||
use type_::Type;
|
||||
use value::Value;
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::layout::Layout;
|
||||
use rustc::traits::{self, SelectionContext, ProjectionMode};
|
||||
use rustc::ty::fold::TypeFoldable;
|
||||
use rustc::hir;
|
||||
@ -99,6 +100,63 @@ pub fn type_is_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns Some([a, b]) if the type has a pair of fields with types a and b.
|
||||
pub fn type_pair_fields<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>)
|
||||
-> Option<[Ty<'tcx>; 2]> {
|
||||
match ty.sty {
|
||||
ty::TyEnum(adt, substs) | ty::TyStruct(adt, substs) => {
|
||||
assert_eq!(adt.variants.len(), 1);
|
||||
let fields = &adt.variants[0].fields;
|
||||
if fields.len() != 2 {
|
||||
return None;
|
||||
}
|
||||
Some([monomorphize::field_ty(ccx.tcx(), substs, &fields[0]),
|
||||
monomorphize::field_ty(ccx.tcx(), substs, &fields[1])])
|
||||
}
|
||||
ty::TyClosure(_, ty::ClosureSubsts { upvar_tys: tys, .. }) |
|
||||
ty::TyTuple(tys) => {
|
||||
if tys.len() != 2 {
|
||||
return None;
|
||||
}
|
||||
Some([tys[0], tys[1]])
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if the type is represented as a pair of immediates.
|
||||
pub fn type_is_imm_pair<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>)
|
||||
-> bool {
|
||||
let tcx = ccx.tcx();
|
||||
let layout = tcx.normalizing_infer_ctxt(ProjectionMode::Any).enter(|infcx| {
|
||||
match ty.layout(&infcx) {
|
||||
Ok(layout) => layout,
|
||||
Err(err) => {
|
||||
bug!("type_is_imm_pair: layout for `{:?}` failed: {}",
|
||||
ty, err);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
match *layout {
|
||||
Layout::FatPointer { .. } => true,
|
||||
Layout::Univariant { ref variant, .. } => {
|
||||
// There must be only 2 fields.
|
||||
if variant.offset_after_field.len() != 2 {
|
||||
return false;
|
||||
}
|
||||
|
||||
match type_pair_fields(ccx, ty) {
|
||||
Some([a, b]) => {
|
||||
type_is_immediate(ccx, a) && type_is_immediate(ccx, b)
|
||||
}
|
||||
None => false
|
||||
}
|
||||
}
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
/// Identify types which have size zero at runtime.
|
||||
pub fn type_is_zero_size<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
use machine::llsize_of_alloc;
|
||||
|
@ -17,7 +17,7 @@ use adt;
|
||||
use base;
|
||||
use build;
|
||||
use callee::{Callee, CalleeData, Fn, Intrinsic, NamedTupleConstructor, Virtual};
|
||||
use common::{self, type_is_fat_ptr, Block, BlockAndBuilder, LandingPad};
|
||||
use common::{self, Block, BlockAndBuilder, LandingPad};
|
||||
use common::{C_bool, C_str_slice, C_struct, C_u32, C_undef};
|
||||
use consts;
|
||||
use debuginfo::DebugLoc;
|
||||
@ -36,7 +36,7 @@ use super::analyze::CleanupKind;
|
||||
use super::constant::Const;
|
||||
use super::lvalue::{LvalueRef, load_fat_ptr};
|
||||
use super::operand::OperandRef;
|
||||
use super::operand::OperandValue::{self, FatPtr, Immediate, Ref};
|
||||
use super::operand::OperandValue::*;
|
||||
|
||||
impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
pub fn trans_block(&mut self, bb: mir::BasicBlock) {
|
||||
@ -410,8 +410,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
let val = self.trans_operand(&bcx, arg).val;
|
||||
self.trans_argument(&bcx, val, &mut llargs, &fn_ty,
|
||||
let op = self.trans_operand(&bcx, arg);
|
||||
self.trans_argument(&bcx, op, &mut llargs, &fn_ty,
|
||||
&mut idx, &mut callee.data);
|
||||
}
|
||||
if let Some(tup) = untuple {
|
||||
@ -449,7 +449,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
|
||||
// Make a fake operand for store_return
|
||||
let op = OperandRef {
|
||||
val: OperandValue::Ref(dst),
|
||||
val: Ref(dst),
|
||||
ty: sig.output.unwrap()
|
||||
};
|
||||
self.store_return(&bcx, ret_dest, fn_ty.ret, op);
|
||||
@ -487,7 +487,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
ret_bcx.at_start(|ret_bcx| {
|
||||
debug_loc.apply_to_bcx(ret_bcx);
|
||||
let op = OperandRef {
|
||||
val: OperandValue::Immediate(invokeret),
|
||||
val: Immediate(invokeret),
|
||||
ty: sig.output.unwrap()
|
||||
};
|
||||
self.store_return(&ret_bcx, ret_dest, fn_ty.ret, op);
|
||||
@ -498,7 +498,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
fn_ty.apply_attrs_callsite(llret);
|
||||
if let Some((_, target)) = *destination {
|
||||
let op = OperandRef {
|
||||
val: OperandValue::Immediate(llret),
|
||||
val: Immediate(llret),
|
||||
ty: sig.output.unwrap()
|
||||
};
|
||||
self.store_return(&bcx, ret_dest, fn_ty.ret, op);
|
||||
@ -513,25 +513,36 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
|
||||
fn trans_argument(&mut self,
|
||||
bcx: &BlockAndBuilder<'bcx, 'tcx>,
|
||||
val: OperandValue,
|
||||
mut op: OperandRef<'tcx>,
|
||||
llargs: &mut Vec<ValueRef>,
|
||||
fn_ty: &FnType,
|
||||
next_idx: &mut usize,
|
||||
callee: &mut CalleeData) {
|
||||
// Treat the values in a fat pointer separately.
|
||||
if let FatPtr(ptr, meta) = val {
|
||||
if *next_idx == 0 {
|
||||
if let Virtual(idx) = *callee {
|
||||
let llfn = bcx.with_block(|bcx| {
|
||||
meth::get_virtual_method(bcx, meta, idx)
|
||||
});
|
||||
let llty = fn_ty.llvm_type(bcx.ccx()).ptr_to();
|
||||
*callee = Fn(bcx.pointercast(llfn, llty));
|
||||
if let Pair(a, b) = op.val {
|
||||
// Treat the values in a fat pointer separately.
|
||||
if common::type_is_fat_ptr(bcx.tcx(), op.ty) {
|
||||
let (ptr, meta) = (a, b);
|
||||
if *next_idx == 0 {
|
||||
if let Virtual(idx) = *callee {
|
||||
let llfn = bcx.with_block(|bcx| {
|
||||
meth::get_virtual_method(bcx, meta, idx)
|
||||
});
|
||||
let llty = fn_ty.llvm_type(bcx.ccx()).ptr_to();
|
||||
*callee = Fn(bcx.pointercast(llfn, llty));
|
||||
}
|
||||
}
|
||||
|
||||
let imm_op = |x| OperandRef {
|
||||
val: Immediate(x),
|
||||
// We won't be checking the type again.
|
||||
ty: bcx.tcx().types.err
|
||||
};
|
||||
self.trans_argument(bcx, imm_op(ptr), llargs, fn_ty, next_idx, callee);
|
||||
self.trans_argument(bcx, imm_op(meta), llargs, fn_ty, next_idx, callee);
|
||||
return;
|
||||
}
|
||||
self.trans_argument(bcx, Immediate(ptr), llargs, fn_ty, next_idx, callee);
|
||||
self.trans_argument(bcx, Immediate(meta), llargs, fn_ty, next_idx, callee);
|
||||
return;
|
||||
|
||||
op = op.pack_if_pair(bcx);
|
||||
}
|
||||
|
||||
let arg = &fn_ty.args[*next_idx];
|
||||
@ -547,7 +558,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
}
|
||||
|
||||
// Force by-ref if we have to load through a cast pointer.
|
||||
let (mut llval, by_ref) = match val {
|
||||
let (mut llval, by_ref) = match op.val {
|
||||
Immediate(llval) if arg.is_indirect() || arg.cast.is_some() => {
|
||||
let llscratch = build::AllocaFcx(bcx.fcx(), arg.original_ty, "arg");
|
||||
bcx.store(llval, llscratch);
|
||||
@ -555,7 +566,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
}
|
||||
Immediate(llval) => (llval, false),
|
||||
Ref(llval) => (llval, true),
|
||||
FatPtr(_, _) => bug!("fat pointers handled above")
|
||||
Pair(..) => bug!("pairs handled above")
|
||||
};
|
||||
|
||||
if by_ref && !arg.is_indirect() {
|
||||
@ -602,12 +613,16 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
let ptr = adt::trans_field_ptr_builder(bcx, &base_repr, base, Disr(0), n);
|
||||
let val = if common::type_is_fat_ptr(bcx.tcx(), ty) {
|
||||
let (lldata, llextra) = load_fat_ptr(bcx, ptr);
|
||||
FatPtr(lldata, llextra)
|
||||
Pair(lldata, llextra)
|
||||
} else {
|
||||
// trans_argument will load this if it needs to
|
||||
Ref(ptr)
|
||||
};
|
||||
self.trans_argument(bcx, val, llargs, fn_ty, next_idx, callee);
|
||||
let op = OperandRef {
|
||||
val: val,
|
||||
ty: ty
|
||||
};
|
||||
self.trans_argument(bcx, op, llargs, fn_ty, next_idx, callee);
|
||||
}
|
||||
|
||||
}
|
||||
@ -619,11 +634,29 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
elem = bcx.trunc(elem, Type::i1(bcx.ccx()));
|
||||
}
|
||||
// If the tuple is immediate, the elements are as well
|
||||
let val = Immediate(elem);
|
||||
self.trans_argument(bcx, val, llargs, fn_ty, next_idx, callee);
|
||||
let op = OperandRef {
|
||||
val: Immediate(elem),
|
||||
ty: ty
|
||||
};
|
||||
self.trans_argument(bcx, op, llargs, fn_ty, next_idx, callee);
|
||||
}
|
||||
}
|
||||
Pair(a, b) => {
|
||||
let elems = [a, b];
|
||||
for (n, &ty) in arg_types.iter().enumerate() {
|
||||
let mut elem = elems[n];
|
||||
// Truncate bools to i1, if needed
|
||||
if ty.is_bool() && common::val_ty(elem) != Type::i1(bcx.ccx()) {
|
||||
elem = bcx.trunc(elem, Type::i1(bcx.ccx()));
|
||||
}
|
||||
// Pair is always made up of immediates
|
||||
let op = OperandRef {
|
||||
val: Immediate(elem),
|
||||
ty: ty
|
||||
};
|
||||
self.trans_argument(bcx, op, llargs, fn_ty, next_idx, callee);
|
||||
}
|
||||
}
|
||||
FatPtr(_, _) => bug!("tuple is a fat pointer?!")
|
||||
}
|
||||
|
||||
}
|
||||
@ -779,7 +812,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
let f = Callee::def(bcx.ccx(), def_id, substs);
|
||||
let datum = f.reify(bcx.ccx());
|
||||
val = OperandRef {
|
||||
val: OperandValue::Immediate(datum.val),
|
||||
val: Immediate(datum.val),
|
||||
ty: datum.ty
|
||||
};
|
||||
}
|
||||
@ -806,17 +839,15 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
self.temps[idx as usize] = TempRef::Operand(Some(op));
|
||||
}
|
||||
DirectOperand(idx) => {
|
||||
let op = if type_is_fat_ptr(bcx.tcx(), op.ty) {
|
||||
let llval = op.immediate();
|
||||
let ptr = bcx.extract_value(llval, 0);
|
||||
let meta = bcx.extract_value(llval, 1);
|
||||
|
||||
OperandRef {
|
||||
val: OperandValue::FatPtr(ptr, meta),
|
||||
ty: op.ty
|
||||
}
|
||||
// If there is a cast, we have to store and reload.
|
||||
let op = if ret_ty.cast.is_some() {
|
||||
let tmp = bcx.with_block(|bcx| {
|
||||
base::alloc_ty(bcx, op.ty, "tmp_ret")
|
||||
});
|
||||
ret_ty.store(bcx, op.immediate(), tmp);
|
||||
self.trans_load(bcx, tmp, op.ty)
|
||||
} else {
|
||||
op
|
||||
op.unpack_if_pair(bcx)
|
||||
};
|
||||
self.temps[idx as usize] = TempRef::Operand(Some(op));
|
||||
}
|
||||
|
@ -98,9 +98,15 @@ impl<'tcx> Const<'tcx> {
|
||||
Const::new(val, ty)
|
||||
}
|
||||
|
||||
fn get_pair(&self) -> (ValueRef, ValueRef) {
|
||||
(const_get_elt(self.llval, &[0]),
|
||||
const_get_elt(self.llval, &[1]))
|
||||
}
|
||||
|
||||
fn get_fat_ptr(&self) -> (ValueRef, ValueRef) {
|
||||
(const_get_elt(self.llval, &[abi::FAT_PTR_ADDR as u32]),
|
||||
const_get_elt(self.llval, &[abi::FAT_PTR_EXTRA as u32]))
|
||||
assert_eq!(abi::FAT_PTR_ADDR, 0);
|
||||
assert_eq!(abi::FAT_PTR_EXTRA, 1);
|
||||
self.get_pair()
|
||||
}
|
||||
|
||||
fn as_lvalue(&self) -> ConstLvalue<'tcx> {
|
||||
@ -115,9 +121,9 @@ impl<'tcx> Const<'tcx> {
|
||||
let llty = type_of::immediate_type_of(ccx, self.ty);
|
||||
let llvalty = val_ty(self.llval);
|
||||
|
||||
let val = if common::type_is_fat_ptr(ccx.tcx(), self.ty) {
|
||||
let (data, extra) = self.get_fat_ptr();
|
||||
OperandValue::FatPtr(data, extra)
|
||||
let val = if common::type_is_imm_pair(ccx, self.ty) {
|
||||
let (a, b) = self.get_pair();
|
||||
OperandValue::Pair(a, b)
|
||||
} else if common::type_is_immediate(ccx, self.ty) && llty == llvalty {
|
||||
// If the types match, we can use the value directly.
|
||||
OperandValue::Immediate(self.llval)
|
||||
@ -656,7 +662,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
|
||||
consts::ptrcast(data_ptr, ll_cast_ty)
|
||||
}
|
||||
} else {
|
||||
bug!("Unexpected non-FatPtr operand")
|
||||
bug!("Unexpected non-fat-pointer operand")
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -13,12 +13,12 @@ use rustc::ty::Ty;
|
||||
use rustc::mir::repr as mir;
|
||||
use base;
|
||||
use common::{self, Block, BlockAndBuilder};
|
||||
use datum;
|
||||
use value::Value;
|
||||
use type_of;
|
||||
use type_::Type;
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use super::lvalue::load_fat_ptr;
|
||||
use super::{MirContext, TempRef};
|
||||
|
||||
/// The representation of a Rust value. The enum variant is in fact
|
||||
@ -31,9 +31,8 @@ pub enum OperandValue {
|
||||
Ref(ValueRef),
|
||||
/// A single LLVM value.
|
||||
Immediate(ValueRef),
|
||||
/// A fat pointer. The first ValueRef is the data and the second
|
||||
/// is the extra.
|
||||
FatPtr(ValueRef, ValueRef)
|
||||
/// A pair of immediate LLVM values. Used by fat pointers too.
|
||||
Pair(ValueRef, ValueRef)
|
||||
}
|
||||
|
||||
/// An `OperandRef` is an "SSA" reference to a Rust value, along with
|
||||
@ -64,15 +63,15 @@ impl<'tcx> fmt::Debug for OperandRef<'tcx> {
|
||||
write!(f, "OperandRef(Immediate({:?}) @ {:?})",
|
||||
Value(i), self.ty)
|
||||
}
|
||||
OperandValue::FatPtr(a, d) => {
|
||||
write!(f, "OperandRef(FatPtr({:?}, {:?}) @ {:?})",
|
||||
Value(a), Value(d), self.ty)
|
||||
OperandValue::Pair(a, b) => {
|
||||
write!(f, "OperandRef(Pair({:?}, {:?}) @ {:?})",
|
||||
Value(a), Value(b), self.ty)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> OperandRef<'tcx> {
|
||||
impl<'bcx, 'tcx> OperandRef<'tcx> {
|
||||
/// Asserts that this operand refers to a scalar and returns
|
||||
/// a reference to its value.
|
||||
pub fn immediate(self) -> ValueRef {
|
||||
@ -81,6 +80,54 @@ impl<'tcx> OperandRef<'tcx> {
|
||||
_ => bug!()
|
||||
}
|
||||
}
|
||||
|
||||
/// If this operand is a Pair, we return an
|
||||
/// Immediate aggregate with the two values.
|
||||
pub fn pack_if_pair(mut self, bcx: &BlockAndBuilder<'bcx, 'tcx>)
|
||||
-> OperandRef<'tcx> {
|
||||
if let OperandValue::Pair(a, b) = self.val {
|
||||
// Reconstruct the immediate aggregate.
|
||||
let llty = type_of::type_of(bcx.ccx(), self.ty);
|
||||
let mut llpair = common::C_undef(llty);
|
||||
let elems = [a, b];
|
||||
for i in 0..2 {
|
||||
let mut elem = elems[i];
|
||||
// Extend boolean i1's to i8.
|
||||
if common::val_ty(elem) == Type::i1(bcx.ccx()) {
|
||||
elem = bcx.zext(elem, Type::i8(bcx.ccx()));
|
||||
}
|
||||
llpair = bcx.insert_value(llpair, elem, i);
|
||||
}
|
||||
self.val = OperandValue::Immediate(llpair);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// If this operand is a pair in an Immediate,
|
||||
/// we return a Pair with the two halves.
|
||||
pub fn unpack_if_pair(mut self, bcx: &BlockAndBuilder<'bcx, 'tcx>)
|
||||
-> OperandRef<'tcx> {
|
||||
if let OperandValue::Immediate(llval) = self.val {
|
||||
// Deconstruct the immediate aggregate.
|
||||
if common::type_is_imm_pair(bcx.ccx(), self.ty) {
|
||||
let mut a = bcx.extract_value(llval, 0);
|
||||
let mut b = bcx.extract_value(llval, 1);
|
||||
|
||||
let pair_fields = common::type_pair_fields(bcx.ccx(), self.ty);
|
||||
if let Some([a_ty, b_ty]) = pair_fields {
|
||||
if a_ty.is_bool() {
|
||||
a = bcx.trunc(a, Type::i1(bcx.ccx()));
|
||||
}
|
||||
if b_ty.is_bool() {
|
||||
b = bcx.trunc(b, Type::i1(bcx.ccx()));
|
||||
}
|
||||
}
|
||||
|
||||
self.val = OperandValue::Pair(a, b);
|
||||
}
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
@ -92,15 +139,24 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
{
|
||||
debug!("trans_load: {:?} @ {:?}", Value(llval), ty);
|
||||
|
||||
let val = match datum::appropriate_rvalue_mode(bcx.ccx(), ty) {
|
||||
datum::ByValue => {
|
||||
OperandValue::Immediate(base::load_ty_builder(bcx, llval, ty))
|
||||
}
|
||||
datum::ByRef if common::type_is_fat_ptr(bcx.tcx(), ty) => {
|
||||
let (lldata, llextra) = load_fat_ptr(bcx, llval);
|
||||
OperandValue::FatPtr(lldata, llextra)
|
||||
}
|
||||
datum::ByRef => OperandValue::Ref(llval)
|
||||
let val = if common::type_is_imm_pair(bcx.ccx(), ty) {
|
||||
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)
|
||||
} else if common::type_is_immediate(bcx.ccx(), ty) {
|
||||
OperandValue::Immediate(base::load_ty_builder(bcx, llval, ty))
|
||||
} else {
|
||||
OperandValue::Ref(llval)
|
||||
};
|
||||
|
||||
OperandRef { val: val, ty: ty }
|
||||
@ -173,8 +229,12 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
match operand.val {
|
||||
OperandValue::Ref(r) => base::memcpy_ty(bcx, lldest, r, operand.ty),
|
||||
OperandValue::Immediate(s) => base::store_ty(bcx, s, lldest, operand.ty),
|
||||
OperandValue::FatPtr(data, extra) => {
|
||||
base::store_fat_ptr(bcx, data, extra, lldest, operand.ty);
|
||||
OperandValue::Pair(a, b) => {
|
||||
use build::*;
|
||||
let a = base::from_immediate(bcx, a);
|
||||
let b = base::from_immediate(bcx, b);
|
||||
Store(bcx, a, StructGEP(bcx, lldest, 0));
|
||||
Store(bcx, b, StructGEP(bcx, lldest, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,14 +16,12 @@ use rustc::mir::repr as mir;
|
||||
use asm;
|
||||
use base;
|
||||
use callee::Callee;
|
||||
use common::{self, val_ty,
|
||||
C_null, C_uint, C_undef, BlockAndBuilder, Result};
|
||||
use common::{self, val_ty, C_null, C_uint, BlockAndBuilder, Result};
|
||||
use datum::{Datum, Lvalue};
|
||||
use debuginfo::DebugLoc;
|
||||
use adt;
|
||||
use machine;
|
||||
use type_of;
|
||||
use type_::Type;
|
||||
use tvec;
|
||||
use value::Value;
|
||||
use Disr;
|
||||
@ -68,9 +66,10 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
// `CoerceUnsized` can be passed by a where-clause,
|
||||
// so the (generic) MIR may not be able to expand it.
|
||||
let operand = self.trans_operand(&bcx, source);
|
||||
let operand = operand.pack_if_pair(&bcx);
|
||||
bcx.with_block(|bcx| {
|
||||
match operand.val {
|
||||
OperandValue::FatPtr(..) => bug!(),
|
||||
OperandValue::Pair(..) => bug!(),
|
||||
OperandValue::Immediate(llval) => {
|
||||
// unsize from an immediate structure. We don't
|
||||
// really need a temporary alloca here, but
|
||||
@ -255,7 +254,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
assert!(common::type_is_fat_ptr(bcx.tcx(), cast_ty));
|
||||
|
||||
match operand.val {
|
||||
OperandValue::FatPtr(lldata, llextra) => {
|
||||
OperandValue::Pair(lldata, llextra) => {
|
||||
// unsize from a fat pointer - this is a
|
||||
// "trait-object-to-supertrait" coercion, for
|
||||
// example,
|
||||
@ -264,7 +263,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
// the types match up.
|
||||
let llcast_ty = type_of::fat_ptr_base_ty(bcx.ccx(), cast_ty);
|
||||
let lldata = bcx.pointercast(lldata, llcast_ty);
|
||||
OperandValue::FatPtr(lldata, llextra)
|
||||
OperandValue::Pair(lldata, llextra)
|
||||
}
|
||||
OperandValue::Immediate(lldata) => {
|
||||
// "standard" unsize
|
||||
@ -272,7 +271,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
base::unsize_thin_ptr(bcx, lldata,
|
||||
operand.ty, cast_ty)
|
||||
});
|
||||
OperandValue::FatPtr(lldata, llextra)
|
||||
OperandValue::Pair(lldata, llextra)
|
||||
}
|
||||
OperandValue::Ref(_) => {
|
||||
bug!("by-ref operand {:?} in trans_rvalue_operand",
|
||||
@ -343,13 +342,13 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
mir::CastKind::Misc => { // Casts from a fat-ptr.
|
||||
let ll_cast_ty = type_of::immediate_type_of(bcx.ccx(), cast_ty);
|
||||
let ll_from_ty = type_of::immediate_type_of(bcx.ccx(), operand.ty);
|
||||
if let OperandValue::FatPtr(data_ptr, meta_ptr) = operand.val {
|
||||
if let OperandValue::Pair(data_ptr, meta_ptr) = operand.val {
|
||||
if common::type_is_fat_ptr(bcx.tcx(), cast_ty) {
|
||||
let ll_cft = ll_cast_ty.field_types();
|
||||
let ll_fft = ll_from_ty.field_types();
|
||||
let data_cast = bcx.pointercast(data_ptr, ll_cft[0]);
|
||||
assert_eq!(ll_cft[1].kind(), ll_fft[1].kind());
|
||||
OperandValue::FatPtr(data_cast, meta_ptr)
|
||||
OperandValue::Pair(data_cast, meta_ptr)
|
||||
} else { // cast to thin-ptr
|
||||
// Cast of fat-ptr to thin-ptr is an extraction of data-ptr and
|
||||
// pointer-cast of that pointer to desired pointer type.
|
||||
@ -357,7 +356,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
OperandValue::Immediate(llval)
|
||||
}
|
||||
} else {
|
||||
bug!("Unexpected non-FatPtr operand")
|
||||
bug!("Unexpected non-Pair operand")
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -386,8 +385,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
}
|
||||
} else {
|
||||
OperandRef {
|
||||
val: OperandValue::FatPtr(tr_lvalue.llval,
|
||||
tr_lvalue.llextra),
|
||||
val: OperandValue::Pair(tr_lvalue.llval,
|
||||
tr_lvalue.llextra),
|
||||
ty: ref_ty,
|
||||
}
|
||||
};
|
||||
@ -408,8 +407,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
let rhs = self.trans_operand(&bcx, rhs);
|
||||
let llresult = if common::type_is_fat_ptr(bcx.tcx(), lhs.ty) {
|
||||
match (lhs.val, rhs.val) {
|
||||
(OperandValue::FatPtr(lhs_addr, lhs_extra),
|
||||
OperandValue::FatPtr(rhs_addr, rhs_extra)) => {
|
||||
(OperandValue::Pair(lhs_addr, lhs_extra),
|
||||
OperandValue::Pair(rhs_addr, rhs_extra)) => {
|
||||
bcx.with_block(|bcx| {
|
||||
base::compare_fat_ptrs(bcx,
|
||||
lhs_addr, lhs_extra,
|
||||
@ -441,7 +440,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
let val_ty = self.mir.binop_ty(bcx.tcx(), op, lhs.ty, rhs.ty);
|
||||
let operand_ty = bcx.tcx().mk_tup(vec![val_ty, bcx.tcx().types.bool]);
|
||||
let operand = OperandRef {
|
||||
val: OperandValue::Immediate(result),
|
||||
val: result,
|
||||
ty: operand_ty
|
||||
};
|
||||
|
||||
@ -579,7 +578,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
op: mir::BinOp,
|
||||
lhs: ValueRef,
|
||||
rhs: ValueRef,
|
||||
input_ty: Ty<'tcx>) -> ValueRef {
|
||||
input_ty: Ty<'tcx>) -> OperandValue {
|
||||
let (val, of) = match op {
|
||||
// These are checked using intrinsics
|
||||
mir::BinOp::Add | mir::BinOp::Sub | mir::BinOp::Mul => {
|
||||
@ -592,10 +591,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
let intrinsic = get_overflow_intrinsic(oop, bcx, input_ty);
|
||||
let res = bcx.call(intrinsic, &[lhs, rhs], None);
|
||||
|
||||
let val = bcx.extract_value(res, 0);
|
||||
let of = bcx.extract_value(res, 1);
|
||||
|
||||
(val, bcx.zext(of, Type::bool(bcx.ccx())))
|
||||
(bcx.extract_value(res, 0),
|
||||
bcx.extract_value(res, 1))
|
||||
}
|
||||
mir::BinOp::Shl | mir::BinOp::Shr => {
|
||||
let lhs_llty = val_ty(lhs);
|
||||
@ -608,19 +605,14 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
let of = bcx.icmp(llvm::IntNE, outer_bits, C_null(rhs_llty));
|
||||
let val = self.trans_scalar_binop(bcx, op, lhs, rhs, input_ty);
|
||||
|
||||
(val, bcx.zext(of, Type::bool(bcx.ccx())))
|
||||
(val, of)
|
||||
}
|
||||
_ => {
|
||||
bug!("Operator `{:?}` is not a checkable operator", op)
|
||||
}
|
||||
};
|
||||
|
||||
let val_ty = val_ty(val);
|
||||
let res_ty = Type::struct_(bcx.ccx(), &[val_ty, Type::bool(bcx.ccx())], false);
|
||||
|
||||
let mut res_val = C_undef(res_ty);
|
||||
res_val = bcx.insert_value(res_val, val, 0);
|
||||
bcx.insert_value(res_val, of, 1)
|
||||
OperandValue::Pair(val, of)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user