Skip to content

Commit d63535c

Browse files
authored
transpile: Avoid some identity transmutes for function pointers (#1510)
I noticed that in some cases, a transmute would be added between a K&R style function declaration using `()` as the parameters, and a full type with `(void)` as the parameters. Since both of those are translated to the same Rust type, you'd end up with pointless transmute. This PR gates the transmute to only happen if the two Rust types actually differ.
2 parents 0933ed7 + 3dd70a8 commit d63535c

File tree

2 files changed

+36
-22
lines changed

2 files changed

+36
-22
lines changed

c2rust-transpile/src/translator/mod.rs

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3495,12 +3495,14 @@ impl<'c> Translation<'c> {
34953495
parameters,
34963496
)?;
34973497
if let Some(actual_ty) = actual_ty {
3498-
// If we're casting a concrete function to
3499-
// a K&R function pointer type, use transmute
3500-
self.import_type(qual_ty.ctype);
3498+
if actual_ty != ty {
3499+
// If we're casting a concrete function to
3500+
// a K&R function pointer type, use transmute
3501+
self.import_type(qual_ty.ctype);
35013502

3502-
val = transmute_expr(actual_ty, ty, val);
3503-
set_unsafe = true;
3503+
val = transmute_expr(actual_ty, ty, val);
3504+
set_unsafe = true;
3505+
}
35043506
} else {
35053507
let decl_kind = &self.ast_context[decl_id].kind;
35063508
let kind_with_declared_args =
@@ -4406,21 +4408,35 @@ impl<'c> Translation<'c> {
44064408

44074409
match kind {
44084410
CastKind::BitCast | CastKind::NoOp => {
4409-
val.and_then(|x| {
4410-
if self.ast_context.is_function_pointer(target_cty.ctype)
4411-
|| self.ast_context.is_function_pointer(source_cty.ctype)
4412-
{
4413-
let source_ty = self.convert_type(source_cty.ctype)?;
4414-
let target_ty = self.convert_type(target_cty.ctype)?;
4411+
if self.ast_context.is_function_pointer(target_cty.ctype)
4412+
|| self.ast_context.is_function_pointer(source_cty.ctype)
4413+
{
4414+
let source_ty = self
4415+
.type_converter
4416+
.borrow_mut()
4417+
.convert(&self.ast_context, source_cty.ctype)?;
4418+
let target_ty = self
4419+
.type_converter
4420+
.borrow_mut()
4421+
.convert(&self.ast_context, target_cty.ctype)?;
4422+
4423+
if source_ty == target_ty {
4424+
return Ok(val);
4425+
}
4426+
4427+
self.import_type(source_cty.ctype);
4428+
self.import_type(target_cty.ctype);
4429+
4430+
val.and_then(|val| {
44154431
Ok(WithStmts::new_unsafe_val(transmute_expr(
4416-
source_ty, target_ty, x,
4432+
source_ty, target_ty, val,
44174433
)))
4418-
} else {
4419-
// Normal case
4420-
let target_ty = self.convert_type(target_cty.ctype)?;
4421-
Ok(WithStmts::new_val(mk().cast_expr(x, target_ty)))
4422-
}
4423-
})
4434+
})
4435+
} else {
4436+
// Normal case
4437+
let target_ty = self.convert_type(target_cty.ctype)?;
4438+
Ok(val.map(|val| mk().cast_expr(val, target_ty)))
4439+
}
44244440
}
44254441

44264442
CastKind::IntegralToPointer

c2rust-transpile/tests/snapshots/snapshots__transpile@exprs.c.snap

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,8 @@ pub unsafe extern "C" fn unary_with_side_effect() {
4444
side_effect();
4545
!side_effect();
4646
(side_effect() == 0) as ::core::ffi::c_int;
47-
(b"\0" as *const u8 as *const ::core::ffi::c_char).offset(::core::mem::transmute::<
48-
unsafe extern "C" fn() -> ::core::ffi::c_int,
49-
unsafe extern "C" fn() -> ::core::ffi::c_int,
50-
>(side_effect)() as isize) as *const ::core::ffi::c_char;
47+
(b"\0" as *const u8 as *const ::core::ffi::c_char).offset(side_effect() as isize)
48+
as *const ::core::ffi::c_char;
5149
*arr[side_effect() as usize];
5250
arr[side_effect() as usize] = arr[side_effect() as usize].offset(1);
5351
arr[side_effect() as usize] = arr[side_effect() as usize].offset(-1);

0 commit comments

Comments
 (0)