diff --git a/nac3artiq/src/codegen.rs b/nac3artiq/src/codegen.rs
index f9da2e9b..17d2593d 100644
--- a/nac3artiq/src/codegen.rs
+++ b/nac3artiq/src/codegen.rs
@@ -1,6 +1,7 @@
use nac3core::{
codegen::{
expr::gen_call,
+ llvm_intrinsics::{call_int_smax, call_stackrestore, call_stacksave},
stmt::{gen_block, gen_with},
CodeGenContext, CodeGenerator,
},
@@ -15,7 +16,7 @@ use inkwell::{
context::Context,
module::Linkage,
types::IntType,
- values::{BasicValueEnum, CallSiteValue},
+ values::BasicValueEnum,
AddressSpace,
};
@@ -29,7 +30,6 @@ use std::{
hash::{Hash, Hasher},
sync::Arc,
};
-use itertools::Either;
/// The parallelism mode within a block.
#[derive(Copy, Clone, Eq, PartialEq)]
@@ -133,20 +133,12 @@ impl<'a> ArtiqCodeGenerator<'a> {
.unwrap()
.to_basic_value_enum(ctx, self, end.custom.unwrap())?;
let now = self.timeline.emit_now_mu(ctx);
- let smax = ctx.module.get_function("llvm.smax.i64").unwrap_or_else(|| {
- let i64 = ctx.ctx.i64_type();
- ctx.module.add_function(
- "llvm.smax.i64",
- i64.fn_type(&[i64.into(), i64.into()], false),
- None,
- )
- });
- let max = ctx
- .builder
- .build_call(smax, &[old_end.into(), now.into()], "smax")
- .map(CallSiteValue::try_as_basic_value)
- .map(Either::unwrap_left)
- .unwrap();
+ let max = call_int_smax(
+ ctx,
+ old_end.into_int_value(),
+ now.into_int_value(),
+ Some("smax")
+ );
let end_store = self.gen_store_target(
ctx,
&end,
@@ -471,18 +463,7 @@ fn rpc_codegen_callback_fn<'ctx>(
let arg_length = args.len() + usize::from(obj.is_some());
- let stacksave = ctx.module.get_function("llvm.stacksave").unwrap_or_else(|| {
- ctx.module.add_function("llvm.stacksave", ptr_type.fn_type(&[], false), None)
- });
- let stackrestore = ctx.module.get_function("llvm.stackrestore").unwrap_or_else(|| {
- ctx.module.add_function(
- "llvm.stackrestore",
- ctx.ctx.void_type().fn_type(&[ptr_type.into()], false),
- None,
- )
- });
-
- let stackptr = ctx.builder.build_call(stacksave, &[], "rpc.stack").unwrap();
+ let stackptr = call_stacksave(ctx, Some("rpc.stack"));
let args_ptr = ctx.builder
.build_array_alloca(
ptr_type,
@@ -558,13 +539,7 @@ fn rpc_codegen_callback_fn<'ctx>(
.unwrap();
// reclaim stack space used by arguments
- ctx.builder
- .build_call(
- stackrestore,
- &[stackptr.try_as_basic_value().unwrap_left().into()],
- "rpc.stackrestore",
- )
- .unwrap();
+ call_stackrestore(ctx, stackptr);
// -- receive value:
// T result = {
@@ -624,13 +599,7 @@ fn rpc_codegen_callback_fn<'ctx>(
let result = ctx.builder.build_load(slot, "rpc.result").unwrap();
if need_load {
- ctx.builder
- .build_call(
- stackrestore,
- &[stackptr.try_as_basic_value().unwrap_left().into()],
- "rpc.stackrestore",
- )
- .unwrap();
+ call_stackrestore(ctx, stackptr);
}
Ok(Some(result))
}
diff --git a/nac3core/src/codegen/classes.rs b/nac3core/src/codegen/classes.rs
index 4394ce02..34463ef4 100644
--- a/nac3core/src/codegen/classes.rs
+++ b/nac3core/src/codegen/classes.rs
@@ -1,13 +1,13 @@
use inkwell::{
IntPredicate,
types::{AnyTypeEnum, BasicTypeEnum, IntType, PointerType},
- values::{ArrayValue, BasicValueEnum, CallSiteValue, IntValue, PointerValue},
+ values::{ArrayValue, BasicValueEnum, IntValue, PointerValue},
};
-use itertools::Either;
use crate::codegen::{
CodeGenContext,
CodeGenerator,
irrt::{call_ndarray_calc_size, call_ndarray_flatten_index, call_ndarray_flatten_index_const},
+ llvm_intrinsics::call_int_umin,
stmt::gen_for_callback,
};
@@ -924,22 +924,7 @@ impl<'ctx> NDArrayDataProxy<'ctx> {
let indices_len = indices.load_size(ctx, None);
let ndarray_len = self.0.load_ndims(ctx);
- let min_fn_name = format!("llvm.umin.i{}", llvm_usize.get_bit_width());
- let min_fn = ctx.module.get_function(min_fn_name.as_str()).unwrap_or_else(|| {
- let fn_type = llvm_usize.fn_type(
- &[llvm_usize.into(), llvm_usize.into()],
- false
- );
- ctx.module.add_function(min_fn_name.as_str(), fn_type, None)
- });
-
- let len = ctx
- .builder
- .build_call(min_fn, &[indices_len.into(), ndarray_len.into()], "")
- .map(CallSiteValue::try_as_basic_value)
- .map(|v| v.map_left(BasicValueEnum::into_int_value))
- .map(Either::unwrap_left)
- .unwrap();
+ let len = call_int_umin(ctx, indices_len, ndarray_len, None);
let i = ctx.builder.build_load(i_addr, "")
.map(BasicValueEnum::into_int_value)
diff --git a/nac3core/src/codegen/expr.rs b/nac3core/src/codegen/expr.rs
index 9f07247e..e0df6f0b 100644
--- a/nac3core/src/codegen/expr.rs
+++ b/nac3core/src/codegen/expr.rs
@@ -8,6 +8,7 @@ use crate::{
get_llvm_type,
get_llvm_abi_type,
irrt::*,
+ llvm_intrinsics::{call_expect, call_float_floor, call_float_pow, call_float_powi},
stmt::{gen_raise, gen_var},
CodeGenContext, CodeGenTask,
},
@@ -30,7 +31,7 @@ use nac3parser::ast::{
self, Boolop, Comprehension, Constant, Expr, ExprKind, Location, Operator, StrRef,
};
-use super::{CodeGenerator, need_sret};
+use super::{CodeGenerator, llvm_intrinsics::call_memcpy_generic, need_sret};
pub fn get_subst_key(
unifier: &mut Unifier,
@@ -371,7 +372,6 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
let (BasicValueEnum::FloatValue(lhs), BasicValueEnum::FloatValue(rhs)) = (lhs, rhs) else {
unreachable!()
};
- let float = self.ctx.f64_type();
match op {
Operator::Add => self.builder.build_float_add(lhs, rhs, "fadd").map(Into::into).unwrap(),
Operator::Sub => self.builder.build_float_sub(lhs, rhs, "fsub").map(Into::into).unwrap(),
@@ -380,28 +380,9 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
Operator::Mod => self.builder.build_float_rem(lhs, rhs, "fmod").map(Into::into).unwrap(),
Operator::FloorDiv => {
let div = self.builder.build_float_div(lhs, rhs, "fdiv").unwrap();
- let floor_intrinsic =
- self.module.get_function("llvm.floor.f64").unwrap_or_else(|| {
- let fn_type = float.fn_type(&[float.into()], false);
- self.module.add_function("llvm.floor.f64", fn_type, None)
- });
- self.builder
- .build_call(floor_intrinsic, &[div.into()], "floor")
- .map(CallSiteValue::try_as_basic_value)
- .map(Either::unwrap_left)
- .unwrap()
- }
- Operator::Pow => {
- let pow_intrinsic = self.module.get_function("llvm.pow.f64").unwrap_or_else(|| {
- let fn_type = float.fn_type(&[float.into(), float.into()], false);
- self.module.add_function("llvm.pow.f64", fn_type, None)
- });
- self.builder
- .build_call(pow_intrinsic, &[lhs.into(), rhs.into()], "f_pow")
- .map(CallSiteValue::try_as_basic_value)
- .map(Either::unwrap_left)
- .unwrap()
+ call_float_floor(self, div, Some("floor")).into()
}
+ Operator::Pow => call_float_pow(self, lhs, rhs, Some("f_pow")).into(),
// special implementation?
_ => unimplemented!(),
}
@@ -585,24 +566,11 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
) {
let i1 = self.ctx.bool_type();
let i1_true = i1.const_all_ones();
- let expect_fun = self.module.get_function("llvm.expect.i1").unwrap_or_else(|| {
- self.module.add_function(
- "llvm.expect.i1",
- i1.fn_type(&[i1.into(), i1.into()], false),
- None,
- )
- });
// we assume that the condition is most probably true, so the normal path is the most
// probable path
// even if this assumption is violated, it does not matter as exception unwinding is
// slow anyway...
- let cond = self
- .builder
- .build_call(expect_fun, &[cond.into(), i1_true.into()], "expect")
- .map(CallSiteValue::try_as_basic_value)
- .map(|v| v.map_left(BasicValueEnum::into_int_value))
- .map(Either::unwrap_left)
- .unwrap();
+ let cond = call_expect(self, cond, i1_true, Some("expect"));
let current_fun = self.builder.get_insert_block().unwrap().get_parent().unwrap();
let then_block = self.ctx.append_basic_block(current_fun, "succ");
let exn_block = self.ctx.append_basic_block(current_fun, "fail");
@@ -1150,17 +1118,12 @@ pub fn gen_binop_expr<'ctx, G: CodeGenerator>(
} else if ty1 == ctx.primitives.float && ty2 == ctx.primitives.int32 {
// Pow is the only operator that would pass typecheck between float and int
assert_eq!(*op, Operator::Pow);
- let i32_t = ctx.ctx.i32_type();
- let pow_intr = ctx.module.get_function("llvm.powi.f64.i32").unwrap_or_else(|| {
- let f64_t = ctx.ctx.f64_type();
- let ty = f64_t.fn_type(&[f64_t.into(), i32_t.into()], false);
- ctx.module.add_function("llvm.powi.f64.i32", ty, None)
- });
- let res = ctx.builder
- .build_call(pow_intr, &[left_val.into(), right_val.into()], "f_pow_i")
- .map(CallSiteValue::try_as_basic_value)
- .map(Either::unwrap_left)
- .unwrap();
+ let res = call_float_powi(
+ ctx,
+ left_val.into_float_value(),
+ right_val.into_int_value(),
+ Some("f_pow_i")
+ );
Ok(Some(res.into()))
} else {
let left_ty_enum = ctx.unifier.get_ty_immutable(left.custom.unwrap());
@@ -1229,11 +1192,8 @@ fn gen_ndarray_subscript_expr<'ctx, G: CodeGenerator>(
v: NDArrayValue<'ctx>,
slice: &Expr