From 2b688a959def6d3441d3e4854fde557de0913e36 Mon Sep 17 00:00:00 2001
From: bjorn3 <bjorn3@users.noreply.github.com>
Date: Sun, 2 Dec 2018 12:54:54 +0100
Subject: [PATCH 01/18] Don't use c_uint in cg_ssa

---
 src/librustc_codegen_llvm/context.rs    |  4 ++--
 src/librustc_codegen_ssa/mir/mod.rs     | 13 ++++++-------
 src/librustc_codegen_ssa/traits/misc.rs |  3 +--
 3 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs
index 619304ad9afd0..0060751d60641 100644
--- a/src/librustc_codegen_llvm/context.rs
+++ b/src/librustc_codegen_llvm/context.rs
@@ -326,8 +326,8 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         get_fn(self, instance)
     }
 
-    fn get_param(&self, llfn: &'ll Value, index: c_uint) -> &'ll Value {
-        llvm::get_param(llfn, index)
+    fn get_param(&self, llfn: &'ll Value, index: usize) -> &'ll Value {
+        llvm::get_param(llfn, index as c_uint)
     }
 
     fn eh_personality(&self) -> &'ll Value {
diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs
index bc77097425bd1..b0f53de17ea31 100644
--- a/src/librustc_codegen_ssa/mir/mod.rs
+++ b/src/librustc_codegen_ssa/mir/mod.rs
@@ -1,4 +1,3 @@
-use libc::c_uint;
 use rustc::ty::{self, Ty, TypeFoldable, UpvarSubsts};
 use rustc::ty::layout::{TyLayout, HasTyCtxt};
 use rustc::mir::{self, Mir};
@@ -534,18 +533,18 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
                 }
                 PassMode::Ignore(IgnoreMode::CVarArgs) => {}
                 PassMode::Direct(_) => {
-                    let llarg = bx.get_param(bx.llfn(), llarg_idx as c_uint);
+                    let llarg = bx.get_param(bx.llfn(), llarg_idx);
                     bx.set_value_name(llarg, &name);
                     llarg_idx += 1;
                     return local(
                         OperandRef::from_immediate_or_packed_pair(bx, llarg, arg.layout));
                 }
                 PassMode::Pair(..) => {
-                    let a = bx.get_param(bx.llfn(), llarg_idx as c_uint);
+                    let a = bx.get_param(bx.llfn(), llarg_idx);
                     bx.set_value_name(a, &(name.clone() + ".0"));
                     llarg_idx += 1;
 
-                    let b = bx.get_param(bx.llfn(), llarg_idx as c_uint);
+                    let b = bx.get_param(bx.llfn(), llarg_idx);
                     bx.set_value_name(b, &(name + ".1"));
                     llarg_idx += 1;
 
@@ -562,16 +561,16 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
             // Don't copy an indirect argument to an alloca, the caller
             // already put it in a temporary alloca and gave it up.
             // FIXME: lifetimes
-            let llarg = bx.get_param(bx.llfn(), llarg_idx as c_uint);
+            let llarg = bx.get_param(bx.llfn(), llarg_idx);
             bx.set_value_name(llarg, &name);
             llarg_idx += 1;
             PlaceRef::new_sized(llarg, arg.layout, arg.layout.align.abi)
         } else if arg.is_unsized_indirect() {
             // As the storage for the indirect argument lives during
             // the whole function call, we just copy the fat pointer.
-            let llarg = bx.get_param(bx.llfn(), llarg_idx as c_uint);
+            let llarg = bx.get_param(bx.llfn(), llarg_idx);
             llarg_idx += 1;
-            let llextra = bx.get_param(bx.llfn(), llarg_idx as c_uint);
+            let llextra = bx.get_param(bx.llfn(), llarg_idx);
             llarg_idx += 1;
             let indirect_operand = OperandValue::Pair(llarg, llextra);
 
diff --git a/src/librustc_codegen_ssa/traits/misc.rs b/src/librustc_codegen_ssa/traits/misc.rs
index b23155563665d..b3d458f3a3be8 100644
--- a/src/librustc_codegen_ssa/traits/misc.rs
+++ b/src/librustc_codegen_ssa/traits/misc.rs
@@ -1,5 +1,4 @@
 use super::BackendTypes;
-use libc::c_uint;
 use rustc::mir::mono::Stats;
 use rustc::session::Session;
 use rustc::ty::{self, Instance, Ty};
@@ -15,7 +14,7 @@ pub trait MiscMethods<'tcx>: BackendTypes {
     fn check_overflow(&self) -> bool;
     fn instances(&self) -> &RefCell<FxHashMap<Instance<'tcx>, Self::Value>>;
     fn get_fn(&self, instance: Instance<'tcx>) -> Self::Value;
-    fn get_param(&self, llfn: Self::Value, index: c_uint) -> Self::Value;
+    fn get_param(&self, llfn: Self::Value, index: usize) -> Self::Value;
     fn eh_personality(&self) -> Self::Value;
     fn eh_unwind_resume(&self) -> Self::Value;
     fn sess(&self) -> &Session;

From a0c2ca1b56e64f4a5658ae0371da44e7af7cd58f Mon Sep 17 00:00:00 2001
From: bjorn3 <bjorn3@users.noreply.github.com>
Date: Sun, 2 Dec 2018 13:57:41 +0100
Subject: [PATCH 02/18] `eval_mir_constant` doesn't need a builder param

---
 src/librustc_codegen_ssa/mir/block.rs    | 2 +-
 src/librustc_codegen_ssa/mir/constant.rs | 7 +++----
 src/librustc_codegen_ssa/mir/operand.rs  | 2 +-
 3 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index 4774f8fe5a380..494355efeaaa7 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -657,7 +657,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                             span_bug!(span, "shuffle indices must be constant");
                         }
                         mir::Operand::Constant(ref constant) => {
-                            let c = self.eval_mir_constant(&bx, constant);
+                            let c = self.eval_mir_constant(constant);
                             let (llval, ty) = self.simd_shuffle_indices(
                                 &bx,
                                 constant.span,
diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs
index a1d44b228a516..3f8dc420cf402 100644
--- a/src/librustc_codegen_ssa/mir/constant.rs
+++ b/src/librustc_codegen_ssa/mir/constant.rs
@@ -3,7 +3,7 @@ use rustc_mir::const_eval::const_field;
 use rustc::mir;
 use rustc_data_structures::indexed_vec::Idx;
 use rustc::ty::{self, Ty};
-use rustc::ty::layout;
+use rustc::ty::layout::{self, HasTyCtxt};
 use syntax::source_map::Span;
 use crate::traits::*;
 
@@ -12,20 +12,19 @@ use super::FunctionCx;
 impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     pub fn eval_mir_constant(
         &mut self,
-        bx: &Bx,
         constant: &mir::Constant<'tcx>,
     ) -> Result<ty::Const<'tcx>, ErrorHandled> {
         match constant.literal.val {
             mir::interpret::ConstValue::Unevaluated(def_id, ref substs) => {
                 let substs = self.monomorphize(substs);
                 let instance = ty::Instance::resolve(
-                    bx.tcx(), ty::ParamEnv::reveal_all(), def_id, substs,
+                    self.cx.tcx(), ty::ParamEnv::reveal_all(), def_id, substs,
                 ).unwrap();
                 let cid = mir::interpret::GlobalId {
                     instance,
                     promoted: None,
                 };
-                bx.tcx().const_eval(ty::ParamEnv::reveal_all().and(cid))
+                self.cx.tcx().const_eval(ty::ParamEnv::reveal_all().and(cid))
             },
             _ => Ok(*self.monomorphize(&constant.literal)),
         }
diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs
index e17a6e7b03f81..289129e8e62ff 100644
--- a/src/librustc_codegen_ssa/mir/operand.rs
+++ b/src/librustc_codegen_ssa/mir/operand.rs
@@ -460,7 +460,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
             mir::Operand::Constant(ref constant) => {
                 let ty = self.monomorphize(&constant.ty);
-                self.eval_mir_constant(bx, constant)
+                self.eval_mir_constant(constant)
                     .and_then(|c| OperandRef::from_const(bx, c))
                     .unwrap_or_else(|err| {
                         match err {

From 83e80a74436179588703db2d597e80f57e42efbe Mon Sep 17 00:00:00 2001
From: bjorn3 <bjorn3@users.noreply.github.com>
Date: Fri, 1 Mar 2019 15:03:48 +0100
Subject: [PATCH 03/18] Use Builder instead of CodegenCx for OperandRef and
 LocalRef

---
 src/librustc_codegen_llvm/builder.rs    |  2 +-
 src/librustc_codegen_ssa/mir/mod.rs     | 14 ++++++------
 src/librustc_codegen_ssa/mir/operand.rs | 30 ++++++++++++-------------
 src/librustc_codegen_ssa/mir/rvalue.rs  |  7 ++++--
 4 files changed, 28 insertions(+), 25 deletions(-)

diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs
index d4d38a464576d..d0a861171c17c 100644
--- a/src/librustc_codegen_llvm/builder.rs
+++ b/src/librustc_codegen_llvm/builder.rs
@@ -616,7 +616,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         assert_eq!(place.llextra.is_some(), place.layout.is_unsized());
 
         if place.layout.is_zst() {
-            return OperandRef::new_zst(self.cx(), place.layout);
+            return OperandRef::new_zst(self, place.layout);
         }
 
         fn scalar_load_metadata<'a, 'll, 'tcx>(
diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs
index b0f53de17ea31..5e2144751c125 100644
--- a/src/librustc_codegen_ssa/mir/mod.rs
+++ b/src/librustc_codegen_ssa/mir/mod.rs
@@ -178,16 +178,16 @@ enum LocalRef<'tcx, V> {
     Operand(Option<OperandRef<'tcx, V>>),
 }
 
-impl<'tcx, V: CodegenObject> LocalRef<'tcx, V> {
-    fn new_operand<Cx: CodegenMethods<'tcx, Value = V>>(
-        cx: &Cx,
+impl<'a, 'tcx: 'a, V: CodegenObject> LocalRef<'tcx, V> {
+    fn new_operand<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
+        bx: &mut Bx,
         layout: TyLayout<'tcx>,
     ) -> LocalRef<'tcx, V> {
         if layout.is_zst() {
             // Zero-size temporaries aren't always initialized, which
             // doesn't matter because they don't contain data, but
             // we need something in the operand.
-            LocalRef::Operand(Some(OperandRef::new_zst(cx, layout)))
+            LocalRef::Operand(Some(OperandRef::new_zst(bx, layout)))
         } else {
             LocalRef::Operand(None)
         }
@@ -275,7 +275,7 @@ pub fn codegen_mir<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
 
                 if !memory_locals.contains(local) && !dbg {
                     debug!("alloc: {:?} ({}) -> operand", local, name);
-                    return LocalRef::new_operand(bx.cx(), layout);
+                    return LocalRef::new_operand(&mut bx, layout);
                 }
 
                 debug!("alloc: {:?} ({}) -> place", local, name);
@@ -320,7 +320,7 @@ pub fn codegen_mir<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
                     // alloca in advance. Instead we wait until we see the
                     // definition and update the operand there.
                     debug!("alloc: {:?} -> operand", local);
-                    LocalRef::new_operand(bx.cx(), layout)
+                    LocalRef::new_operand(&mut bx, layout)
                 }
             }
         };
@@ -529,7 +529,7 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
             let local = |op| LocalRef::Operand(Some(op));
             match arg.mode {
                 PassMode::Ignore(IgnoreMode::Zst) => {
-                    return local(OperandRef::new_zst(bx.cx(), arg.layout));
+                    return local(OperandRef::new_zst(bx, arg.layout));
                 }
                 PassMode::Ignore(IgnoreMode::CVarArgs) => {}
                 PassMode::Direct(_) => {
diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs
index 289129e8e62ff..c2b1021f816a6 100644
--- a/src/librustc_codegen_ssa/mir/operand.rs
+++ b/src/librustc_codegen_ssa/mir/operand.rs
@@ -54,13 +54,13 @@ impl<V: CodegenObject> fmt::Debug for OperandRef<'tcx, V> {
 }
 
 impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> {
-    pub fn new_zst<Cx: CodegenMethods<'tcx, Value = V>>(
-        cx: &Cx,
+    pub fn new_zst<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
+        bx: &mut Bx,
         layout: TyLayout<'tcx>
     ) -> OperandRef<'tcx, V> {
         assert!(layout.is_zst());
         OperandRef {
-            val: OperandValue::Immediate(cx.const_undef(cx.immediate_backend_type(layout))),
+            val: OperandValue::Immediate(bx.const_undef(bx.immediate_backend_type(layout))),
             layout
         }
     }
@@ -69,10 +69,10 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> {
         bx: &mut Bx,
         val: ty::Const<'tcx>
     ) -> Result<Self, ErrorHandled> {
-        let layout = bx.cx().layout_of(val.ty);
+        let layout = bx.layout_of(val.ty);
 
         if layout.is_zst() {
-            return Ok(OperandRef::new_zst(bx.cx(), layout));
+            return Ok(OperandRef::new_zst(bx, layout));
         }
 
         let val = match val.val {
@@ -84,10 +84,10 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> {
                     layout::Abi::Scalar(ref x) => x,
                     _ => bug!("from_const: invalid ByVal layout: {:#?}", layout)
                 };
-                let llval = bx.cx().scalar_to_backend(
+                let llval = bx.scalar_to_backend(
                     x,
                     scalar,
-                    bx.cx().immediate_backend_type(layout),
+                    bx.immediate_backend_type(layout),
                 );
                 OperandValue::Immediate(llval)
             },
@@ -96,16 +96,16 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> {
                     layout::Abi::ScalarPair(ref a, _) => a,
                     _ => bug!("from_const: invalid ScalarPair layout: {:#?}", layout)
                 };
-                let a_llval = bx.cx().scalar_to_backend(
+                let a_llval = bx.scalar_to_backend(
                     a,
                     a_scalar,
-                    bx.cx().scalar_pair_element_backend_type(layout, 0, true),
+                    bx.scalar_pair_element_backend_type(layout, 0, true),
                 );
-                let b_llval = bx.cx().const_usize(b);
+                let b_llval = bx.const_usize(b);
                 OperandValue::Pair(a_llval, b_llval)
             },
             ConstValue::ByRef(ptr, alloc) => {
-                return Ok(bx.load_operand(bx.cx().from_const_alloc(layout, alloc, ptr.offset)));
+                return Ok(bx.load_operand(bx.from_const_alloc(layout, alloc, ptr.offset)));
             },
         };
 
@@ -124,7 +124,7 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> {
         }
     }
 
-    pub fn deref<Cx: CodegenMethods<'tcx, Value = V>>(
+    pub fn deref<Cx: LayoutTypeMethods<'tcx>>(
         self,
         cx: &Cx
     ) -> PlaceRef<'tcx, V> {
@@ -199,7 +199,7 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> {
         let mut val = match (self.val, &self.layout.abi) {
             // If the field is ZST, it has no data.
             _ if field.is_zst() => {
-                return OperandRef::new_zst(bx.cx(), field);
+                return OperandRef::new_zst(bx, field);
             }
 
             // Newtype of a scalar, scalar pair or vector.
@@ -409,7 +409,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         // checks in `codegen_consume` and `extract_field`.
                         let elem = o.layout.field(bx.cx(), 0);
                         if elem.is_zst() {
-                            return Some(OperandRef::new_zst(bx.cx(), elem));
+                            return Some(OperandRef::new_zst(bx, elem));
                         }
                     }
                     _ => {}
@@ -432,7 +432,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
         // ZSTs don't require any actual memory access.
         if layout.is_zst() {
-            return OperandRef::new_zst(bx.cx(), layout);
+            return OperandRef::new_zst(bx, layout);
         }
 
         if let Some(o) = self.maybe_codegen_consume_direct(bx, place) {
diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs
index b8131671320e1..c20d3f44bc528 100644
--- a/src/librustc_codegen_ssa/mir/rvalue.rs
+++ b/src/librustc_codegen_ssa/mir/rvalue.rs
@@ -523,8 +523,11 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 // According to `rvalue_creates_operand`, only ZST
                 // aggregate rvalues are allowed to be operands.
                 let ty = rvalue.ty(self.mir, self.cx.tcx());
-                (bx, OperandRef::new_zst(self.cx,
-                    self.cx.layout_of(self.monomorphize(&ty))))
+                let operand = OperandRef::new_zst(
+                    &mut bx,
+                    self.cx.layout_of(self.monomorphize(&ty)),
+                );
+                (bx, operand)
             }
         }
     }

From fe88440bd2aa2647d41ed33193ce5eac682afa17 Mon Sep 17 00:00:00 2001
From: bjorn3 <bjorn3@users.noreply.github.com>
Date: Fri, 1 Mar 2019 15:05:18 +0100
Subject: [PATCH 04/18] Add a comment

---
 src/librustc_codegen_llvm/builder.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs
index d0a861171c17c..048adb0fb80ff 100644
--- a/src/librustc_codegen_llvm/builder.rs
+++ b/src/librustc_codegen_llvm/builder.rs
@@ -1472,6 +1472,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
 
 impl StaticBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
     fn get_static(&self, def_id: DefId) -> &'ll Value {
+        // Forward to the `get_static` method of `CodegenCx`
         self.cx().get_static(def_id)
     }
 }

From a0056333f12ae3b916fbd0a14c1b641460140797 Mon Sep 17 00:00:00 2001
From: bjorn3 <bjorn3@users.noreply.github.com>
Date: Sun, 2 Dec 2018 14:35:11 +0100
Subject: [PATCH 05/18] Misc

---
 src/librustc_codegen_llvm/builder.rs       | 2 +-
 src/librustc_codegen_ssa/mir/place.rs      | 5 +++--
 src/librustc_codegen_ssa/traits/statics.rs | 2 +-
 3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs
index 048adb0fb80ff..ebe3a81acc601 100644
--- a/src/librustc_codegen_llvm/builder.rs
+++ b/src/librustc_codegen_llvm/builder.rs
@@ -1471,7 +1471,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
 }
 
 impl StaticBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
-    fn get_static(&self, def_id: DefId) -> &'ll Value {
+    fn get_static(&mut self, def_id: DefId) -> &'ll Value {
         // Forward to the `get_static` method of `CodegenCx`
         self.cx().get_static(def_id)
     }
diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs
index 7cafa0088a012..bf2afbbabab96 100644
--- a/src/librustc_codegen_ssa/mir/place.rs
+++ b/src/librustc_codegen_ssa/mir/place.rs
@@ -80,7 +80,7 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> {
         Self::alloca(bx, ptr_layout, name)
     }
 
-    pub fn len<Cx: CodegenMethods<'tcx, Value = V>>(
+    pub fn len<Cx: ConstMethods<'tcx, Value = V>>(
         &self,
         cx: &Cx
     ) -> V {
@@ -447,7 +447,8 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 // NB: The layout of a static may be unsized as is the case when working
                 // with a static that is an extern_type.
                 let layout = cx.layout_of(self.monomorphize(&ty));
-                PlaceRef::new_thin_place(bx, bx.get_static(def_id), layout, layout.align.abi)
+                let static_ = bx.get_static(def_id);
+                PlaceRef::new_thin_place(bx, static_, layout, layout.align.abi)
             },
             mir::Place::Projection(box mir::Projection {
                 ref base,
diff --git a/src/librustc_codegen_ssa/traits/statics.rs b/src/librustc_codegen_ssa/traits/statics.rs
index c4e7fe703c219..55c1253f10673 100644
--- a/src/librustc_codegen_ssa/traits/statics.rs
+++ b/src/librustc_codegen_ssa/traits/statics.rs
@@ -8,5 +8,5 @@ pub trait StaticMethods: BackendTypes {
 }
 
 pub trait StaticBuilderMethods<'tcx>: BackendTypes {
-    fn get_static(&self, def_id: DefId) -> Self::Value;
+    fn get_static(&mut self, def_id: DefId) -> Self::Value;
 }

From a3fa1161d22f5055e28340cd6c00d1451e4d9572 Mon Sep 17 00:00:00 2001
From: bjorn3 <bjorn3@users.noreply.github.com>
Date: Sun, 2 Dec 2018 15:58:40 +0100
Subject: [PATCH 06/18] Remove const_{fat_ptr,array,vector,bytes} from cg_ssa

---
 src/librustc_codegen_llvm/common.rs       | 54 ++++++++++++-----------
 src/librustc_codegen_ssa/traits/consts.rs |  4 --
 2 files changed, 28 insertions(+), 30 deletions(-)

diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs
index 4bd036ea3b17a..aab0d8ac60271 100644
--- a/src/librustc_codegen_llvm/common.rs
+++ b/src/librustc_codegen_llvm/common.rs
@@ -93,6 +93,34 @@ impl BackendTypes for CodegenCx<'ll, 'tcx> {
     type DIScope = &'ll llvm::debuginfo::DIScope;
 }
 
+impl CodegenCx<'ll, 'tcx> {
+    pub fn const_fat_ptr(
+        &self,
+        ptr: &'ll Value,
+        meta: &'ll Value
+    ) -> &'ll Value {
+        assert_eq!(abi::FAT_PTR_ADDR, 0);
+        assert_eq!(abi::FAT_PTR_EXTRA, 1);
+        self.const_struct(&[ptr, meta], false)
+    }
+
+    pub fn const_array(&self, ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value {
+        unsafe {
+            return llvm::LLVMConstArray(ty, elts.as_ptr(), elts.len() as c_uint);
+        }
+    }
+
+    pub fn const_vector(&self, elts: &[&'ll Value]) -> &'ll Value {
+        unsafe {
+            return llvm::LLVMConstVector(elts.as_ptr(), elts.len() as c_uint);
+        }
+    }
+
+    pub fn const_bytes(&self, bytes: &[u8]) -> &'ll Value {
+        bytes_in_context(self.llcx, bytes)
+    }
+}
+
 impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
     fn const_null(&self, t: &'ll Type) -> &'ll Value {
         unsafe {
@@ -189,16 +217,6 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         self.const_fat_ptr(cs, self.const_usize(len as u64))
     }
 
-    fn const_fat_ptr(
-        &self,
-        ptr: &'ll Value,
-        meta: &'ll Value
-    ) -> &'ll Value {
-        assert_eq!(abi::FAT_PTR_ADDR, 0);
-        assert_eq!(abi::FAT_PTR_EXTRA, 1);
-        self.const_struct(&[ptr, meta], false)
-    }
-
     fn const_struct(
         &self,
         elts: &[&'ll Value],
@@ -207,22 +225,6 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         struct_in_context(self.llcx, elts, packed)
     }
 
-    fn const_array(&self, ty: &'ll Type, elts: &[&'ll Value]) -> &'ll Value {
-        unsafe {
-            return llvm::LLVMConstArray(ty, elts.as_ptr(), elts.len() as c_uint);
-        }
-    }
-
-    fn const_vector(&self, elts: &[&'ll Value]) -> &'ll Value {
-        unsafe {
-            return llvm::LLVMConstVector(elts.as_ptr(), elts.len() as c_uint);
-        }
-    }
-
-    fn const_bytes(&self, bytes: &[u8]) -> &'ll Value {
-        bytes_in_context(self.llcx, bytes)
-    }
-
     fn const_get_elt(&self, v: &'ll Value, idx: u64) -> &'ll Value {
         unsafe {
             assert_eq!(idx as c_uint as u64, idx);
diff --git a/src/librustc_codegen_ssa/traits/consts.rs b/src/librustc_codegen_ssa/traits/consts.rs
index 319f4b4e5e4b5..61db94d53d881 100644
--- a/src/librustc_codegen_ssa/traits/consts.rs
+++ b/src/librustc_codegen_ssa/traits/consts.rs
@@ -24,11 +24,7 @@ pub trait ConstMethods<'tcx>: BackendTypes {
     fn const_cstr(&self, s: LocalInternedString, null_terminated: bool) -> Self::Value;
 
     fn const_str_slice(&self, s: LocalInternedString) -> Self::Value;
-    fn const_fat_ptr(&self, ptr: Self::Value, meta: Self::Value) -> Self::Value;
     fn const_struct(&self, elts: &[Self::Value], packed: bool) -> Self::Value;
-    fn const_array(&self, ty: Self::Type, elts: &[Self::Value]) -> Self::Value;
-    fn const_vector(&self, elts: &[Self::Value]) -> Self::Value;
-    fn const_bytes(&self, bytes: &[u8]) -> Self::Value;
 
     fn const_get_elt(&self, v: Self::Value, idx: u64) -> Self::Value;
     fn const_get_real(&self, v: Self::Value) -> Option<(f64, bool)>;

From 7b94195c22f20feed07dd033f4e2f866a0a29b0b Mon Sep 17 00:00:00 2001
From: bjorn3 <bjorn3@users.noreply.github.com>
Date: Sun, 2 Dec 2018 16:53:39 +0100
Subject: [PATCH 07/18] Remove const_{cstr,str_slice,get_elt,get_real} and
 is_const_real methods from cg_ssa

This introduces the static_panic_msg trait method to StaticBuilderMethods.
---
 src/librustc_codegen_llvm/builder.rs       |  31 +++++
 src/librustc_codegen_llvm/common.rs        | 132 ++++++++++-----------
 src/librustc_codegen_ssa/mir/block.rs      |  53 ++++-----
 src/librustc_codegen_ssa/traits/consts.rs  |   9 --
 src/librustc_codegen_ssa/traits/statics.rs |   9 ++
 5 files changed, 126 insertions(+), 108 deletions(-)

diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs
index ebe3a81acc601..3b3b437007aeb 100644
--- a/src/librustc_codegen_llvm/builder.rs
+++ b/src/librustc_codegen_llvm/builder.rs
@@ -5,6 +5,7 @@ use crate::context::CodegenCx;
 use crate::type_::Type;
 use crate::type_of::LayoutLlvmExt;
 use crate::value::Value;
+use syntax::symbol::LocalInternedString;
 use rustc_codegen_ssa::common::{IntPredicate, TypeKind, RealPredicate};
 use rustc_codegen_ssa::MemFlags;
 use libc::{c_uint, c_char};
@@ -1475,6 +1476,36 @@ impl StaticBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
         // Forward to the `get_static` method of `CodegenCx`
         self.cx().get_static(def_id)
     }
+
+    fn static_panic_msg(
+        &mut self,
+        msg: Option<LocalInternedString>,
+        filename: LocalInternedString,
+        line: Self::Value,
+        col: Self::Value,
+        kind: &str,
+    ) -> Self::Value {
+        let align = self.tcx.data_layout.aggregate_align.abi
+            .max(self.tcx.data_layout.i32_align.abi)
+            .max(self.tcx.data_layout.pointer_align.abi);
+
+        let filename = self.const_str_slice(filename);
+
+        let with_msg_components;
+        let without_msg_components;
+
+        let components = if let Some(msg) = msg {
+            let msg = self.const_str_slice(msg);
+            with_msg_components = [msg, filename, line, col];
+            &with_msg_components as &[_]
+        } else {
+            without_msg_components = [filename, line, col];
+            &without_msg_components as &[_]
+        };
+
+        let struct_ = self.const_struct(&components, false);
+        self.static_addr_of(struct_, align, Some(kind))
+    }
 }
 
 impl Builder<'a, 'll, 'tcx> {
diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs
index aab0d8ac60271..9554e54e4142a 100644
--- a/src/librustc_codegen_llvm/common.rs
+++ b/src/librustc_codegen_llvm/common.rs
@@ -119,6 +119,72 @@ impl CodegenCx<'ll, 'tcx> {
     pub fn const_bytes(&self, bytes: &[u8]) -> &'ll Value {
         bytes_in_context(self.llcx, bytes)
     }
+
+    fn const_cstr(
+        &self,
+        s: LocalInternedString,
+        null_terminated: bool,
+    ) -> &'ll Value {
+        unsafe {
+            if let Some(&llval) = self.const_cstr_cache.borrow().get(&s) {
+                return llval;
+            }
+
+            let sc = llvm::LLVMConstStringInContext(self.llcx,
+                                                    s.as_ptr() as *const c_char,
+                                                    s.len() as c_uint,
+                                                    !null_terminated as Bool);
+            let sym = self.generate_local_symbol_name("str");
+            let g = self.define_global(&sym[..], self.val_ty(sc)).unwrap_or_else(||{
+                bug!("symbol `{}` is already defined", sym);
+            });
+            llvm::LLVMSetInitializer(g, sc);
+            llvm::LLVMSetGlobalConstant(g, True);
+            llvm::LLVMRustSetLinkage(g, llvm::Linkage::InternalLinkage);
+
+            self.const_cstr_cache.borrow_mut().insert(s, g);
+            g
+        }
+    }
+
+    pub fn const_str_slice(&self, s: LocalInternedString) -> &'ll Value {
+        let len = s.len();
+        let cs = consts::ptrcast(self.const_cstr(s, false),
+            self.type_ptr_to(self.layout_of(self.tcx.mk_str()).llvm_type(self)));
+        self.const_fat_ptr(cs, self.const_usize(len as u64))
+    }
+
+    pub fn const_get_elt(&self, v: &'ll Value, idx: u64) -> &'ll Value {
+        unsafe {
+            assert_eq!(idx as c_uint as u64, idx);
+            let us = &[idx as c_uint];
+            let r = llvm::LLVMConstExtractValue(v, us.as_ptr(), us.len() as c_uint);
+
+            debug!("const_get_elt(v={:?}, idx={}, r={:?})",
+                   v, idx, r);
+
+            r
+        }
+    }
+
+    pub fn const_get_real(&self, v: &'ll Value) -> Option<(f64, bool)> {
+        unsafe {
+            if self.is_const_real(v) {
+                let mut loses_info: llvm::Bool = ::std::mem::uninitialized();
+                let r = llvm::LLVMConstRealGetDouble(v, &mut loses_info);
+                let loses_info = if loses_info == 1 { true } else { false };
+                Some((r, loses_info))
+            } else {
+                None
+            }
+        }
+    }
+
+    fn is_const_real(&self, v: &'ll Value) -> bool {
+        unsafe {
+            llvm::LLVMIsAConstantFP(v).is_some()
+        }
+    }
 }
 
 impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
@@ -183,40 +249,6 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         self.const_uint(self.type_i8(), i as u64)
     }
 
-    fn const_cstr(
-        &self,
-        s: LocalInternedString,
-        null_terminated: bool,
-    ) -> &'ll Value {
-        unsafe {
-            if let Some(&llval) = self.const_cstr_cache.borrow().get(&s) {
-                return llval;
-            }
-
-            let sc = llvm::LLVMConstStringInContext(self.llcx,
-                                                    s.as_ptr() as *const c_char,
-                                                    s.len() as c_uint,
-                                                    !null_terminated as Bool);
-            let sym = self.generate_local_symbol_name("str");
-            let g = self.define_global(&sym[..], self.val_ty(sc)).unwrap_or_else(||{
-                bug!("symbol `{}` is already defined", sym);
-            });
-            llvm::LLVMSetInitializer(g, sc);
-            llvm::LLVMSetGlobalConstant(g, True);
-            llvm::LLVMRustSetLinkage(g, llvm::Linkage::InternalLinkage);
-
-            self.const_cstr_cache.borrow_mut().insert(s, g);
-            g
-        }
-    }
-
-    fn const_str_slice(&self, s: LocalInternedString) -> &'ll Value {
-        let len = s.len();
-        let cs = consts::ptrcast(self.const_cstr(s, false),
-            self.type_ptr_to(self.layout_of(self.tcx.mk_str()).llvm_type(self)));
-        self.const_fat_ptr(cs, self.const_usize(len as u64))
-    }
-
     fn const_struct(
         &self,
         elts: &[&'ll Value],
@@ -225,32 +257,6 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         struct_in_context(self.llcx, elts, packed)
     }
 
-    fn const_get_elt(&self, v: &'ll Value, idx: u64) -> &'ll Value {
-        unsafe {
-            assert_eq!(idx as c_uint as u64, idx);
-            let us = &[idx as c_uint];
-            let r = llvm::LLVMConstExtractValue(v, us.as_ptr(), us.len() as c_uint);
-
-            debug!("const_get_elt(v={:?}, idx={}, r={:?})",
-                   v, idx, r);
-
-            r
-        }
-    }
-
-    fn const_get_real(&self, v: &'ll Value) -> Option<(f64, bool)> {
-        unsafe {
-            if self.is_const_real(v) {
-                let mut loses_info: llvm::Bool = ::std::mem::uninitialized();
-                let r = llvm::LLVMConstRealGetDouble(v, &mut loses_info);
-                let loses_info = if loses_info == 1 { true } else { false };
-                Some((r, loses_info))
-            } else {
-                None
-            }
-        }
-    }
-
     fn const_to_uint(&self, v: &'ll Value) -> u64 {
         unsafe {
             llvm::LLVMConstIntGetZExtValue(v)
@@ -263,12 +269,6 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         }
     }
 
-    fn is_const_real(&self, v: &'ll Value) -> bool {
-        unsafe {
-            llvm::LLVMIsAConstantFP(v).is_some()
-        }
-    }
-
     fn const_to_opt_u128(&self, v: &'ll Value, sign_ext: bool) -> Option<u128> {
         unsafe {
             if self.is_const_integral(v) {
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index 494355efeaaa7..f0e8a18c479b1 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -399,12 +399,8 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         // Get the location information.
         let loc = bx.sess().source_map().lookup_char_pos(span.lo());
         let filename = Symbol::intern(&loc.file.name.to_string()).as_str();
-        let filename = bx.const_str_slice(filename);
         let line = bx.const_u32(loc.line as u32);
         let col = bx.const_u32(loc.col.to_usize() as u32 + 1);
-        let align = self.cx.tcx().data_layout.aggregate_align.abi
-            .max(self.cx.tcx().data_layout.i32_align.abi)
-            .max(self.cx.tcx().data_layout.pointer_align.abi);
 
         // Put together the arguments to the panic entry point.
         let (lang_item, args) = match *msg {
@@ -412,30 +408,28 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 let len = self.codegen_operand(&mut bx, len).immediate();
                 let index = self.codegen_operand(&mut bx, index).immediate();
 
-                let file_line_col = bx.const_struct(&[filename, line, col], false);
-                let file_line_col = bx.static_addr_of(
-                    file_line_col,
-                    align,
-                    Some("panic_bounds_check_loc")
+                let file_line_col = bx.static_panic_msg(
+                    None,
+                    filename,
+                    line,
+                    col,
+                    "panic_bounds_check_loc",
                 );
                 (lang_items::PanicBoundsCheckFnLangItem,
-                 vec![file_line_col, index, len])
+                    vec![file_line_col, index, len])
             }
             _ => {
                 let str = msg.description();
                 let msg_str = Symbol::intern(str).as_str();
-                let msg_str = bx.const_str_slice(msg_str);
-                let msg_file_line_col = bx.const_struct(
-                    &[msg_str, filename, line, col],
-                    false
-                );
-                let msg_file_line_col = bx.static_addr_of(
-                    msg_file_line_col,
-                    align,
-                    Some("panic_loc")
+                let msg_file_line_col = bx.static_panic_msg(
+                    Some(msg_str),
+                    filename,
+                    line,
+                    col,
+                    "panic_loc",
                 );
                 (lang_items::PanicFnLangItem,
-                 vec![msg_file_line_col])
+                    vec![msg_file_line_col])
             }
         };
 
@@ -539,27 +533,20 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             if layout.abi.is_uninhabited() {
                 let loc = bx.sess().source_map().lookup_char_pos(span.lo());
                 let filename = Symbol::intern(&loc.file.name.to_string()).as_str();
-                let filename = bx.const_str_slice(filename);
                 let line = bx.const_u32(loc.line as u32);
                 let col = bx.const_u32(loc.col.to_usize() as u32 + 1);
-                let align = self.cx.tcx().data_layout.aggregate_align.abi
-                    .max(self.cx.tcx().data_layout.i32_align.abi)
-                    .max(self.cx.tcx().data_layout.pointer_align.abi);
 
                 let str = format!(
                     "Attempted to instantiate uninhabited type {}",
                     ty
                 );
                 let msg_str = Symbol::intern(&str).as_str();
-                let msg_str = bx.const_str_slice(msg_str);
-                let msg_file_line_col = bx.const_struct(
-                    &[msg_str, filename, line, col],
-                    false,
-                );
-                let msg_file_line_col = bx.static_addr_of(
-                    msg_file_line_col,
-                    align,
-                    Some("panic_loc"),
+                let msg_file_line_col = bx.static_panic_msg(
+                    Some(msg_str),
+                    filename,
+                    line,
+                    col,
+                    "panic_loc",
                 );
 
                 // Obtain the panic entry point.
diff --git a/src/librustc_codegen_ssa/traits/consts.rs b/src/librustc_codegen_ssa/traits/consts.rs
index 61db94d53d881..32412f303c155 100644
--- a/src/librustc_codegen_ssa/traits/consts.rs
+++ b/src/librustc_codegen_ssa/traits/consts.rs
@@ -3,7 +3,6 @@ use crate::mir::place::PlaceRef;
 use rustc::mir::interpret::Allocation;
 use rustc::mir::interpret::Scalar;
 use rustc::ty::layout;
-use syntax::symbol::LocalInternedString;
 
 pub trait ConstMethods<'tcx>: BackendTypes {
     // Constant constructors
@@ -19,20 +18,12 @@ pub trait ConstMethods<'tcx>: BackendTypes {
     fn const_usize(&self, i: u64) -> Self::Value;
     fn const_u8(&self, i: u8) -> Self::Value;
 
-    // This is a 'c-like' raw string, which differs from
-    // our boxed-and-length-annotated strings.
-    fn const_cstr(&self, s: LocalInternedString, null_terminated: bool) -> Self::Value;
-
-    fn const_str_slice(&self, s: LocalInternedString) -> Self::Value;
     fn const_struct(&self, elts: &[Self::Value], packed: bool) -> Self::Value;
 
-    fn const_get_elt(&self, v: Self::Value, idx: u64) -> Self::Value;
-    fn const_get_real(&self, v: Self::Value) -> Option<(f64, bool)>;
     fn const_to_uint(&self, v: Self::Value) -> u64;
     fn const_to_opt_u128(&self, v: Self::Value, sign_ext: bool) -> Option<u128>;
 
     fn is_const_integral(&self, v: Self::Value) -> bool;
-    fn is_const_real(&self, v: Self::Value) -> bool;
 
     fn scalar_to_backend(
         &self,
diff --git a/src/librustc_codegen_ssa/traits/statics.rs b/src/librustc_codegen_ssa/traits/statics.rs
index 55c1253f10673..d8992c159337d 100644
--- a/src/librustc_codegen_ssa/traits/statics.rs
+++ b/src/librustc_codegen_ssa/traits/statics.rs
@@ -1,4 +1,5 @@
 use super::BackendTypes;
+use syntax_pos::symbol::LocalInternedString;
 use rustc::hir::def_id::DefId;
 use rustc::ty::layout::Align;
 
@@ -9,4 +10,12 @@ pub trait StaticMethods: BackendTypes {
 
 pub trait StaticBuilderMethods<'tcx>: BackendTypes {
     fn get_static(&mut self, def_id: DefId) -> Self::Value;
+    fn static_panic_msg(
+        &mut self,
+        msg: Option<LocalInternedString>,
+        filename: LocalInternedString,
+        line: Self::Value,
+        col: Self::Value,
+        kind: &str,
+    ) -> Self::Value;
 }

From f1fe9253e2b9ed072af6bc2d80feb6be0ffee8a5 Mon Sep 17 00:00:00 2001
From: bjorn3 <bjorn3@users.noreply.github.com>
Date: Sun, 2 Dec 2018 18:04:39 +0100
Subject: [PATCH 08/18] Remove param_substs from FunctionCx

---
 src/librustc_codegen_ssa/mir/mod.rs | 12 +++---------
 1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs
index 5e2144751c125..62bbfa316b50d 100644
--- a/src/librustc_codegen_ssa/mir/mod.rs
+++ b/src/librustc_codegen_ssa/mir/mod.rs
@@ -1,7 +1,6 @@
 use rustc::ty::{self, Ty, TypeFoldable, UpvarSubsts};
 use rustc::ty::layout::{TyLayout, HasTyCtxt};
 use rustc::mir::{self, Mir};
-use rustc::ty::subst::SubstsRef;
 use rustc::session::config::DebugInfo;
 use rustc_mir::monomorphize::Instance;
 use rustc_target::abi::call::{FnType, PassMode, IgnoreMode};
@@ -83,9 +82,6 @@ pub struct FunctionCx<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> {
     /// Debug information for MIR scopes.
     scopes: IndexVec<mir::SourceScope, debuginfo::MirDebugScope<Bx::DIScope>>,
 
-    /// If this function is being monomorphized, this contains the type substitutions used.
-    param_substs: SubstsRef<'tcx>,
-
     /// If this function is a C-variadic function, this contains the `PlaceRef` of the
     /// "spoofed" `VaList`.
     va_list_ref: Option<PlaceRef<'tcx, Bx::Value>>,
@@ -96,7 +92,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         where T: TypeFoldable<'tcx>
     {
         self.cx.tcx().subst_and_normalize_erasing_regions(
-            self.param_substs,
+            self.instance.substs,
             ty::ParamEnv::reveal_all(),
             value,
         )
@@ -203,6 +199,8 @@ pub fn codegen_mir<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
     instance: Instance<'tcx>,
     sig: ty::FnSig<'tcx>,
 ) {
+    assert!(!instance.substs.needs_infer());
+
     let fn_ty = cx.new_fn_type(sig, &[]);
     debug!("fn_ty: {:?}", fn_ty);
     let debug_context =
@@ -245,10 +243,6 @@ pub fn codegen_mir<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
         scopes,
         locals: IndexVec::new(),
         debug_context,
-        param_substs: {
-            assert!(!instance.substs.needs_infer());
-            instance.substs
-        },
         va_list_ref: None,
     };
 

From ab8f1527e485d0de49139ca7b9d42c320991a53b Mon Sep 17 00:00:00 2001
From: bjorn3 <bjorn3@users.noreply.github.com>
Date: Sun, 2 Dec 2018 18:09:26 +0100
Subject: [PATCH 09/18] Remove internal mutability from
 source_locations_enabled

---
 src/librustc_codegen_llvm/debuginfo/mod.rs        | 6 +++---
 src/librustc_codegen_llvm/debuginfo/source_loc.rs | 2 +-
 src/librustc_codegen_ssa/debuginfo.rs             | 9 ++++-----
 src/librustc_codegen_ssa/mir/mod.rs               | 2 +-
 4 files changed, 9 insertions(+), 10 deletions(-)

diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs
index c0869bb889afa..c262167d92092 100644
--- a/src/librustc_codegen_llvm/debuginfo/mod.rs
+++ b/src/librustc_codegen_llvm/debuginfo/mod.rs
@@ -32,7 +32,7 @@ use rustc_codegen_ssa::debuginfo::{FunctionDebugContext, MirDebugScope, Variable
     VariableKind, FunctionDebugContextData};
 
 use libc::c_uint;
-use std::cell::{Cell, RefCell};
+use std::cell::RefCell;
 use std::ffi::CString;
 
 use syntax_pos::{self, Span, Pos};
@@ -158,7 +158,7 @@ impl DebugInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
         variable_kind: VariableKind,
         span: Span,
     ) {
-        assert!(!dbg_context.get_ref(span).source_locations_enabled.get());
+        assert!(!dbg_context.get_ref(span).source_locations_enabled);
         let cx = self.cx();
 
         let file = span_start(cx, span).file;
@@ -327,7 +327,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         // Initialize fn debug context (including scope map and namespace map)
         let fn_debug_context = FunctionDebugContextData {
             fn_metadata,
-            source_locations_enabled: Cell::new(false),
+            source_locations_enabled: false,
             defining_crate: def_id.krate,
         };
 
diff --git a/src/librustc_codegen_llvm/debuginfo/source_loc.rs b/src/librustc_codegen_llvm/debuginfo/source_loc.rs
index f7620e11c233d..dec93a65dbaf4 100644
--- a/src/librustc_codegen_llvm/debuginfo/source_loc.rs
+++ b/src/librustc_codegen_llvm/debuginfo/source_loc.rs
@@ -30,7 +30,7 @@ pub fn set_source_location<D>(
         FunctionDebugContext::RegularContext(ref data) => data
     };
 
-    let dbg_loc = if function_debug_context.source_locations_enabled.get() {
+    let dbg_loc = if function_debug_context.source_locations_enabled {
         debug!("set_source_location: {}", bx.sess().source_map().span_to_string(span));
         let loc = span_start(bx.cx(), span);
         InternalDebugLocation::new(scope.unwrap(), loc.line, loc.col.to_usize())
diff --git a/src/librustc_codegen_ssa/debuginfo.rs b/src/librustc_codegen_ssa/debuginfo.rs
index c4531ff90ae7c..aa7cdbed99446 100644
--- a/src/librustc_codegen_ssa/debuginfo.rs
+++ b/src/librustc_codegen_ssa/debuginfo.rs
@@ -1,6 +1,5 @@
 use syntax_pos::{BytePos, Span};
 use rustc::hir::def_id::CrateNum;
-use std::cell::Cell;
 
 pub enum FunctionDebugContext<D> {
     RegularContext(FunctionDebugContextData<D>),
@@ -36,10 +35,10 @@ impl<D> FunctionDebugContext<D> {
 /// they are disabled when beginning to codegen a new function. This functions
 /// switches source location emitting on and must therefore be called before the
 /// first real statement/expression of the function is codegened.
-pub fn start_emitting_source_locations<D>(dbg_context: &FunctionDebugContext<D>) {
+pub fn start_emitting_source_locations<D>(dbg_context: &mut FunctionDebugContext<D>) {
     match *dbg_context {
-        FunctionDebugContext::RegularContext(ref data) => {
-            data.source_locations_enabled.set(true)
+        FunctionDebugContext::RegularContext(ref mut data) => {
+            data.source_locations_enabled = true;
         },
         _ => { /* safe to ignore */ }
     }
@@ -47,7 +46,7 @@ pub fn start_emitting_source_locations<D>(dbg_context: &FunctionDebugContext<D>)
 
 pub struct FunctionDebugContextData<D> {
     pub fn_metadata: D,
-    pub source_locations_enabled: Cell<bool>,
+    pub source_locations_enabled: bool,
     pub defining_crate: CrateNum,
 }
 
diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs
index 62bbfa316b50d..15597542d4992 100644
--- a/src/librustc_codegen_ssa/mir/mod.rs
+++ b/src/librustc_codegen_ssa/mir/mod.rs
@@ -334,7 +334,7 @@ pub fn codegen_mir<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
     // Up until here, IR instructions for this function have explicitly not been annotated with
     // source code location, so we don't step into call setup code. From here on, source location
     // emitting should be enabled.
-    debuginfo::start_emitting_source_locations(&fx.debug_context);
+    debuginfo::start_emitting_source_locations(&mut fx.debug_context);
 
     let rpo = traversal::reverse_postorder(&mir);
     let mut visited = BitSet::new_empty(mir.basic_blocks().len());

From 794ecd965ab39d767caebd79c0e32702e86a3ff1 Mon Sep 17 00:00:00 2001
From: bjorn3 <bjorn3@users.noreply.github.com>
Date: Sun, 2 Dec 2018 18:25:42 +0100
Subject: [PATCH 10/18] [WIP] Make some debug info methods take &mut
 FunctionDebugContext

declare_local still takes &FunctionDebugContext, because of borrowck errors
---
 src/librustc_codegen_llvm/debuginfo/mod.rs   |  4 ++--
 src/librustc_codegen_ssa/mir/mod.rs          | 14 +++++---------
 src/librustc_codegen_ssa/traits/debuginfo.rs |  4 ++--
 3 files changed, 9 insertions(+), 13 deletions(-)

diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs
index c262167d92092..066ac8f019e00 100644
--- a/src/librustc_codegen_llvm/debuginfo/mod.rs
+++ b/src/librustc_codegen_llvm/debuginfo/mod.rs
@@ -216,7 +216,7 @@ impl DebugInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
 
     fn set_source_location(
         &mut self,
-        debug_context: &FunctionDebugContext<&'ll DISubprogram>,
+        debug_context: &mut FunctionDebugContext<&'ll DISubprogram>,
         scope: Option<&'ll DIScope>,
         span: Span,
     ) {
@@ -519,7 +519,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
     fn create_mir_scopes(
         &self,
         mir: &mir::Mir<'_>,
-        debug_context: &FunctionDebugContext<&'ll DISubprogram>,
+        debug_context: &mut FunctionDebugContext<&'ll DISubprogram>,
     ) -> IndexVec<mir::SourceScope, MirDebugScope<&'ll DIScope>> {
         create_scope_map::create_mir_scopes(self, mir, debug_context)
     }
diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs
index 15597542d4992..4d9579504c857 100644
--- a/src/librustc_codegen_ssa/mir/mod.rs
+++ b/src/librustc_codegen_ssa/mir/mod.rs
@@ -104,7 +104,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         source_info: mir::SourceInfo
     ) {
         let (scope, span) = self.debug_loc(source_info);
-        bx.set_source_location(&self.debug_context, scope, span);
+        bx.set_source_location(&mut self.debug_context, scope, span);
     }
 
     pub fn debug_loc(&self, source_info: mir::SourceInfo) -> (Option<Bx::DIScope>, Span) {
@@ -203,7 +203,7 @@ pub fn codegen_mir<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
 
     let fn_ty = cx.new_fn_type(sig, &[]);
     debug!("fn_ty: {:?}", fn_ty);
-    let debug_context =
+    let mut debug_context =
         cx.create_function_debug_context(instance, sig, llfn, mir);
     let mut bx = Bx::new_block(cx, llfn, "start");
 
@@ -225,7 +225,7 @@ pub fn codegen_mir<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
         }).collect();
 
     // Compute debuginfo scopes from MIR scopes.
-    let scopes = cx.create_mir_scopes(mir, &debug_context);
+    let scopes = cx.create_mir_scopes(mir, &mut debug_context);
     let (landing_pads, funclets) = create_funclets(mir, &mut bx, &cleanup_kinds, &block_bxs);
 
     let mut fx = FunctionCx {
@@ -253,7 +253,7 @@ pub fn codegen_mir<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
         // FIXME(dlrobertson): This is ugly. Find a better way of getting the `PlaceRef` or
         // `LocalRef` from `arg_local_refs`
         let mut va_list_ref = None;
-        let args = arg_local_refs(&mut bx, &fx, &fx.scopes, &memory_locals, &mut va_list_ref);
+        let args = arg_local_refs(&mut bx, &fx, &memory_locals, &mut va_list_ref);
         fx.va_list_ref = va_list_ref;
 
         let mut allocate_local = |local| {
@@ -430,10 +430,6 @@ fn create_funclets<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
 fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
     bx: &mut Bx,
     fx: &FunctionCx<'a, 'tcx, Bx>,
-    scopes: &IndexVec<
-        mir::SourceScope,
-        debuginfo::MirDebugScope<Bx::DIScope>
-    >,
     memory_locals: &BitSet<mir::Local>,
     va_list_ref: &mut Option<PlaceRef<'tcx, Bx::Value>>,
 ) -> Vec<LocalRef<'tcx, Bx::Value>> {
@@ -443,7 +439,7 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
     let mut llarg_idx = fx.fn_ty.ret.is_indirect() as usize;
 
     // Get the argument scope, if it exists and if we need it.
-    let arg_scope = scopes[mir::OUTERMOST_SOURCE_SCOPE];
+    let arg_scope = fx.scopes[mir::OUTERMOST_SOURCE_SCOPE];
     let arg_scope = if bx.sess().opts.debuginfo == DebugInfo::Full {
         arg_scope.scope_metadata
     } else {
diff --git a/src/librustc_codegen_ssa/traits/debuginfo.rs b/src/librustc_codegen_ssa/traits/debuginfo.rs
index 135188e98c71c..dcbb4e66cb385 100644
--- a/src/librustc_codegen_ssa/traits/debuginfo.rs
+++ b/src/librustc_codegen_ssa/traits/debuginfo.rs
@@ -28,7 +28,7 @@ pub trait DebugInfoMethods<'tcx>: BackendTypes {
     fn create_mir_scopes(
         &self,
         mir: &mir::Mir<'_>,
-        debug_context: &FunctionDebugContext<Self::DIScope>,
+        debug_context: &mut FunctionDebugContext<Self::DIScope>,
     ) -> IndexVec<mir::SourceScope, MirDebugScope<Self::DIScope>>;
     fn extend_scope_to_file(
         &self,
@@ -53,7 +53,7 @@ pub trait DebugInfoBuilderMethods<'tcx>: BackendTypes {
     );
     fn set_source_location(
         &mut self,
-        debug_context: &FunctionDebugContext<Self::DIScope>,
+        debug_context: &mut FunctionDebugContext<Self::DIScope>,
         scope: Option<Self::DIScope>,
         span: Span,
     );

From bcab49720e5226bc96a78e896877213d1773eaa5 Mon Sep 17 00:00:00 2001
From: bjorn3 <bjorn3@users.noreply.github.com>
Date: Sun, 2 Dec 2018 18:54:46 +0100
Subject: [PATCH 11/18] Remove a lot of methods from BuilderMethods

---
 src/librustc_codegen_llvm/builder.rs       | 426 ++++++++++-----------
 src/librustc_codegen_ssa/traits/builder.rs |  47 ---
 2 files changed, 213 insertions(+), 260 deletions(-)

diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs
index 3b3b437007aeb..ebee3ab6cedaa 100644
--- a/src/librustc_codegen_llvm/builder.rs
+++ b/src/librustc_codegen_llvm/builder.rs
@@ -133,19 +133,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         }
     }
 
-    fn count_insn(&self, category: &str) {
-        if self.sess().codegen_stats() {
-            self.stats.borrow_mut().n_llvm_insns += 1;
-        }
-        if self.sess().count_llvm_insns() {
-            *self.stats
-                      .borrow_mut()
-                      .llvm_insns
-                      .entry(category.to_string())
-                      .or_insert(0) += 1;
-        }
-    }
-
     fn set_value_name(&mut self, value: &'ll Value, name: &str) {
         let cname = SmallCStr::new(name);
         unsafe {
@@ -159,12 +146,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         }
     }
 
-    fn position_at_start(&mut self, llbb: &'ll BasicBlock) {
-        unsafe {
-            llvm::LLVMRustPositionBuilderAtStart(self.llbuilder, llbb);
-        }
-    }
-
     fn ret_void(&mut self) {
         self.count_insn("retvoid");
         unsafe {
@@ -897,17 +878,12 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
     }
 
     /* Miscellaneous instructions */
-    fn empty_phi(&mut self, ty: &'ll Type) -> &'ll Value {
-        self.count_insn("emptyphi");
-        unsafe {
-            llvm::LLVMBuildPhi(self.llbuilder, ty, noname())
-        }
-    }
-
     fn phi(&mut self, ty: &'ll Type, vals: &[&'ll Value], bbs: &[&'ll BasicBlock]) -> &'ll Value {
-        assert_eq!(vals.len(), bbs.len());
-        let phi = self.empty_phi(ty);
         self.count_insn("addincoming");
+        assert_eq!(vals.len(), bbs.len());
+        let phi = unsafe {
+            llvm::LLVMBuildPhi(self.llbuilder, ty, noname())
+        };
         unsafe {
             llvm::LLVMAddIncoming(phi, vals.as_ptr(),
                                   bbs.as_ptr(),
@@ -1012,15 +988,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         self.call(llintrinsicfn, &[ptr, fill_byte, size, align, volatile], None);
     }
 
-    fn minnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        self.count_insn("minnum");
-        unsafe { llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs) }
-    }
-    fn maxnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        self.count_insn("maxnum");
-        unsafe { llvm::LLVMRustBuildMaxNum(self.llbuilder, lhs, rhs) }
-    }
-
     fn select(
         &mut self, cond: &'ll Value,
         then_val: &'ll Value,
@@ -1032,14 +999,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         }
     }
 
-    #[allow(dead_code)]
-    fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value {
-        self.count_insn("vaarg");
-        unsafe {
-            llvm::LLVMBuildVAArg(self.llbuilder, list, ty, noname())
-        }
-    }
-
     fn extract_element(&mut self, vec: &'ll Value, idx: &'ll Value) -> &'ll Value {
         self.count_insn("extractelement");
         unsafe {
@@ -1047,24 +1006,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         }
     }
 
-    fn insert_element(
-        &mut self, vec: &'ll Value,
-        elt: &'ll Value,
-        idx: &'ll Value,
-    ) -> &'ll Value {
-        self.count_insn("insertelement");
-        unsafe {
-            llvm::LLVMBuildInsertElement(self.llbuilder, vec, elt, idx, noname())
-        }
-    }
-
-    fn shuffle_vector(&mut self, v1: &'ll Value, v2: &'ll Value, mask: &'ll Value) -> &'ll Value {
-        self.count_insn("shufflevector");
-        unsafe {
-            llvm::LLVMBuildShuffleVector(self.llbuilder, v1, v2, mask, noname())
-        }
-    }
-
     fn vector_splat(&mut self, num_elts: usize, elt: &'ll Value) -> &'ll Value {
         unsafe {
             let elt_ty = self.cx.val_ty(elt);
@@ -1075,81 +1016,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         }
     }
 
-    fn vector_reduce_fadd_fast(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value {
-        self.count_insn("vector.reduce.fadd_fast");
-        unsafe {
-            // FIXME: add a non-fast math version once
-            // https://bugs.llvm.org/show_bug.cgi?id=36732
-            // is fixed.
-            let instr = llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src);
-            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
-            instr
-        }
-    }
-    fn vector_reduce_fmul_fast(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value {
-        self.count_insn("vector.reduce.fmul_fast");
-        unsafe {
-            // FIXME: add a non-fast math version once
-            // https://bugs.llvm.org/show_bug.cgi?id=36732
-            // is fixed.
-            let instr = llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src);
-            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
-            instr
-        }
-    }
-    fn vector_reduce_add(&mut self, src: &'ll Value) -> &'ll Value {
-        self.count_insn("vector.reduce.add");
-        unsafe { llvm::LLVMRustBuildVectorReduceAdd(self.llbuilder, src) }
-    }
-    fn vector_reduce_mul(&mut self, src: &'ll Value) -> &'ll Value {
-        self.count_insn("vector.reduce.mul");
-        unsafe { llvm::LLVMRustBuildVectorReduceMul(self.llbuilder, src) }
-    }
-    fn vector_reduce_and(&mut self, src: &'ll Value) -> &'ll Value {
-        self.count_insn("vector.reduce.and");
-        unsafe { llvm::LLVMRustBuildVectorReduceAnd(self.llbuilder, src) }
-    }
-    fn vector_reduce_or(&mut self, src: &'ll Value) -> &'ll Value {
-        self.count_insn("vector.reduce.or");
-        unsafe { llvm::LLVMRustBuildVectorReduceOr(self.llbuilder, src) }
-    }
-    fn vector_reduce_xor(&mut self, src: &'ll Value) -> &'ll Value {
-        self.count_insn("vector.reduce.xor");
-        unsafe { llvm::LLVMRustBuildVectorReduceXor(self.llbuilder, src) }
-    }
-    fn vector_reduce_fmin(&mut self, src: &'ll Value) -> &'ll Value {
-        self.count_insn("vector.reduce.fmin");
-        unsafe { llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ false) }
-    }
-    fn vector_reduce_fmax(&mut self, src: &'ll Value) -> &'ll Value {
-        self.count_insn("vector.reduce.fmax");
-        unsafe { llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ false) }
-    }
-    fn vector_reduce_fmin_fast(&mut self, src: &'ll Value) -> &'ll Value {
-        self.count_insn("vector.reduce.fmin_fast");
-        unsafe {
-            let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ true);
-            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
-            instr
-        }
-    }
-    fn vector_reduce_fmax_fast(&mut self, src: &'ll Value) -> &'ll Value {
-        self.count_insn("vector.reduce.fmax_fast");
-        unsafe {
-            let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ true);
-            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
-            instr
-        }
-    }
-    fn vector_reduce_min(&mut self, src: &'ll Value, is_signed: bool) -> &'ll Value {
-        self.count_insn("vector.reduce.min");
-        unsafe { llvm::LLVMRustBuildVectorReduceMin(self.llbuilder, src, is_signed) }
-    }
-    fn vector_reduce_max(&mut self, src: &'ll Value, is_signed: bool) -> &'ll Value {
-        self.count_insn("vector.reduce.max");
-        unsafe { llvm::LLVMRustBuildVectorReduceMax(self.llbuilder, src, is_signed) }
-    }
-
     fn extract_value(&mut self, agg_val: &'ll Value, idx: u64) -> &'ll Value {
         self.count_insn("extractvalue");
         assert_eq!(idx as c_uint as u64, idx);
@@ -1177,12 +1043,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         }
     }
 
-    fn add_clause(&mut self, landing_pad: &'ll Value, clause: &'ll Value) {
-        unsafe {
-            llvm::LLVMAddClause(landing_pad, clause);
-        }
-    }
-
     fn set_cleanup(&mut self, landing_pad: &'ll Value) {
         self.count_insn("setcleanup");
         unsafe {
@@ -1236,14 +1096,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         Funclet::new(ret.expect("LLVM does not have support for catchpad"))
     }
 
-    fn catch_ret(&mut self, funclet: &Funclet<'ll>, unwind: &'ll BasicBlock) -> &'ll Value {
-        self.count_insn("catchret");
-        let ret = unsafe {
-            llvm::LLVMRustBuildCatchRet(self.llbuilder, funclet.cleanuppad(), unwind)
-        };
-        ret.expect("LLVM does not have support for catchret")
-    }
-
     fn catch_switch(
         &mut self,
         parent: Option<&'ll Value>,
@@ -1347,67 +1199,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         }
     }
 
-    fn check_store<'b>(&mut self,
-                       val: &'ll Value,
-                       ptr: &'ll Value) -> &'ll Value {
-        let dest_ptr_ty = self.cx.val_ty(ptr);
-        let stored_ty = self.cx.val_ty(val);
-        let stored_ptr_ty = self.cx.type_ptr_to(stored_ty);
-
-        assert_eq!(self.cx.type_kind(dest_ptr_ty), TypeKind::Pointer);
-
-        if dest_ptr_ty == stored_ptr_ty {
-            ptr
-        } else {
-            debug!("Type mismatch in store. \
-                    Expected {:?}, got {:?}; inserting bitcast",
-                   dest_ptr_ty, stored_ptr_ty);
-            self.bitcast(ptr, stored_ptr_ty)
-        }
-    }
-
-    fn check_call<'b>(&mut self,
-                      typ: &str,
-                      llfn: &'ll Value,
-                      args: &'b [&'ll Value]) -> Cow<'b, [&'ll Value]> {
-        let mut fn_ty = self.cx.val_ty(llfn);
-        // Strip off pointers
-        while self.cx.type_kind(fn_ty) == TypeKind::Pointer {
-            fn_ty = self.cx.element_type(fn_ty);
-        }
-
-        assert!(self.cx.type_kind(fn_ty) == TypeKind::Function,
-                "builder::{} not passed a function, but {:?}", typ, fn_ty);
-
-        let param_tys = self.cx.func_params_types(fn_ty);
-
-        let all_args_match = param_tys.iter()
-            .zip(args.iter().map(|&v| self.val_ty(v)))
-            .all(|(expected_ty, actual_ty)| *expected_ty == actual_ty);
-
-        if all_args_match {
-            return Cow::Borrowed(args);
-        }
-
-        let casted_args: Vec<_> = param_tys.into_iter()
-            .zip(args.iter())
-            .enumerate()
-            .map(|(i, (expected_ty, &actual_val))| {
-                let actual_ty = self.val_ty(actual_val);
-                if expected_ty != actual_ty {
-                    debug!("Type mismatch in function call of {:?}. \
-                            Expected {:?} for param {}, got {:?}; injecting bitcast",
-                           llfn, expected_ty, i, actual_ty);
-                    self.bitcast(actual_val, expected_ty)
-                } else {
-                    actual_val
-                }
-            })
-            .collect();
-
-        Cow::Owned(casted_args)
-    }
-
     fn lifetime_start(&mut self, ptr: &'ll Value, size: Size) {
         self.call_lifetime_intrinsic("llvm.lifetime.start", ptr, size);
     }
@@ -1509,6 +1300,215 @@ impl StaticBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
 }
 
 impl Builder<'a, 'll, 'tcx> {
+    fn count_insn(&self, category: &str) {
+        if self.sess().codegen_stats() {
+            self.stats.borrow_mut().n_llvm_insns += 1;
+        }
+        if self.sess().count_llvm_insns() {
+            *self.stats
+                      .borrow_mut()
+                      .llvm_insns
+                      .entry(category.to_string())
+                      .or_insert(0) += 1;
+        }
+    }
+
+    fn position_at_start(&mut self, llbb: &'ll BasicBlock) {
+        unsafe {
+            llvm::LLVMRustPositionBuilderAtStart(self.llbuilder, llbb);
+        }
+    }
+
+    pub fn minnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
+        self.count_insn("minnum");
+        unsafe { llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs) }
+    }
+
+    pub fn maxnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
+        self.count_insn("maxnum");
+        unsafe { llvm::LLVMRustBuildMaxNum(self.llbuilder, lhs, rhs) }
+    }
+
+    pub fn insert_element(
+        &mut self, vec: &'ll Value,
+        elt: &'ll Value,
+        idx: &'ll Value,
+    ) -> &'ll Value {
+        self.count_insn("insertelement");
+        unsafe {
+            llvm::LLVMBuildInsertElement(self.llbuilder, vec, elt, idx, noname())
+        }
+    }
+
+    pub fn shuffle_vector(
+        &mut self,
+        v1: &'ll Value,
+        v2: &'ll Value,
+        mask: &'ll Value,
+    ) -> &'ll Value {
+        self.count_insn("shufflevector");
+        unsafe {
+            llvm::LLVMBuildShuffleVector(self.llbuilder, v1, v2, mask, noname())
+        }
+    }
+
+    pub fn vector_reduce_fadd_fast(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value {
+        self.count_insn("vector.reduce.fadd_fast");
+        unsafe {
+            // FIXME: add a non-fast math version once
+            // https://bugs.llvm.org/show_bug.cgi?id=36732
+            // is fixed.
+            let instr = llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src);
+            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
+            instr
+        }
+    }
+    pub fn vector_reduce_fmul_fast(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value {
+        self.count_insn("vector.reduce.fmul_fast");
+        unsafe {
+            // FIXME: add a non-fast math version once
+            // https://bugs.llvm.org/show_bug.cgi?id=36732
+            // is fixed.
+            let instr = llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src);
+            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
+            instr
+        }
+    }
+    pub fn vector_reduce_add(&mut self, src: &'ll Value) -> &'ll Value {
+        self.count_insn("vector.reduce.add");
+        unsafe { llvm::LLVMRustBuildVectorReduceAdd(self.llbuilder, src) }
+    }
+    pub fn vector_reduce_mul(&mut self, src: &'ll Value) -> &'ll Value {
+        self.count_insn("vector.reduce.mul");
+        unsafe { llvm::LLVMRustBuildVectorReduceMul(self.llbuilder, src) }
+    }
+    pub fn vector_reduce_and(&mut self, src: &'ll Value) -> &'ll Value {
+        self.count_insn("vector.reduce.and");
+        unsafe { llvm::LLVMRustBuildVectorReduceAnd(self.llbuilder, src) }
+    }
+    pub fn vector_reduce_or(&mut self, src: &'ll Value) -> &'ll Value {
+        self.count_insn("vector.reduce.or");
+        unsafe { llvm::LLVMRustBuildVectorReduceOr(self.llbuilder, src) }
+    }
+    pub fn vector_reduce_xor(&mut self, src: &'ll Value) -> &'ll Value {
+        self.count_insn("vector.reduce.xor");
+        unsafe { llvm::LLVMRustBuildVectorReduceXor(self.llbuilder, src) }
+    }
+    pub fn vector_reduce_fmin(&mut self, src: &'ll Value) -> &'ll Value {
+        self.count_insn("vector.reduce.fmin");
+        unsafe { llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ false) }
+    }
+    pub fn vector_reduce_fmax(&mut self, src: &'ll Value) -> &'ll Value {
+        self.count_insn("vector.reduce.fmax");
+        unsafe { llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ false) }
+    }
+    pub fn vector_reduce_fmin_fast(&mut self, src: &'ll Value) -> &'ll Value {
+        self.count_insn("vector.reduce.fmin_fast");
+        unsafe {
+            let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ true);
+            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
+            instr
+        }
+    }
+    pub fn vector_reduce_fmax_fast(&mut self, src: &'ll Value) -> &'ll Value {
+        self.count_insn("vector.reduce.fmax_fast");
+        unsafe {
+            let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ true);
+            llvm::LLVMRustSetHasUnsafeAlgebra(instr);
+            instr
+        }
+    }
+    pub fn vector_reduce_min(&mut self, src: &'ll Value, is_signed: bool) -> &'ll Value {
+        self.count_insn("vector.reduce.min");
+        unsafe { llvm::LLVMRustBuildVectorReduceMin(self.llbuilder, src, is_signed) }
+    }
+    pub fn vector_reduce_max(&mut self, src: &'ll Value, is_signed: bool) -> &'ll Value {
+        self.count_insn("vector.reduce.max");
+        unsafe { llvm::LLVMRustBuildVectorReduceMax(self.llbuilder, src, is_signed) }
+    }
+
+    pub fn add_clause(&mut self, landing_pad: &'ll Value, clause: &'ll Value) {
+        unsafe {
+            llvm::LLVMAddClause(landing_pad, clause);
+        }
+    }
+
+    pub fn catch_ret(&mut self, funclet: &Funclet<'ll>, unwind: &'ll BasicBlock) -> &'ll Value {
+        self.count_insn("catchret");
+        let ret = unsafe {
+            llvm::LLVMRustBuildCatchRet(self.llbuilder, funclet.cleanuppad(), unwind)
+        };
+        ret.expect("LLVM does not have support for catchret")
+    }
+
+    fn check_store<'b>(&mut self,
+                       val: &'ll Value,
+                       ptr: &'ll Value) -> &'ll Value {
+        let dest_ptr_ty = self.cx.val_ty(ptr);
+        let stored_ty = self.cx.val_ty(val);
+        let stored_ptr_ty = self.cx.type_ptr_to(stored_ty);
+
+        assert_eq!(self.cx.type_kind(dest_ptr_ty), TypeKind::Pointer);
+
+        if dest_ptr_ty == stored_ptr_ty {
+            ptr
+        } else {
+            debug!("Type mismatch in store. \
+                    Expected {:?}, got {:?}; inserting bitcast",
+                   dest_ptr_ty, stored_ptr_ty);
+            self.bitcast(ptr, stored_ptr_ty)
+        }
+    }
+
+    fn check_call<'b>(&mut self,
+                      typ: &str,
+                      llfn: &'ll Value,
+                      args: &'b [&'ll Value]) -> Cow<'b, [&'ll Value]> {
+        let mut fn_ty = self.cx.val_ty(llfn);
+        // Strip off pointers
+        while self.cx.type_kind(fn_ty) == TypeKind::Pointer {
+            fn_ty = self.cx.element_type(fn_ty);
+        }
+
+        assert!(self.cx.type_kind(fn_ty) == TypeKind::Function,
+                "builder::{} not passed a function, but {:?}", typ, fn_ty);
+
+        let param_tys = self.cx.func_params_types(fn_ty);
+
+        let all_args_match = param_tys.iter()
+            .zip(args.iter().map(|&v| self.val_ty(v)))
+            .all(|(expected_ty, actual_ty)| *expected_ty == actual_ty);
+
+        if all_args_match {
+            return Cow::Borrowed(args);
+        }
+
+        let casted_args: Vec<_> = param_tys.into_iter()
+            .zip(args.iter())
+            .enumerate()
+            .map(|(i, (expected_ty, &actual_val))| {
+                let actual_ty = self.val_ty(actual_val);
+                if expected_ty != actual_ty {
+                    debug!("Type mismatch in function call of {:?}. \
+                            Expected {:?} for param {}, got {:?}; injecting bitcast",
+                           llfn, expected_ty, i, actual_ty);
+                    self.bitcast(actual_val, expected_ty)
+                } else {
+                    actual_val
+                }
+            })
+            .collect();
+
+        Cow::Owned(casted_args)
+    }
+
+    pub fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value {
+        self.count_insn("vaarg");
+        unsafe {
+            llvm::LLVMBuildVAArg(self.llbuilder, list, ty, noname())
+        }
+    }
+
     fn call_lifetime_intrinsic(&mut self, intrinsic: &str, ptr: &'ll Value, size: Size) {
         if self.cx.sess().opts.optimize == config::OptLevel::No {
             return;
diff --git a/src/librustc_codegen_ssa/traits/builder.rs b/src/librustc_codegen_ssa/traits/builder.rs
index 5099107a39303..6dd2a36bf2648 100644
--- a/src/librustc_codegen_ssa/traits/builder.rs
+++ b/src/librustc_codegen_ssa/traits/builder.rs
@@ -13,7 +13,6 @@ use rustc::ty::Ty;
 use rustc::ty::layout::{Align, Size};
 use std::ffi::CStr;
 
-use std::borrow::Cow;
 use std::ops::Range;
 use syntax::ast::AsmDialect;
 
@@ -39,11 +38,9 @@ pub trait BuilderMethods<'a, 'tcx: 'a>:
     fn cx(&self) -> &Self::CodegenCx;
     fn llfn(&self) -> Self::Value;
     fn llbb(&self) -> Self::BasicBlock;
-    fn count_insn(&self, category: &str);
 
     fn set_value_name(&mut self, value: Self::Value, name: &str);
     fn position_at_end(&mut self, llbb: Self::BasicBlock);
-    fn position_at_start(&mut self, llbb: Self::BasicBlock);
     fn ret_void(&mut self);
     fn ret(&mut self, v: Self::Value);
     fn br(&mut self, dest: Self::BasicBlock);
@@ -161,7 +158,6 @@ pub trait BuilderMethods<'a, 'tcx: 'a>:
     fn icmp(&mut self, op: IntPredicate, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
     fn fcmp(&mut self, op: RealPredicate, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
 
-    fn empty_phi(&mut self, ty: Self::Type) -> Self::Value;
     fn phi(
         &mut self,
         ty: Self::Type,
@@ -206,8 +202,6 @@ pub trait BuilderMethods<'a, 'tcx: 'a>:
         flags: MemFlags,
     );
 
-    fn minnum(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
-    fn maxnum(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
     fn select(
         &mut self,
         cond: Self::Value,
@@ -215,34 +209,8 @@ pub trait BuilderMethods<'a, 'tcx: 'a>:
         else_val: Self::Value,
     ) -> Self::Value;
 
-    fn va_arg(&mut self, list: Self::Value, ty: Self::Type) -> Self::Value;
     fn extract_element(&mut self, vec: Self::Value, idx: Self::Value) -> Self::Value;
-    fn insert_element(
-        &mut self,
-        vec: Self::Value,
-        elt: Self::Value,
-        idx: Self::Value,
-    ) -> Self::Value;
-    fn shuffle_vector(
-        &mut self,
-        v1: Self::Value,
-        v2: Self::Value,
-        mask: Self::Value,
-    ) -> Self::Value;
     fn vector_splat(&mut self, num_elts: usize, elt: Self::Value) -> Self::Value;
-    fn vector_reduce_fadd_fast(&mut self, acc: Self::Value, src: Self::Value) -> Self::Value;
-    fn vector_reduce_fmul_fast(&mut self, acc: Self::Value, src: Self::Value) -> Self::Value;
-    fn vector_reduce_add(&mut self, src: Self::Value) -> Self::Value;
-    fn vector_reduce_mul(&mut self, src: Self::Value) -> Self::Value;
-    fn vector_reduce_and(&mut self, src: Self::Value) -> Self::Value;
-    fn vector_reduce_or(&mut self, src: Self::Value) -> Self::Value;
-    fn vector_reduce_xor(&mut self, src: Self::Value) -> Self::Value;
-    fn vector_reduce_fmin(&mut self, src: Self::Value) -> Self::Value;
-    fn vector_reduce_fmax(&mut self, src: Self::Value) -> Self::Value;
-    fn vector_reduce_fmin_fast(&mut self, src: Self::Value) -> Self::Value;
-    fn vector_reduce_fmax_fast(&mut self, src: Self::Value) -> Self::Value;
-    fn vector_reduce_min(&mut self, src: Self::Value, is_signed: bool) -> Self::Value;
-    fn vector_reduce_max(&mut self, src: Self::Value, is_signed: bool) -> Self::Value;
     fn extract_value(&mut self, agg_val: Self::Value, idx: u64) -> Self::Value;
     fn insert_value(&mut self, agg_val: Self::Value, elt: Self::Value, idx: u64) -> Self::Value;
 
@@ -252,7 +220,6 @@ pub trait BuilderMethods<'a, 'tcx: 'a>:
         pers_fn: Self::Value,
         num_clauses: usize,
     ) -> Self::Value;
-    fn add_clause(&mut self, landing_pad: Self::Value, clause: Self::Value);
     fn set_cleanup(&mut self, landing_pad: Self::Value);
     fn resume(&mut self, exn: Self::Value) -> Self::Value;
     fn cleanup_pad(&mut self, parent: Option<Self::Value>, args: &[Self::Value]) -> Self::Funclet;
@@ -262,7 +229,6 @@ pub trait BuilderMethods<'a, 'tcx: 'a>:
         unwind: Option<Self::BasicBlock>,
     ) -> Self::Value;
     fn catch_pad(&mut self, parent: Self::Value, args: &[Self::Value]) -> Self::Funclet;
-    fn catch_ret(&mut self, funclet: &Self::Funclet, unwind: Self::BasicBlock) -> Self::Value;
     fn catch_switch(
         &mut self,
         parent: Option<Self::Value>,
@@ -293,19 +259,6 @@ pub trait BuilderMethods<'a, 'tcx: 'a>:
     fn add_incoming_to_phi(&mut self, phi: Self::Value, val: Self::Value, bb: Self::BasicBlock);
     fn set_invariant_load(&mut self, load: Self::Value);
 
-    /// Returns the ptr value that should be used for storing `val`.
-    fn check_store(&mut self, val: Self::Value, ptr: Self::Value) -> Self::Value;
-
-    /// Returns the args that should be used for a call to `llfn`.
-    fn check_call<'b>(
-        &mut self,
-        typ: &str,
-        llfn: Self::Value,
-        args: &'b [Self::Value],
-    ) -> Cow<'b, [Self::Value]>
-    where
-        [Self::Value]: ToOwned;
-
     /// Called for `StorageLive`
     fn lifetime_start(&mut self, ptr: Self::Value, size: Size);
 

From 7de0b1de19beac340691d260e7d5ed3dfeb92081 Mon Sep 17 00:00:00 2001
From: bjorn3 <bjorn3@users.noreply.github.com>
Date: Tue, 4 Dec 2018 20:20:45 +0100
Subject: [PATCH 12/18] Move get_param and set_value_name

---
 src/librustc_codegen_llvm/abi.rs             |  4 ++
 src/librustc_codegen_llvm/builder.rs         | 44 ++++++++++----------
 src/librustc_codegen_llvm/context.rs         |  5 ---
 src/librustc_codegen_llvm/debuginfo/mod.rs   |  7 ++++
 src/librustc_codegen_ssa/base.rs             |  4 +-
 src/librustc_codegen_ssa/mir/mod.rs          | 14 +++----
 src/librustc_codegen_ssa/traits/abi.rs       |  1 +
 src/librustc_codegen_ssa/traits/builder.rs   |  3 +-
 src/librustc_codegen_ssa/traits/debuginfo.rs |  1 +
 src/librustc_codegen_ssa/traits/misc.rs      |  1 -
 10 files changed, 46 insertions(+), 38 deletions(-)

diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs
index 49c9555a2c682..3a0d9e1334cf6 100644
--- a/src/librustc_codegen_llvm/abi.rs
+++ b/src/librustc_codegen_llvm/abi.rs
@@ -859,4 +859,8 @@ impl AbiBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
     ) {
         ty.apply_attrs_callsite(self, callsite)
     }
+
+    fn get_param(&self, index: usize) -> Self::Value {
+        llvm::get_param(self.llfn(), index as c_uint)
+    }
 }
diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs
index ebee3ab6cedaa..8e6299a45ae03 100644
--- a/src/librustc_codegen_llvm/builder.rs
+++ b/src/librustc_codegen_llvm/builder.rs
@@ -121,25 +121,12 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         Builder::new_block(self.cx, self.llfn(), name)
     }
 
-    fn llfn(&self) -> &'ll Value {
-        unsafe {
-            llvm::LLVMGetBasicBlockParent(self.llbb())
-        }
-    }
-
     fn llbb(&self) -> &'ll BasicBlock {
         unsafe {
             llvm::LLVMGetInsertBlock(self.llbuilder)
         }
     }
 
-    fn set_value_name(&mut self, value: &'ll Value, name: &str) {
-        let cname = SmallCStr::new(name);
-        unsafe {
-            llvm::LLVMSetValueName(value, cname.as_ptr());
-        }
-    }
-
     fn position_at_end(&mut self, llbb: &'ll BasicBlock) {
         unsafe {
             llvm::LLVMPositionBuilderAtEnd(self.llbuilder, llbb);
@@ -768,6 +755,14 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         }
     }
 
+    fn struct_gep(&mut self, ptr: &'ll Value, idx: u64) -> &'ll Value {
+        self.count_insn("structgep");
+        assert_eq!(idx as c_uint as u64, idx);
+        unsafe {
+            llvm::LLVMBuildStructGEP(self.llbuilder, ptr, idx as c_uint, noname())
+        }
+    }
+
     /* Casts */
     fn trunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         self.count_insn("trunc");
@@ -999,6 +994,14 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         }
     }
 
+    #[allow(dead_code)]
+    fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value {
+        self.count_insn("vaarg");
+        unsafe {
+            llvm::LLVMBuildVAArg(self.llbuilder, list, ty, noname())
+        }
+    }
+
     fn extract_element(&mut self, vec: &'ll Value, idx: &'ll Value) -> &'ll Value {
         self.count_insn("extractelement");
         unsafe {
@@ -1241,13 +1244,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         }
     }
 
-    fn struct_gep(&mut self, ptr: &'ll Value, idx: u64) -> &'ll Value {
-        self.count_insn("structgep");
-        assert_eq!(idx as c_uint as u64, idx);
-        unsafe {
-            llvm::LLVMBuildStructGEP(self.llbuilder, ptr, idx as c_uint, noname())
-        }
-    }
 
     fn cx(&self) -> &CodegenCx<'ll, 'tcx> {
         self.cx
@@ -1263,7 +1259,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
 }
 
 impl StaticBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
-    fn get_static(&mut self, def_id: DefId) -> &'ll Value {
+fn get_static(&mut self, def_id: DefId) -> &'ll Value {
         // Forward to the `get_static` method of `CodegenCx`
         self.cx().get_static(def_id)
     }
@@ -1300,6 +1296,12 @@ impl StaticBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
 }
 
 impl Builder<'a, 'll, 'tcx> {
+    pub fn llfn(&self) -> &'ll Value {
+        unsafe {
+            llvm::LLVMGetBasicBlockParent(self.llbb())
+        }
+    }
+
     fn count_insn(&self, category: &str) {
         if self.sess().codegen_stats() {
             self.stats.borrow_mut().n_llvm_insns += 1;
diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs
index 0060751d60641..fc79e868fb4bf 100644
--- a/src/librustc_codegen_llvm/context.rs
+++ b/src/librustc_codegen_llvm/context.rs
@@ -10,7 +10,6 @@ use crate::monomorphize::partitioning::CodegenUnit;
 use crate::type_::Type;
 use crate::type_of::PointeeInfo;
 use rustc_codegen_ssa::traits::*;
-use libc::c_uint;
 
 use rustc_data_structures::base_n;
 use rustc_data_structures::small_c_str::SmallCStr;
@@ -326,10 +325,6 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         get_fn(self, instance)
     }
 
-    fn get_param(&self, llfn: &'ll Value, index: usize) -> &'ll Value {
-        llvm::get_param(llfn, index as c_uint)
-    }
-
     fn eh_personality(&self) -> &'ll Value {
         // The exception handling personality function.
         //
diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs
index 066ac8f019e00..6abbcd9feba7a 100644
--- a/src/librustc_codegen_llvm/debuginfo/mod.rs
+++ b/src/librustc_codegen_llvm/debuginfo/mod.rs
@@ -225,6 +225,13 @@ impl DebugInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
     fn insert_reference_to_gdb_debug_scripts_section_global(&mut self) {
         gdb::insert_reference_to_gdb_debug_scripts_section_global(self)
     }
+
+    fn set_value_name(&mut self, value: &'ll Value, name: &str) {
+        let cname = SmallCStr::new(name);
+        unsafe {
+            llvm::LLVMSetValueName(value, cname.as_ptr());
+        }
+    }
 }
 
 impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs
index 48743be3a2551..27e3e30669905 100644
--- a/src/librustc_codegen_ssa/base.rs
+++ b/src/librustc_codegen_ssa/base.rs
@@ -501,8 +501,8 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
         bx.insert_reference_to_gdb_debug_scripts_section_global();
 
         // Params from native main() used as args for rust start function
-        let param_argc = cx.get_param(llfn, 0);
-        let param_argv = cx.get_param(llfn, 1);
+        let param_argc = bx.get_param(0);
+        let param_argv = bx.get_param(1);
         let arg_argc = bx.intcast(param_argc, cx.type_isize(), true);
         let arg_argv = param_argv;
 
diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs
index 4d9579504c857..91aa9bcc7808b 100644
--- a/src/librustc_codegen_ssa/mir/mod.rs
+++ b/src/librustc_codegen_ssa/mir/mod.rs
@@ -295,7 +295,7 @@ pub fn codegen_mir<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
                 // Temporary or return place
                 if local == mir::RETURN_PLACE && fx.fn_ty.ret.is_indirect() {
                     debug!("alloc: {:?} (return place) -> place", local);
-                    let llretptr = fx.cx.get_param(llfn, 0);
+                    let llretptr = bx.get_param(0);
                     LocalRef::Place(PlaceRef::new_sized(llretptr, layout, layout.align.abi))
                 } else if memory_locals.contains(local) {
                     debug!("alloc: {:?} -> place", local);
@@ -523,18 +523,18 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
                 }
                 PassMode::Ignore(IgnoreMode::CVarArgs) => {}
                 PassMode::Direct(_) => {
-                    let llarg = bx.get_param(bx.llfn(), llarg_idx);
+                    let llarg = bx.get_param(llarg_idx);
                     bx.set_value_name(llarg, &name);
                     llarg_idx += 1;
                     return local(
                         OperandRef::from_immediate_or_packed_pair(bx, llarg, arg.layout));
                 }
                 PassMode::Pair(..) => {
-                    let a = bx.get_param(bx.llfn(), llarg_idx);
+                    let a = bx.get_param(llarg_idx);
                     bx.set_value_name(a, &(name.clone() + ".0"));
                     llarg_idx += 1;
 
-                    let b = bx.get_param(bx.llfn(), llarg_idx);
+                    let b = bx.get_param(llarg_idx);
                     bx.set_value_name(b, &(name + ".1"));
                     llarg_idx += 1;
 
@@ -551,16 +551,16 @@ fn arg_local_refs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
             // Don't copy an indirect argument to an alloca, the caller
             // already put it in a temporary alloca and gave it up.
             // FIXME: lifetimes
-            let llarg = bx.get_param(bx.llfn(), llarg_idx);
+            let llarg = bx.get_param(llarg_idx);
             bx.set_value_name(llarg, &name);
             llarg_idx += 1;
             PlaceRef::new_sized(llarg, arg.layout, arg.layout.align.abi)
         } else if arg.is_unsized_indirect() {
             // As the storage for the indirect argument lives during
             // the whole function call, we just copy the fat pointer.
-            let llarg = bx.get_param(bx.llfn(), llarg_idx);
+            let llarg = bx.get_param(llarg_idx);
             llarg_idx += 1;
-            let llextra = bx.get_param(bx.llfn(), llarg_idx);
+            let llextra = bx.get_param(llarg_idx);
             llarg_idx += 1;
             let indirect_operand = OperandValue::Pair(llarg, llextra);
 
diff --git a/src/librustc_codegen_ssa/traits/abi.rs b/src/librustc_codegen_ssa/traits/abi.rs
index 8f7fa199b057a..a8fd4e1d2c7c7 100644
--- a/src/librustc_codegen_ssa/traits/abi.rs
+++ b/src/librustc_codegen_ssa/traits/abi.rs
@@ -10,4 +10,5 @@ pub trait AbiMethods<'tcx> {
 
 pub trait AbiBuilderMethods<'tcx>: BackendTypes {
     fn apply_attrs_callsite(&mut self, ty: &FnType<'tcx, Ty<'tcx>>, callsite: Self::Value);
+    fn get_param(&self, index: usize) -> Self::Value;
 }
diff --git a/src/librustc_codegen_ssa/traits/builder.rs b/src/librustc_codegen_ssa/traits/builder.rs
index 6dd2a36bf2648..da5da58d1674d 100644
--- a/src/librustc_codegen_ssa/traits/builder.rs
+++ b/src/librustc_codegen_ssa/traits/builder.rs
@@ -36,10 +36,8 @@ pub trait BuilderMethods<'a, 'tcx: 'a>:
     fn with_cx(cx: &'a Self::CodegenCx) -> Self;
     fn build_sibling_block<'b>(&self, name: &'b str) -> Self;
     fn cx(&self) -> &Self::CodegenCx;
-    fn llfn(&self) -> Self::Value;
     fn llbb(&self) -> Self::BasicBlock;
 
-    fn set_value_name(&mut self, value: Self::Value, name: &str);
     fn position_at_end(&mut self, llbb: Self::BasicBlock);
     fn ret_void(&mut self);
     fn ret(&mut self, v: Self::Value);
@@ -209,6 +207,7 @@ pub trait BuilderMethods<'a, 'tcx: 'a>:
         else_val: Self::Value,
     ) -> Self::Value;
 
+    fn va_arg(&mut self, list: Self::Value, ty: Self::Type) -> Self::Value;
     fn extract_element(&mut self, vec: Self::Value, idx: Self::Value) -> Self::Value;
     fn vector_splat(&mut self, num_elts: usize, elt: Self::Value) -> Self::Value;
     fn extract_value(&mut self, agg_val: Self::Value, idx: u64) -> Self::Value;
diff --git a/src/librustc_codegen_ssa/traits/debuginfo.rs b/src/librustc_codegen_ssa/traits/debuginfo.rs
index dcbb4e66cb385..a0b53fde09c4d 100644
--- a/src/librustc_codegen_ssa/traits/debuginfo.rs
+++ b/src/librustc_codegen_ssa/traits/debuginfo.rs
@@ -58,4 +58,5 @@ pub trait DebugInfoBuilderMethods<'tcx>: BackendTypes {
         span: Span,
     );
     fn insert_reference_to_gdb_debug_scripts_section_global(&mut self);
+    fn set_value_name(&mut self, value: Self::Value, name: &str);
 }
diff --git a/src/librustc_codegen_ssa/traits/misc.rs b/src/librustc_codegen_ssa/traits/misc.rs
index b3d458f3a3be8..2797dd89f5b15 100644
--- a/src/librustc_codegen_ssa/traits/misc.rs
+++ b/src/librustc_codegen_ssa/traits/misc.rs
@@ -14,7 +14,6 @@ pub trait MiscMethods<'tcx>: BackendTypes {
     fn check_overflow(&self) -> bool;
     fn instances(&self) -> &RefCell<FxHashMap<Instance<'tcx>, Self::Value>>;
     fn get_fn(&self, instance: Instance<'tcx>) -> Self::Value;
-    fn get_param(&self, llfn: Self::Value, index: usize) -> Self::Value;
     fn eh_personality(&self) -> Self::Value;
     fn eh_unwind_resume(&self) -> Self::Value;
     fn sess(&self) -> &Session;

From b0ee1f7f99c1190d51ecdb592e23b868f488a346 Mon Sep 17 00:00:00 2001
From: bjorn3 <bjorn3@users.noreply.github.com>
Date: Fri, 7 Dec 2018 18:04:34 +0100
Subject: [PATCH 13/18] Remove scalar_lltypes from cg_ssa

---
 src/librustc_codegen_llvm/type_.rs       | 6 ------
 src/librustc_codegen_ssa/traits/type_.rs | 3 ---
 2 files changed, 9 deletions(-)

diff --git a/src/librustc_codegen_llvm/type_.rs b/src/librustc_codegen_llvm/type_.rs
index d5424fa459166..426c70fb2dc58 100644
--- a/src/librustc_codegen_llvm/type_.rs
+++ b/src/librustc_codegen_llvm/type_.rs
@@ -11,7 +11,6 @@ use rustc_codegen_ssa::traits::*;
 use crate::common;
 use crate::type_of::LayoutLlvmExt;
 use crate::abi::{LlvmType, FnTypeExt};
-use rustc::util::nodemap::FxHashMap;
 use rustc::ty::Ty;
 use rustc::ty::layout::TyLayout;
 use rustc_target::abi::call::{CastTarget, FnType, Reg};
@@ -19,7 +18,6 @@ use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_codegen_ssa::common::TypeKind;
 
 use std::fmt;
-use std::cell::RefCell;
 use std::ptr;
 
 use libc::c_uint;
@@ -232,10 +230,6 @@ impl BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
     fn val_ty(&self, v: &'ll Value) -> &'ll Type {
         common::val_ty(v)
     }
-
-    fn scalar_lltypes(&self) -> &RefCell<FxHashMap<Ty<'tcx>, Self::Type>> {
-        &self.scalar_lltypes
-    }
 }
 
 impl Type {
diff --git a/src/librustc_codegen_ssa/traits/type_.rs b/src/librustc_codegen_ssa/traits/type_.rs
index fe00276a55a45..442b25ce0b61d 100644
--- a/src/librustc_codegen_ssa/traits/type_.rs
+++ b/src/librustc_codegen_ssa/traits/type_.rs
@@ -5,9 +5,7 @@ use crate::common::{self, TypeKind};
 use crate::mir::place::PlaceRef;
 use rustc::ty::layout::{self, Align, Size, TyLayout};
 use rustc::ty::{self, Ty};
-use rustc::util::nodemap::FxHashMap;
 use rustc_target::abi::call::{ArgType, CastTarget, FnType, Reg};
-use std::cell::RefCell;
 use syntax::ast;
 
 // This depends on `Backend` and not `BackendTypes`, because consumers will probably want to use
@@ -49,7 +47,6 @@ pub trait BaseTypeMethods<'tcx>: Backend<'tcx> {
     fn int_width(&self, ty: Self::Type) -> u64;
 
     fn val_ty(&self, v: Self::Value) -> Self::Type;
-    fn scalar_lltypes(&self) -> &RefCell<FxHashMap<Ty<'tcx>, Self::Type>>;
 }
 
 pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {

From 0e166bb217463a26028ad9b1724e686d54ba1415 Mon Sep 17 00:00:00 2001
From: bjorn3 <bjorn3@users.noreply.github.com>
Date: Fri, 1 Mar 2019 15:47:06 +0100
Subject: [PATCH 14/18] Remove a lot of methods from *TypeMethods

---
 src/librustc_codegen_llvm/type_.rs       | 120 ++++++++++++++++-------
 src/librustc_codegen_ssa/common.rs       |  16 +--
 src/librustc_codegen_ssa/traits/type_.rs |  70 ++-----------
 3 files changed, 92 insertions(+), 114 deletions(-)

diff --git a/src/librustc_codegen_llvm/type_.rs b/src/librustc_codegen_llvm/type_.rs
index 426c70fb2dc58..bcd90aeceb647 100644
--- a/src/librustc_codegen_llvm/type_.rs
+++ b/src/librustc_codegen_llvm/type_.rs
@@ -11,8 +11,9 @@ use rustc_codegen_ssa::traits::*;
 use crate::common;
 use crate::type_of::LayoutLlvmExt;
 use crate::abi::{LlvmType, FnTypeExt};
+use syntax::ast;
 use rustc::ty::Ty;
-use rustc::ty::layout::TyLayout;
+use rustc::ty::layout::{self, Align, Size, TyLayout};
 use rustc_target::abi::call::{CastTarget, FnType, Reg};
 use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_codegen_ssa::common::TypeKind;
@@ -50,21 +51,99 @@ impl CodegenCx<'ll, 'tcx> {
                                     els.len() as c_uint, packed as Bool)
         }
     }
-}
 
-impl BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
-    fn type_void(&self) -> &'ll Type {
+    crate fn type_void(&self) -> &'ll Type {
         unsafe {
             llvm::LLVMVoidTypeInContext(self.llcx)
         }
     }
 
-    fn type_metadata(&self) -> &'ll Type {
+    crate fn type_metadata(&self) -> &'ll Type {
         unsafe {
             llvm::LLVMRustMetadataTypeInContext(self.llcx)
         }
     }
 
+    ///x Creates an integer type with the given number of bits, e.g., i24
+    crate fn type_ix(&self, num_bits: u64) -> &'ll Type {
+        unsafe {
+            llvm::LLVMIntTypeInContext(self.llcx, num_bits as c_uint)
+        }
+    }
+
+    crate fn type_x86_mmx(&self) -> &'ll Type {
+        unsafe {
+            llvm::LLVMX86MMXTypeInContext(self.llcx)
+        }
+    }
+
+    crate fn type_vector(&self, ty: &'ll Type, len: u64) -> &'ll Type {
+        unsafe {
+            llvm::LLVMVectorType(ty, len as c_uint)
+        }
+    }
+
+    crate fn func_params_types(&self, ty: &'ll Type) -> Vec<&'ll Type> {
+        unsafe {
+            let n_args = llvm::LLVMCountParamTypes(ty) as usize;
+            let mut args = Vec::with_capacity(n_args);
+            llvm::LLVMGetParamTypes(ty, args.as_mut_ptr());
+            args.set_len(n_args);
+            args
+        }
+    }
+
+    crate fn type_bool(&self) -> &'ll Type {
+        self.type_i8()
+    }
+
+    crate fn type_int_from_ty(&self, t: ast::IntTy) -> &'ll Type {
+        match t {
+            ast::IntTy::Isize => self.type_isize(),
+            ast::IntTy::I8 => self.type_i8(),
+            ast::IntTy::I16 => self.type_i16(),
+            ast::IntTy::I32 => self.type_i32(),
+            ast::IntTy::I64 => self.type_i64(),
+            ast::IntTy::I128 => self.type_i128(),
+        }
+    }
+
+    crate fn type_uint_from_ty(&self, t: ast::UintTy) -> &'ll Type {
+        match t {
+            ast::UintTy::Usize => self.type_isize(),
+            ast::UintTy::U8 => self.type_i8(),
+            ast::UintTy::U16 => self.type_i16(),
+            ast::UintTy::U32 => self.type_i32(),
+            ast::UintTy::U64 => self.type_i64(),
+            ast::UintTy::U128 => self.type_i128(),
+        }
+    }
+
+    crate fn type_float_from_ty(&self, t: ast::FloatTy) -> &'ll Type {
+        match t {
+            ast::FloatTy::F32 => self.type_f32(),
+            ast::FloatTy::F64 => self.type_f64(),
+        }
+    }
+
+    crate fn type_pointee_for_align(&self, align: Align) -> &'ll Type {
+        // FIXME(eddyb) We could find a better approximation if ity.align < align.
+        let ity = layout::Integer::approximate_align(self, align);
+        self.type_from_integer(ity)
+    }
+
+    /// Return a LLVM type that has at most the required alignment,
+    /// and exactly the required size, as a best-effort padding array.
+    crate fn type_padding_filler(&self, size: Size, align: Align) -> &'ll Type {
+        let unit = layout::Integer::approximate_align(self, align);
+        let size = size.bytes();
+        let unit_size = unit.size().bytes();
+        assert_eq!(size % unit_size, 0);
+        self.type_array(self.type_from_integer(unit), size / unit_size)
+    }
+}
+
+impl BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
     fn type_i1(&self) -> &'ll Type {
         unsafe {
             llvm::LLVMInt1TypeInContext(self.llcx)
@@ -102,12 +181,6 @@ impl BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         }
     }
 
