diff --git a/nac3core/src/codegen/expr.rs b/nac3core/src/codegen/expr.rs index 33c0eec..5e7f5b2 100644 --- a/nac3core/src/codegen/expr.rs +++ b/nac3core/src/codegen/expr.rs @@ -957,10 +957,36 @@ pub fn gen_binop_expr<'ctx, 'a, G: CodeGenerator>( ctx.module.add_function("llvm.powi.f64.i16", ty, None) }); let right = ctx.builder.build_int_truncate(right.into_int_value(), i16_t, "r_pow"); - ctx.builder + let is_neg = ctx.builder.build_int_compare( + inkwell::IntPredicate::SLT, + right, + i16_t.const_zero(), + "powi_pow_neg", + ); + let abs_intr = ctx.module.get_function("llvm.abs.i16").unwrap_or_else(|| { + let ty = i16_t.fn_type(&[i16_t.into(), ctx.ctx.bool_type().into()], false); + ctx.module.add_function("llvm.abs.i16", ty, None) + }); + let right = ctx + .builder + .build_call( + abs_intr, + &[right.into(), ctx.ctx.bool_type().const_int(0, false).into()], + "pow_abs", + ) + .try_as_basic_value() + .unwrap_left(); + let pow = ctx + .builder .build_call(pow_intr, &[left.into(), right.into()], "f_pow_i") .try_as_basic_value() - .unwrap_left() + .unwrap_left(); + let reciprocal = ctx.builder.build_float_div( + ctx.ctx.f64_type().const_float(1.0), + pow.into_float_value(), + "recip", + ); + ctx.builder.build_select(is_neg, reciprocal, pow.into_float_value(), "float_pow_i") } else { unimplemented!() }