]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_codegen_llvm/base.rs
All CommonMethods now real methods (not static)
[rust.git] / src / librustc_codegen_llvm / base.rs
index 806025937cb110c75028094c56caee1e6fda7f1e..e13c488d2b74bb044272d5d4b23f64ad794e89f6 100644 (file)
@@ -39,7 +39,7 @@
 use rustc::mir::mono::{Linkage, Visibility, Stats, CodegenUnitNameBuilder};
 use rustc::middle::cstore::{EncodedMetadata};
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc::ty::layout::{self, Align, TyLayout, LayoutOf};
+use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx};
 use rustc::ty::query::Providers;
 use rustc::middle::cstore::{self, LinkagePreference};
 use rustc::middle::exported_symbols;
@@ -53,9 +53,8 @@
 use attributes;
 use builder::{Builder, MemFlags};
 use callee;
-use common::{C_bool, C_bytes_in_context, C_usize};
 use rustc_mir::monomorphize::item::DefPathBasedNames;
-use common::{C_struct_in_context, C_array, val_ty};
+use common::{IntPredicate, RealPredicate};
 use consts;
 use context::CodegenCx;
 use debuginfo;
@@ -73,6 +72,9 @@
 use CrateInfo;
 use rustc_data_structures::small_c_str::SmallCStr;
 use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::indexed_vec::Idx;
+
+use interfaces::{BuilderMethods, CommonMethods, CommonWriteMethods};
 
 use std::any::Any;
 use std::cmp;
