Skip to content

Commit 673ac7e

Browse files
authored
transpile: Rename and replace convert_cast (#1844)
This is mostly a refactor, but having the new `convert_cast` available will allow it to be called/reused from other places too.
2 parents 5e5b9ff + 706382e commit 673ac7e

3 files changed

Lines changed: 130 additions & 121 deletions

File tree

c2rust-transpile/src/translator/macros.rs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -206,16 +206,8 @@ impl<'c> Translation<'c> {
206206
// so we need to cast it to the `override_ty` here.
207207
let expr_ty = override_ty.or_else(|| expr_kind.get_qual_type());
208208
if let Some(expr_ty) = expr_ty {
209-
self.convert_cast(
210-
ctx,
211-
CQualTypeId::new(macro_ty),
212-
expr_ty,
213-
val,
214-
None,
215-
None,
216-
None,
217-
)
218-
.map(Some)
209+
self.make_cast(ctx, CQualTypeId::new(macro_ty), expr_ty, val)
210+
.map(Some)
219211
} else {
220212
Ok(Some(val))
221213
}

c2rust-transpile/src/translator/mod.rs

Lines changed: 124 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -2985,7 +2985,7 @@ impl<'c> Translation<'c> {
29852985
/// and in many cases should override it.
29862986
pub fn convert_expr(
29872987
&self,
2988-
mut ctx: ExprContext,
2988+
ctx: ExprContext,
29892989
expr_id: CExprId,
29902990
override_ty: Option<CQualTypeId>,
29912991
) -> TranslationResult<WithStmts<Box<Expr>>> {
@@ -3268,102 +3268,15 @@ impl<'c> Translation<'c> {
32683268
Literal(ty, ref kind) => self.convert_literal(ctx, override_ty.unwrap_or(ty), kind),
32693269

32703270
ImplicitCast(ty, expr, kind, opt_field_id, _)
3271-
| ExplicitCast(ty, expr, kind, opt_field_id, _) => {
3272-
let is_explicit = matches!(expr_kind, CExprKind::ExplicitCast(..));
3273-
// A reference must be decayed if a bitcast is required. Const casts in
3274-
// LLVM 8 are now NoOp casts, so we need to include it as well.
3275-
match kind {
3276-
CastKind::IntegralToBoolean
3277-
| CastKind::FloatingToBoolean
3278-
| CastKind::PointerToBoolean => {
3279-
return self.convert_condition(ctx, true, expr);
3280-
}
3281-
CastKind::BitCast | CastKind::PointerToIntegral | CastKind::NoOp => {
3282-
ctx.decay_ref = DecayRef::Yes
3283-
}
3284-
CastKind::ArrayToPointerDecay
3285-
| CastKind::FunctionToPointerDecay
3286-
| CastKind::BuiltinFnToFnPtr => {
3287-
ctx.needs_address = true;
3288-
}
3289-
_ => {}
3290-
}
3291-
3292-
let expr_kind = &self.ast_context.index_unwrap_parens(expr).kind;
3293-
let target_ty = override_ty.unwrap_or(ty);
3294-
3295-
// In general, if we are casting the result of an expression, then the inner
3296-
// expression should be translated to whatever type it normally would.
3297-
// But for literals, if we don't absolutely have to cast, we would rather the
3298-
// literal is translated according to the type we're expecting, and then we can
3299-
// skip the cast entirely.
3300-
if !is_explicit {
3301-
let mut literal_expr_kind = expr_kind;
3302-
let mut is_negated = false;
3303-
3304-
if let &CExprKind::Unary(_, CUnOp::Negate, subexpr_id, _) = literal_expr_kind {
3305-
literal_expr_kind = &self.ast_context.index_unwrap_parens(subexpr_id).kind;
3306-
is_negated = true;
3307-
}
3308-
3309-
if let CExprKind::Literal(_, lit) = literal_expr_kind {
3310-
if self.literal_matches_ty(lit, target_ty, is_negated) {
3311-
return self.convert_expr(ctx, expr, Some(target_ty));
3312-
}
3313-
}
3314-
}
3315-
3316-
let mut val = self.convert_expr(ctx, expr, None)?;
3317-
3318-
if is_explicit {
3319-
let stmts = self.compute_variable_array_sizes(ctx, ty.ctype)?;
3320-
val = val.prepend_stmts(stmts);
3321-
}
3322-
3323-
// Shuffle Vector "function" builtins will add a cast to the output of the
3324-
// builtin call which is unnecessary for translation purposes
3325-
if self.casting_simd_builtin_call(expr, is_explicit, kind) {
3326-
return Ok(val);
3327-
}
3328-
3329-
let source_ty = if let Some(func_decl) = self
3330-
.ast_context
3331-
.fn_declref_decl(expr)
3332-
.filter(|_| is_explicit)
3333-
{
3334-
// If we're casting a function, look for its declared ty to use as a more
3335-
// precise source type. The AST node's type will not preserve typedef arg types
3336-
// but the function's declaration will.
3337-
let kind_with_declared_args =
3338-
self.ast_context.fn_decl_ty_with_declared_args(func_decl);
3339-
let func_ty = self
3340-
.ast_context
3341-
.type_for_kind(&kind_with_declared_args)
3342-
.unwrap_or_else(|| panic!("no type for kind {kind_with_declared_args:?}"));
3343-
let func_ptr_ty = self
3344-
.ast_context
3345-
.type_for_kind(&CTypeKind::Pointer(CQualTypeId::new(func_ty)))
3346-
.unwrap_or_else(|| panic!("no type for kind {kind_with_declared_args:?}"));
3347-
3348-
CQualTypeId::new(func_ptr_ty)
3349-
} else {
3350-
self.ast_context
3351-
.index_unwrap_parens(expr)
3352-
.kind
3353-
.get_qual_type()
3354-
.ok_or_else(|| format_err!("bad source type"))?
3355-
};
3356-
3357-
self.convert_cast(
3358-
ctx,
3359-
source_ty,
3360-
target_ty,
3361-
val,
3362-
Some(expr),
3363-
Some(kind),
3364-
opt_field_id,
3365-
)
3366-
}
3271+
| ExplicitCast(ty, expr, kind, opt_field_id, _) => self.convert_cast(
3272+
ctx,
3273+
override_ty,
3274+
ty,
3275+
expr,
3276+
kind,
3277+
opt_field_id,
3278+
matches!(expr_kind, CExprKind::ExplicitCast(..)),
3279+
),
33673280

33683281
Unary(type_id, op, arg, _lrvalue) => {
33693282
self.convert_unary_operator(ctx, op, override_ty.unwrap_or(type_id), arg)
@@ -3653,6 +3566,120 @@ impl<'c> Translation<'c> {
36533566
}
36543567

36553568
pub fn convert_cast(
3569+
&self,
3570+
mut ctx: ExprContext,
3571+
override_ty: Option<CQualTypeId>,
3572+
ty: CQualTypeId,
3573+
expr: CExprId,
3574+
kind: CastKind,
3575+
opt_field_id: Option<CDeclId>,
3576+
is_explicit: bool,
3577+
) -> TranslationResult<WithStmts<Box<Expr>>> {
3578+
// A reference must be decayed if a bitcast is required. Const casts in
3579+
// LLVM 8 are now NoOp casts, so we need to include it as well.
3580+
match kind {
3581+
CastKind::IntegralToBoolean
3582+
| CastKind::FloatingToBoolean
3583+
| CastKind::PointerToBoolean => {
3584+
return self.convert_condition(ctx, true, expr);
3585+
}
3586+
CastKind::BitCast | CastKind::PointerToIntegral | CastKind::NoOp => {
3587+
ctx.decay_ref = DecayRef::Yes
3588+
}
3589+
CastKind::ArrayToPointerDecay
3590+
| CastKind::FunctionToPointerDecay
3591+
| CastKind::BuiltinFnToFnPtr => {
3592+
ctx.needs_address = true;
3593+
}
3594+
_ => {}
3595+
}
3596+
3597+
let expr_kind = &self.ast_context.index_unwrap_parens(expr).kind;
3598+
let target_ty = override_ty.unwrap_or(ty);
3599+
3600+
// In general, if we are casting the result of an expression, then the inner
3601+
// expression should be translated to whatever type it normally would.
3602+
// But for literals, if we don't absolutely have to cast, we would rather the
3603+
// literal is translated according to the type we're expecting, and then we can
3604+
// skip the cast entirely.
3605+
if !is_explicit {
3606+
let mut literal_expr_kind = expr_kind;
3607+
let mut is_negated = false;
3608+
3609+
if let &CExprKind::Unary(_, CUnOp::Negate, subexpr_id, _) = literal_expr_kind {
3610+
literal_expr_kind = &self.ast_context.index_unwrap_parens(subexpr_id).kind;
3611+
is_negated = true;
3612+
}
3613+
3614+
if let CExprKind::Literal(_, lit) = literal_expr_kind {
3615+
if self.literal_matches_ty(lit, target_ty, is_negated) {
3616+
return self.convert_expr(ctx, expr, Some(target_ty));
3617+
}
3618+
}
3619+
}
3620+
3621+
let mut val = self.convert_expr(ctx, expr, None)?;
3622+
3623+
if is_explicit {
3624+
let stmts = self.compute_variable_array_sizes(ctx, ty.ctype)?;
3625+
val = val.prepend_stmts(stmts);
3626+
}
3627+
3628+
// Shuffle Vector "function" builtins will add a cast to the output of the
3629+
// builtin call which is unnecessary for translation purposes
3630+
if self.casting_simd_builtin_call(expr, is_explicit, kind) {
3631+
return Ok(val);
3632+
}
3633+
3634+
let source_ty = if let Some(func_decl) = self
3635+
.ast_context
3636+
.fn_declref_decl(expr)
3637+
.filter(|_| is_explicit)
3638+
{
3639+
// If we're casting a function, look for its declared ty to use as a more
3640+
// precise source type. The AST node's type will not preserve typedef arg types
3641+
// but the function's declaration will.
3642+
let kind_with_declared_args = self.ast_context.fn_decl_ty_with_declared_args(func_decl);
3643+
let func_ty = self
3644+
.ast_context
3645+
.type_for_kind(&kind_with_declared_args)
3646+
.unwrap_or_else(|| panic!("no type for kind {kind_with_declared_args:?}"));
3647+
let func_ptr_ty = self
3648+
.ast_context
3649+
.type_for_kind(&CTypeKind::Pointer(CQualTypeId::new(func_ty)))
3650+
.unwrap_or_else(|| panic!("no type for kind {kind_with_declared_args:?}"));
3651+
3652+
CQualTypeId::new(func_ptr_ty)
3653+
} else {
3654+
self.ast_context
3655+
.index_unwrap_parens(expr)
3656+
.kind
3657+
.get_qual_type()
3658+
.ok_or_else(|| format_err!("bad source type"))?
3659+
};
3660+
3661+
self.make_cast_full(
3662+
ctx,
3663+
source_ty,
3664+
target_ty,
3665+
val,
3666+
Some(expr),
3667+
Some(kind),
3668+
opt_field_id,
3669+
)
3670+
}
3671+
3672+
pub fn make_cast(
3673+
&self,
3674+
ctx: ExprContext,
3675+
source_type_id: CQualTypeId,
3676+
target_type_id: CQualTypeId,
3677+
val: WithStmts<Box<Expr>>,
3678+
) -> TranslationResult<WithStmts<Box<Expr>>> {
3679+
self.make_cast_full(ctx, source_type_id, target_type_id, val, None, None, None)
3680+
}
3681+
3682+
pub fn make_cast_full(
36563683
&self,
36573684
ctx: ExprContext,
36583685
source_cty: CQualTypeId,

c2rust-transpile/src/translator/operators.rs

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -211,14 +211,11 @@ impl<'c> Translation<'c> {
211211
rhs,
212212
)))
213213
} else {
214-
let lhs = self.convert_cast(
214+
let lhs = self.make_cast(
215215
ctx,
216216
initial_lhs_type_id,
217217
compute_lhs_type_id,
218218
WithStmts::new_val(read.clone()),
219-
None,
220-
None,
221-
None,
222219
)?;
223220

224221
let ty = self.convert_type(compute_res_type_id.ctype)?;
@@ -234,8 +231,7 @@ impl<'c> Translation<'c> {
234231
)
235232
})?;
236233

237-
let val =
238-
self.convert_cast(ctx, compute_res_type_id, lhs_type_id, val, None, None, None)?;
234+
let val = self.make_cast(ctx, compute_res_type_id, lhs_type_id, val)?;
239235

240236
Ok(val.map(|val| mk().assign_expr(write.clone(), val)))
241237
}
@@ -423,14 +419,11 @@ impl<'c> Translation<'c> {
423419
.underlying_assignment()
424420
.expect("Cannot convert non-assignment operator");
425421

426-
let lhs = self.convert_cast(
422+
let lhs = self.make_cast(
427423
ctx,
428424
initial_lhs_type_id,
429425
expr_or_comp_type_id,
430426
WithStmts::new_val(read.clone()),
431-
None,
432-
None,
433-
None,
434427
)?;
435428

436429
let ty = self.convert_type(result_type_id.ctype)?;
@@ -446,14 +439,11 @@ impl<'c> Translation<'c> {
446439
)
447440
)?;
448441

449-
let val = self.convert_cast(
442+
let val = self.make_cast(
450443
ctx,
451444
result_type_id,
452445
expr_type_id,
453446
val,
454-
None,
455-
None,
456-
None,
457447
)?;
458448

459449
#[allow(clippy::let_and_return /* , reason = "block is large, so variable name helps" */)]

0 commit comments

Comments
 (0)