fn gen_expr_val()

in lwcb/blang/src/passes/bpfir.rs [204:311]


fn gen_expr_val(ctx: &mut LocalContext, fb: &mut FunctionBuilder, expr: &Expr) -> Result<Value> {
    match &expr.kind {
        ExprKind::Unary(op, e) => match op {
            UnaryOp::Deref => {
                let addr = gen_expr_val(ctx, fb, e)?;
                if let TypeKind::Ptr(x) = &expr.ty.kind {
                    return Ok(fb
                        .ins()
                        .load(to_clif_type(&expr.ty), MemFlags::trusted(), addr, 0));
                }
                return Ok(addr);
            }
            UnaryOp::Neg => {
                let val = gen_expr_val(ctx, fb, e)?;
                return Ok(fb.ins().ineg(val));
            }
            _ => todo!(),
        },
        ExprKind::Ident(_) => {
            return gen_expr_addr(ctx, fb, expr);
        }
        ExprKind::Constant(c) => {
            return Ok(fb.ins().iconst(to_clif_type(&expr.ty), *c));
        }
        ExprKind::Binary(op, l, r) => {
            match op {
                BinaryOp::Assign => {
                    let rval = gen_expr_val(ctx, fb, r)?;

                    match &l.kind {
                        ExprKind::Ident(i) => {
                            let var = ctx.find_var(fb, i, &l.ty);
                            fb.def_var(var, rval);
                            // should never use this value
                            return Ok(rval);
                        }

                        ExprKind::Binary(op, l2, r2) => {
                            if let BinaryOp::Index = op {
                                if let ExprKind::Ident(sym) = &l2.kind {
                                    let map = ctx.find_map(sym, l2.ty.clone(), fb);

                                    let keyval = gen_expr_val(ctx, fb, r2)?;
                                    let keyaddr = value_to_stack(fb, keyval, &r2.ty);

                                    let valaddr = value_to_stack(fb, rval, &r.ty);

                                    let flags = fb.ins().iconst(I64, libbpf_sys::BPF_ANY as i64);
                                    let fr = ctx.find_helper_function(
                                        libbpf_sys::BPF_FUNC_map_update_elem,
                                        fb,
                                    );
                                    let inst =
                                        fb.ins().call(fr, &vec![map, keyaddr, valaddr, flags]);
                                    return Ok(fb.inst_results(inst)[0]);
                                }
                            }
                            todo!()
                        }

                        _ => {
                            panic!("Currently lvalue only supports variables and index expressions")
                        }
                    }
                }
                BinaryOp::Index => {
                    // When we get here it should be an rvalue, we need to load this value
                    let addr = gen_expr_addr(ctx, fb, expr)?;
                    todo!()
                }
                BinaryOp::Add
                | BinaryOp::Sub
                | BinaryOp::Mult
                | BinaryOp::Div
                | BinaryOp::Mod
                | BinaryOp::BitOr
                | BinaryOp::BitAnd
                | BinaryOp::BitXor => {
                    let lval = gen_expr_val(ctx, fb, l)?;
                    let rval = gen_expr_val(ctx, fb, r)?;
                    return Ok(to_clif_binary(fb, op, lval, rval));
                }
                BinaryOp::LT
                | BinaryOp::LTE
                | BinaryOp::GT
                | BinaryOp::GTE
                | BinaryOp::NonEqual
                | BinaryOp::Equal => {
                    return gen_expr_cf(ctx, fb, expr);
                }
                _ => todo!(),
            }
        }
        ExprKind::Cast(from, to) => gen_expr_val(ctx, fb, from),
        ExprKind::Call(c, args) => match c {
            Call::Print => gen_call_print(ctx, fb, args),
            _ => todo!(),
        },
        ExprKind::Member(p, s, _) => {
            let addr = gen_expr_addr(ctx, fb, expr)?;
            let val = fb
                .ins()
                .load(to_clif_type(&expr.ty), MemFlags::trusted(), addr, 0);
            return Ok(val);
        }
        _ => todo!("{:?}", expr.kind),
    }
}