@@ -123,14 +125,14 @@ fn drop(&mut self) {
 
 pub fn bin_op_to_icmp_predicate(op: hir::BinOpKind,
                                 signed: bool)
-                                -> llvm::IntPredicate {
+                                -> IntPredicate {
     match op {
-        hir::BinOpKind::Eq => llvm::IntEQ,
-        hir::BinOpKind::Ne => llvm::IntNE,
-        hir::BinOpKind::Lt => if signed { llvm::IntSLT } else { llvm::IntULT },
-        hir::BinOpKind::Le => if signed { llvm::IntSLE } else { llvm::IntULE },
-        hir::BinOpKind::Gt => if signed { llvm::IntSGT } else { llvm::IntUGT },
-        hir::BinOpKind::Ge => if signed { llvm::IntSGE } else { llvm::IntUGE },
+        hir::BinOpKind::Eq => IntPredicate::IntEQ,
+        hir::BinOpKind::Ne => IntPredicate::IntNE,
+        hir::BinOpKind::Lt => if signed { IntPredicate::IntSLT } else { IntPredicate::IntULT },
+        hir::BinOpKind::Le => if signed { IntPredicate::IntSLE } else { IntPredicate::IntULE },
+        hir::BinOpKind::Gt => if signed { IntPredicate::IntSGT } else { IntPredicate::IntUGT },
+        hir::BinOpKind::Ge => if signed { IntPredicate::IntSGE } else { IntPredicate::IntUGE },
         op => {
             bug!("comparison_op_to_icmp_predicate: expected comparison operator, \
                   found {:?}",
@@ -139,14 +141,14 @@ pub fn bin_op_to_icmp_predicate(op: hir::BinOpKind,
     }
 }
 
-pub fn bin_op_to_fcmp_predicate(op: hir::BinOpKind) -> llvm::RealPredicate {
+pub fn bin_op_to_fcmp_predicate(op: hir::BinOpKind) -> RealPredicate {
     match op {
-        hir::BinOpKind::Eq => llvm::RealOEQ,
-        hir::BinOpKind::Ne => llvm::RealUNE,
-        hir::BinOpKind::Lt => llvm::RealOLT,
-        hir::BinOpKind::Le => llvm::RealOLE,
-        hir::BinOpKind::Gt => llvm::RealOGT,
-        hir::BinOpKind::Ge => llvm::RealOGE,
+        hir::BinOpKind::Eq => RealPredicate::RealOEQ,
+        hir::BinOpKind::Ne => RealPredicate::RealUNE,
+        hir::BinOpKind::Lt => RealPredicate::RealOLT,
+        hir::BinOpKind::Le => RealPredicate::RealOLE,
+        hir::BinOpKind::Gt => RealPredicate::RealOGT,
+        hir::BinOpKind::Ge => RealPredicate::RealOGE,
         op => {
             bug!("comparison_op_to_fcmp_predicate: expected comparison operator, \
                   found {:?}",
@@ -196,7 +198,7 @@ pub fn unsized_info(
     let (source, target) = cx.tcx.struct_lockstep_tails(source, target);
     match (&source.sty, &target.sty) {
         (&ty::Array(_, len), &ty::Slice(_)) => {
-            C_usize(cx, len.unwrap_usize(cx.tcx))
+            CodegenCx::c_usize(cx, len.unwrap_usize(cx.tcx))
         }
         (&ty::Dynamic(..), &ty::Dynamic(..)) => {
             // For now, upcasts are limited to changes in marker
@@ -231,24 +233,24 @@ pub fn unsize_thin_ptr(
          &ty::RawPtr(ty::TypeAndMut { ty: b, .. })) |
         (&ty::RawPtr(ty::TypeAndMut { ty: a, .. }),
          &ty::RawPtr(ty::TypeAndMut { ty: b, .. })) => {
-            assert!(bx.cx.type_is_sized(a));
-            let ptr_ty = bx.cx.layout_of(b).llvm_type(bx.cx).ptr_to();
-            (bx.pointercast(src, ptr_ty), unsized_info(bx.cx, a, b, None))
+            assert!(bx.cx().type_is_sized(a));
+            let ptr_ty = bx.cx().layout_of(b).llvm_type(bx.cx()).ptr_to();
+            (bx.pointercast(src, ptr_ty), unsized_info(bx.cx(), a, b, None))
         }
         (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => {
             let (a, b) = (src_ty.boxed_ty(), dst_ty.boxed_ty());
-            assert!(bx.cx.type_is_sized(a));
-            let ptr_ty = bx.cx.layout_of(b).llvm_type(bx.cx).ptr_to();
-            (bx.pointercast(src, ptr_ty), unsized_info(bx.cx, a, b, None))
+            assert!(bx.cx().type_is_sized(a));
+            let ptr_ty = bx.cx().layout_of(b).llvm_type(bx.cx()).ptr_to();
+            (bx.pointercast(src, ptr_ty), unsized_info(bx.cx(), a, b, None))
         }
         (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
             assert_eq!(def_a, def_b);
 
-            let src_layout = bx.cx.layout_of(src_ty);
-            let dst_layout = bx.cx.layout_of(dst_ty);
+            let src_layout = bx.cx().layout_of(src_ty);
+            let dst_layout = bx.cx().layout_of(dst_ty);
             let mut result = None;
             for i in 0..src_layout.fields.count() {
-                let src_f = src_layout.field(bx.cx, i);
+                let src_f = src_layout.field(bx.cx(), i);
                 assert_eq!(src_layout.fields.offset(i).bytes(), 0);
                 assert_eq!(dst_layout.fields.offset(i).bytes(), 0);
                 if src_f.is_zst() {
@@ -256,15 +258,15 @@ pub fn unsize_thin_ptr(
                 }
                 assert_eq!(src_layout.size, src_f.size);
 
-                let dst_f = dst_layout.field(bx.cx, i);
+                let dst_f = dst_layout.field(bx.cx(), i);
                 assert_ne!(src_f.ty, dst_f.ty);
                 assert_eq!(result, None);
                 result = Some(unsize_thin_ptr(bx, src, src_f.ty, dst_f.ty));
             }
             let (lldata, llextra) = result.unwrap();
             // HACK(eddyb) have to bitcast pointers until LLVM removes pointee types.
-            (bx.bitcast(lldata, dst_layout.scalar_pair_element_llvm_type(bx.cx, 0, true)),
-             bx.bitcast(llextra, dst_layout.scalar_pair_element_llvm_type(bx.cx, 1, true)))
+            (bx.bitcast(lldata, dst_layout.scalar_pair_element_llvm_type(bx.cx(), 0, true)),
+             bx.bitcast(llextra, dst_layout.scalar_pair_element_llvm_type(bx.cx(), 1, true)))
         }
         _ => bug!("unsize_thin_ptr: called on bad types"),
     }
@@ -274,8 +276,8 @@ pub fn unsize_thin_ptr(
 /// to a value of type `dst_ty` and store the result in `dst`
 pub fn coerce_unsized_into(
     bx: &Builder<'a, 'll, 'tcx>,
-    src: PlaceRef<'ll, 'tcx>,
-    dst: PlaceRef<'ll, 'tcx>
+    src: PlaceRef<'tcx, &'ll Value>,
+    dst: PlaceRef<'tcx, &'ll Value>
 ) {
     let src_ty = src.layout.ty;
     let dst_ty = dst.layout.ty;
@@ -286,8 +288,8 @@ pub fn coerce_unsized_into(
                 // i.e. &'a fmt::Debug+Send => &'a fmt::Debug
                 // So we need to pointercast the base to ensure
                 // the types match up.
-                let thin_ptr = dst.layout.field(bx.cx, abi::FAT_PTR_ADDR);
-                (bx.pointercast(base, thin_ptr.llvm_type(bx.cx)), info)
+                let thin_ptr = dst.layout.field(bx.cx(), abi::FAT_PTR_ADDR);
+                (bx.pointercast(base, thin_ptr.llvm_type(bx.cx())), info)
             }
             OperandValue::Immediate(base) => {
                 unsize_thin_ptr(bx, base, src_ty, dst_ty)
@@ -309,7 +311,7 @@ pub fn coerce_unsized_into(
         (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
             assert_eq!(def_a, def_b);
 
-            for i in 0..def_a.variants[0].fields.len() {
+            for i in 0..def_a.variants[VariantIdx::new(0)].fields.len() {
                 let src_f = src.project_field(bx, i);
                 let dst_f = dst.project_field(bx, i);
 
@@ -332,12 +334,13 @@ pub fn coerce_unsized_into(
 }
 
 pub fn cast_shift_expr_rhs(
-    cx: &Builder<'_, 'll, '_>, op: hir::BinOpKind, lhs: &'ll Value, rhs: &'ll Value
+    bx: &Builder<'_, 'll, '_>, op: hir::BinOpKind, lhs: &'ll Value, rhs: &'ll Value
 ) -> &'ll Value {
-    cast_shift_rhs(op, lhs, rhs, |a, b| cx.trunc(a, b), |a, b| cx.zext(a, b))
+    cast_shift_rhs(bx, op, lhs, rhs, |a, b| bx.trunc(a, b), |a, b| bx.zext(a, b))
 }
 
-fn cast_shift_rhs<'ll, F, G>(op: hir::BinOpKind,
+fn cast_shift_rhs<'ll, F, G>(bx: &Builder<'_, 'll, '_>,
+                             op: hir::BinOpKind,
                              lhs: &'ll Value,
                              rhs: &'ll Value,
                              trunc: F,
@@ -348,8 +351,8 @@ fn cast_shift_rhs<'ll, F, G>(op: hir::BinOpKind,
 {
     // Shifts may have any size int on the rhs
     if op.is_shift() {
-        let mut rhs_llty = val_ty(rhs);
-        let mut lhs_llty = val_ty(lhs);
+        let mut rhs_llty = bx.cx().val_ty(rhs);
+        let mut lhs_llty = bx.cx().val_ty(lhs);
         if rhs_llty.kind() == TypeKind::Vector {
             rhs_llty = rhs_llty.element_type()
         }
@@ -382,13 +385,16 @@ pub fn wants_msvc_seh(sess: &Session) -> bool {
 }
 
 pub fn call_assume(bx: &Builder<'_, 'll, '_>, val: &'ll Value) {
-    let assume_intrinsic = bx.cx.get_intrinsic("llvm.assume");
+    let assume_intrinsic = bx.cx().get_intrinsic("llvm.assume");
     bx.call(assume_intrinsic, &[val], None);
 }
 
-pub fn from_immediate(bx: &Builder<'_, 'll, '_>, val: &'ll Value) -> &'ll Value {
-    if val_ty(val) == Type::i1(bx.cx) {
-        bx.zext(val, Type::i8(bx.cx))
+pub fn from_immediate<'a, 'll: 'a, 'tcx: 'll>(
+    bx: &Builder<'_ ,'ll, '_, &'ll Value>,
+    val: &'ll Value
+) -> &'ll Value {
+    if bx.cx().val_ty(val) == Type::i1(bx.cx()) {
+        bx.zext(val, Type::i8(bx.cx()))
     } else {
         val
     }
@@ -411,13 +417,13 @@ pub fn to_immediate_scalar(
     scalar: &layout::Scalar,
 ) -> &'ll Value {
     if scalar.is_bool() {
-        return bx.trunc(val, Type::i1(bx.cx));
+        return bx.trunc(val, Type::i1(bx.cx()));
     }
     val
 }
 
-pub fn call_memcpy(
-    bx: &Builder<'_, 'll, '_>,
+pub fn call_memcpy<'a, 'll: 'a, 'tcx: 'll>(
+    bx: &Builder<'_ ,'ll, '_, &'ll Value>,
     dst: &'ll Value,
     dst_align: Align,
     src: &'ll Value,
@@ -428,11 +434,11 @@ pub fn call_memcpy(
     if flags.contains(MemFlags::NONTEMPORAL) {
         // HACK(nox): This is inefficient but there is no nontemporal memcpy.
         let val = bx.load(src, src_align);
-        let ptr = bx.pointercast(dst, val_ty(val).ptr_to());
+        let ptr = bx.pointercast(dst, bx.cx().val_ty(val).ptr_to());
         bx.store_with_flags(val, ptr, dst_align, flags);
         return;
     }
-    let cx = bx.cx;
+    let cx = bx.cx();
     let src_ptr = bx.pointercast(src, Type::i8p(cx));
     let dst_ptr = bx.pointercast(dst, Type::i8p(cx));
     let size = bx.intcast(n_bytes, cx.isize_ty, false);
@@ -440,8 +446,8 @@ pub fn call_memcpy(
     bx.memcpy(dst_ptr, dst_align.abi(), src_ptr, src_align.abi(), size, volatile);
 }
 
-pub fn memcpy_ty(
-    bx: &Builder<'_, 'll, 'tcx>,
+pub fn memcpy_ty<'a, 'll: 'a, 'tcx: 'll>(
+    bx: &Builder<'_ ,'ll, '_, &'ll Value>,
     dst: &'ll Value,
     dst_align: Align,
     src: &'ll Value,
@@ -454,7 +460,7 @@ pub fn memcpy_ty(
         return;
     }
 
-    call_memcpy(bx, dst, dst_align, src, src_align, C_usize(bx.cx, size), flags);
+    call_memcpy(bx, dst, dst_align, src, src_align, CodegenCx::c_usize(bx.cx(), size), flags);
 }
 
 pub fn call_memset(
@@ -465,10 +471,10 @@ pub fn call_memset(
     align: &'ll Value,
     volatile: bool,
 ) -> &'ll Value {
-    let ptr_width = &bx.cx.sess().target.target.target_pointer_width;
+    let ptr_width = &bx.cx().sess().target.target.target_pointer_width;
     let intrinsic_key = format!("llvm.memset.p0i8.i{}", ptr_width);
-    let llintrinsicfn = bx.cx.get_intrinsic(&intrinsic_key);
-    let volatile = C_bool(bx.cx, volatile);
+    let llintrinsicfn = bx.cx().get_intrinsic(&intrinsic_key);
+    let volatile = CodegenCx::c_bool(bx.cx(), volatile);
     bx.call(llintrinsicfn, &[ptr, fill_byte, size, align, volatile], None)
 }
 
@@ -544,7 +550,8 @@ fn create_entry_fn(
         rust_main_def_id: DefId,
         use_start_lang_item: bool,
     ) {
-        let llfty = Type::func(&[Type::c_int(cx), Type::i8p(cx).ptr_to()], Type::c_int(cx));
+        let llfty =
+            Type::func(&[Type::c_int(cx), Type::i8p(cx).ptr_to()], Type::c_int(cx));
 
         let main_ret_ty = cx.tcx.fn_sig(rust_main_def_id).output();
         // Given that `main()` has no arguments,
@@ -642,12 +649,12 @@ enum MetadataKind {
     DeflateEncoder::new(&mut compressed, Compression::fast())
         .write_all(&metadata.raw_data).unwrap();
 
-    let llmeta = C_bytes_in_context(metadata_llcx, &compressed);
-    let llconst = C_struct_in_context(metadata_llcx, &[llmeta], false);
+    let llmeta = llvm_module.c_bytes_in_context(metadata_llcx, &compressed);
+    let llconst = llvm_module.c_struct_in_context(metadata_llcx, &[llmeta], false);
     let name = exported_symbols::metadata_symbol_name(tcx);
     let buf = CString::new(name).unwrap();
     let llglobal = unsafe {
-        llvm::LLVMAddGlobal(metadata_llmod, val_ty(llconst), buf.as_ptr())
+        llvm::LLVMAddGlobal(metadata_llmod, llvm_module.val_ty(llconst), buf.as_ptr())
     };
     unsafe {
         llvm::LLVMSetInitializer(llglobal, llconst);
@@ -941,7 +948,7 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 ///
 /// In the process of working on rust-lang/rust#55238 a mysterious segfault was
 /// stumbled upon. The segfault was never reproduced locally, but it was
-/// suspected to be releated to the fact that codegen worker threads were
+/// suspected to be related to the fact that codegen worker threads were
 /// sticking around by the time the main thread was exiting, causing issues.
 ///
 /// This structure is an attempt to fix that issue where the `codegen_aborted`
@@ -1133,7 +1140,7 @@ fn module_codegen<'a, 'tcx>(
             // Run replace-all-uses-with for statics that need it
             for &(old_g, new_g) in cx.statics_to_rauw.borrow().iter() {
                 unsafe {
-                    let bitcast = llvm::LLVMConstPointerCast(new_g, val_ty(old_g));
+                    let bitcast = llvm::LLVMConstPointerCast(new_g, cx.val_ty(old_g));
                     llvm::LLVMReplaceAllUsesWith(old_g, bitcast);
                     llvm::LLVMDeleteGlobal(old_g);
                 }
@@ -1144,11 +1151,11 @@ fn module_codegen<'a, 'tcx>(
             if !cx.used_statics.borrow().is_empty() {
                 let name = const_cstr!("llvm.used");
                 let section = const_cstr!("llvm.metadata");
-                let array = C_array(Type::i8(&cx).ptr_to(), &*cx.used_statics.borrow());
+                let array = cx.c_array(Type::i8(&cx).ptr_to(), &*cx.used_statics.borrow());
 
                 unsafe {
                     let g = llvm::LLVMAddGlobal(cx.llmod,
-                                                val_ty(array),
+                                                cx.val_ty(array),
                                                 name.as_ptr());
                     llvm::LLVMSetInitializer(g, array);
                     llvm::LLVMRustSetLinkage(g, llvm::Linkage::AppendingLinkage);