Skip to content

Commit 2fbf70b

Browse files
pnkfelixbrson
authored andcommitted
Fix ICE by injecting bitcasts if types mismatch when building invokes or calls.
1 parent 6d9b0bf commit 2fbf70b

File tree

1 file changed

+32
-17
lines changed

1 file changed

+32
-17
lines changed

src/librustc_trans/builder.rs

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use value::Value;
2222
use util::nodemap::FnvHashMap;
2323
use libc::{c_uint, c_char};
2424

25+
use std::borrow::Cow;
2526
use std::ffi::CString;
2627
use std::ptr;
2728
use syntax_pos::Span;
@@ -175,8 +176,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
175176
.collect::<Vec<String>>()
176177
.join(", "));
177178

178-
check_call("invoke", llfn, args);
179-
179+
let args = self.check_call("invoke", llfn, args);
180180
let bundle = bundle.as_ref().map(|b| b.raw()).unwrap_or(ptr::null_mut());
181181

182182
unsafe {
@@ -857,8 +857,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
857857
.collect::<Vec<String>>()
858858
.join(", "));
859859

860-
check_call("call", llfn, args);
861-
860+
let args = self.check_call("call", llfn, args);
862861
let bundle = bundle.as_ref().map(|b| b.raw()).unwrap_or(ptr::null_mut());
863862

864863
unsafe {
@@ -1100,10 +1099,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
11001099
llvm::LLVMRustBuildAtomicFence(self.llbuilder, order, scope);
11011100
}
11021101
}
1103-
}
11041102

1105-
fn check_call(typ: &str, llfn: ValueRef, args: &[ValueRef]) {
1106-
if cfg!(debug_assertions) {
1103+
fn check_call<'b>(&self,
1104+
typ: &str,
1105+
llfn: ValueRef,
1106+
args: &'b [ValueRef]) -> Cow<'b, [ValueRef]> {
11071107
let mut fn_ty = val_ty(llfn);
11081108
// Strip off pointers
11091109
while fn_ty.kind() == llvm::TypeKind::Pointer {
@@ -1115,16 +1115,31 @@ fn check_call(typ: &str, llfn: ValueRef, args: &[ValueRef]) {
11151115

11161116
let param_tys = fn_ty.func_params();
11171117

1118-
let iter = param_tys.into_iter()
1119-
.zip(args.iter().map(|&v| val_ty(v)));
1120-
for (i, (expected_ty, actual_ty)) in iter.enumerate() {
1121-
if expected_ty != actual_ty {
1122-
bug!("Type mismatch in function call of {:?}. \
1123-
Expected {:?} for param {}, got {:?}",
1124-
Value(llfn),
1125-
expected_ty, i, actual_ty);
1118+
let all_args_match = param_tys.iter()
1119+
.zip(args.iter().map(|&v| val_ty(v)))
1120+
.all(|(expected_ty, actual_ty)| *expected_ty == actual_ty);
1121+
1122+
if all_args_match {
1123+
return Cow::Borrowed(args);
1124+
}
1125+
1126+
let casted_args: Vec<_> = param_tys.into_iter()
1127+
.zip(args.iter())
1128+
.enumerate()
1129+
.map(|(i, (expected_ty, &actual_val))| {
1130+
let actual_ty = val_ty(actual_val);
1131+
if expected_ty != actual_ty {
1132+
debug!("Type mismatch in function call of {:?}. \
1133+
Expected {:?} for param {}, got {:?}; injecting bitcast",
1134+
Value(llfn),
1135+
expected_ty, i, actual_ty);
1136+
self.bitcast(actual_val, expected_ty)
1137+
} else {
1138+
actual_val
1139+
}
1140+
})
1141+
.collect();
11261142

1127-
}
1128-
}
1143+
return Cow::Owned(casted_args);
11291144
}
11301145
}

0 commit comments

Comments
 (0)