1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
14 use rustc_data_structures::indexed_vec::Idx;
25 use super::{MirContext, LocalRef};
27 /// The representation of a Rust value. The enum variant is in fact
28 /// uniquely determined by the value's type, but is kept as a
30 #[derive(Copy, Clone)]
31 pub enum OperandValue {
32 /// A reference to the actual operand. The data is guaranteed
33 /// to be valid for the operand's lifetime.
35 /// A single LLVM value.
37 /// A pair of immediate LLVM values. Used by fat pointers too.
38 Pair(ValueRef, ValueRef)
41 /// An `OperandRef` is an "SSA" reference to a Rust value, along with
44 /// NOTE: unless you know a value's type exactly, you should not
45 /// generate LLVM opcodes acting on it and instead act via methods,
46 /// to avoid nasty edge cases. In particular, using `Builder.store`
47 /// directly is sure to cause problems -- use `MirContext.store_operand`
49 #[derive(Copy, Clone)]
50 pub struct OperandRef<'tcx> {
52 pub val: OperandValue,
54 // The type of value being returned.
58 impl<'tcx> fmt::Debug for OperandRef<'tcx> {
59 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
61 OperandValue::Ref(r) => {
62 write!(f, "OperandRef(Ref({:?}) @ {:?})",
65 OperandValue::Immediate(i) => {
66 write!(f, "OperandRef(Immediate({:?}) @ {:?})",
69 OperandValue::Pair(a, b) => {
70 write!(f, "OperandRef(Pair({:?}, {:?}) @ {:?})",
71 Value(a), Value(b), self.ty)
77 impl<'a, 'tcx> OperandRef<'tcx> {
78 /// Asserts that this operand refers to a scalar and returns
79 /// a reference to its value.
80 pub fn immediate(self) -> ValueRef {
82 OperandValue::Immediate(s) => s,
83 _ => bug!("not immediate: {:?}", self)
87 /// If this operand is a Pair, we return an
88 /// Immediate aggregate with the two values.
89 pub fn pack_if_pair(mut self, bcx: &Builder<'a, 'tcx>) -> OperandRef<'tcx> {
90 if let OperandValue::Pair(a, b) = self.val {
91 // Reconstruct the immediate aggregate.
92 let llty = type_of::type_of(bcx.ccx, self.ty);
93 let mut llpair = common::C_undef(llty);
96 let mut elem = elems[i];
97 // Extend boolean i1's to i8.
98 if common::val_ty(elem) == Type::i1(bcx.ccx) {
99 elem = bcx.zext(elem, Type::i8(bcx.ccx));
101 llpair = bcx.insert_value(llpair, elem, i);
103 self.val = OperandValue::Immediate(llpair);
108 /// If this operand is a pair in an Immediate,
109 /// we return a Pair with the two halves.
110 pub fn unpack_if_pair(mut self, bcx: &Builder<'a, 'tcx>) -> OperandRef<'tcx> {
111 if let OperandValue::Immediate(llval) = self.val {
112 // Deconstruct the immediate aggregate.
113 if common::type_is_imm_pair(bcx.ccx, self.ty) {
114 debug!("Operand::unpack_if_pair: unpacking {:?}", self);
116 let mut a = bcx.extract_value(llval, 0);
117 let mut b = bcx.extract_value(llval, 1);
119 let pair_fields = common::type_pair_fields(bcx.ccx, self.ty);
120 if let Some([a_ty, b_ty]) = pair_fields {
122 a = bcx.trunc(a, Type::i1(bcx.ccx));
125 b = bcx.trunc(b, Type::i1(bcx.ccx));
129 self.val = OperandValue::Pair(a, b);
136 impl<'a, 'tcx> MirContext<'a, 'tcx> {
137 pub fn trans_load(&mut self,
138 bcx: &Builder<'a, 'tcx>,
143 debug!("trans_load: {:?} @ {:?}", Value(llval), ty);
145 let val = if common::type_is_fat_ptr(bcx.ccx, ty) {
146 let (lldata, llextra) = base::load_fat_ptr(bcx, llval, ty);
147 OperandValue::Pair(lldata, llextra)
148 } else if common::type_is_imm_pair(bcx.ccx, ty) {
149 let [a_ty, b_ty] = common::type_pair_fields(bcx.ccx, ty).unwrap();
150 let a_ptr = bcx.struct_gep(llval, 0);
151 let b_ptr = bcx.struct_gep(llval, 1);
154 base::load_ty(bcx, a_ptr, a_ty),
155 base::load_ty(bcx, b_ptr, b_ty)
157 } else if common::type_is_immediate(bcx.ccx, ty) {
158 OperandValue::Immediate(base::load_ty(bcx, llval, ty))
160 OperandValue::Ref(llval)
163 OperandRef { val: val, ty: ty }
166 pub fn trans_consume(&mut self,
167 bcx: &Builder<'a, 'tcx>,
168 lvalue: &mir::Lvalue<'tcx>)
171 debug!("trans_consume(lvalue={:?})", lvalue);
173 // watch out for locals that do not have an
174 // alloca; they are handled somewhat differently
175 if let mir::Lvalue::Local(index) = *lvalue {
176 match self.locals[index] {
177 LocalRef::Operand(Some(o)) => {
180 LocalRef::Operand(None) => {
181 bug!("use of {:?} before def", lvalue);
183 LocalRef::Lvalue(..) => {
189 // Moves out of pair fields are trivial.
190 if let &mir::Lvalue::Projection(ref proj) = lvalue {
191 if let mir::Lvalue::Local(index) = proj.base {
192 if let LocalRef::Operand(Some(o)) = self.locals[index] {
193 match (o.val, &proj.elem) {
194 (OperandValue::Pair(a, b),
195 &mir::ProjectionElem::Field(ref f, ty)) => {
196 let llval = [a, b][f.index()];
197 let op = OperandRef {
198 val: OperandValue::Immediate(llval),
199 ty: self.monomorphize(&ty)
202 // Handle nested pairs.
203 return op.unpack_if_pair(bcx);
211 // for most lvalues, to consume them we just load them
212 // out from their home
213 let tr_lvalue = self.trans_lvalue(bcx, lvalue);
214 let ty = tr_lvalue.ty.to_ty(bcx.tcx());
215 self.trans_load(bcx, tr_lvalue.llval, ty)
218 pub fn trans_operand(&mut self,
219 bcx: &Builder<'a, 'tcx>,
220 operand: &mir::Operand<'tcx>)
223 debug!("trans_operand(operand={:?})", operand);
226 mir::Operand::Consume(ref lvalue) => {
227 self.trans_consume(bcx, lvalue)
230 mir::Operand::Constant(ref constant) => {
231 let val = self.trans_constant(bcx, constant);
232 let operand = val.to_operand(bcx.ccx);
233 if let OperandValue::Ref(ptr) = operand.val {
234 // If this is a OperandValue::Ref to an immediate constant, load it.
235 self.trans_load(bcx, ptr, operand.ty)
243 pub fn store_operand(&mut self,
244 bcx: &Builder<'a, 'tcx>,
246 operand: OperandRef<'tcx>,
247 align: Option<u32>) {
248 debug!("store_operand: operand={:?}, align={:?}", operand, align);
249 // Avoid generating stores of zero-sized values, because the only way to have a zero-sized
250 // value is through `undef`, and store itself is useless.
251 if common::type_is_zero_size(bcx.ccx, operand.ty) {
255 OperandValue::Ref(r) => base::memcpy_ty(bcx, lldest, r, operand.ty, align),
256 OperandValue::Immediate(s) => {
257 bcx.store(base::from_immediate(bcx, s), lldest, align);
259 OperandValue::Pair(a, b) => {
260 let a = base::from_immediate(bcx, a);
261 let b = base::from_immediate(bcx, b);
262 bcx.store(a, bcx.struct_gep(lldest, 0), align);
263 bcx.store(b, bcx.struct_gep(lldest, 1), align);