CQCL / hugr-llvm

4 stars 2 forks source link

Implement codgen extension for int_ops #20

Open doug-q opened 3 weeks ago

doug-q commented 3 weeks ago

See https://github.com/CQCL/hugr/blob/main/specification/hugr.md#arithmeticint for the spec of these ops.

doug-q commented 3 weeks ago

I do have a small amount of progress here

fn emit_icmp<'c, H: HugrView>(
    context: &mut EmitFuncContext<'c, H>,
    args: EmitOpArgs<'c, CustomOp, H>,
    pred: inkwell::IntPredicate,
) -> Result<()> {
    let true_val = emit_value(context, &Value::true_val())?;
    let false_val = emit_value(context, &Value::false_val())?;
    let builder = context.builder();
    let [lhs, rhs] = TryInto::<[_; 2]>::try_into(args.inputs).unwrap();
    let a = builder.build_int_compare(pred, lhs.into_int_value(), rhs.into_int_value(), "")?;
    let a = builder.build_select(a, true_val, false_val, "")?;
    args.outputs.finish(builder, [a.into()])
}

impl<'c, H: HugrView> EmitOp<'c, CustomOp, H> for IntOpEmitter<'c, '_, H> {
    fn emit(&mut self, args: EmitOpArgs<'c, CustomOp, H>) -> Result<()> {
        let iot = ConcreteIntOp::from_optype(&args.node().generalise())
            .ok_or(anyhow!("IntOpEmitter from_optype_failed"))?;
        match iot.name().as_str() {
            "iadd" => {
                let builder = self.0.builder();
                let [lhs, rhs] = TryInto::<[_; 2]>::try_into(args.inputs).unwrap();
                let a = builder.build_int_add(lhs.into_int_value(), rhs.into_int_value(), "")?;
                args.outputs.finish(builder, [a.into()])
            }
            "ieq" => {
                emit_icmp(self.0, args, inkwell::IntPredicate::EQ)
            }
            "ilt_s" => {
                emit_icmp(self.0, args, inkwell::IntPredicate::SLT)
            }
            "isub" => {
                let builder = self.0.builder();
                let [lhs, rhs] = TryInto::<[_; 2]>::try_into(args.inputs).unwrap();
                let a = builder.build_int_sub(lhs.into_int_value(), rhs.into_int_value(), "")?;
                args.outputs.finish(builder, [a.into()])
            }
            n => Err(anyhow!("IntOpEmitter: unknown name: {n}")),
        }
    }
}