// except according to those terms.
use llvm::ValueRef;
-use rustc::ty::Ty;
-use rustc::ty::layout::Layout;
+use rustc::ty::{self, Ty};
+use rustc::ty::layout::{Layout, LayoutTyper};
use rustc::mir;
+use rustc::mir::tcx::LvalueTy;
use rustc_data_structures::indexed_vec::Idx;
use base;
-use common;
+use common::{self, CrateContext, C_null};
use builder::Builder;
use value::Value;
use type_of;
use type_::Type;
use std::fmt;
+use std::ptr;
use super::{MirContext, LocalRef};
-use super::lvalue::Alignment;
+use super::lvalue::{Alignment, LvalueRef};
/// The representation of a Rust value. The enum variant is in fact
/// uniquely determined by the value's type, but is kept as a
}
impl<'a, 'tcx> OperandRef<'tcx> {
+ pub fn new_zst(ccx: &CrateContext<'a, 'tcx>,
+ ty: Ty<'tcx>) -> OperandRef<'tcx> {
+ assert!(common::type_is_zero_size(ccx, ty));
+ let llty = type_of::type_of(ccx, ty);
+ let val = if common::type_is_imm_pair(ccx, ty) {
+ let fields = llty.field_types();
+ OperandValue::Pair(C_null(fields[0]), C_null(fields[1]))
+ } else {
+ OperandValue::Immediate(C_null(llty))
+ };
+ OperandRef {
+ val: val,
+ ty: ty
+ }
+ }
+
/// Asserts that this operand refers to a scalar and returns
/// a reference to its value.
pub fn immediate(self) -> ValueRef {
}
}
+ pub fn deref(self) -> LvalueRef<'tcx> {
+ let projected_ty = self.ty.builtin_deref(true, ty::NoPreference)
+ .unwrap().ty;
+ let (llptr, llextra) = match self.val {
+ OperandValue::Immediate(llptr) => (llptr, ptr::null_mut()),
+ OperandValue::Pair(llptr, llextra) => (llptr, llextra),
+ OperandValue::Ref(..) => bug!("Deref of by-Ref operand {:?}", self)
+ };
+ LvalueRef {
+ llval: llptr,
+ llextra: llextra,
+ ty: LvalueTy::from_ty(projected_ty),
+ alignment: Alignment::AbiAligned,
+ }
+ }
+
/// If this operand is a Pair, we return an
/// Immediate aggregate with the two values.
pub fn pack_if_pair(mut self, bcx: &Builder<'a, 'tcx>) -> OperandRef<'tcx> {
}
mir::Operand::Constant(ref constant) => {
- let val = self.trans_constant(bcx, constant);
+ let val = self.trans_constant(&bcx, constant);
let operand = val.to_operand(bcx.ccx);
if let OperandValue::Ref(ptr, align) = operand.val {
// If this is a OperandValue::Ref to an immediate constant, load it.
bcx.store(base::from_immediate(bcx, s), lldest, align);
}
OperandValue::Pair(a, b) => {
+ let f_align = match *bcx.ccx.layout_of(operand.ty) {
+ Layout::Univariant { ref variant, .. } if variant.packed => {
+ Some(1)
+ }
+ _ => align
+ };
+
let a = base::from_immediate(bcx, a);
let b = base::from_immediate(bcx, b);
- bcx.store(a, bcx.struct_gep(lldest, 0), align);
- bcx.store(b, bcx.struct_gep(lldest, 1), align);
+ bcx.store(a, bcx.struct_gep(lldest, 0), f_align);
+ bcx.store(b, bcx.struct_gep(lldest, 1), f_align);
}
}
}