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 libc::{c_uint, c_char};
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::ffi::CString;
|
||||
use std::ptr;
|
||||
use syntax_pos::Span;
|
||||
|
@ -175,8 +176,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
.collect::<Vec<String>>()
|
||||
.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());
|
||||
|
||||
unsafe {
|
||||
|
@ -857,8 +857,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
.collect::<Vec<String>>()
|
||||
.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());
|
||||
|
||||
unsafe {
|
||||
|
@ -1100,10 +1099,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
llvm::LLVMRustBuildAtomicFence(self.llbuilder, order, scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_call(typ: &str, llfn: ValueRef, args: &[ValueRef]) {
|
||||
if cfg!(debug_assertions) {
|
||||
fn check_call<'b>(&self,
|
||||
typ: &str,
|
||||
llfn: ValueRef,
|
||||
args: &'b [ValueRef]) -> Cow<'b, [ValueRef]> {
|
||||
let mut fn_ty = val_ty(llfn);
|
||||
// Strip off pointers
|
||||
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 iter = param_tys.into_iter()
|
||||
.zip(args.iter().map(|&v| val_ty(v)));
|
||||
for (i, (expected_ty, actual_ty)) in iter.enumerate() {
|
||||
if expected_ty != actual_ty {
|
||||
bug!("Type mismatch in function call of {:?}. \
|
||||
Expected {:?} for param {}, got {:?}",
|
||||
Value(llfn),
|
||||
expected_ty, i, actual_ty);
|
||||
let all_args_match = param_tys.iter()
|
||||
.zip(args.iter().map(|&v| 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 = 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