Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix ICE by injecting bitcasts if types mismatch when building invokes…
… or calls.
  • Loading branch information
pnkfelix committed Oct 12, 2016
1 parent a29c49f commit 97e4143
Showing 1 changed file with 32 additions and 17 deletions.
49 changes: 32 additions & 17 deletions src/librustc_trans/builder.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand All @@ -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);
}
}

0 comments on commit 97e4143

Please sign in to comment.