@@ -49,6 +49,7 @@ impl<'c> Translation<'c> {
4949 pub fn convert_builtin (
5050 & self ,
5151 ctx : ExprContext ,
52+ expected_type_id : Option < CQualTypeId > ,
5253 result_type_id : CQualTypeId ,
5354 fexp : CExprId ,
5455 args : & [ CExprId ] ,
@@ -73,6 +74,8 @@ impl<'c> Translation<'c> {
7374 }
7475 } ;
7576
77+ let mut source_type_id = result_type_id;
78+ let target_type_id = expected_type_id. unwrap_or ( result_type_id) ;
7679 let val = match builtin_name {
7780 "__builtin_huge_valf" => {
7881 WithStmts :: new_val ( mk ( ) . abs_path_expr ( vec ! [ "core" , "f32" , "INFINITY" ] ) )
@@ -105,17 +108,14 @@ impl<'c> Translation<'c> {
105108 }
106109 "__builtin_signbit" | "__builtin_signbitf" | "__builtin_signbitl" => {
107110 let val = self . convert_expr ( ctx. used ( ) , args[ 0 ] , None ) ?;
108- let result_type_rs = self . convert_type ( result_type_id . ctype ) ? ;
111+ source_type_id . ctype = self . ast_context . type_for_kind ( & CTypeKind :: Bool ) . unwrap ( ) ;
109112 self . import_num_traits ( args[ 0 ] ) ?;
110113
111- val. map ( |v| {
112- let val = mk ( ) . method_call_expr ( v, "is_sign_negative" , vec ! [ ] ) ;
113- mk ( ) . cast_expr ( val, result_type_rs)
114- } )
114+ val. map ( |v| mk ( ) . method_call_expr ( v, "is_sign_negative" , vec ! [ ] ) )
115115 }
116116 "__builtin_ffs" | "__builtin_ffsl" | "__builtin_ffsll" => {
117117 let val = self . convert_expr ( ctx. used ( ) , args[ 0 ] , None ) ?;
118- let result_type_rs = self . convert_type ( result_type_id . ctype ) ? ;
118+ source_type_id . ctype = self . ast_context . type_for_kind ( & CTypeKind :: UInt32 ) . unwrap ( ) ;
119119
120120 let zero = mk ( ) . lit_expr ( mk ( ) . int_unsuffixed_lit ( 0 ) ) ;
121121 let one = mk ( ) . lit_expr ( mk ( ) . int_unsuffixed_lit ( 1 ) ) ;
@@ -125,10 +125,7 @@ impl<'c> Translation<'c> {
125125 mk ( ) . binary_expr ( BinOp :: Eq ( Default :: default ( ) ) , val. clone ( ) , zero. clone ( ) ) ;
126126 let zeros_plus1 = mk ( ) . binary_expr (
127127 BinOp :: Add ( Default :: default ( ) ) ,
128- mk ( ) . cast_expr (
129- mk ( ) . method_call_expr ( val, "trailing_zeros" , vec ! [ ] ) ,
130- result_type_rs,
131- ) ,
128+ mk ( ) . method_call_expr ( val, "trailing_zeros" , vec ! [ ] ) ,
132129 one,
133130 ) ;
134131
@@ -141,21 +138,15 @@ impl<'c> Translation<'c> {
141138 }
142139 "__builtin_clz" | "__builtin_clzl" | "__builtin_clzll" => {
143140 let val = self . convert_expr ( ctx. used ( ) , args[ 0 ] , None ) ?;
144- let result_type_rs = self . convert_type ( result_type_id . ctype ) ? ;
141+ source_type_id . ctype = self . ast_context . type_for_kind ( & CTypeKind :: UInt32 ) . unwrap ( ) ;
145142
146- val. map ( |x| {
147- let zeros = mk ( ) . method_call_expr ( x, "leading_zeros" , vec ! [ ] ) ;
148- mk ( ) . cast_expr ( zeros, result_type_rs)
149- } )
143+ val. map ( |x| mk ( ) . method_call_expr ( x, "leading_zeros" , vec ! [ ] ) )
150144 }
151145 "__builtin_ctz" | "__builtin_ctzl" | "__builtin_ctzll" => {
152146 let val = self . convert_expr ( ctx. used ( ) , args[ 0 ] , None ) ?;
153- let result_type_rs = self . convert_type ( result_type_id . ctype ) ? ;
147+ source_type_id . ctype = self . ast_context . type_for_kind ( & CTypeKind :: UInt32 ) . unwrap ( ) ;
154148
155- val. map ( |x| {
156- let zeros = mk ( ) . method_call_expr ( x, "trailing_zeros" , vec ! [ ] ) ;
157- mk ( ) . cast_expr ( zeros, result_type_rs)
158- } )
149+ val. map ( |x| mk ( ) . method_call_expr ( x, "trailing_zeros" , vec ! [ ] ) )
159150 }
160151 "__builtin_bswap16" | "__builtin_bswap32" | "__builtin_bswap64" => {
161152 let val = self . convert_expr ( ctx. used ( ) , args[ 0 ] , None ) ?;
@@ -175,19 +166,17 @@ impl<'c> Translation<'c> {
175166 "__builtin_isnan" => "is_nan" ,
176167 _ => panic ! ( ) ,
177168 } ;
178- let result_type_rs = self . convert_type ( result_type_id . ctype ) ? ;
169+ source_type_id . ctype = self . ast_context . type_for_kind ( & CTypeKind :: Bool ) . unwrap ( ) ;
179170
180- val. map ( |x| {
181- let call = mk ( ) . method_call_expr ( x, seg, vec ! [ ] ) ;
182- mk ( ) . cast_expr ( call, result_type_rs)
183- } )
171+ val. map ( |x| mk ( ) . method_call_expr ( x, seg, vec ! [ ] ) )
184172 }
185173 "__builtin_isinf_sign" => {
186174 let val = self . convert_expr ( ctx. used ( ) , args[ 0 ] , None ) ?;
187175
188- let zero = self . mk_int_lit ( result_type_id, 0 , IntBase :: Dec , false ) ?;
189- let one = self . mk_int_lit ( result_type_id, 1 , IntBase :: Dec , false ) ?;
190- let minus_one = self . mk_int_lit ( result_type_id, 1 , IntBase :: Dec , true ) ?;
176+ source_type_id = target_type_id;
177+ let zero = self . mk_int_lit ( target_type_id, 0 , IntBase :: Dec , false ) ?;
178+ let one = self . mk_int_lit ( target_type_id, 1 , IntBase :: Dec , false ) ?;
179+ let minus_one = self . mk_int_lit ( target_type_id, 1 , IntBase :: Dec , true ) ?;
191180 self . import_num_traits ( args[ 0 ] ) ?;
192181
193182 val. map ( |val| {
@@ -211,18 +200,16 @@ impl<'c> Translation<'c> {
211200 // LLVM simply lowers this to the constant one which means
212201 // that floats are rounded to the nearest number.
213202 // https://github.com/llvm-mirror/llvm/blob/master/lib/CodeGen/IntrinsicLowering.cpp#L470
214- WithStmts :: new_val ( self . mk_int_lit ( result_type_id, 1 , IntBase :: Dec , false ) ?)
203+ source_type_id = target_type_id;
204+ WithStmts :: new_val ( self . mk_int_lit ( target_type_id, 1 , IntBase :: Dec , false ) ?)
215205 }
216206 "__builtin_expect" => self . convert_expr ( ctx. used ( ) , args[ 0 ] , None ) ?,
217207
218208 "__builtin_popcount" | "__builtin_popcountl" | "__builtin_popcountll" => {
219209 let val = self . convert_expr ( ctx. used ( ) , args[ 0 ] , None ) ?;
220- let result_type_rs = self . convert_type ( result_type_id . ctype ) ? ;
210+ source_type_id . ctype = self . ast_context . type_for_kind ( & CTypeKind :: UInt32 ) . unwrap ( ) ;
221211
222- val. map ( |x| {
223- let zeros = mk ( ) . method_call_expr ( x, "count_ones" , vec ! [ ] ) ;
224- mk ( ) . cast_expr ( zeros, result_type_rs)
225- } )
212+ val. map ( |x| mk ( ) . method_call_expr ( x, "count_ones" , vec ! [ ] ) )
226213 }
227214 "__builtin_bzero" => {
228215 let ptr_stmts = self . convert_expr ( ctx. used ( ) , args[ 0 ] , None ) ?;
@@ -310,7 +297,8 @@ impl<'c> Translation<'c> {
310297 // value is *not* a constant, but merely that GCC cannot prove it is a constant with
311298 // the specified value of the -O option. "
312299 "__builtin_constant_p" => {
313- WithStmts :: new_val ( self . mk_int_lit ( result_type_id, 0 , IntBase :: Dec , false ) ?)
300+ source_type_id = target_type_id;
301+ WithStmts :: new_val ( self . mk_int_lit ( target_type_id, 0 , IntBase :: Dec , false ) ?)
314302 }
315303
316304 "__builtin_object_size" => {
@@ -320,8 +308,9 @@ impl<'c> Translation<'c> {
320308 let ptr_arg = self . convert_expr ( ctx. unused ( ) , args[ 0 ] , None ) ?;
321309 let type_arg = self . convert_expr ( ctx. used ( ) , args[ 1 ] , None ) ?;
322310
323- let zero = self . mk_int_lit ( result_type_id, 0 , IntBase :: Dec , false ) ?;
324- let minus_one = self . mk_int_lit ( result_type_id, 1 , IntBase :: Dec , true ) ?;
311+ source_type_id = target_type_id;
312+ let zero = self . mk_int_lit ( target_type_id, 0 , IntBase :: Dec , false ) ?;
313+ let minus_one = self . mk_int_lit ( target_type_id, 1 , IntBase :: Dec , true ) ?;
325314
326315 ptr_arg. zip ( type_arg) . map ( |( _ptr_arg, type_arg) | {
327316 let type_and_2 = mk ( ) . binary_expr (
@@ -402,16 +391,30 @@ impl<'c> Translation<'c> {
402391 } ;
403392
404393 // c2rust_alloca_allocations.last_mut().unwrap().as_mut_ptr() as *mut ::core::ffi::c_void
405- let expr = mk ( ) . method_chain_expr (
394+ let mut expr = mk ( ) . method_chain_expr (
406395 alloca_allocations_ident. clone ( ) ,
407396 vec ! [
408397 ( mk( ) . path_segment( "last_mut" ) , vec![ ] ) ,
409398 ( mk( ) . path_segment( "unwrap" ) , vec![ ] ) ,
410399 ( mk( ) . path_segment( "as_mut_ptr" ) , vec![ ] ) ,
411400 ] ,
412401 ) ;
413- let result_type_rs = self . convert_type ( result_type_id. ctype ) ?;
414- let expr = mk ( ) . cast_expr ( expr, result_type_rs) ;
402+
403+ source_type_id = target_type_id;
404+ let target_type_kind = & self . ast_context . resolve_type ( target_type_id. ctype ) . kind ;
405+ let needs_cast = match target_type_kind {
406+ & CTypeKind :: Pointer ( pointee_type_id) => {
407+ let pointee_type_kind =
408+ & self . ast_context . resolve_type ( pointee_type_id. ctype ) . kind ;
409+ !matches ! ( pointee_type_kind, CTypeKind :: UInt8 )
410+ }
411+ _ => true ,
412+ } ;
413+
414+ if needs_cast {
415+ let target_type_rs = self . convert_type ( target_type_id. ctype ) ?;
416+ expr = mk ( ) . cast_expr ( expr, target_type_rs) ;
417+ }
415418
416419 count. and_then ( |count| {
417420 // c2rust_alloca_allocations.push(std::vec::from_elem(0, count));
@@ -628,7 +631,7 @@ impl<'c> Translation<'c> {
628631 }
629632 } ;
630633
631- Ok ( val)
634+ self . convert_cast ( ctx , source_type_id , target_type_id , val, None , None , None )
632635 }
633636
634637 fn import_num_traits ( & self , arg_id : CExprId ) -> TranslationResult < ( ) > {
0 commit comments