about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFelix S. Klock II <pnkfelix@pnkfx.org>2016-10-12 19:26:06 +0200
committerBrian Anderson <banderson@mozilla.com>2016-10-18 22:51:02 +0000
commit45d365ae253c0b0cc3f88b8dce8722e9e7fb06c1 (patch)
tree7360d3b87719cfa104fc52fe867bd7e0fc384bef
parent3361f1335024816cf4418cbf93eb47a5c38d970d (diff)
downloadrust-45d365ae253c0b0cc3f88b8dce8722e9e7fb06c1.tar.gz
rust-45d365ae253c0b0cc3f88b8dce8722e9e7fb06c1.zip
Inject bitcast if types mismatch when building a store instruction.
-rw-r--r--src/librustc_trans/builder.rs24
1 files changed, 24 insertions, 0 deletions
diff --git a/src/librustc_trans/builder.rs b/src/librustc_trans/builder.rs
index 7e72b977de4..8556e95903c 100644
--- a/src/librustc_trans/builder.rs
+++ b/src/librustc_trans/builder.rs
@@ -543,6 +543,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         debug!("Store {:?} -> {:?}", Value(val), Value(ptr));
         assert!(!self.llbuilder.is_null());
         self.count_insn("store");
+        let ptr = self.check_store(val, ptr);
         unsafe {
             llvm::LLVMBuildStore(self.llbuilder, val, ptr)
         }
@@ -552,6 +553,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         debug!("Store {:?} -> {:?}", Value(val), Value(ptr));
         assert!(!self.llbuilder.is_null());
         self.count_insn("store.volatile");
+        let ptr = self.check_store(val, ptr);
         unsafe {
             let insn = llvm::LLVMBuildStore(self.llbuilder, val, ptr);
             llvm::LLVMSetVolatile(insn, llvm::True);
@@ -562,6 +564,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     pub fn atomic_store(&self, val: ValueRef, ptr: ValueRef, order: AtomicOrdering) {
         debug!("Store {:?} -> {:?}", Value(val), Value(ptr));
         self.count_insn("store.atomic");
+        let ptr = self.check_store(val, ptr);
         unsafe {
             let ty = Type::from_ref(llvm::LLVMTypeOf(ptr));
             let align = llalign_of_pref(self.ccx, ty.element_type());
@@ -1100,6 +1103,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         }
     }
 
+    /// Returns the ptr value that should be used for storing `val`.
+    fn check_store<'b>(&self,
+                       val: ValueRef,
+                       ptr: ValueRef) -> ValueRef {
+        let dest_ptr_ty = val_ty(ptr);
+        let stored_ty = val_ty(val);
+        let stored_ptr_ty = stored_ty.ptr_to();
+
+        assert_eq!(dest_ptr_ty.kind(), llvm::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)
+        }
+    }
+
+    /// Returns the args that should be used for a call to `llfn`.
     fn check_call<'b>(&self,
                       typ: &str,
                       llfn: ValueRef,