diff options
| author | Felix S. Klock II <pnkfelix@pnkfx.org> | 2016-10-12 19:26:06 +0200 |
|---|---|---|
| committer | Brian Anderson <banderson@mozilla.com> | 2016-10-18 22:51:02 +0000 |
| commit | 45d365ae253c0b0cc3f88b8dce8722e9e7fb06c1 (patch) | |
| tree | 7360d3b87719cfa104fc52fe867bd7e0fc384bef | |
| parent | 3361f1335024816cf4418cbf93eb47a5c38d970d (diff) | |
| download | rust-45d365ae253c0b0cc3f88b8dce8722e9e7fb06c1.tar.gz rust-45d365ae253c0b0cc3f88b8dce8722e9e7fb06c1.zip | |
Inject bitcast if types mismatch when building a store instruction.
| -rw-r--r-- | src/librustc_trans/builder.rs | 24 |
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, |
