Skip to content

Commit 7a907b6

Browse files
committed
transpile: Cast to expected type in convert_builtin
1 parent 5e8aef2 commit 7a907b6

2 files changed

Lines changed: 45 additions & 42 deletions

File tree

c2rust-transpile/src/translator/builtins.rs

Lines changed: 44 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -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<()> {

c2rust-transpile/src/translator/functions.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ impl<'c> Translation<'c> {
397397

398398
// Builtin function call
399399
CExprKind::ImplicitCast(_, fexp, CastKind::BuiltinFnToFnPtr, _, _) => {
400-
return self.convert_builtin(ctx, call_expr_ty, fexp, args);
400+
return self.convert_builtin(ctx, override_ty, call_expr_ty, fexp, args);
401401
}
402402

403403
// Function pointer call

0 commit comments

Comments
 (0)