Skip to content

Commit 37d4534

Browse files
authored
transpile: Add CBinOp methods for querying operator kinds (#1790)
Some less repetition, cleaner code.
2 parents a5733bd + 86ddc95 commit 37d4534

3 files changed

Lines changed: 89 additions & 91 deletions

File tree

c2rust-transpile/src/c_ast/mod.rs

Lines changed: 68 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,7 +1279,7 @@ impl TypedAstContext {
12791279
} else {
12801280
Some(rhs_type_id)
12811281
}
1282-
} else if op == CBinOp::ShiftLeft || op == CBinOp::ShiftRight {
1282+
} else if op.is_bitshift() {
12831283
Some(lhs_type_id)
12841284
} else {
12851285
return;
@@ -2164,28 +2164,81 @@ impl CBinOp {
21642164
}
21652165
}
21662166

2167-
/// Does the rust equivalent of this operator have type (T, T) -> U?
2168-
#[rustfmt::skip]
2169-
pub fn input_types_same(&self) -> bool {
2167+
/// Is this a (non-assignment) arithmetic operator?
2168+
pub fn is_arithmetic(&self) -> bool {
21702169
use CBinOp::*;
2171-
self.all_types_same() || matches!(self,
2172-
Less | Greater | LessEqual | GreaterEqual | EqualEqual | NotEqual
2173-
| And | Or
2174-
| AssignAdd | AssignSubtract | AssignMultiply | AssignDivide | AssignModulus
2175-
| AssignBitXor | AssignShiftLeft | AssignShiftRight | AssignBitOr | AssignBitAnd
2176-
| Assign
2177-
)
2170+
matches!(self, Add | Subtract | Multiply | Divide | Modulus)
21782171
}
21792172

2180-
/// Does the rust equivalent of this operator have type (T, T) -> T?
2181-
/// This ignores cases where one argument is a pointer and we translate to `.offset()`.
2182-
pub fn all_types_same(&self) -> bool {
2173+
/// Is this a (non-assignment) arithmetic operator that can be used with pointers?
2174+
pub fn is_pointer_arithmetic(&self) -> bool {
2175+
use CBinOp::*;
2176+
matches!(self, Add | Subtract)
2177+
}
2178+
2179+
/// Is this a (non-assignment, non-shift) bitwise operator?
2180+
pub fn is_bitwise(&self) -> bool {
2181+
use CBinOp::*;
2182+
matches!(self, BitAnd | BitOr | BitXor)
2183+
}
2184+
2185+
/// Is this a (non-assignment) bitshift operator?
2186+
pub fn is_bitshift(&self) -> bool {
2187+
use CBinOp::*;
2188+
matches!(self, ShiftLeft | ShiftRight)
2189+
}
2190+
2191+
/// Is this a logical operator?
2192+
pub fn is_logical(&self) -> bool {
2193+
use CBinOp::*;
2194+
matches!(self, And | Or)
2195+
}
2196+
2197+
/// Is this a comparison operator?
2198+
pub fn is_comparison(&self) -> bool {
21832199
use CBinOp::*;
21842200
matches!(
21852201
self,
2186-
Multiply | Divide | Modulus | Add | Subtract | BitAnd | BitXor | BitOr
2202+
EqualEqual | NotEqual | Less | Greater | LessEqual | GreaterEqual
21872203
)
21882204
}
2205+
2206+
/// Is this a (simple or compound) assignment operator?
2207+
pub fn is_assignment(&self) -> bool {
2208+
matches!(self, Self::Assign) || self.underlying_assignment().is_some()
2209+
}
2210+
2211+
/// Maps compound assignment operators to operator underlying them, and returns `None` for all
2212+
/// other operators.
2213+
///
2214+
/// For example, `AssignAdd` maps to `Some(Add)` but `Add` maps to `None`.
2215+
pub fn underlying_assignment(&self) -> Option<CBinOp> {
2216+
use CBinOp::*;
2217+
Some(match *self {
2218+
AssignAdd => Add,
2219+
AssignSubtract => Subtract,
2220+
AssignMultiply => Multiply,
2221+
AssignDivide => Divide,
2222+
AssignModulus => Modulus,
2223+
AssignBitXor => BitXor,
2224+
AssignShiftLeft => ShiftLeft,
2225+
AssignShiftRight => ShiftRight,
2226+
AssignBitOr => BitOr,
2227+
AssignBitAnd => BitAnd,
2228+
_ => return None,
2229+
})
2230+
}
2231+
2232+
/// Does the rust equivalent of this operator have type (T, T) -> U?
2233+
pub fn input_types_same(&self) -> bool {
2234+
self.all_types_same() || self.is_logical() || self.is_comparison() || self.is_assignment()
2235+
}
2236+
2237+
/// Does the rust equivalent of this operator have type (T, T) -> T?
2238+
/// This ignores cases where one argument is a pointer and we translate to `.offset()`.
2239+
pub fn all_types_same(&self) -> bool {
2240+
self.is_arithmetic() || self.is_bitwise()
2241+
}
21892242
}
21902243

21912244
impl From<CBinOp> for BinOp {
@@ -2232,34 +2285,6 @@ impl Display for CBinOp {
22322285
}
22332286
}
22342287

2235-
impl CBinOp {
2236-
/// Maps compound assignment operators to operator underlying them, and returns `None` for all
2237-
/// other operators.
2238-
///
2239-
/// For example, `AssignAdd` maps to `Some(Add)` but `Add` maps to `None`.
2240-
pub fn underlying_assignment(&self) -> Option<CBinOp> {
2241-
use CBinOp::*;
2242-
Some(match *self {
2243-
AssignAdd => Add,
2244-
AssignSubtract => Subtract,
2245-
AssignMultiply => Multiply,
2246-
AssignDivide => Divide,
2247-
AssignModulus => Modulus,
2248-
AssignBitXor => BitXor,
2249-
AssignShiftLeft => ShiftLeft,
2250-
AssignShiftRight => ShiftRight,
2251-
AssignBitOr => BitOr,
2252-
AssignBitAnd => BitAnd,
2253-
_ => return None,
2254-
})
2255-
}
2256-
2257-
/// Determines whether or not this is an assignment op
2258-
pub fn is_assignment(&self) -> bool {
2259-
matches!(self, Self::Assign) || self.underlying_assignment().is_some()
2260-
}
2261-
}
2262-
22632288
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
22642289
pub enum IntBase {
22652290
Dec,

c2rust-transpile/src/translator/mod.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1638,7 +1638,6 @@ impl<'c> Translation<'c> {
16381638
expr_id: Option<CExprId>,
16391639
qtype: CQualTypeId,
16401640
) -> bool {
1641-
use crate::c_ast::CBinOp::{Add, Divide, Modulus, Multiply, Subtract};
16421641
use crate::c_ast::CUnOp::{AddressOf, Negate};
16431642
use crate::c_ast::CastKind::{IntegralToPointer, PointerToIntegral};
16441643

@@ -1687,9 +1686,7 @@ impl<'c> Translation<'c> {
16871686
| ExplicitCast(_, _, PointerToIntegral, _, _) => return true,
16881687

16891688
Binary(typ, op, _, _, _, _) => {
1690-
let problematic_op = matches!(op, Add | Subtract | Multiply | Divide | Modulus);
1691-
1692-
if problematic_op {
1689+
if op.is_arithmetic() {
16931690
let k = &self.ast_context.resolve_type(typ.ctype).kind;
16941691
if k.is_unsigned_integral_type() || k.is_pointer() {
16951692
return true;

c2rust-transpile/src/translator/operators.rs

Lines changed: 20 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ impl<'c> Translation<'c> {
2929
.and_then_try(|_| self.convert_expr(ctx, rhs, Some(expr_type_id)))
3030
}
3131

32-
And | Or => {
32+
op if op.is_logical() => {
3333
let lhs = self.convert_condition(ctx, true, lhs)?;
3434
let rhs = self.convert_condition(ctx, true, rhs)?;
3535
Ok(lhs
@@ -47,9 +47,7 @@ impl<'c> Translation<'c> {
4747
}
4848

4949
// No sequence-point cases
50-
AssignAdd | AssignSubtract | AssignMultiply | AssignDivide | AssignModulus
51-
| AssignBitXor | AssignShiftLeft | AssignShiftRight | AssignBitOr | AssignBitAnd
52-
| Assign => self.convert_assignment_operator(
50+
op if op.is_assignment() => self.convert_assignment_operator(
5351
ctx,
5452
op,
5553
expr_type_id,
@@ -133,7 +131,7 @@ impl<'c> Translation<'c> {
133131
// When we use methods on pointers (ie wrapping_offset_from or offset)
134132
// we must ensure we have an explicit raw ptr for the self param, as
135133
// self references do not decay
136-
if op == CBinOp::Subtract || op == CBinOp::Add {
134+
if op.is_pointer_arithmetic() {
137135
let ty_kind = &self.ast_context.resolve_type(lhs_type_id.ctype).kind;
138136

139137
if let CTypeKind::Pointer(_) = ty_kind {
@@ -287,21 +285,13 @@ impl<'c> Translation<'c> {
287285
let neither_ptr =
288286
!lhs_resolved_ty.kind.is_pointer() && !rhs_resolved_ty.kind.is_pointer();
289287

290-
use CBinOp::*;
291-
match op.underlying_assignment() {
292-
Some(Add) => neither_ptr,
293-
Some(Subtract) => neither_ptr,
294-
Some(Multiply) => true,
295-
Some(Divide) => true,
296-
Some(Modulus) => true,
297-
Some(BitXor) => true,
298-
Some(ShiftLeft) => false,
299-
Some(ShiftRight) => false,
300-
Some(BitOr) => true,
301-
Some(BitAnd) => true,
302-
None => true,
303-
_ => unreachable!(),
304-
}
288+
op.underlying_assignment().map_or(true, |op| {
289+
if op.is_pointer_arithmetic() {
290+
neither_ptr
291+
} else {
292+
op.is_arithmetic() || op.is_bitwise()
293+
}
294+
})
305295
};
306296
if lhs_rhs_types_must_match {
307297
// For compound assignment, use the compute type; for regular assignment, use lhs type
@@ -388,14 +378,10 @@ impl<'c> Translation<'c> {
388378
_ => None,
389379
};
390380

391-
let is_unsigned_arith = match op {
392-
CBinOp::AssignAdd
393-
| CBinOp::AssignSubtract
394-
| CBinOp::AssignMultiply
395-
| CBinOp::AssignDivide
396-
| CBinOp::AssignModulus => compute_resolved_ty.kind.is_unsigned_integral_type(),
397-
_ => false,
398-
};
381+
let is_unsigned_arith = op
382+
.underlying_assignment()
383+
.map_or(false, |op| op.is_arithmetic())
384+
&& compute_resolved_ty.kind.is_unsigned_integral_type();
399385

400386
let lhs_translation = if initial_lhs_type_id.ctype != expr_or_comp_type_id.ctype
401387
|| ctx.is_used()
@@ -545,25 +531,15 @@ impl<'c> Translation<'c> {
545531
CBinOp::Add => return self.convert_addition(lhs_type, rhs_type, lhs, rhs),
546532
CBinOp::Subtract => return self.convert_subtraction(ty, lhs_type, rhs_type, lhs, rhs),
547533

548-
CBinOp::Multiply | CBinOp::Divide | CBinOp::Modulus if is_unsigned_integral_type => {
534+
op if op.is_arithmetic() && is_unsigned_integral_type => {
549535
mk().method_call_expr(lhs, op.wrapping_method(), vec![rhs])
550536
}
551537

552-
CBinOp::Multiply
553-
| CBinOp::Divide
554-
| CBinOp::Modulus
555-
| CBinOp::BitAnd
556-
| CBinOp::BitOr
557-
| CBinOp::BitXor
558-
| CBinOp::ShiftRight
559-
| CBinOp::ShiftLeft => mk().binary_expr(BinOp::from(op), lhs, rhs),
560-
561-
CBinOp::EqualEqual
562-
| CBinOp::NotEqual
563-
| CBinOp::Less
564-
| CBinOp::Greater
565-
| CBinOp::GreaterEqual
566-
| CBinOp::LessEqual => bool_to_int(mk().binary_expr(BinOp::from(op), lhs, rhs)),
538+
op if op.is_arithmetic() || op.is_bitwise() || op.is_bitshift() => {
539+
mk().binary_expr(BinOp::from(op), lhs, rhs)
540+
}
541+
542+
op if op.is_comparison() => bool_to_int(mk().binary_expr(BinOp::from(op), lhs, rhs)),
567543

568544
op => unimplemented!("Translation of binary operator {:?}", op),
569545
}))

0 commit comments

Comments
 (0)