]> git.proxmox.com Git - rustc.git/blame - src/librustc_trans/trans/mir/rvalue.rs
Imported Upstream version 1.8.0+dfsg1
[rustc.git] / src / librustc_trans / trans / mir / rvalue.rs
CommitLineData
92a42be0
SL
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.
4//
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.
10
11use llvm::ValueRef;
12use rustc::middle::ty::{self, Ty};
9cc50fc6 13use middle::ty::cast::{CastTy, IntTy};
92a42be0
SL
14use rustc::mir::repr as mir;
15
16use trans::asm;
17use trans::base;
7453a54e 18use trans::common::{self, BlockAndBuilder, Result};
92a42be0
SL
19use trans::debuginfo::DebugLoc;
20use trans::declare;
21use trans::expr;
9cc50fc6 22use trans::adt;
92a42be0
SL
23use trans::machine;
24use trans::type_::Type;
25use trans::type_of;
26use trans::tvec;
9cc50fc6 27use trans::Disr;
92a42be0
SL
28
29use super::MirContext;
30use super::operand::{OperandRef, OperandValue};
9cc50fc6 31use super::lvalue::LvalueRef;
92a42be0
SL
32
33impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
34 pub fn trans_rvalue(&mut self,
7453a54e 35 bcx: BlockAndBuilder<'bcx, 'tcx>,
9cc50fc6 36 dest: LvalueRef<'tcx>,
92a42be0 37 rvalue: &mir::Rvalue<'tcx>)
7453a54e 38 -> BlockAndBuilder<'bcx, 'tcx>
92a42be0 39 {
9cc50fc6
SL
40 debug!("trans_rvalue(dest.llval={}, rvalue={:?})",
41 bcx.val_to_string(dest.llval),
92a42be0
SL
42 rvalue);
43
44 match *rvalue {
45 mir::Rvalue::Use(ref operand) => {
7453a54e 46 self.trans_operand_into(&bcx, dest.llval, operand);
92a42be0
SL
47 bcx
48 }
49
50 mir::Rvalue::Cast(mir::CastKind::Unsize, ref operand, cast_ty) => {
51 if common::type_is_fat_ptr(bcx.tcx(), cast_ty) {
52 // into-coerce of a thin pointer to a fat pointer - just
53 // use the operand path.
54 let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue);
7453a54e 55 self.store_operand(&bcx, dest.llval, temp);
92a42be0
SL
56 return bcx;
57 }
58
59 // Unsize of a nontrivial struct. I would prefer for
60 // this to be eliminated by MIR translation, but
61 // `CoerceUnsized` can be passed by a where-clause,
62 // so the (generic) MIR may not be able to expand it.
7453a54e
SL
63 let operand = self.trans_operand(&bcx, operand);
64 bcx.with_block(|bcx| {
65 match operand.val {
66 OperandValue::FatPtr(..) => unreachable!(),
67 OperandValue::Immediate(llval) => {
68 // unsize from an immediate structure. We don't
69 // really need a temporary alloca here, but
70 // avoiding it would require us to have
71 // `coerce_unsized_into` use extractvalue to
72 // index into the struct, and this case isn't
73 // important enough for it.
74 debug!("trans_rvalue: creating ugly alloca");
75 let lltemp = base::alloc_ty(bcx, operand.ty, "__unsize_temp");
76 base::store_ty(bcx, llval, lltemp, operand.ty);
77 base::coerce_unsized_into(bcx,
78 lltemp, operand.ty,
79 dest.llval, cast_ty);
80 }
81 OperandValue::Ref(llref) => {
82 base::coerce_unsized_into(bcx,
83 llref, operand.ty,
84 dest.llval, cast_ty);
85 }
92a42be0 86 }
7453a54e 87 });
92a42be0
SL
88 bcx
89 }
90
91 mir::Rvalue::Repeat(ref elem, ref count) => {
7453a54e
SL
92 let elem = self.trans_operand(&bcx, elem);
93 let size = self.trans_constval(&bcx, &count.value, count.ty).immediate();
94 bcx.map_block(|block| {
95 let base = expr::get_dataptr(block, dest.llval);
96 tvec::iter_vec_raw(block, base, elem.ty, size, |block, llslot, _| {
97 self.store_operand_direct(block, llslot, elem);
98 block
99 })
92a42be0
SL
100 })
101 }
102
9cc50fc6
SL
103 mir::Rvalue::Aggregate(ref kind, ref operands) => {
104 match *kind {
105 mir::AggregateKind::Adt(adt_def, index, _) => {
106 let repr = adt::represent_type(bcx.ccx(), dest.ty.to_ty(bcx.tcx()));
107 let disr = Disr::from(adt_def.variants[index].disr_val);
7453a54e
SL
108 bcx.with_block(|bcx| {
109 adt::trans_set_discr(bcx, &repr, dest.llval, Disr::from(disr));
110 });
9cc50fc6 111 for (i, operand) in operands.iter().enumerate() {
7453a54e 112 let op = self.trans_operand(&bcx, operand);
9cc50fc6
SL
113 // Do not generate stores and GEPis for zero-sized fields.
114 if !common::type_is_zero_size(bcx.ccx(), op.ty) {
115 let val = adt::MaybeSizedValue::sized(dest.llval);
7453a54e
SL
116 let lldest_i = bcx.with_block(|bcx| {
117 adt::trans_field_ptr(bcx, &repr, val, disr, i)
118 });
119 self.store_operand(&bcx, lldest_i, op);
9cc50fc6
SL
120 }
121 }
122 },
123 _ => {
124 for (i, operand) in operands.iter().enumerate() {
7453a54e 125 let op = self.trans_operand(&bcx, operand);
9cc50fc6
SL
126 // Do not generate stores and GEPis for zero-sized fields.
127 if !common::type_is_zero_size(bcx.ccx(), op.ty) {
128 // Note: perhaps this should be StructGep, but
129 // note that in some cases the values here will
130 // not be structs but arrays.
7453a54e
SL
131 let dest = bcx.gepi(dest.llval, &[0, i]);
132 self.store_operand(&bcx, dest, op);
9cc50fc6
SL
133 }
134 }
135 }
92a42be0
SL
136 }
137 bcx
138 }
139
140 mir::Rvalue::Slice { ref input, from_start, from_end } => {
141 let ccx = bcx.ccx();
7453a54e
SL
142 let input = self.trans_lvalue(&bcx, input);
143 let (llbase, lllen) = bcx.with_block(|bcx| {
144 tvec::get_base_and_len(bcx,
145 input.llval,
146 input.ty.to_ty(bcx.tcx()))
147 });
148 let llbase1 = bcx.gepi(llbase, &[from_start]);
92a42be0 149 let adj = common::C_uint(ccx, from_start + from_end);
7453a54e
SL
150 let lllen1 = bcx.sub(lllen, adj);
151 let (lladdrdest, llmetadest) = bcx.with_block(|bcx| {
152 (expr::get_dataptr(bcx, dest.llval), expr::get_meta(bcx, dest.llval))
153 });
154 bcx.store(llbase1, lladdrdest);
155 bcx.store(lllen1, llmetadest);
92a42be0
SL
156 bcx
157 }
158
9cc50fc6 159 mir::Rvalue::InlineAsm(ref inline_asm) => {
7453a54e
SL
160 bcx.map_block(|bcx| {
161 asm::trans_inline_asm(bcx, inline_asm)
162 })
92a42be0
SL
163 }
164
165 _ => {
166 assert!(rvalue_creates_operand(rvalue));
167 let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue);
7453a54e 168 self.store_operand(&bcx, dest.llval, temp);
92a42be0
SL
169 bcx
170 }
171 }
172 }
173
174 pub fn trans_rvalue_operand(&mut self,
7453a54e 175 bcx: BlockAndBuilder<'bcx, 'tcx>,
92a42be0 176 rvalue: &mir::Rvalue<'tcx>)
7453a54e 177 -> (BlockAndBuilder<'bcx, 'tcx>, OperandRef<'tcx>)
92a42be0
SL
178 {
179 assert!(rvalue_creates_operand(rvalue), "cannot trans {:?} to operand", rvalue);
180
181 match *rvalue {
182 mir::Rvalue::Use(ref operand) => {
7453a54e 183 let operand = self.trans_operand(&bcx, operand);
92a42be0
SL
184 (bcx, operand)
185 }
186
187 mir::Rvalue::Cast(ref kind, ref operand, cast_ty) => {
7453a54e
SL
188 let operand = self.trans_operand(&bcx, operand);
189 debug!("cast operand is {}", operand.repr(&bcx));
92a42be0
SL
190 let cast_ty = bcx.monomorphize(&cast_ty);
191
192 let val = match *kind {
193 mir::CastKind::ReifyFnPointer |
194 mir::CastKind::UnsafeFnPointer => {
195 // these are no-ops at the LLVM level
196 operand.val
197 }
198 mir::CastKind::Unsize => {
199 // unsize targets other than to a fat pointer currently
200 // can't be operands.
201 assert!(common::type_is_fat_ptr(bcx.tcx(), cast_ty));
202
203 match operand.val {
204 OperandValue::FatPtr(..) => {
205 // unsize from a fat pointer - this is a
206 // "trait-object-to-supertrait" coercion, for
207 // example,
208 // &'a fmt::Debug+Send => &'a fmt::Debug,
209 // and is a no-op at the LLVM level
210 operand.val
211 }
212 OperandValue::Immediate(lldata) => {
213 // "standard" unsize
7453a54e 214 let (lldata, llextra) = bcx.with_block(|bcx| {
92a42be0 215 base::unsize_thin_ptr(bcx, lldata,
7453a54e
SL
216 operand.ty, cast_ty)
217 });
92a42be0
SL
218 OperandValue::FatPtr(lldata, llextra)
219 }
220 OperandValue::Ref(_) => {
221 bcx.sess().bug(
222 &format!("by-ref operand {} in trans_rvalue_operand",
7453a54e 223 operand.repr(&bcx)));
92a42be0
SL
224 }
225 }
226 }
9cc50fc6
SL
227 mir::CastKind::Misc if common::type_is_immediate(bcx.ccx(), operand.ty) => {
228 debug_assert!(common::type_is_immediate(bcx.ccx(), cast_ty));
229 let r_t_in = CastTy::from_ty(operand.ty).expect("bad input type for cast");
230 let r_t_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
231 let ll_t_in = type_of::arg_type_of(bcx.ccx(), operand.ty);
232 let ll_t_out = type_of::arg_type_of(bcx.ccx(), cast_ty);
233 let (llval, ll_t_in, signed) = if let CastTy::Int(IntTy::CEnum) = r_t_in {
234 let repr = adt::represent_type(bcx.ccx(), operand.ty);
235 let llval = operand.immediate();
7453a54e
SL
236 let discr = bcx.with_block(|bcx| {
237 adt::trans_get_discr(bcx, &repr, llval, None, true)
238 });
239 (discr, common::val_ty(discr), adt::is_discr_signed(&repr))
9cc50fc6
SL
240 } else {
241 (operand.immediate(), ll_t_in, operand.ty.is_signed())
242 };
243
244 let newval = match (r_t_in, r_t_out) {
245 (CastTy::Int(_), CastTy::Int(_)) => {
246 let srcsz = ll_t_in.int_width();
247 let dstsz = ll_t_out.int_width();
248 if srcsz == dstsz {
7453a54e 249 bcx.bitcast(llval, ll_t_out)
9cc50fc6 250 } else if srcsz > dstsz {
7453a54e 251 bcx.trunc(llval, ll_t_out)
9cc50fc6 252 } else if signed {
7453a54e 253 bcx.sext(llval, ll_t_out)
9cc50fc6 254 } else {
7453a54e 255 bcx.zext(llval, ll_t_out)
9cc50fc6
SL
256 }
257 }
258 (CastTy::Float, CastTy::Float) => {
259 let srcsz = ll_t_in.float_width();
260 let dstsz = ll_t_out.float_width();
261 if dstsz > srcsz {
7453a54e 262 bcx.fpext(llval, ll_t_out)
9cc50fc6 263 } else if srcsz > dstsz {
7453a54e 264 bcx.fptrunc(llval, ll_t_out)
9cc50fc6
SL
265 } else {
266 llval
267 }
268 }
269 (CastTy::Ptr(_), CastTy::Ptr(_)) |
270 (CastTy::FnPtr, CastTy::Ptr(_)) |
271 (CastTy::RPtr(_), CastTy::Ptr(_)) =>
7453a54e 272 bcx.pointercast(llval, ll_t_out),
9cc50fc6
SL
273 (CastTy::Ptr(_), CastTy::Int(_)) |
274 (CastTy::FnPtr, CastTy::Int(_)) =>
7453a54e 275 bcx.ptrtoint(llval, ll_t_out),
9cc50fc6 276 (CastTy::Int(_), CastTy::Ptr(_)) =>
7453a54e 277 bcx.inttoptr(llval, ll_t_out),
9cc50fc6 278 (CastTy::Int(_), CastTy::Float) if signed =>
7453a54e 279 bcx.sitofp(llval, ll_t_out),
9cc50fc6 280 (CastTy::Int(_), CastTy::Float) =>
7453a54e 281 bcx.uitofp(llval, ll_t_out),
9cc50fc6 282 (CastTy::Float, CastTy::Int(IntTy::I)) =>
7453a54e 283 bcx.fptosi(llval, ll_t_out),
9cc50fc6 284 (CastTy::Float, CastTy::Int(_)) =>
7453a54e 285 bcx.fptoui(llval, ll_t_out),
9cc50fc6
SL
286 _ => bcx.ccx().sess().bug(
287 &format!("unsupported cast: {:?} to {:?}", operand.ty, cast_ty)
288 )
289 };
290 OperandValue::Immediate(newval)
291 }
292 mir::CastKind::Misc => { // Casts from a fat-ptr.
293 let ll_cast_ty = type_of::arg_type_of(bcx.ccx(), cast_ty);
294 let ll_from_ty = type_of::arg_type_of(bcx.ccx(), operand.ty);
295 if let OperandValue::FatPtr(data_ptr, meta_ptr) = operand.val {
296 if common::type_is_fat_ptr(bcx.tcx(), cast_ty) {
297 let ll_cft = ll_cast_ty.field_types();
298 let ll_fft = ll_from_ty.field_types();
7453a54e 299 let data_cast = bcx.pointercast(data_ptr, ll_cft[0]);
9cc50fc6
SL
300 assert_eq!(ll_cft[1].kind(), ll_fft[1].kind());
301 OperandValue::FatPtr(data_cast, meta_ptr)
302 } else { // cast to thin-ptr
303 // Cast of fat-ptr to thin-ptr is an extraction of data-ptr and
304 // pointer-cast of that pointer to desired pointer type.
7453a54e 305 let llval = bcx.pointercast(data_ptr, ll_cast_ty);
9cc50fc6
SL
306 OperandValue::Immediate(llval)
307 }
308 } else {
309 panic!("Unexpected non-FatPtr operand")
310 }
311 }
92a42be0 312 };
7453a54e 313 let operand = OperandRef {
92a42be0
SL
314 val: val,
315 ty: cast_ty
7453a54e
SL
316 };
317 (bcx, operand)
92a42be0
SL
318 }
319
320 mir::Rvalue::Ref(_, bk, ref lvalue) => {
7453a54e 321 let tr_lvalue = self.trans_lvalue(&bcx, lvalue);
92a42be0
SL
322
323 let ty = tr_lvalue.ty.to_ty(bcx.tcx());
324 let ref_ty = bcx.tcx().mk_ref(
325 bcx.tcx().mk_region(ty::ReStatic),
326 ty::TypeAndMut { ty: ty, mutbl: bk.to_mutbl_lossy() }
327 );
328
329 // Note: lvalues are indirect, so storing the `llval` into the
330 // destination effectively creates a reference.
7453a54e
SL
331 let operand = if common::type_is_sized(bcx.tcx(), ty) {
332 OperandRef {
92a42be0
SL
333 val: OperandValue::Immediate(tr_lvalue.llval),
334 ty: ref_ty,
7453a54e 335 }
92a42be0 336 } else {
7453a54e 337 OperandRef {
92a42be0
SL
338 val: OperandValue::FatPtr(tr_lvalue.llval,
339 tr_lvalue.llextra),
340 ty: ref_ty,
7453a54e
SL
341 }
342 };
343 (bcx, operand)
92a42be0
SL
344 }
345
346 mir::Rvalue::Len(ref lvalue) => {
7453a54e
SL
347 let tr_lvalue = self.trans_lvalue(&bcx, lvalue);
348 let operand = OperandRef {
349 val: OperandValue::Immediate(self.lvalue_len(&bcx, tr_lvalue)),
92a42be0 350 ty: bcx.tcx().types.usize,
7453a54e
SL
351 };
352 (bcx, operand)
92a42be0
SL
353 }
354
355 mir::Rvalue::BinaryOp(op, ref lhs, ref rhs) => {
7453a54e
SL
356 let lhs = self.trans_operand(&bcx, lhs);
357 let rhs = self.trans_operand(&bcx, rhs);
92a42be0
SL
358 let llresult = if common::type_is_fat_ptr(bcx.tcx(), lhs.ty) {
359 match (lhs.val, rhs.val) {
360 (OperandValue::FatPtr(lhs_addr, lhs_extra),
361 OperandValue::FatPtr(rhs_addr, rhs_extra)) => {
7453a54e
SL
362 bcx.with_block(|bcx| {
363 base::compare_fat_ptrs(bcx,
364 lhs_addr, lhs_extra,
365 rhs_addr, rhs_extra,
366 lhs.ty, op.to_hir_binop(),
367 DebugLoc::None)
368 })
92a42be0
SL
369 }
370 _ => unreachable!()
371 }
372
373 } else {
7453a54e 374 self.trans_scalar_binop(&bcx, op,
92a42be0 375 lhs.immediate(), rhs.immediate(),
7453a54e 376 lhs.ty)
92a42be0 377 };
7453a54e 378 let operand = OperandRef {
92a42be0
SL
379 val: OperandValue::Immediate(llresult),
380 ty: self.mir.binop_ty(bcx.tcx(), op, lhs.ty, rhs.ty),
7453a54e
SL
381 };
382 (bcx, operand)
92a42be0
SL
383 }
384
385 mir::Rvalue::UnaryOp(op, ref operand) => {
7453a54e 386 let operand = self.trans_operand(&bcx, operand);
92a42be0
SL
387 let lloperand = operand.immediate();
388 let is_float = operand.ty.is_fp();
92a42be0 389 let llval = match op {
7453a54e 390 mir::UnOp::Not => bcx.not(lloperand),
92a42be0 391 mir::UnOp::Neg => if is_float {
7453a54e 392 bcx.fneg(lloperand)
92a42be0 393 } else {
7453a54e 394 bcx.neg(lloperand)
92a42be0
SL
395 }
396 };
397 (bcx, OperandRef {
398 val: OperandValue::Immediate(llval),
399 ty: operand.ty,
400 })
401 }
402
403 mir::Rvalue::Box(content_ty) => {
404 let content_ty: Ty<'tcx> = bcx.monomorphize(&content_ty);
405 let llty = type_of::type_of(bcx.ccx(), content_ty);
406 let llsize = machine::llsize_of(bcx.ccx(), llty);
407 let align = type_of::align_of(bcx.ccx(), content_ty);
408 let llalign = common::C_uint(bcx.ccx(), align);
409 let llty_ptr = llty.ptr_to();
410 let box_ty = bcx.tcx().mk_box(content_ty);
7453a54e
SL
411 let mut llval = None;
412 let bcx = bcx.map_block(|bcx| {
413 let Result { bcx, val } = base::malloc_raw_dyn(bcx,
414 llty_ptr,
415 box_ty,
416 llsize,
417 llalign,
418 DebugLoc::None);
419 llval = Some(val);
420 bcx
421 });
422 let operand = OperandRef {
423 val: OperandValue::Immediate(llval.unwrap()),
92a42be0 424 ty: box_ty,
7453a54e
SL
425 };
426 (bcx, operand)
92a42be0
SL
427 }
428
429 mir::Rvalue::Repeat(..) |
430 mir::Rvalue::Aggregate(..) |
431 mir::Rvalue::Slice { .. } |
432 mir::Rvalue::InlineAsm(..) => {
433 bcx.tcx().sess.bug(&format!("cannot generate operand from rvalue {:?}", rvalue));
434 }
435 }
436 }
437
438 pub fn trans_scalar_binop(&mut self,
7453a54e 439 bcx: &BlockAndBuilder<'bcx, 'tcx>,
92a42be0
SL
440 op: mir::BinOp,
441 lhs: ValueRef,
442 rhs: ValueRef,
7453a54e 443 input_ty: Ty<'tcx>) -> ValueRef {
92a42be0
SL
444 let is_float = input_ty.is_fp();
445 let is_signed = input_ty.is_signed();
446 match op {
447 mir::BinOp::Add => if is_float {
7453a54e 448 bcx.fadd(lhs, rhs)
92a42be0 449 } else {
7453a54e 450 bcx.add(lhs, rhs)
92a42be0
SL
451 },
452 mir::BinOp::Sub => if is_float {
7453a54e 453 bcx.fsub(lhs, rhs)
92a42be0 454 } else {
7453a54e 455 bcx.sub(lhs, rhs)
92a42be0
SL
456 },
457 mir::BinOp::Mul => if is_float {
7453a54e 458 bcx.fmul(lhs, rhs)
92a42be0 459 } else {
7453a54e 460 bcx.mul(lhs, rhs)
92a42be0
SL
461 },
462 mir::BinOp::Div => if is_float {
7453a54e 463 bcx.fdiv(lhs, rhs)
92a42be0 464 } else if is_signed {
7453a54e 465 bcx.sdiv(lhs, rhs)
92a42be0 466 } else {
7453a54e 467 bcx.udiv(lhs, rhs)
92a42be0
SL
468 },
469 mir::BinOp::Rem => if is_float {
470 // LLVM currently always lowers the `frem` instructions appropriate
471 // library calls typically found in libm. Notably f64 gets wired up
472 // to `fmod` and f32 gets wired up to `fmodf`. Inconveniently for
473 // us, 32-bit MSVC does not actually have a `fmodf` symbol, it's
474 // instead just an inline function in a header that goes up to a
475 // f64, uses `fmod`, and then comes back down to a f32.
476 //
477 // Although LLVM knows that `fmodf` doesn't exist on MSVC, it will
478 // still unconditionally lower frem instructions over 32-bit floats
479 // to a call to `fmodf`. To work around this we special case MSVC
480 // 32-bit float rem instructions and instead do the call out to
481 // `fmod` ourselves.
482 //
483 // Note that this is currently duplicated with src/libcore/ops.rs
484 // which does the same thing, and it would be nice to perhaps unify
485 // these two implementations one day! Also note that we call `fmod`
486 // for both 32 and 64-bit floats because if we emit any FRem
487 // instruction at all then LLVM is capable of optimizing it into a
488 // 32-bit FRem (which we're trying to avoid).
489 let tcx = bcx.tcx();
490 let use_fmod = tcx.sess.target.target.options.is_like_msvc &&
491 tcx.sess.target.target.arch == "x86";
492 if use_fmod {
493 let f64t = Type::f64(bcx.ccx());
494 let fty = Type::func(&[f64t, f64t], &f64t);
495 let llfn = declare::declare_cfn(bcx.ccx(), "fmod", fty,
496 tcx.types.f64);
497 if input_ty == tcx.types.f32 {
7453a54e
SL
498 let lllhs = bcx.fpext(lhs, f64t);
499 let llrhs = bcx.fpext(rhs, f64t);
500 let llres = bcx.call(llfn, &[lllhs, llrhs], None, None);
501 bcx.fptrunc(llres, Type::f32(bcx.ccx()))
92a42be0 502 } else {
7453a54e 503 bcx.call(llfn, &[lhs, rhs], None, None)
92a42be0
SL
504 }
505 } else {
7453a54e 506 bcx.frem(lhs, rhs)
92a42be0
SL
507 }
508 } else if is_signed {
7453a54e 509 bcx.srem(lhs, rhs)
92a42be0 510 } else {
7453a54e 511 bcx.urem(lhs, rhs)
92a42be0 512 },
7453a54e
SL
513 mir::BinOp::BitOr => bcx.or(lhs, rhs),
514 mir::BinOp::BitAnd => bcx.and(lhs, rhs),
515 mir::BinOp::BitXor => bcx.xor(lhs, rhs),
516 mir::BinOp::Shl => {
517 bcx.with_block(|bcx| {
518 common::build_unchecked_lshift(bcx,
519 lhs,
520 rhs,
521 DebugLoc::None)
522 })
523 }
524 mir::BinOp::Shr => {
525 bcx.with_block(|bcx| {
526 common::build_unchecked_rshift(bcx,
527 input_ty,
528 lhs,
529 rhs,
530 DebugLoc::None)
531 })
532 }
92a42be0
SL
533 mir::BinOp::Eq | mir::BinOp::Lt | mir::BinOp::Gt |
534 mir::BinOp::Ne | mir::BinOp::Le | mir::BinOp::Ge => {
7453a54e
SL
535 bcx.with_block(|bcx| {
536 base::compare_scalar_types(bcx, lhs, rhs, input_ty,
537 op.to_hir_binop(), DebugLoc::None)
538 })
92a42be0
SL
539 }
540 }
541 }
542}
543
544pub fn rvalue_creates_operand<'tcx>(rvalue: &mir::Rvalue<'tcx>) -> bool {
545 match *rvalue {
546 mir::Rvalue::Use(..) | // (*)
547 mir::Rvalue::Ref(..) |
548 mir::Rvalue::Len(..) |
549 mir::Rvalue::Cast(..) | // (*)
550 mir::Rvalue::BinaryOp(..) |
551 mir::Rvalue::UnaryOp(..) |
552 mir::Rvalue::Box(..) =>
553 true,
554 mir::Rvalue::Repeat(..) |
555 mir::Rvalue::Aggregate(..) |
556 mir::Rvalue::Slice { .. } |
557 mir::Rvalue::InlineAsm(..) =>
558 false,
559 }
560
561 // (*) this is only true if the type is suitable
562}