-    fn type_ix(&self, num_bits: u64) -> &'ll Type {
-        unsafe {
-            llvm::LLVMIntTypeInContext(self.llcx, num_bits as c_uint)
-        }
-    }
-
     fn type_isize(&self) -> &'ll Type {
         self.isize_ty
     }
@@ -124,12 +197,6 @@ impl BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         }
     }
 
-    fn type_x86_mmx(&self) -> &'ll Type {
-        unsafe {
-            llvm::LLVMX86MMXTypeInContext(self.llcx)
-        }
-    }
-
     fn type_func(
         &self,
         args: &[&'ll Type],
@@ -171,12 +238,6 @@ impl BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         }
     }
 
-    fn type_vector(&self, ty: &'ll Type, len: u64) -> &'ll Type {
-        unsafe {
-            llvm::LLVMVectorType(ty, len as c_uint)
-        }
-    }
-
     fn type_kind(&self, ty: &'ll Type) -> TypeKind {
         unsafe {
             llvm::LLVMRustGetTypeKind(ty).to_generic()
@@ -201,16 +262,6 @@ impl BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         }
     }
 
-    fn func_params_types(&self, ty: &'ll Type) -> Vec<&'ll Type> {
-        unsafe {
-            let n_args = llvm::LLVMCountParamTypes(ty) as usize;
-            let mut args = Vec::with_capacity(n_args);
-            llvm::LLVMGetParamTypes(ty, args.as_mut_ptr());
-            args.set_len(n_args);
-            args
-        }
-    }
-
     fn float_width(&self, ty: &'ll Type) -> usize {
         match self.type_kind(ty) {
             TypeKind::Float => 32,
@@ -288,9 +339,6 @@ impl LayoutTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
     fn cast_backend_type(&self, ty: &CastTarget) -> &'ll Type {
         ty.llvm_type(self)
     }
-    fn fn_backend_type(&self, ty: &FnType<'tcx, Ty<'tcx>>) -> &'ll Type {
-        ty.llvm_type(self)
-    }
     fn fn_ptr_backend_type(&self, ty: &FnType<'tcx, Ty<'tcx>>) -> &'ll Type {
         ty.ptr_to_llvm_type(self)
     }
diff --git a/src/librustc_codegen_ssa/common.rs b/src/librustc_codegen_ssa/common.rs
index db77074deef94..0e1885fe29ba6 100644
--- a/src/librustc_codegen_ssa/common.rs
+++ b/src/librustc_codegen_ssa/common.rs
@@ -1,7 +1,7 @@
 #![allow(non_camel_case_types, non_snake_case)]
 
-use rustc::ty::{self, Ty, TyCtxt};
-use syntax_pos::{DUMMY_SP, Span};
+use rustc::ty::{Ty, TyCtxt};
+use syntax_pos::Span;
 
 use rustc::hir::def_id::DefId;
 use rustc::middle::lang_items::LangItem;
@@ -11,18 +11,6 @@ use crate::traits::*;
 use rustc::hir;
 use crate::traits::BuilderMethods;
 
-pub fn type_needs_drop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool {
-    ty.needs_drop(tcx, ty::ParamEnv::reveal_all())
-}
-
-pub fn type_is_sized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool {
-    ty.is_sized(tcx.at(DUMMY_SP), ty::ParamEnv::reveal_all())
-}
-
-pub fn type_is_freeze<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool {
-    ty.is_freeze(tcx, ty::ParamEnv::reveal_all(), DUMMY_SP)
-}
-
 pub enum IntPredicate {
     IntEQ,
     IntNE,
diff --git a/src/librustc_codegen_ssa/traits/type_.rs b/src/librustc_codegen_ssa/traits/type_.rs
index 442b25ce0b61d..8d7f225d9950b 100644
--- a/src/librustc_codegen_ssa/traits/type_.rs
+++ b/src/librustc_codegen_ssa/traits/type_.rs
@@ -1,38 +1,31 @@
 use super::misc::MiscMethods;
 use super::Backend;
 use super::HasCodegen;
-use crate::common::{self, TypeKind};
+use crate::common::TypeKind;
 use crate::mir::place::PlaceRef;
-use rustc::ty::layout::{self, Align, Size, TyLayout};
 use rustc::ty::{self, Ty};
+use rustc::ty::layout::{self, TyLayout};
 use rustc_target::abi::call::{ArgType, CastTarget, FnType, Reg};
-use syntax::ast;
+use syntax_pos::DUMMY_SP;
 
 // This depends on `Backend` and not `BackendTypes`, because consumers will probably want to use
 // `LayoutOf` or `HasTyCtxt`. This way, they don't have to add a constraint on it themselves.
 pub trait BaseTypeMethods<'tcx>: Backend<'tcx> {
-    fn type_void(&self) -> Self::Type;
-    fn type_metadata(&self) -> Self::Type;
     fn type_i1(&self) -> Self::Type;
     fn type_i8(&self) -> Self::Type;
     fn type_i16(&self) -> Self::Type;
     fn type_i32(&self) -> Self::Type;
     fn type_i64(&self) -> Self::Type;
     fn type_i128(&self) -> Self::Type;
-
-    // Creates an integer type with the given number of bits, e.g., i24
-    fn type_ix(&self, num_bits: u64) -> Self::Type;
     fn type_isize(&self) -> Self::Type;
 
     fn type_f32(&self) -> Self::Type;
     fn type_f64(&self) -> Self::Type;
-    fn type_x86_mmx(&self) -> Self::Type;
 
     fn type_func(&self, args: &[Self::Type], ret: Self::Type) -> Self::Type;
     fn type_variadic_func(&self, args: &[Self::Type], ret: Self::Type) -> Self::Type;
     fn type_struct(&self, els: &[Self::Type], packed: bool) -> Self::Type;
     fn type_array(&self, ty: Self::Type, len: u64) -> Self::Type;
-    fn type_vector(&self, ty: Self::Type, len: u64) -> Self::Type;
     fn type_kind(&self, ty: Self::Type) -> TypeKind;
     fn type_ptr_to(&self, ty: Self::Type) -> Self::Type;
     fn element_type(&self, ty: Self::Type) -> Self::Type;
@@ -40,7 +33,6 @@ pub trait BaseTypeMethods<'tcx>: Backend<'tcx> {
     /// Returns the number of elements in `self` if it is a LLVM vector type.
     fn vector_length(&self, ty: Self::Type) -> usize;
 
-    fn func_params_types(&self, ty: Self::Type) -> Vec<Self::Type>;
     fn float_width(&self, ty: Self::Type) -> usize;
 
     /// Retrieves the bit width of the integer type `self`.
@@ -50,10 +42,6 @@ pub trait BaseTypeMethods<'tcx>: Backend<'tcx> {
 }
 
 pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {
-    fn type_bool(&self) -> Self::Type {
-        self.type_i8()
-    }
-
     fn type_i8p(&self) -> Self::Type {
         self.type_ptr_to(self.type_i8())
     }
@@ -67,35 +55,6 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {
         }
     }
 
-    fn type_int_from_ty(&self, t: ast::IntTy) -> Self::Type {
-        match t {
-            ast::IntTy::Isize => self.type_isize(),
-            ast::IntTy::I8 => self.type_i8(),
-            ast::IntTy::I16 => self.type_i16(),
-            ast::IntTy::I32 => self.type_i32(),
-            ast::IntTy::I64 => self.type_i64(),
-            ast::IntTy::I128 => self.type_i128(),
-        }
-    }
-
-    fn type_uint_from_ty(&self, t: ast::UintTy) -> Self::Type {
-        match t {
-            ast::UintTy::Usize => self.type_isize(),
-            ast::UintTy::U8 => self.type_i8(),
-            ast::UintTy::U16 => self.type_i16(),
-            ast::UintTy::U32 => self.type_i32(),
-            ast::UintTy::U64 => self.type_i64(),
-            ast::UintTy::U128 => self.type_i128(),
-        }
-    }
-
-    fn type_float_from_ty(&self, t: ast::FloatTy) -> Self::Type {
-        match t {
-            ast::FloatTy::F32 => self.type_f32(),
-            ast::FloatTy::F64 => self.type_f64(),
-        }
-    }
-
     fn type_from_integer(&self, i: layout::Integer) -> Self::Type {
         use rustc::ty::layout::Integer::*;
         match i {
@@ -107,32 +66,16 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {
         }
     }
 
-    fn type_pointee_for_align(&self, align: Align) -> Self::Type {
-        // FIXME(eddyb) We could find a better approximation if ity.align < align.
-        let ity = layout::Integer::approximate_align(self, align);
-        self.type_from_integer(ity)
-    }
-
-    /// Return a LLVM type that has at most the required alignment,
-    /// and exactly the required size, as a best-effort padding array.
-    fn type_padding_filler(&self, size: Size, align: Align) -> Self::Type {
-        let unit = layout::Integer::approximate_align(self, align);
-        let size = size.bytes();
-        let unit_size = unit.size().bytes();
-        assert_eq!(size % unit_size, 0);
-        self.type_array(self.type_from_integer(unit), size / unit_size)
-    }
-
     fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool {
-        common::type_needs_drop(self.tcx(), ty)
+        ty.needs_drop(self.tcx(), ty::ParamEnv::reveal_all())
     }
 
     fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
-        common::type_is_sized(self.tcx(), ty)
+        ty.is_sized(self.tcx().at(DUMMY_SP), ty::ParamEnv::reveal_all())
     }
 
     fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
-        common::type_is_freeze(self.tcx(), ty)
+        ty.is_freeze(self.tcx(), ty::ParamEnv::reveal_all(), DUMMY_SP)
     }
 
     fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool {
@@ -155,7 +98,6 @@ impl<T> DerivedTypeMethods<'tcx> for T where Self: BaseTypeMethods<'tcx> + MiscM
 pub trait LayoutTypeMethods<'tcx>: Backend<'tcx> {
     fn backend_type(&self, layout: TyLayout<'tcx>) -> Self::Type;
     fn cast_backend_type(&self, ty: &CastTarget) -> Self::Type;
-    fn fn_backend_type(&self, ty: &FnType<'tcx, Ty<'tcx>>) -> Self::Type;
     fn fn_ptr_backend_type(&self, ty: &FnType<'tcx, Ty<'tcx>>) -> Self::Type;
     fn reg_backend_type(&self, ty: &Reg) -> Self::Type;
     fn immediate_backend_type(&self, layout: TyLayout<'tcx>) -> Self::Type;

From b71c429007e6ce1dcbae2f909cf5cd6d10a9901d Mon Sep 17 00:00:00 2001
From: bjorn3 <bjorn3@users.noreply.github.com>
Date: Sat, 8 Dec 2018 11:48:43 +0100
Subject: [PATCH 15/18] Remove type_variadic_func and typ_array from cg_ssa

---
 src/librustc_codegen_llvm/builder.rs       | 72 +++++++++++++++-------
 src/librustc_codegen_llvm/type_.rs         | 35 +++++------
 src/librustc_codegen_ssa/mir/rvalue.rs     | 29 ++-------
 src/librustc_codegen_ssa/traits/builder.rs | 15 ++---
 src/librustc_codegen_ssa/traits/type_.rs   |  2 -
 5 files changed, 80 insertions(+), 73 deletions(-)

diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs
index 8e6299a45ae03..c2da49e3ac97e 100644
--- a/src/librustc_codegen_llvm/builder.rs
+++ b/src/librustc_codegen_llvm/builder.rs
@@ -652,7 +652,37 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         OperandRef { val, layout: place.layout }
     }
 
+    fn write_operand_repeatedly(
+        mut self,
+        cg_elem: OperandRef<'tcx, &'ll Value>,
+        count: u64,
+        dest: PlaceRef<'tcx, &'ll Value>,
+    ) -> Self {
+        let zero = self.const_usize(0);
+        let count = self.const_usize(count);
+        let start = dest.project_index(&mut self, zero).llval;
+        let end = dest.project_index(&mut self, count).llval;
+
+        let mut header_bx = self.build_sibling_block("repeat_loop_header");
+        let mut body_bx = self.build_sibling_block("repeat_loop_body");
+        let next_bx = self.build_sibling_block("repeat_loop_next");
+
+        self.br(header_bx.llbb());
+        let current = header_bx.phi(self.val_ty(start), &[start], &[self.llbb()]);
+
+        let keep_going = header_bx.icmp(IntPredicate::IntNE, current, end);
+        header_bx.cond_br(keep_going, body_bx.llbb(), next_bx.llbb());
 
+        let align = dest.align.restrict_for_offset(dest.layout.field(self.cx(), 0).size);
+        cg_elem.val.store(&mut body_bx,
+            PlaceRef::new_sized(current, cg_elem.layout, align));
+
+        let next = body_bx.inbounds_gep(current, &[self.const_usize(1)]);
+        body_bx.br(header_bx.llbb());
+        header_bx.add_incoming_to_phi(current, next, body_bx.llbb());
+
+        next_bx
+    }
 
     fn range_metadata(&mut self, load: &'ll Value, range: Range<u128>) {
         if self.sess().target.target.arch == "amdgpu" {
@@ -873,20 +903,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
     }
 
     /* Miscellaneous instructions */
-    fn phi(&mut self, ty: &'ll Type, vals: &[&'ll Value], bbs: &[&'ll BasicBlock]) -> &'ll Value {
-        self.count_insn("addincoming");
-        assert_eq!(vals.len(), bbs.len());
-        let phi = unsafe {
-            llvm::LLVMBuildPhi(self.llbuilder, ty, noname())
-        };
-        unsafe {
-            llvm::LLVMAddIncoming(phi, vals.as_ptr(),
-                                  bbs.as_ptr(),
-                                  vals.len() as c_uint);
-            phi
-        }
-    }
-
     fn inline_asm_call(&mut self, asm: &CStr, cons: &CStr,
                        inputs: &[&'ll Value], output: &'ll Type,
                        volatile: bool, alignstack: bool,
@@ -1188,13 +1204,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         }
     }
 
-    fn add_incoming_to_phi(&mut self, phi: &'ll Value, val: &'ll Value, bb: &'ll BasicBlock) {
-        self.count_insn("addincoming");
-        unsafe {
-            llvm::LLVMAddIncoming(phi, &val, &bb, 1 as c_uint);
-        }
-    }
-
     fn set_invariant_load(&mut self, load: &'ll Value) {
         unsafe {
             llvm::LLVMSetMetadata(load, llvm::MD_invariant_load as c_uint,
@@ -1526,4 +1535,25 @@ impl Builder<'a, 'll, 'tcx> {
         let ptr = self.pointercast(ptr, self.cx.type_i8p());
         self.call(lifetime_intrinsic, &[self.cx.const_u64(size), ptr], None);
     }
+
+    fn phi(&mut self, ty: &'ll Type, vals: &[&'ll Value], bbs: &[&'ll BasicBlock]) -> &'ll Value {
+        self.count_insn("addincoming");
+        assert_eq!(vals.len(), bbs.len());
+        let phi = unsafe {
+            llvm::LLVMBuildPhi(self.llbuilder, ty, noname())
+        };
+        unsafe {
+            llvm::LLVMAddIncoming(phi, vals.as_ptr(),
+                                  bbs.as_ptr(),
+                                  vals.len() as c_uint);
+            phi
+        }
+    }
+
+    fn add_incoming_to_phi(&mut self, phi: &'ll Value, val: &'ll Value, bb: &'ll BasicBlock) {
+        self.count_insn("addincoming");
+        unsafe {
+            llvm::LLVMAddIncoming(phi, &val, &bb, 1 as c_uint);
+        }
+    }
 }
diff --git a/src/librustc_codegen_llvm/type_.rs b/src/librustc_codegen_llvm/type_.rs
index bcd90aeceb647..a5ed64a66a39d 100644
--- a/src/librustc_codegen_llvm/type_.rs
+++ b/src/librustc_codegen_llvm/type_.rs
@@ -141,6 +141,23 @@ impl CodegenCx<'ll, 'tcx> {
         assert_eq!(size % unit_size, 0);
         self.type_array(self.type_from_integer(unit), size / unit_size)
     }
+
+    crate fn type_variadic_func(
+        &self,
+        args: &[&'ll Type],
+        ret: &'ll Type
+    ) -> &'ll Type {
+        unsafe {
+            llvm::LLVMFunctionType(ret, args.as_ptr(),
+                                   args.len() as c_uint, True)
+        }
+    }
+
+    crate fn type_array(&self, ty: &'ll Type, len: u64) -> &'ll Type {
+        unsafe {
+            llvm::LLVMRustArrayType(ty, len)
+        }
+    }
 }
 
 impl BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
@@ -208,17 +225,6 @@ impl BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         }
     }
 
-    fn type_variadic_func(
-        &self,
-        args: &[&'ll Type],
-        ret: &'ll Type
-    ) -> &'ll Type {
-        unsafe {
-            llvm::LLVMFunctionType(ret, args.as_ptr(),
-                                   args.len() as c_uint, True)
-        }
-    }
-
     fn type_struct(
         &self,
         els: &[&'ll Type],
@@ -231,13 +237,6 @@ impl BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         }
     }
 
-
-    fn type_array(&self, ty: &'ll Type, len: u64) -> &'ll Type {
-        unsafe {
-            llvm::LLVMRustArrayType(ty, len)
-        }
-    }
-
     fn type_kind(&self, ty: &'ll Type) -> TypeKind {
         unsafe {
             llvm::LLVMRustGetTypeKind(ty).to_generic()
diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs
index c20d3f44bc528..7a31c5b3950e0 100644
--- a/src/librustc_codegen_ssa/mir/rvalue.rs
+++ b/src/librustc_codegen_ssa/mir/rvalue.rs
@@ -87,11 +87,11 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 if dest.layout.is_zst() {
                     return bx;
                 }
-                let zero = bx.cx().const_usize(0);
-                let start = dest.project_index(&mut bx, zero).llval;
 
                 if let OperandValue::Immediate(v) = cg_elem.val {
-                    let size = bx.cx().const_usize(dest.layout.size.bytes());
+                    let zero = bx.const_usize(0);
+                    let start = dest.project_index(&mut bx, zero).llval;
+                    let size = bx.const_usize(dest.layout.size.bytes());
 
                     // Use llvm.memset.p0i8.* to initialize all zero arrays
                     if bx.cx().is_const_integral(v) && bx.cx().const_to_uint(v) == 0 {
@@ -108,28 +108,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     }
                 }
 
-                let count = bx.cx().const_usize(count);
-                let end = dest.project_index(&mut bx, count).llval;
-
-                let mut header_bx = bx.build_sibling_block("repeat_loop_header");
-                let mut body_bx = bx.build_sibling_block("repeat_loop_body");
-                let next_bx = bx.build_sibling_block("repeat_loop_next");
-
-                bx.br(header_bx.llbb());
-                let current = header_bx.phi(bx.cx().val_ty(start), &[start], &[bx.llbb()]);
-
-                let keep_going = header_bx.icmp(IntPredicate::IntNE, current, end);
-                header_bx.cond_br(keep_going, body_bx.llbb(), next_bx.llbb());
-
-                let align = dest.align.restrict_for_offset(dest.layout.field(bx.cx(), 0).size);
-                cg_elem.val.store(&mut body_bx,
-                    PlaceRef::new_sized(current, cg_elem.layout, align));
-
-                let next = body_bx.inbounds_gep(current, &[bx.cx().const_usize(1)]);
-                body_bx.br(header_bx.llbb());
-                header_bx.add_incoming_to_phi(current, next, body_bx.llbb());
-
-                next_bx
+                bx.write_operand_repeatedly(cg_elem, count, dest)
             }
 
             mir::Rvalue::Aggregate(ref kind, ref operands) => {
diff --git a/src/librustc_codegen_ssa/traits/builder.rs b/src/librustc_codegen_ssa/traits/builder.rs
index da5da58d1674d..e121299363fda 100644
--- a/src/librustc_codegen_ssa/traits/builder.rs
+++ b/src/librustc_codegen_ssa/traits/builder.rs
@@ -116,6 +116,14 @@ pub trait BuilderMethods<'a, 'tcx: 'a>:
     fn load_operand(&mut self, place: PlaceRef<'tcx, Self::Value>)
         -> OperandRef<'tcx, Self::Value>;
 
+        /// Called for Rvalue::Repeat when the elem is neither a ZST nor optimizable using memset.
+    fn write_operand_repeatedly(
+        self,
+        elem: OperandRef<'tcx, Self::Value>,
+        count: u64,
+        dest: PlaceRef<'tcx, Self::Value>,
+    ) -> Self;
+
     fn range_metadata(&mut self, load: Self::Value, range: Range<u128>);
     fn nonnull_metadata(&mut self, load: Self::Value);
 
@@ -156,12 +164,6 @@ pub trait BuilderMethods<'a, 'tcx: 'a>:
     fn icmp(&mut self, op: IntPredicate, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
     fn fcmp(&mut self, op: RealPredicate, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
 
-    fn phi(
-        &mut self,
-        ty: Self::Type,
-        vals: &[Self::Value],
-        bbs: &[Self::BasicBlock],
-    ) -> Self::Value;
     fn inline_asm_call(
         &mut self,
         asm: &CStr,
@@ -255,7 +257,6 @@ pub trait BuilderMethods<'a, 'tcx: 'a>:
     ) -> Self::Value;
     fn atomic_fence(&mut self, order: AtomicOrdering, scope: SynchronizationScope);
     fn add_case(&mut self, s: Self::Value, on_val: Self::Value, dest: Self::BasicBlock);
-    fn add_incoming_to_phi(&mut self, phi: Self::Value, val: Self::Value, bb: Self::BasicBlock);
     fn set_invariant_load(&mut self, load: Self::Value);
 
     /// Called for `StorageLive`
diff --git a/src/librustc_codegen_ssa/traits/type_.rs b/src/librustc_codegen_ssa/traits/type_.rs
index 8d7f225d9950b..7fb2cb9d39362 100644
--- a/src/librustc_codegen_ssa/traits/type_.rs
+++ b/src/librustc_codegen_ssa/traits/type_.rs
@@ -23,9 +23,7 @@ pub trait BaseTypeMethods<'tcx>: Backend<'tcx> {
     fn type_f64(&self) -> Self::Type;
 
     fn type_func(&self, args: &[Self::Type], ret: Self::Type) -> Self::Type;
-    fn type_variadic_func(&self, args: &[Self::Type], ret: Self::Type) -> Self::Type;
     fn type_struct(&self, els: &[Self::Type], packed: bool) -> Self::Type;
-    fn type_array(&self, ty: Self::Type, len: u64) -> Self::Type;
     fn type_kind(&self, ty: Self::Type) -> TypeKind;
     fn type_ptr_to(&self, ty: Self::Type) -> Self::Type;
     fn element_type(&self, ty: Self::Type) -> Self::Type;

From b2e61946fa0dd5058165ed7c36f30b42c168cc02 Mon Sep 17 00:00:00 2001
From: bjorn3 <bjorn3@users.noreply.github.com>
Date: Sat, 8 Dec 2018 16:07:27 +0100
Subject: [PATCH 16/18] Remove inline_asm_call from cg_ssa

`count_insn` is no longer called for inline asm, because it is private to builder.rs
---
 src/librustc_codegen_llvm/asm.rs           | 48 +++++++++++++++++++++-
 src/librustc_codegen_llvm/builder.rs       | 42 +------------------
 src/librustc_codegen_ssa/traits/builder.rs | 14 -------
 3 files changed, 47 insertions(+), 57 deletions(-)

diff --git a/src/librustc_codegen_llvm/asm.rs b/src/librustc_codegen_llvm/asm.rs
index 4427308f4155d..100a896ea0c7d 100644
--- a/src/librustc_codegen_llvm/asm.rs
+++ b/src/librustc_codegen_llvm/asm.rs
@@ -10,7 +10,7 @@ use rustc_codegen_ssa::traits::*;
 use rustc_codegen_ssa::mir::place::PlaceRef;
 use rustc_codegen_ssa::mir::operand::OperandValue;
 
-use std::ffi::CString;
+use std::ffi::{CStr, CString};
 use libc::{c_uint, c_char};
 
 
@@ -73,7 +73,8 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
 
         let asm = CString::new(ia.asm.as_str().as_bytes()).unwrap();
         let constraint_cstr = CString::new(all_constraints).unwrap();
-        let r = self.inline_asm_call(
+        let r = inline_asm_call(
+            self,
             &asm,
             &constraint_cstr,
             &inputs,
@@ -119,3 +120,46 @@ impl AsmMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         }
     }
 }
+
+fn inline_asm_call(
+    bx: &mut Builder<'a, 'll, 'tcx>,
+    asm: &CStr,
+    cons: &CStr,
+    inputs: &[&'ll Value],
+    output: &'ll llvm::Type,
+    volatile: bool,
+    alignstack: bool,
+    dia: ::syntax::ast::AsmDialect,
+) -> Option<&'ll Value> {
+    let volatile = if volatile { llvm::True }
+                    else        { llvm::False };
+    let alignstack = if alignstack { llvm::True }
+                        else          { llvm::False };
+
+    let argtys = inputs.iter().map(|v| {
+        debug!("Asm Input Type: {:?}", *v);
+        bx.cx.val_ty(*v)
+    }).collect::<Vec<_>>();
+
+    debug!("Asm Output Type: {:?}", output);
+    let fty = bx.cx.type_func(&argtys[..], output);
+    unsafe {
+        // Ask LLVM to verify that the constraints are well-formed.
+        let constraints_ok = llvm::LLVMRustInlineAsmVerify(fty, cons.as_ptr());
+        debug!("Constraint verification result: {:?}", constraints_ok);
+        if constraints_ok {
+            let v = llvm::LLVMRustInlineAsm(
+                fty,
+                asm.as_ptr(),
+                cons.as_ptr(),
+                volatile,
+                alignstack,
+                llvm::AsmDialect::from_generic(dia),
+            );
+            Some(bx.call(v, inputs, None))
+        } else {
+            // LLVM has detected an issue with our constraints, bail out
+            None
+        }
+    }
+}
diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs
index c2da49e3ac97e..f53bb6a196a99 100644
--- a/src/librustc_codegen_llvm/builder.rs
+++ b/src/librustc_codegen_llvm/builder.rs
@@ -1,4 +1,4 @@
-use crate::llvm::{AtomicRmwBinOp, AtomicOrdering, SynchronizationScope, AsmDialect};
+use crate::llvm::{AtomicRmwBinOp, AtomicOrdering, SynchronizationScope};
 use crate::llvm::{self, False, BasicBlock};
 use crate::common::Funclet;
 use crate::context::CodegenCx;
@@ -19,7 +19,6 @@ use rustc_codegen_ssa::base::to_immediate;
 use rustc_codegen_ssa::mir::operand::{OperandValue, OperandRef};
 use rustc_codegen_ssa::mir::place::PlaceRef;
 use std::borrow::Cow;
-use std::ffi::CStr;
 use std::ops::{Deref, Range};
 use std::ptr;
 
@@ -903,45 +902,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
     }
 
     /* Miscellaneous instructions */
-    fn inline_asm_call(&mut self, asm: &CStr, cons: &CStr,
-                       inputs: &[&'ll Value], output: &'ll Type,
-                       volatile: bool, alignstack: bool,
-                       dia: syntax::ast::AsmDialect) -> Option<&'ll Value> {
-        self.count_insn("inlineasm");
-
-        let volatile = if volatile { llvm::True }
-                       else        { llvm::False };
-        let alignstack = if alignstack { llvm::True }
-                         else          { llvm::False };
-
-        let argtys = inputs.iter().map(|v| {
-            debug!("Asm Input Type: {:?}", *v);
-            self.cx.val_ty(*v)
-        }).collect::<Vec<_>>();
-
-        debug!("Asm Output Type: {:?}", output);
-        let fty = self.type_func(&argtys[..], output);
-        unsafe {
-            // Ask LLVM to verify that the constraints are well-formed.
-            let constraints_ok = llvm::LLVMRustInlineAsmVerify(fty, cons.as_ptr());
-            debug!("Constraint verification result: {:?}", constraints_ok);
-            if constraints_ok {
-                let v = llvm::LLVMRustInlineAsm(
-                    fty,
-                    asm.as_ptr(),
-                    cons.as_ptr(),
-                    volatile,
-                    alignstack,
-                    AsmDialect::from_generic(dia),
-                );
-                Some(self.call(v, inputs, None))
-            } else {
-                // LLVM has detected an issue with our constraints, bail out
-                None
-            }
-        }
-    }
-
     fn memcpy(&mut self, dst: &'ll Value, dst_align: Align,
                   src: &'ll Value, src_align: Align,
                   size: &'ll Value, flags: MemFlags) {
diff --git a/src/librustc_codegen_ssa/traits/builder.rs b/src/librustc_codegen_ssa/traits/builder.rs
index e121299363fda..e54ae76022217 100644
--- a/src/librustc_codegen_ssa/traits/builder.rs
+++ b/src/librustc_codegen_ssa/traits/builder.rs
@@ -11,10 +11,7 @@ use crate::mir::place::PlaceRef;
 use crate::MemFlags;
 use rustc::ty::Ty;
 use rustc::ty::layout::{Align, Size};
-use std::ffi::CStr;
-
 use std::ops::Range;
-use syntax::ast::AsmDialect;
 
 #[derive(Copy, Clone)]
 pub enum OverflowOp {
@@ -164,17 +161,6 @@ pub trait BuilderMethods<'a, 'tcx: 'a>:
     fn icmp(&mut self, op: IntPredicate, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
     fn fcmp(&mut self, op: RealPredicate, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
 
-    fn inline_asm_call(
-        &mut self,
-        asm: &CStr,
-        cons: &CStr,
-        inputs: &[Self::Value],
-        output: Self::Type,
-        volatile: bool,
-        alignstack: bool,
-        dia: AsmDialect,
-    ) -> Option<Self::Value>;
-
     fn memcpy(
         &mut self,
         dst: Self::Value,

From 56842b2154c0c2dd243f64e864b9c6aee718a161 Mon Sep 17 00:00:00 2001
From: bjorn3 <bjorn3@users.noreply.github.com>
Date: Sat, 8 Dec 2018 18:42:31 +0100
Subject: [PATCH 17/18] Add a method for emiting a switch.

---
 src/librustc_codegen_llvm/builder.rs       | 17 +++++++++--------
 src/librustc_codegen_ssa/mir/block.rs      | 17 +++++++----------
 src/librustc_codegen_ssa/traits/builder.rs |  5 +++--
 3 files changed, 19 insertions(+), 20 deletions(-)

diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs
index f53bb6a196a99..fbeb978413a92 100644
--- a/src/librustc_codegen_llvm/builder.rs
+++ b/src/librustc_codegen_llvm/builder.rs
@@ -170,9 +170,16 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         v: &'ll Value,
         else_llbb: &'ll BasicBlock,
         num_cases: usize,
-    ) -> &'ll Value {
-        unsafe {
+        cases: impl Iterator<Item = (u128, &'ll BasicBlock)>,
+    ) {
+        let switch = unsafe {
             llvm::LLVMBuildSwitch(self.llbuilder, v, else_llbb, num_cases as c_uint)
+        };
+        for (on_val, dest) in cases {
+            let on_val = self.const_uint_big(self.val_ty(v), on_val);
+            unsafe {
+                llvm::LLVMAddCase(switch, on_val, dest)
+            }
         }
     }
 
@@ -1158,12 +1165,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         }
     }
 
-    fn add_case(&mut self, s: &'ll Value, on_val: &'ll Value, dest: &'ll BasicBlock) {
-        unsafe {
-            llvm::LLVMAddCase(s, on_val, dest)
-        }
-    }
-
     fn set_invariant_load(&mut self, load: &'ll Value) {
         unsafe {
             llvm::LLVMSetMetadata(load, llvm::MD_invariant_load as c_uint,
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index f0e8a18c479b1..0ce97553bea77 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -214,17 +214,14 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             }
         } else {
             let (otherwise, targets) = targets.split_last().unwrap();
-            let switch = bx.switch(discr.immediate(),
-                                   helper.llblock(self, *otherwise),
-                                   values.len());
-            let switch_llty = bx.immediate_backend_type(
-                bx.layout_of(switch_ty)
+            bx.switch(
+                discr.immediate(),
+                helper.llblock(self, *otherwise),
+                values.len(),
+                values.iter().zip(targets).map(|(&value, target)| {
+                    (value, helper.llblock(self, *target))
+                })
             );
-            for (&value, target) in values.iter().zip(targets) {
-                let llval = bx.const_uint_big(switch_llty, value);
-                let llbb = helper.llblock(self, *target);
-                bx.add_case(switch, llval, llbb)
-            }
         }
     }
 
diff --git a/src/librustc_codegen_ssa/traits/builder.rs b/src/librustc_codegen_ssa/traits/builder.rs
index e54ae76022217..3b0f047d97414 100644
--- a/src/librustc_codegen_ssa/traits/builder.rs
+++ b/src/librustc_codegen_ssa/traits/builder.rs
@@ -50,7 +50,8 @@ pub trait BuilderMethods<'a, 'tcx: 'a>:
         v: Self::Value,
         else_llbb: Self::BasicBlock,
         num_cases: usize,
-    ) -> Self::Value;
+        cases: impl Iterator<Item = (u128, Self::BasicBlock)>,
+    );
     fn invoke(
         &mut self,
         llfn: Self::Value,
@@ -60,6 +61,7 @@ pub trait BuilderMethods<'a, 'tcx: 'a>:
         funclet: Option<&Self::Funclet>,
     ) -> Self::Value;
     fn unreachable(&mut self);
+
     fn add(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
     fn fadd(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
     fn fadd_fast(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
@@ -242,7 +244,6 @@ pub trait BuilderMethods<'a, 'tcx: 'a>:
         order: AtomicOrdering,
     ) -> Self::Value;
     fn atomic_fence(&mut self, order: AtomicOrdering, scope: SynchronizationScope);
-    fn add_case(&mut self, s: Self::Value, on_val: Self::Value, dest: Self::BasicBlock);
     fn set_invariant_load(&mut self, load: Self::Value);
 
     /// Called for `StorageLive`

From 35705dee7eb10783280e0be92aedfc187e019dd2 Mon Sep 17 00:00:00 2001
From: bjorn3 <bjorn3@users.noreply.github.com>
Date: Fri, 29 Mar 2019 17:23:52 +0100
Subject: [PATCH 18/18] Use ExactSizeIterator + TrustedLen instead of num_cases
 arg for switch

---
 src/librustc_codegen_llvm/builder.rs       | 6 +++---
 src/librustc_codegen_llvm/lib.rs           | 1 +
 src/librustc_codegen_ssa/lib.rs            | 1 +
 src/librustc_codegen_ssa/mir/block.rs      | 1 -
 src/librustc_codegen_ssa/traits/builder.rs | 4 ++--
 5 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs
index fbeb978413a92..123fda1e215ff 100644
--- a/src/librustc_codegen_llvm/builder.rs
+++ b/src/librustc_codegen_llvm/builder.rs
@@ -21,6 +21,7 @@ use rustc_codegen_ssa::mir::place::PlaceRef;
 use std::borrow::Cow;
 use std::ops::{Deref, Range};
 use std::ptr;
+use std::iter::TrustedLen;
 
 // All Builders must have an llfn associated with them
 #[must_use]
@@ -169,11 +170,10 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         &mut self,
         v: &'ll Value,
         else_llbb: &'ll BasicBlock,
-        num_cases: usize,
-        cases: impl Iterator<Item = (u128, &'ll BasicBlock)>,
+        cases: impl ExactSizeIterator<Item = (u128, &'ll BasicBlock)> + TrustedLen,
     ) {
         let switch = unsafe {
-            llvm::LLVMBuildSwitch(self.llbuilder, v, else_llbb, num_cases as c_uint)
+            llvm::LLVMBuildSwitch(self.llbuilder, v, else_llbb, cases.len() as c_uint)
         };
         for (on_val, dest) in cases {
             let on_val = self.const_uint_big(self.val_ty(v), on_val);
diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs
index c95feafa29aba..0aae6b46e3def 100644
--- a/src/librustc_codegen_llvm/lib.rs
+++ b/src/librustc_codegen_llvm/lib.rs
@@ -20,6 +20,7 @@
 #![feature(concat_idents)]
 #![feature(link_args)]
 #![feature(static_nobundle)]
+#![feature(trusted_len)]
 #![deny(rust_2018_idioms)]
 #![allow(explicit_outlives_requirements)]
 
diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs
index fe9b88c85f009..1e898ced7a600 100644
--- a/src/librustc_codegen_ssa/lib.rs
+++ b/src/librustc_codegen_ssa/lib.rs
@@ -10,6 +10,7 @@
 #![feature(try_blocks)]
 #![feature(in_band_lifetimes)]
 #![feature(nll)]
+#![feature(trusted_len)]
 #![allow(unused_attributes)]
 #![allow(dead_code)]
 #![deny(rust_2018_idioms)]
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index 0ce97553bea77..98da07a905e25 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -217,7 +217,6 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             bx.switch(
                 discr.immediate(),
                 helper.llblock(self, *otherwise),
-                values.len(),
                 values.iter().zip(targets).map(|(&value, target)| {
                     (value, helper.llblock(self, *target))
                 })
diff --git a/src/librustc_codegen_ssa/traits/builder.rs b/src/librustc_codegen_ssa/traits/builder.rs
index 3b0f047d97414..48142fc9fa9f4 100644
--- a/src/librustc_codegen_ssa/traits/builder.rs
+++ b/src/librustc_codegen_ssa/traits/builder.rs
@@ -12,6 +12,7 @@ use crate::MemFlags;
 use rustc::ty::Ty;
 use rustc::ty::layout::{Align, Size};
 use std::ops::Range;
+use std::iter::TrustedLen;
 
 #[derive(Copy, Clone)]
 pub enum OverflowOp {
@@ -49,8 +50,7 @@ pub trait BuilderMethods<'a, 'tcx: 'a>:
         &mut self,
         v: Self::Value,
         else_llbb: Self::BasicBlock,
-        num_cases: usize,
-        cases: impl Iterator<Item = (u128, Self::BasicBlock)>,
+        cases: impl ExactSizeIterator<Item = (u128, Self::BasicBlock)> + TrustedLen,
     );
     fn invoke(
         &mut self,