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),
}
}