charon_lib/transform/resugar/
reconstruct_intrinsics.rs1use crate::transform::TransformCtx;
2use crate::transform::ctx::{BodyTransformCtx, UllbcPass};
3use crate::ullbc_ast::*;
4
5pub struct Transform;
6impl UllbcPass for Transform {
7 fn transform_function(&self, ctx: &mut TransformCtx, decl: &mut FunDecl) {
8 decl.transform_ullbc_terminators(ctx, |ctx, term| {
9 let TerminatorKind::Call { call, target, .. } = &term.kind else {
10 return;
11 };
12 let FnOperand::Regular(fn_ptr) = &call.func else {
13 return;
14 };
15 let FnPtrKind::Fun(FunId::Regular(fun_id)) = &fn_ptr.kind else {
16 return;
17 };
18 let Some(fun_decl) = ctx.ctx.translated.fun_decls.get(*fun_id) else {
19 return;
20 };
21 if fun_decl.item_meta.lang_item.as_deref() == Some("offset_of")
22 && let generics = fn_ptr.pre_mono_generics(&ctx.ctx.translated)
23 && let Some(ty) = generics.types.get(TypeVarId::ZERO)
24 && let TyKind::Adt(tref) = ty.kind()
25 && let TypeId::Adt(type_id) = tref.id
26 && let [Operand::Const(arg0), Operand::Const(arg1)] = call.args.as_slice()
27 && let ConstantExprKind::Literal(Literal::Scalar(ScalarValue::Unsigned(
28 UIntTy::U32,
29 variant_id,
30 ))) = &arg0.kind
31 && let ConstantExprKind::Literal(Literal::Scalar(ScalarValue::Unsigned(
32 UIntTy::U32,
33 field_id,
34 ))) = &arg1.kind
35 && let Some(tdecl) = ctx.ctx.translated.type_decls.get(type_id)
36 {
37 let variant_id = if tdecl.kind.is_enum() {
40 Some(VariantId::from_usize(*variant_id as usize))
41 } else {
42 None
43 };
44 let field_id = FieldId::from_usize(*field_id as usize);
45 let rval = Rvalue::NullaryOp(
46 NullOp::OffsetOf(tref.clone(), variant_id, field_id),
47 Ty::mk_usize(),
48 );
49 ctx.insert_assn_stmt(call.dest.clone(), rval);
50 term.kind = TerminatorKind::Goto { target: *target };
51 }
52 });
53 }
54}