@@ -22,6 +22,7 @@ use value::Value;
22
22
use util:: nodemap:: FnvHashMap ;
23
23
use libc:: { c_uint, c_char} ;
24
24
25
+ use std:: borrow:: Cow ;
25
26
use std:: ffi:: CString ;
26
27
use std:: ptr;
27
28
use syntax_pos:: Span ;
@@ -175,8 +176,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
175
176
. collect:: <Vec <String >>( )
176
177
. join( ", " ) ) ;
177
178
178
- check_call ( "invoke" , llfn, args) ;
179
-
179
+ let args = self . check_call ( "invoke" , llfn, args) ;
180
180
let bundle = bundle. as_ref ( ) . map ( |b| b. raw ( ) ) . unwrap_or ( ptr:: null_mut ( ) ) ;
181
181
182
182
unsafe {
@@ -543,6 +543,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
543
543
debug ! ( "Store {:?} -> {:?}" , Value ( val) , Value ( ptr) ) ;
544
544
assert ! ( !self . llbuilder. is_null( ) ) ;
545
545
self . count_insn ( "store" ) ;
546
+ let ptr = self . check_store ( val, ptr) ;
546
547
unsafe {
547
548
llvm:: LLVMBuildStore ( self . llbuilder , val, ptr)
548
549
}
@@ -552,6 +553,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
552
553
debug ! ( "Store {:?} -> {:?}" , Value ( val) , Value ( ptr) ) ;
553
554
assert ! ( !self . llbuilder. is_null( ) ) ;
554
555
self . count_insn ( "store.volatile" ) ;
556
+ let ptr = self . check_store ( val, ptr) ;
555
557
unsafe {
556
558
let insn = llvm:: LLVMBuildStore ( self . llbuilder , val, ptr) ;
557
559
llvm:: LLVMSetVolatile ( insn, llvm:: True ) ;
@@ -562,6 +564,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
562
564
pub fn atomic_store ( & self , val : ValueRef , ptr : ValueRef , order : AtomicOrdering ) {
563
565
debug ! ( "Store {:?} -> {:?}" , Value ( val) , Value ( ptr) ) ;
564
566
self . count_insn ( "store.atomic" ) ;
567
+ let ptr = self . check_store ( val, ptr) ;
565
568
unsafe {
566
569
let ty = Type :: from_ref ( llvm:: LLVMTypeOf ( ptr) ) ;
567
570
let align = llalign_of_pref ( self . ccx , ty. element_type ( ) ) ;
@@ -857,8 +860,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
857
860
. collect:: <Vec <String >>( )
858
861
. join( ", " ) ) ;
859
862
860
- check_call ( "call" , llfn, args) ;
861
-
863
+ let args = self . check_call ( "call" , llfn, args) ;
862
864
let bundle = bundle. as_ref ( ) . map ( |b| b. raw ( ) ) . unwrap_or ( ptr:: null_mut ( ) ) ;
863
865
864
866
unsafe {
@@ -1100,10 +1102,32 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1100
1102
llvm:: LLVMRustBuildAtomicFence ( self . llbuilder , order, scope) ;
1101
1103
}
1102
1104
}
1103
- }
1104
1105
1105
- fn check_call ( typ : & str , llfn : ValueRef , args : & [ ValueRef ] ) {
1106
- if cfg ! ( debug_assertions) {
1106
+ /// Returns the ptr value that should be used for storing `val`.
1107
+ fn check_store < ' b > ( & self ,
1108
+ val : ValueRef ,
1109
+ ptr : ValueRef ) -> ValueRef {
1110
+ let dest_ptr_ty = val_ty ( ptr) ;
1111
+ let stored_ty = val_ty ( val) ;
1112
+ let stored_ptr_ty = stored_ty. ptr_to ( ) ;
1113
+
1114
+ assert_eq ! ( dest_ptr_ty. kind( ) , llvm:: TypeKind :: Pointer ) ;
1115
+
1116
+ if dest_ptr_ty == stored_ptr_ty {
1117
+ ptr
1118
+ } else {
1119
+ debug ! ( "Type mismatch in store. \
1120
+ Expected {:?}, got {:?}; inserting bitcast",
1121
+ dest_ptr_ty, stored_ptr_ty) ;
1122
+ self . bitcast ( ptr, stored_ptr_ty)
1123
+ }
1124
+ }
1125
+
1126
+ /// Returns the args that should be used for a call to `llfn`.
1127
+ fn check_call < ' b > ( & self ,
1128
+ typ : & str ,
1129
+ llfn : ValueRef ,
1130
+ args : & ' b [ ValueRef ] ) -> Cow < ' b , [ ValueRef ] > {
1107
1131
let mut fn_ty = val_ty ( llfn) ;
1108
1132
// Strip off pointers
1109
1133
while fn_ty. kind ( ) == llvm:: TypeKind :: Pointer {
@@ -1115,16 +1139,31 @@ fn check_call(typ: &str, llfn: ValueRef, args: &[ValueRef]) {
1115
1139
1116
1140
let param_tys = fn_ty. func_params ( ) ;
1117
1141
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) ;
1142
+ let all_args_match = param_tys. iter ( )
1143
+ . zip ( args. iter ( ) . map ( |& v| val_ty ( v) ) )
1144
+ . all ( |( expected_ty, actual_ty) | * expected_ty == actual_ty) ;
1145
+
1146
+ if all_args_match {
1147
+ return Cow :: Borrowed ( args) ;
1148
+ }
1149
+
1150
+ let casted_args: Vec < _ > = param_tys. into_iter ( )
1151
+ . zip ( args. iter ( ) )
1152
+ . enumerate ( )
1153
+ . map ( |( i, ( expected_ty, & actual_val) ) | {
1154
+ let actual_ty = val_ty ( actual_val) ;
1155
+ if expected_ty != actual_ty {
1156
+ debug ! ( "Type mismatch in function call of {:?}. \
1157
+ Expected {:?} for param {}, got {:?}; injecting bitcast",
1158
+ Value ( llfn) ,
1159
+ expected_ty, i, actual_ty) ;
1160
+ self . bitcast ( actual_val, expected_ty)
1161
+ } else {
1162
+ actual_val
1163
+ }
1164
+ } )
1165
+ . collect ( ) ;
1126
1166
1127
- }
1128
- }
1167
+ return Cow :: Owned ( casted_args) ;
1129
1168
}
1130
1169
}
0 commit comments