]> git.lizzy.rs Git - rust.git/blob - src/librustc_trans/mir/rvalue.rs
Make saturating u128 -> f32 casts the default behavior
[rust.git] / src / librustc_trans / mir / rvalue.rs
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
11 use llvm::{self, ValueRef};
12 use rustc::ty::{self, Ty};
13 use rustc::ty::cast::{CastTy, IntTy};
14 use rustc::ty::layout::{Layout, LayoutTyper};
15 use rustc::mir::tcx::LvalueTy;
16 use rustc::mir;
17 use rustc::middle::lang_items::ExchangeMallocFnLangItem;
18 use rustc_apfloat::{ieee, Float, Status, Round};
19 use rustc_const_math::MAX_F32_PLUS_HALF_ULP;
20 use std::{u128, i128};
21
22 use base;
23 use builder::Builder;
24 use callee;
25 use common::{self, val_ty, C_bool, C_i32, C_u32, C_u64, C_null, C_usize, C_uint, C_big_integral};
26 use consts;
27 use adt;
28 use machine;
29 use monomorphize;
30 use type_::Type;
31 use type_of;
32 use tvec;
33 use value::Value;
34
35 use super::{MirContext, LocalRef};
36 use super::constant::const_scalar_checked_binop;
37 use super::operand::{OperandRef, OperandValue};
38 use super::lvalue::LvalueRef;
39
40 impl<'a, 'tcx> MirContext<'a, 'tcx> {
41     pub fn trans_rvalue(&mut self,
42                         bcx: Builder<'a, 'tcx>,
43                         dest: LvalueRef<'tcx>,
44                         rvalue: &mir::Rvalue<'tcx>)
45                         -> Builder<'a, 'tcx>
46     {
47         debug!("trans_rvalue(dest.llval={:?}, rvalue={:?})",
48                Value(dest.llval), rvalue);
49
50         match *rvalue {
51            mir::Rvalue::Use(ref operand) => {
52                let tr_operand = self.trans_operand(&bcx, operand);
53                // FIXME: consider not copying constants through stack. (fixable by translating
54                // constants into OperandValue::Ref, why don’t we do that yet if we don’t?)
55                self.store_operand(&bcx, dest.llval, dest.alignment.to_align(), tr_operand);
56                bcx
57            }
58
59             mir::Rvalue::Cast(mir::CastKind::Unsize, ref source, cast_ty) => {
60                 let cast_ty = self.monomorphize(&cast_ty);
61
62                 if common::type_is_fat_ptr(bcx.ccx, cast_ty) {
63                     // into-coerce of a thin pointer to a fat pointer - just
64                     // use the operand path.
65                     let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue);
66                     self.store_operand(&bcx, dest.llval, dest.alignment.to_align(), temp);
67                     return bcx;
68                 }
69
70                 // Unsize of a nontrivial struct. I would prefer for
71                 // this to be eliminated by MIR translation, but
72                 // `CoerceUnsized` can be passed by a where-clause,
73                 // so the (generic) MIR may not be able to expand it.
74                 let operand = self.trans_operand(&bcx, source);
75                 let operand = operand.pack_if_pair(&bcx);
76                 let llref = match operand.val {
77                     OperandValue::Pair(..) => bug!(),
78                     OperandValue::Immediate(llval) => {
79                         // unsize from an immediate structure. We don't
80                         // really need a temporary alloca here, but
81                         // avoiding it would require us to have
82                         // `coerce_unsized_into` use extractvalue to
83                         // index into the struct, and this case isn't
84                         // important enough for it.
85                         debug!("trans_rvalue: creating ugly alloca");
86                         let scratch = LvalueRef::alloca(&bcx, operand.ty, "__unsize_temp");
87                         base::store_ty(&bcx, llval, scratch.llval, scratch.alignment, operand.ty);
88                         scratch
89                     }
90                     OperandValue::Ref(llref, align) => {
91                         LvalueRef::new_sized_ty(llref, operand.ty, align)
92                     }
93                 };
94                 base::coerce_unsized_into(&bcx, &llref, &dest);
95                 bcx
96             }
97
98             mir::Rvalue::Repeat(ref elem, count) => {
99                 let dest_ty = dest.ty.to_ty(bcx.tcx());
100
101                 // No need to inizialize memory of a zero-sized slice
102                 if common::type_is_zero_size(bcx.ccx, dest_ty) {
103                     return bcx;
104                 }
105
106                 let tr_elem = self.trans_operand(&bcx, elem);
107                 let size = count.as_u64();
108                 let size = C_usize(bcx.ccx, size);
109                 let base = base::get_dataptr(&bcx, dest.llval);
110                 let align = dest.alignment.to_align();
111
112                 if let OperandValue::Immediate(v) = tr_elem.val {
113                     // Use llvm.memset.p0i8.* to initialize all zero arrays
114                     if common::is_const_integral(v) && common::const_to_uint(v) == 0 {
115                         let align = align.unwrap_or_else(|| bcx.ccx.align_of(tr_elem.ty));
116                         let align = C_i32(bcx.ccx, align as i32);
117                         let ty = type_of::type_of(bcx.ccx, dest_ty);
118                         let size = machine::llsize_of(bcx.ccx, ty);
119                         let fill = C_uint(Type::i8(bcx.ccx), 0);
120                         base::call_memset(&bcx, base, fill, size, align, false);
121                         return bcx;
122                     }
123
124                     // Use llvm.memset.p0i8.* to initialize byte arrays
125                     if common::val_ty(v) == Type::i8(bcx.ccx) {
126                         let align = align.unwrap_or_else(|| bcx.ccx.align_of(tr_elem.ty));
127                         let align = C_i32(bcx.ccx, align as i32);
128                         base::call_memset(&bcx, base, v, size, align, false);
129                         return bcx;
130                     }
131                 }
132
133                 tvec::slice_for_each(&bcx, base, tr_elem.ty, size, |bcx, llslot, loop_bb| {
134                     self.store_operand(bcx, llslot, align, tr_elem);
135                     bcx.br(loop_bb);
136                 })
137             }
138
139             mir::Rvalue::Aggregate(ref kind, ref operands) => {
140                 match **kind {
141                     mir::AggregateKind::Adt(adt_def, variant_index, substs, active_field_index) => {
142                         let discr = adt_def.discriminant_for_variant(bcx.tcx(), variant_index)
143                            .to_u128_unchecked() as u64;
144                         let dest_ty = dest.ty.to_ty(bcx.tcx());
145                         adt::trans_set_discr(&bcx, dest_ty, dest.llval, discr);
146                         for (i, operand) in operands.iter().enumerate() {
147                             let op = self.trans_operand(&bcx, operand);
148                             // Do not generate stores and GEPis for zero-sized fields.
149                             if !common::type_is_zero_size(bcx.ccx, op.ty) {
150                                 let mut val = LvalueRef::new_sized(
151                                     dest.llval, dest.ty, dest.alignment);
152                                 let field_index = active_field_index.unwrap_or(i);
153                                 val.ty = LvalueTy::Downcast {
154                                     adt_def,
155                                     substs: self.monomorphize(&substs),
156                                     variant_index,
157                                 };
158                                 let (lldest_i, align) = val.trans_field_ptr(&bcx, field_index);
159                                 self.store_operand(&bcx, lldest_i, align.to_align(), op);
160                             }
161                         }
162                     },
163                     _ => {
164                         // If this is a tuple or closure, we need to translate GEP indices.
165                         let layout = bcx.ccx.layout_of(dest.ty.to_ty(bcx.tcx()));
166                         let get_memory_index = |i| {
167                             if let Layout::Univariant { ref variant, .. } = *layout {
168                                 adt::struct_llfields_index(variant, i)
169                             } else {
170                                 i
171                             }
172                         };
173                         let alignment = dest.alignment;
174                         for (i, operand) in operands.iter().enumerate() {
175                             let op = self.trans_operand(&bcx, operand);
176                             // Do not generate stores and GEPis for zero-sized fields.
177                             if !common::type_is_zero_size(bcx.ccx, op.ty) {
178                                 // Note: perhaps this should be StructGep, but
179                                 // note that in some cases the values here will
180                                 // not be structs but arrays.
181                                 let i = get_memory_index(i);
182                                 let dest = bcx.gepi(dest.llval, &[0, i]);
183                                 self.store_operand(&bcx, dest, alignment.to_align(), op);
184                             }
185                         }
186                     }
187                 }
188                 bcx
189             }
190
191             _ => {
192                 assert!(self.rvalue_creates_operand(rvalue));
193                 let (bcx, temp) = self.trans_rvalue_operand(bcx, rvalue);
194                 self.store_operand(&bcx, dest.llval, dest.alignment.to_align(), temp);
195                 bcx
196             }
197         }
198     }
199
200     pub fn trans_rvalue_operand(&mut self,
201                                 bcx: Builder<'a, 'tcx>,
202                                 rvalue: &mir::Rvalue<'tcx>)
203                                 -> (Builder<'a, 'tcx>, OperandRef<'tcx>)
204     {
205         assert!(self.rvalue_creates_operand(rvalue), "cannot trans {:?} to operand", rvalue);
206
207         match *rvalue {
208             mir::Rvalue::Cast(ref kind, ref source, cast_ty) => {
209                 let operand = self.trans_operand(&bcx, source);
210                 debug!("cast operand is {:?}", operand);
211                 let cast_ty = self.monomorphize(&cast_ty);
212
213                 let val = match *kind {
214                     mir::CastKind::ReifyFnPointer => {
215                         match operand.ty.sty {
216                             ty::TyFnDef(def_id, substs) => {
217                                 OperandValue::Immediate(
218                                     callee::resolve_and_get_fn(bcx.ccx, def_id, substs))
219                             }
220                             _ => {
221                                 bug!("{} cannot be reified to a fn ptr", operand.ty)
222                             }
223                         }
224                     }
225                     mir::CastKind::ClosureFnPointer => {
226                         match operand.ty.sty {
227                             ty::TyClosure(def_id, substs) => {
228                                 let instance = monomorphize::resolve_closure(
229                                     bcx.ccx.tcx(), def_id, substs, ty::ClosureKind::FnOnce);
230                                 OperandValue::Immediate(callee::get_fn(bcx.ccx, instance))
231                             }
232                             _ => {
233                                 bug!("{} cannot be cast to a fn ptr", operand.ty)
234                             }
235                         }
236                     }
237                     mir::CastKind::UnsafeFnPointer => {
238                         // this is a no-op at the LLVM level
239                         operand.val
240                     }
241                     mir::CastKind::Unsize => {
242                         // unsize targets other than to a fat pointer currently
243                         // can't be operands.
244                         assert!(common::type_is_fat_ptr(bcx.ccx, cast_ty));
245
246                         match operand.val {
247                             OperandValue::Pair(lldata, llextra) => {
248                                 // unsize from a fat pointer - this is a
249                                 // "trait-object-to-supertrait" coercion, for
250                                 // example,
251                                 //   &'a fmt::Debug+Send => &'a fmt::Debug,
252                                 // So we need to pointercast the base to ensure
253                                 // the types match up.
254                                 let llcast_ty = type_of::fat_ptr_base_ty(bcx.ccx, cast_ty);
255                                 let lldata = bcx.pointercast(lldata, llcast_ty);
256                                 OperandValue::Pair(lldata, llextra)
257                             }
258                             OperandValue::Immediate(lldata) => {
259                                 // "standard" unsize
260                                 let (lldata, llextra) = base::unsize_thin_ptr(&bcx, lldata,
261                                     operand.ty, cast_ty);
262                                 OperandValue::Pair(lldata, llextra)
263                             }
264                             OperandValue::Ref(..) => {
265                                 bug!("by-ref operand {:?} in trans_rvalue_operand",
266                                      operand);
267                             }
268                         }
269                     }
270                     mir::CastKind::Misc if common::type_is_fat_ptr(bcx.ccx, operand.ty) => {
271                         let ll_cast_ty = type_of::immediate_type_of(bcx.ccx, cast_ty);
272                         let ll_from_ty = type_of::immediate_type_of(bcx.ccx, operand.ty);
273                         if let OperandValue::Pair(data_ptr, meta_ptr) = operand.val {
274                             if common::type_is_fat_ptr(bcx.ccx, cast_ty) {
275                                 let ll_cft = ll_cast_ty.field_types();
276                                 let ll_fft = ll_from_ty.field_types();
277                                 let data_cast = bcx.pointercast(data_ptr, ll_cft[0]);
278                                 assert_eq!(ll_cft[1].kind(), ll_fft[1].kind());
279                                 OperandValue::Pair(data_cast, meta_ptr)
280                             } else { // cast to thin-ptr
281                                 // Cast of fat-ptr to thin-ptr is an extraction of data-ptr and
282                                 // pointer-cast of that pointer to desired pointer type.
283                                 let llval = bcx.pointercast(data_ptr, ll_cast_ty);
284                                 OperandValue::Immediate(llval)
285                             }
286                         } else {
287                             bug!("Unexpected non-Pair operand")
288                         }
289                     }
290                     mir::CastKind::Misc => {
291                         debug_assert!(common::type_is_immediate(bcx.ccx, cast_ty));
292                         let r_t_in = CastTy::from_ty(operand.ty).expect("bad input type for cast");
293                         let r_t_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
294                         let ll_t_in = type_of::immediate_type_of(bcx.ccx, operand.ty);
295                         let ll_t_out = type_of::immediate_type_of(bcx.ccx, cast_ty);
296                         let llval = operand.immediate();
297                         let l = bcx.ccx.layout_of(operand.ty);
298                         let signed = if let Layout::CEnum { signed, min, max, .. } = *l {
299                             if max > min {
300                                 // We want `table[e as usize]` to not
301                                 // have bound checks, and this is the most
302                                 // convenient place to put the `assume`.
303
304                                 base::call_assume(&bcx, bcx.icmp(
305                                     llvm::IntULE,
306                                     llval,
307                                     C_uint(common::val_ty(llval), max)
308                                 ));
309                             }
310
311                             signed
312                         } else {
313                             operand.ty.is_signed()
314                         };
315
316                         let newval = match (r_t_in, r_t_out) {
317                             (CastTy::Int(_), CastTy::Int(_)) => {
318                                 bcx.intcast(llval, ll_t_out, signed)
319                             }
320                             (CastTy::Float, CastTy::Float) => {
321                                 let srcsz = ll_t_in.float_width();
322                                 let dstsz = ll_t_out.float_width();
323                                 if dstsz > srcsz {
324                                     bcx.fpext(llval, ll_t_out)
325                                 } else if srcsz > dstsz {
326                                     bcx.fptrunc(llval, ll_t_out)
327                                 } else {
328                                     llval
329                                 }
330                             }
331                             (CastTy::Ptr(_), CastTy::Ptr(_)) |
332                             (CastTy::FnPtr, CastTy::Ptr(_)) |
333                             (CastTy::RPtr(_), CastTy::Ptr(_)) =>
334                                 bcx.pointercast(llval, ll_t_out),
335                             (CastTy::Ptr(_), CastTy::Int(_)) |
336                             (CastTy::FnPtr, CastTy::Int(_)) =>
337                                 bcx.ptrtoint(llval, ll_t_out),
338                             (CastTy::Int(_), CastTy::Ptr(_)) =>
339                                 bcx.inttoptr(llval, ll_t_out),
340                             (CastTy::Int(_), CastTy::Float) =>
341                                 cast_int_to_float(&bcx, signed, llval, ll_t_in, ll_t_out),
342                             (CastTy::Float, CastTy::Int(IntTy::I)) =>
343                                 cast_float_to_int(&bcx, true, llval, ll_t_in, ll_t_out),
344                             (CastTy::Float, CastTy::Int(_)) =>
345                                 cast_float_to_int(&bcx, false, llval, ll_t_in, ll_t_out),
346                             _ => bug!("unsupported cast: {:?} to {:?}", operand.ty, cast_ty)
347                         };
348                         OperandValue::Immediate(newval)
349                     }
350                 };
351                 let operand = OperandRef {
352                     val,
353                     ty: cast_ty
354                 };
355                 (bcx, operand)
356             }
357
358             mir::Rvalue::Ref(_, bk, ref lvalue) => {
359                 let tr_lvalue = self.trans_lvalue(&bcx, lvalue);
360
361                 let ty = tr_lvalue.ty.to_ty(bcx.tcx());
362                 let ref_ty = bcx.tcx().mk_ref(
363                     bcx.tcx().types.re_erased,
364                     ty::TypeAndMut { ty: ty, mutbl: bk.to_mutbl_lossy() }
365                 );
366
367                 // Note: lvalues are indirect, so storing the `llval` into the
368                 // destination effectively creates a reference.
369                 let operand = if !bcx.ccx.shared().type_has_metadata(ty) {
370                     OperandRef {
371                         val: OperandValue::Immediate(tr_lvalue.llval),
372                         ty: ref_ty,
373                     }
374                 } else {
375                     OperandRef {
376                         val: OperandValue::Pair(tr_lvalue.llval,
377                                                 tr_lvalue.llextra),
378                         ty: ref_ty,
379                     }
380                 };
381                 (bcx, operand)
382             }
383
384             mir::Rvalue::Len(ref lvalue) => {
385                 let size = self.evaluate_array_len(&bcx, lvalue);
386                 let operand = OperandRef {
387                     val: OperandValue::Immediate(size),
388                     ty: bcx.tcx().types.usize,
389                 };
390                 (bcx, operand)
391             }
392
393             mir::Rvalue::BinaryOp(op, ref lhs, ref rhs) => {
394                 let lhs = self.trans_operand(&bcx, lhs);
395                 let rhs = self.trans_operand(&bcx, rhs);
396                 let llresult = if common::type_is_fat_ptr(bcx.ccx, lhs.ty) {
397                     match (lhs.val, rhs.val) {
398                         (OperandValue::Pair(lhs_addr, lhs_extra),
399                          OperandValue::Pair(rhs_addr, rhs_extra)) => {
400                             self.trans_fat_ptr_binop(&bcx, op,
401                                                      lhs_addr, lhs_extra,
402                                                      rhs_addr, rhs_extra,
403                                                      lhs.ty)
404                         }
405                         _ => bug!()
406                     }
407
408                 } else {
409                     self.trans_scalar_binop(&bcx, op,
410                                             lhs.immediate(), rhs.immediate(),
411                                             lhs.ty)
412                 };
413                 let operand = OperandRef {
414                     val: OperandValue::Immediate(llresult),
415                     ty: op.ty(bcx.tcx(), lhs.ty, rhs.ty),
416                 };
417                 (bcx, operand)
418             }
419             mir::Rvalue::CheckedBinaryOp(op, ref lhs, ref rhs) => {
420                 let lhs = self.trans_operand(&bcx, lhs);
421                 let rhs = self.trans_operand(&bcx, rhs);
422                 let result = self.trans_scalar_checked_binop(&bcx, op,
423                                                              lhs.immediate(), rhs.immediate(),
424                                                              lhs.ty);
425                 let val_ty = op.ty(bcx.tcx(), lhs.ty, rhs.ty);
426                 let operand_ty = bcx.tcx().intern_tup(&[val_ty, bcx.tcx().types.bool], false);
427                 let operand = OperandRef {
428                     val: result,
429                     ty: operand_ty
430                 };
431
432                 (bcx, operand)
433             }
434
435             mir::Rvalue::UnaryOp(op, ref operand) => {
436                 let operand = self.trans_operand(&bcx, operand);
437                 let lloperand = operand.immediate();
438                 let is_float = operand.ty.is_fp();
439                 let llval = match op {
440                     mir::UnOp::Not => bcx.not(lloperand),
441                     mir::UnOp::Neg => if is_float {
442                         bcx.fneg(lloperand)
443                     } else {
444                         bcx.neg(lloperand)
445                     }
446                 };
447                 (bcx, OperandRef {
448                     val: OperandValue::Immediate(llval),
449                     ty: operand.ty,
450                 })
451             }
452
453             mir::Rvalue::Discriminant(ref lvalue) => {
454                 let discr_lvalue = self.trans_lvalue(&bcx, lvalue);
455                 let enum_ty = discr_lvalue.ty.to_ty(bcx.tcx());
456                 let discr_ty = rvalue.ty(&*self.mir, bcx.tcx());
457                 let discr_type = type_of::immediate_type_of(bcx.ccx, discr_ty);
458                 let discr = adt::trans_get_discr(&bcx, enum_ty, discr_lvalue.llval,
459                                                   discr_lvalue.alignment, Some(discr_type), true);
460                 (bcx, OperandRef {
461                     val: OperandValue::Immediate(discr),
462                     ty: discr_ty
463                 })
464             }
465
466             mir::Rvalue::NullaryOp(mir::NullOp::SizeOf, ty) => {
467                 assert!(bcx.ccx.shared().type_is_sized(ty));
468                 let val = C_usize(bcx.ccx, bcx.ccx.size_of(ty));
469                 let tcx = bcx.tcx();
470                 (bcx, OperandRef {
471                     val: OperandValue::Immediate(val),
472                     ty: tcx.types.usize,
473                 })
474             }
475
476             mir::Rvalue::NullaryOp(mir::NullOp::Box, content_ty) => {
477                 let content_ty: Ty<'tcx> = self.monomorphize(&content_ty);
478                 let llty = type_of::type_of(bcx.ccx, content_ty);
479                 let llsize = machine::llsize_of(bcx.ccx, llty);
480                 let align = bcx.ccx.align_of(content_ty);
481                 let llalign = C_usize(bcx.ccx, align as u64);
482                 let llty_ptr = llty.ptr_to();
483                 let box_ty = bcx.tcx().mk_box(content_ty);
484
485                 // Allocate space:
486                 let def_id = match bcx.tcx().lang_items().require(ExchangeMallocFnLangItem) {
487                     Ok(id) => id,
488                     Err(s) => {
489                         bcx.sess().fatal(&format!("allocation of `{}` {}", box_ty, s));
490                     }
491                 };
492                 let instance = ty::Instance::mono(bcx.tcx(), def_id);
493                 let r = callee::get_fn(bcx.ccx, instance);
494                 let val = bcx.pointercast(bcx.call(r, &[llsize, llalign], None), llty_ptr);
495
496                 let operand = OperandRef {
497                     val: OperandValue::Immediate(val),
498                     ty: box_ty,
499                 };
500                 (bcx, operand)
501             }
502             mir::Rvalue::Use(ref operand) => {
503                 let operand = self.trans_operand(&bcx, operand);
504                 (bcx, operand)
505             }
506             mir::Rvalue::Repeat(..) |
507             mir::Rvalue::Aggregate(..) => {
508                 // According to `rvalue_creates_operand`, only ZST
509                 // aggregate rvalues are allowed to be operands.
510                 let ty = rvalue.ty(self.mir, self.ccx.tcx());
511                 (bcx, OperandRef::new_zst(self.ccx, self.monomorphize(&ty)))
512             }
513         }
514     }
515
516     fn evaluate_array_len(&mut self,
517                           bcx: &Builder<'a, 'tcx>,
518                           lvalue: &mir::Lvalue<'tcx>) -> ValueRef
519     {
520         // ZST are passed as operands and require special handling
521         // because trans_lvalue() panics if Local is operand.
522         if let mir::Lvalue::Local(index) = *lvalue {
523             if let LocalRef::Operand(Some(op)) = self.locals[index] {
524                 if common::type_is_zero_size(bcx.ccx, op.ty) {
525                     if let ty::TyArray(_, n) = op.ty.sty {
526                         let n = n.val.to_const_int().unwrap().to_u64().unwrap();
527                         return common::C_usize(bcx.ccx, n);
528                     }
529                 }
530             }
531         }
532         // use common size calculation for non zero-sized types
533         let tr_value = self.trans_lvalue(&bcx, lvalue);
534         return tr_value.len(bcx.ccx);
535     }
536
537     pub fn trans_scalar_binop(&mut self,
538                               bcx: &Builder<'a, 'tcx>,
539                               op: mir::BinOp,
540                               lhs: ValueRef,
541                               rhs: ValueRef,
542                               input_ty: Ty<'tcx>) -> ValueRef {
543         let is_float = input_ty.is_fp();
544         let is_signed = input_ty.is_signed();
545         let is_nil = input_ty.is_nil();
546         let is_bool = input_ty.is_bool();
547         match op {
548             mir::BinOp::Add => if is_float {
549                 bcx.fadd(lhs, rhs)
550             } else {
551                 bcx.add(lhs, rhs)
552             },
553             mir::BinOp::Sub => if is_float {
554                 bcx.fsub(lhs, rhs)
555             } else {
556                 bcx.sub(lhs, rhs)
557             },
558             mir::BinOp::Mul => if is_float {
559                 bcx.fmul(lhs, rhs)
560             } else {
561                 bcx.mul(lhs, rhs)
562             },
563             mir::BinOp::Div => if is_float {
564                 bcx.fdiv(lhs, rhs)
565             } else if is_signed {
566                 bcx.sdiv(lhs, rhs)
567             } else {
568                 bcx.udiv(lhs, rhs)
569             },
570             mir::BinOp::Rem => if is_float {
571                 bcx.frem(lhs, rhs)
572             } else if is_signed {
573                 bcx.srem(lhs, rhs)
574             } else {
575                 bcx.urem(lhs, rhs)
576             },
577             mir::BinOp::BitOr => bcx.or(lhs, rhs),
578             mir::BinOp::BitAnd => bcx.and(lhs, rhs),
579             mir::BinOp::BitXor => bcx.xor(lhs, rhs),
580             mir::BinOp::Offset => bcx.inbounds_gep(lhs, &[rhs]),
581             mir::BinOp::Shl => common::build_unchecked_lshift(bcx, lhs, rhs),
582             mir::BinOp::Shr => common::build_unchecked_rshift(bcx, input_ty, lhs, rhs),
583             mir::BinOp::Ne | mir::BinOp::Lt | mir::BinOp::Gt |
584             mir::BinOp::Eq | mir::BinOp::Le | mir::BinOp::Ge => if is_nil {
585                 C_bool(bcx.ccx, match op {
586                     mir::BinOp::Ne | mir::BinOp::Lt | mir::BinOp::Gt => false,
587                     mir::BinOp::Eq | mir::BinOp::Le | mir::BinOp::Ge => true,
588                     _ => unreachable!()
589                 })
590             } else if is_float {
591                 bcx.fcmp(
592                     base::bin_op_to_fcmp_predicate(op.to_hir_binop()),
593                     lhs, rhs
594                 )
595             } else {
596                 let (lhs, rhs) = if is_bool {
597                     // FIXME(#36856) -- extend the bools into `i8` because
598                     // LLVM's i1 comparisons are broken.
599                     (bcx.zext(lhs, Type::i8(bcx.ccx)),
600                      bcx.zext(rhs, Type::i8(bcx.ccx)))
601                 } else {
602                     (lhs, rhs)
603                 };
604
605                 bcx.icmp(
606                     base::bin_op_to_icmp_predicate(op.to_hir_binop(), is_signed),
607                     lhs, rhs
608                 )
609             }
610         }
611     }
612
613     pub fn trans_fat_ptr_binop(&mut self,
614                                bcx: &Builder<'a, 'tcx>,
615                                op: mir::BinOp,
616                                lhs_addr: ValueRef,
617                                lhs_extra: ValueRef,
618                                rhs_addr: ValueRef,
619                                rhs_extra: ValueRef,
620                                _input_ty: Ty<'tcx>)
621                                -> ValueRef {
622         match op {
623             mir::BinOp::Eq => {
624                 bcx.and(
625                     bcx.icmp(llvm::IntEQ, lhs_addr, rhs_addr),
626                     bcx.icmp(llvm::IntEQ, lhs_extra, rhs_extra)
627                 )
628             }
629             mir::BinOp::Ne => {
630                 bcx.or(
631                     bcx.icmp(llvm::IntNE, lhs_addr, rhs_addr),
632                     bcx.icmp(llvm::IntNE, lhs_extra, rhs_extra)
633                 )
634             }
635             mir::BinOp::Le | mir::BinOp::Lt |
636             mir::BinOp::Ge | mir::BinOp::Gt => {
637                 // a OP b ~ a.0 STRICT(OP) b.0 | (a.0 == b.0 && a.1 OP a.1)
638                 let (op, strict_op) = match op {
639                     mir::BinOp::Lt => (llvm::IntULT, llvm::IntULT),
640                     mir::BinOp::Le => (llvm::IntULE, llvm::IntULT),
641                     mir::BinOp::Gt => (llvm::IntUGT, llvm::IntUGT),
642                     mir::BinOp::Ge => (llvm::IntUGE, llvm::IntUGT),
643                     _ => bug!(),
644                 };
645
646                 bcx.or(
647                     bcx.icmp(strict_op, lhs_addr, rhs_addr),
648                     bcx.and(
649                         bcx.icmp(llvm::IntEQ, lhs_addr, rhs_addr),
650                         bcx.icmp(op, lhs_extra, rhs_extra)
651                     )
652                 )
653             }
654             _ => {
655                 bug!("unexpected fat ptr binop");
656             }
657         }
658     }
659
660     pub fn trans_scalar_checked_binop(&mut self,
661                                       bcx: &Builder<'a, 'tcx>,
662                                       op: mir::BinOp,
663                                       lhs: ValueRef,
664                                       rhs: ValueRef,
665                                       input_ty: Ty<'tcx>) -> OperandValue {
666         // This case can currently arise only from functions marked
667         // with #[rustc_inherit_overflow_checks] and inlined from
668         // another crate (mostly core::num generic/#[inline] fns),
669         // while the current crate doesn't use overflow checks.
670         if !bcx.ccx.check_overflow() {
671             let val = self.trans_scalar_binop(bcx, op, lhs, rhs, input_ty);
672             return OperandValue::Pair(val, C_bool(bcx.ccx, false));
673         }
674
675         // First try performing the operation on constants, which
676         // will only succeed if both operands are constant.
677         // This is necessary to determine when an overflow Assert
678         // will always panic at runtime, and produce a warning.
679         if let Some((val, of)) = const_scalar_checked_binop(bcx.tcx(), op, lhs, rhs, input_ty) {
680             return OperandValue::Pair(val, C_bool(bcx.ccx, of));
681         }
682
683         let (val, of) = match op {
684             // These are checked using intrinsics
685             mir::BinOp::Add | mir::BinOp::Sub | mir::BinOp::Mul => {
686                 let oop = match op {
687                     mir::BinOp::Add => OverflowOp::Add,
688                     mir::BinOp::Sub => OverflowOp::Sub,
689                     mir::BinOp::Mul => OverflowOp::Mul,
690                     _ => unreachable!()
691                 };
692                 let intrinsic = get_overflow_intrinsic(oop, bcx, input_ty);
693                 let res = bcx.call(intrinsic, &[lhs, rhs], None);
694
695                 (bcx.extract_value(res, 0),
696                  bcx.extract_value(res, 1))
697             }
698             mir::BinOp::Shl | mir::BinOp::Shr => {
699                 let lhs_llty = val_ty(lhs);
700                 let rhs_llty = val_ty(rhs);
701                 let invert_mask = common::shift_mask_val(&bcx, lhs_llty, rhs_llty, true);
702                 let outer_bits = bcx.and(rhs, invert_mask);
703
704                 let of = bcx.icmp(llvm::IntNE, outer_bits, C_null(rhs_llty));
705                 let val = self.trans_scalar_binop(bcx, op, lhs, rhs, input_ty);
706
707                 (val, of)
708             }
709             _ => {
710                 bug!("Operator `{:?}` is not a checkable operator", op)
711             }
712         };
713
714         OperandValue::Pair(val, of)
715     }
716
717     pub fn rvalue_creates_operand(&self, rvalue: &mir::Rvalue<'tcx>) -> bool {
718         match *rvalue {
719             mir::Rvalue::Ref(..) |
720             mir::Rvalue::Len(..) |
721             mir::Rvalue::Cast(..) | // (*)
722             mir::Rvalue::BinaryOp(..) |
723             mir::Rvalue::CheckedBinaryOp(..) |
724             mir::Rvalue::UnaryOp(..) |
725             mir::Rvalue::Discriminant(..) |
726             mir::Rvalue::NullaryOp(..) |
727             mir::Rvalue::Use(..) => // (*)
728                 true,
729             mir::Rvalue::Repeat(..) |
730             mir::Rvalue::Aggregate(..) => {
731                 let ty = rvalue.ty(self.mir, self.ccx.tcx());
732                 let ty = self.monomorphize(&ty);
733                 common::type_is_zero_size(self.ccx, ty)
734             }
735         }
736
737         // (*) this is only true if the type is suitable
738     }
739 }
740
741 #[derive(Copy, Clone)]
742 enum OverflowOp {
743     Add, Sub, Mul
744 }
745
746 fn get_overflow_intrinsic(oop: OverflowOp, bcx: &Builder, ty: Ty) -> ValueRef {
747     use syntax::ast::IntTy::*;
748     use syntax::ast::UintTy::*;
749     use rustc::ty::{TyInt, TyUint};
750
751     let tcx = bcx.tcx();
752
753     let new_sty = match ty.sty {
754         TyInt(Is) => match &tcx.sess.target.target.target_pointer_width[..] {
755             "16" => TyInt(I16),
756             "32" => TyInt(I32),
757             "64" => TyInt(I64),
758             _ => panic!("unsupported target word size")
759         },
760         TyUint(Us) => match &tcx.sess.target.target.target_pointer_width[..] {
761             "16" => TyUint(U16),
762             "32" => TyUint(U32),
763             "64" => TyUint(U64),
764             _ => panic!("unsupported target word size")
765         },
766         ref t @ TyUint(_) | ref t @ TyInt(_) => t.clone(),
767         _ => panic!("tried to get overflow intrinsic for op applied to non-int type")
768     };
769
770     let name = match oop {
771         OverflowOp::Add => match new_sty {
772             TyInt(I8) => "llvm.sadd.with.overflow.i8",
773             TyInt(I16) => "llvm.sadd.with.overflow.i16",
774             TyInt(I32) => "llvm.sadd.with.overflow.i32",
775             TyInt(I64) => "llvm.sadd.with.overflow.i64",
776             TyInt(I128) => "llvm.sadd.with.overflow.i128",
777
778             TyUint(U8) => "llvm.uadd.with.overflow.i8",
779             TyUint(U16) => "llvm.uadd.with.overflow.i16",
780             TyUint(U32) => "llvm.uadd.with.overflow.i32",
781             TyUint(U64) => "llvm.uadd.with.overflow.i64",
782             TyUint(U128) => "llvm.uadd.with.overflow.i128",
783
784             _ => unreachable!(),
785         },
786         OverflowOp::Sub => match new_sty {
787             TyInt(I8) => "llvm.ssub.with.overflow.i8",
788             TyInt(I16) => "llvm.ssub.with.overflow.i16",
789             TyInt(I32) => "llvm.ssub.with.overflow.i32",
790             TyInt(I64) => "llvm.ssub.with.overflow.i64",
791             TyInt(I128) => "llvm.ssub.with.overflow.i128",
792
793             TyUint(U8) => "llvm.usub.with.overflow.i8",
794             TyUint(U16) => "llvm.usub.with.overflow.i16",
795             TyUint(U32) => "llvm.usub.with.overflow.i32",
796             TyUint(U64) => "llvm.usub.with.overflow.i64",
797             TyUint(U128) => "llvm.usub.with.overflow.i128",
798
799             _ => unreachable!(),
800         },
801         OverflowOp::Mul => match new_sty {
802             TyInt(I8) => "llvm.smul.with.overflow.i8",
803             TyInt(I16) => "llvm.smul.with.overflow.i16",
804             TyInt(I32) => "llvm.smul.with.overflow.i32",
805             TyInt(I64) => "llvm.smul.with.overflow.i64",
806             TyInt(I128) => "llvm.smul.with.overflow.i128",
807
808             TyUint(U8) => "llvm.umul.with.overflow.i8",
809             TyUint(U16) => "llvm.umul.with.overflow.i16",
810             TyUint(U32) => "llvm.umul.with.overflow.i32",
811             TyUint(U64) => "llvm.umul.with.overflow.i64",
812             TyUint(U128) => "llvm.umul.with.overflow.i128",
813
814             _ => unreachable!(),
815         },
816     };
817
818     bcx.ccx.get_intrinsic(&name)
819 }
820
821 fn cast_int_to_float(bcx: &Builder,
822                      signed: bool,
823                      x: ValueRef,
824                      int_ty: Type,
825                      float_ty: Type) -> ValueRef {
826     // Most integer types, even i128, fit into [-f32::MAX, f32::MAX] after rounding.
827     // It's only u128 -> f32 that can cause overflows (i.e., should yield infinity).
828     // LLVM's uitofp produces undef in those cases, so we manually check for that case.
829     let is_u128_to_f32 = !signed && int_ty.int_width() == 128 && float_ty.float_width() == 32;
830     if is_u128_to_f32 {
831         // All inputs greater or equal to (f32::MAX + 0.5 ULP) are rounded to infinity,
832         // and for everything else LLVM's uitofp works just fine.
833         let max = C_big_integral(int_ty, MAX_F32_PLUS_HALF_ULP);
834         let overflow = bcx.icmp(llvm::IntUGE, x, max);
835         let infinity_bits = C_u32(bcx.ccx, ieee::Single::INFINITY.to_bits() as u32);
836         let infinity = consts::bitcast(infinity_bits, float_ty);
837         bcx.select(overflow, infinity, bcx.uitofp(x, float_ty))
838     } else {
839         if signed {
840             bcx.sitofp(x, float_ty)
841         } else {
842             bcx.uitofp(x, float_ty)
843         }
844     }
845 }
846
847 fn cast_float_to_int(bcx: &Builder,
848                      signed: bool,
849                      x: ValueRef,
850                      float_ty: Type,
851                      int_ty: Type) -> ValueRef {
852     let fptosui_result = if signed {
853         bcx.fptosi(x, int_ty)
854     } else {
855         bcx.fptoui(x, int_ty)
856     };
857
858     if !bcx.sess().opts.debugging_opts.saturating_float_casts {
859         return fptosui_result;
860     }
861     // LLVM's fpto[su]i returns undef when the input x is infinite, NaN, or does not fit into the
862     // destination integer type after rounding towards zero. This `undef` value can cause UB in
863     // safe code (see issue #10184), so we implement a saturating conversion on top of it:
864     // Semantically, the mathematical value of the input is rounded towards zero to the next
865     // mathematical integer, and then the result is clamped into the range of the destination
866     // integer type. Positive and negative infinity are mapped to the maximum and minimum value of
867     // the destination integer type. NaN is mapped to 0.
868     //
869     // Define f_min and f_max as the largest and smallest (finite) floats that are exactly equal to
870     // a value representable in int_ty.
871     // They are exactly equal to int_ty::{MIN,MAX} if float_ty has enough significand bits.
872     // Otherwise, int_ty::MAX must be rounded towards zero, as it is one less than a power of two.
873     // int_ty::MIN, however, is either zero or a negative power of two and is thus exactly
874     // representable. Note that this only works if float_ty's exponent range is sufficently large.
875     // f16 or 256 bit integers would break this property. Right now the smallest float type is f32
876     // with exponents ranging up to 127, which is barely enough for i128::MIN = -2^127.
877     // On the other hand, f_max works even if int_ty::MAX is greater than float_ty::MAX. Because
878     // we're rounding towards zero, we just get float_ty::MAX (which is always an integer).
879     // This already happens today with u128::MAX = 2^128 - 1 > f32::MAX.
880     fn compute_clamp_bounds<F: Float>(signed: bool, int_ty: Type) -> (u128, u128) {
881         let rounded_min = F::from_i128_r(int_min(signed, int_ty), Round::TowardZero);
882         assert_eq!(rounded_min.status, Status::OK);
883         let rounded_max = F::from_u128_r(int_max(signed, int_ty), Round::TowardZero);
884         assert!(rounded_max.value.is_finite());
885         (rounded_min.value.to_bits(), rounded_max.value.to_bits())
886     }
887     fn int_max(signed: bool, int_ty: Type) -> u128 {
888         let shift_amount = 128 - int_ty.int_width();
889         if signed {
890             i128::MAX as u128 >> shift_amount
891         } else {
892             u128::MAX >> shift_amount
893         }
894     }
895     fn int_min(signed: bool, int_ty: Type) -> i128 {
896         if signed {
897             i128::MIN >> (128 - int_ty.int_width())
898         } else {
899             0
900         }
901     }
902     let float_bits_to_llval = |bits| {
903         let bits_llval = match float_ty.float_width() {
904             32 => C_u32(bcx.ccx, bits as u32),
905             64 => C_u64(bcx.ccx, bits as u64),
906             n => bug!("unsupported float width {}", n),
907         };
908         consts::bitcast(bits_llval, float_ty)
909     };
910     let (f_min, f_max) = match float_ty.float_width() {
911         32 => compute_clamp_bounds::<ieee::Single>(signed, int_ty),
912         64 => compute_clamp_bounds::<ieee::Double>(signed, int_ty),
913         n => bug!("unsupported float width {}", n),
914     };
915     let f_min = float_bits_to_llval(f_min);
916     let f_max = float_bits_to_llval(f_max);
917     // To implement saturation, we perform the following steps:
918     //
919     // 1. Cast x to an integer with fpto[su]i. This may result in undef.
920     // 2. Compare x to f_min and f_max, and use the comparison results to select:
921     //  a) int_ty::MIN if x < f_min or x is NaN
922     //  b) int_ty::MAX if x > f_max
923     //  c) the result of fpto[su]i otherwise
924     // 3. If x is NaN, return 0.0, otherwise return the result of step 2.
925     //
926     // This avoids resulting undef because values in range [f_min, f_max] by definition fit into the
927     // destination type. It creates an undef temporary, but *producing* undef is not UB. Our use of
928     // undef does not introduce any non-determinism either.
929     // More importantly, the above procedure correctly implements saturating conversion.
930     // Proof (sketch):
931     // If x is NaN, 0 is returned by definition.
932     // Otherwise, x is finite or infinite and thus can be compared with f_min and f_max.
933     // This yields three cases to consider:
934     // (1) if x in [f_min, f_max], the result of fpto[su]i is returned, which agrees with
935     //     saturating conversion for inputs in that range.
936     // (2) if x > f_max, then x is larger than int_ty::MAX. This holds even if f_max is rounded
937     //     (i.e., if f_max < int_ty::MAX) because in those cases, nextUp(f_max) is already larger
938     //     than int_ty::MAX. Because x is larger than int_ty::MAX, the return value of int_ty::MAX
939     //     is correct.
940     // (3) if x < f_min, then x is smaller than int_ty::MIN. As shown earlier, f_min exactly equals
941     //     int_ty::MIN and therefore the return value of int_ty::MIN is correct.
942     // QED.
943
944     // Step 1 was already performed above.
945
946     // Step 2: We use two comparisons and two selects, with %s1 being the result:
947     //     %less_or_nan = fcmp ult %x, %f_min
948     //     %greater = fcmp olt %x, %f_max
949     //     %s0 = select %less_or_nan, int_ty::MIN, %fptosi_result
950     //     %s1 = select %greater, int_ty::MAX, %s0
951     // Note that %less_or_nan uses an *unordered* comparison. This comparison is true if the
952     // operands are not comparable (i.e., if x is NaN). The unordered comparison ensures that s1
953     // becomes int_ty::MIN if x is NaN.
954     // Performance note: Unordered comparison can be lowered to a "flipped" comparison and a
955     // negation, and the negation can be merged into the select. Therefore, it not necessarily any
956     // more expensive than a ordered ("normal") comparison. Whether these optimizations will be
957     // performed is ultimately up to the backend, but at least x86 does perform them.
958     let less_or_nan = bcx.fcmp(llvm::RealULT, x, f_min);
959     let greater = bcx.fcmp(llvm::RealOGT, x, f_max);
960     let int_max = C_big_integral(int_ty, int_max(signed, int_ty));
961     let int_min = C_big_integral(int_ty, int_min(signed, int_ty) as u128);
962     let s0 = bcx.select(less_or_nan, int_min, fptosui_result);
963     let s1 = bcx.select(greater, int_max, s0);
964
965     // Step 3: NaN replacement.
966     // For unsigned types, the above step already yielded int_ty::MIN == 0 if x is NaN.
967     // Therefore we only need to execute this step for signed integer types.
968     if signed {
969         // LLVM has no isNaN predicate, so we use (x == x) instead
970         bcx.select(bcx.fcmp(llvm::RealOEQ, x, x), s1, C_uint(int_ty, 0))
971     } else {
972         s1
973     }
974 }