Fix ICE by injecting bitcasts if types mismatch when building invokes or calls.
This commit is contained in:
parent
a29c49f5cc
commit
97e4143558
1 changed files with 31 additions and 16 deletions
|
@ -22,6 +22,7 @@ use value::Value;
|
||||||
use util::nodemap::FnvHashMap;
|
use util::nodemap::FnvHashMap;
|
||||||
use libc::{c_uint, c_char};
|
use libc::{c_uint, c_char};
|
||||||
|
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
|
@ -175,8 +176,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join(", "));
|
.join(", "));
|
||||||
|
|
||||||
check_call("invoke", llfn, args);
|
let args = self.check_call("invoke", llfn, args);
|
||||||
|
|
||||||
let bundle = bundle.as_ref().map(|b| b.raw()).unwrap_or(ptr::null_mut());
|
let bundle = bundle.as_ref().map(|b| b.raw()).unwrap_or(ptr::null_mut());
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -857,8 +857,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join(", "));
|
.join(", "));
|
||||||
|
|
||||||
check_call("call", llfn, args);
|
let args = self.check_call("call", llfn, args);
|
||||||
|
|
||||||
let bundle = bundle.as_ref().map(|b| b.raw()).unwrap_or(ptr::null_mut());
|
let bundle = bundle.as_ref().map(|b| b.raw()).unwrap_or(ptr::null_mut());
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -1100,10 +1099,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
llvm::LLVMRustBuildAtomicFence(self.llbuilder, order, scope);
|
llvm::LLVMRustBuildAtomicFence(self.llbuilder, order, scope);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn check_call(typ: &str, llfn: ValueRef, args: &[ValueRef]) {
|
fn check_call<'b>(&self,
|
||||||
if cfg!(debug_assertions) {
|
typ: &str,
|
||||||
|
llfn: ValueRef,
|
||||||
|
args: &'b [ValueRef]) -> Cow<'b, [ValueRef]> {
|
||||||
let mut fn_ty = val_ty(llfn);
|
let mut fn_ty = val_ty(llfn);
|
||||||
// Strip off pointers
|
// Strip off pointers
|
||||||
while fn_ty.kind() == llvm::TypeKind::Pointer {
|
while fn_ty.kind() == llvm::TypeKind::Pointer {
|
||||||
|
@ -1115,16 +1115,31 @@ fn check_call(typ: &str, llfn: ValueRef, args: &[ValueRef]) {
|
||||||
|
|
||||||
let param_tys = fn_ty.func_params();
|
let param_tys = fn_ty.func_params();
|
||||||
|
|
||||||
let iter = param_tys.into_iter()
|
let all_args_match = param_tys.iter()
|
||||||
.zip(args.iter().map(|&v| val_ty(v)));
|
.zip(args.iter().map(|&v| val_ty(v)))
|
||||||
for (i, (expected_ty, actual_ty)) in iter.enumerate() {
|
.all(|(expected_ty, actual_ty)| *expected_ty == actual_ty);
|
||||||
if expected_ty != actual_ty {
|
|
||||||
bug!("Type mismatch in function call of {:?}. \
|
|
||||||
Expected {:?} for param {}, got {:?}",
|
|
||||||
Value(llfn),
|
|
||||||
expected_ty, i, 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 = val_ty(actual_val);
|
||||||
|
if expected_ty != actual_ty {
|
||||||
|
debug!("Type mismatch in function call of {:?}. \
|
||||||
|
Expected {:?} for param {}, got {:?}; injecting bitcast",
|
||||||
|
Value(llfn),
|
||||||
|
expected_ty, i, actual_ty);
|
||||||
|
self.bitcast(actual_val, expected_ty)
|
||||||
|
} else {
|
||||||
|
actual_val
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
return Cow::Owned(casted_args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue