diff --git a/Cargo.lock b/Cargo.lock
index 399c90e7..b4f54ad1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -513,6 +513,7 @@ dependencies = [
"nac3parser",
"parking_lot",
"rayon",
+ "regex",
"test-case",
]
diff --git a/nac3artiq/src/lib.rs b/nac3artiq/src/lib.rs
index e1c87f76..7c94d2d6 100644
--- a/nac3artiq/src/lib.rs
+++ b/nac3artiq/src/lib.rs
@@ -21,6 +21,7 @@ use parking_lot::{Mutex, RwLock};
use nac3core::{
codegen::{concrete_type::ConcreteTypeStore, CodeGenTask, WithCall, WorkerRegistry},
+ codegen::irrt::load_irrt,
symbol_resolver::SymbolResolver,
toplevel::{composer::{TopLevelComposer, ComposerConfig}, DefinitionId, GenCall, TopLevelDef},
typecheck::typedef::{FunSignature, FuncArg},
@@ -588,6 +589,8 @@ impl Nac3 {
main.link_in_module(other)
.map_err(|err| exceptions::PyRuntimeError::new_err(err.to_string()))?;
}
+ main.link_in_module(load_irrt(&context))
+ .map_err(|err| exceptions::PyRuntimeError::new_err(err.to_string()))?;
let mut function_iter = main.get_first_function();
while let Some(func) = function_iter {
diff --git a/nac3core/Cargo.toml b/nac3core/Cargo.toml
index 64408af8..ab11b7b9 100644
--- a/nac3core/Cargo.toml
+++ b/nac3core/Cargo.toml
@@ -20,3 +20,6 @@ features = ["llvm13-0", "target-x86", "target-arm", "target-riscv", "no-libffi-l
test-case = "1.2.0"
indoc = "1.0"
insta = "1.5"
+
+[build-dependencies]
+regex = "1"
diff --git a/nac3core/build.rs b/nac3core/build.rs
new file mode 100644
index 00000000..c4dcfc8e
--- /dev/null
+++ b/nac3core/build.rs
@@ -0,0 +1,54 @@
+use regex::Regex;
+use std::{
+ env,
+ io::Write,
+ process::{Command, Stdio},
+};
+
+fn main() {
+ let out_dir = env::var("OUT_DIR").unwrap();
+ const FILE: &str = "src/codegen/irrt/irrt.c";
+ println!("cargo:rerun-if-changed={}", FILE);
+ const FLAG: &[&str] = &[
+ FILE,
+ "-O3",
+ "-emit-llvm",
+ "-S",
+ "-Wall",
+ "-Wextra",
+ "-Wno-implicit-function-declaration",
+ "-o",
+ "-",
+ ];
+ let output = Command::new("clang")
+ .args(FLAG)
+ .output()
+ .map(|o| {
+ assert!(o.status.success(), "{}", std::str::from_utf8(&o.stderr).unwrap());
+ o
+ })
+ .unwrap();
+
+ let output = std::str::from_utf8(&output.stdout).unwrap();
+ let mut filtered_output = String::with_capacity(output.len());
+
+ let regex_filter = regex::Regex::new(r"(?ms:^define.*?\}$)|(?m:^declare.*?$)").unwrap();
+ for f in regex_filter.captures_iter(output) {
+ assert!(f.len() == 1);
+ filtered_output.push_str(&f[0]);
+ filtered_output.push('\n');
+ }
+
+ let filtered_output = Regex::new("(#\\d+)|(, *![0-9A-Za-z.]+)|(![0-9A-Za-z.]+)|(!\".*?\")")
+ .unwrap()
+ .replace_all(&filtered_output, "");
+
+ let mut llvm_as = Command::new("llvm-as")
+ .stdin(Stdio::piped())
+ .arg("-o")
+ .arg(&format!("{}/irrt.bc", out_dir))
+ .spawn()
+ .unwrap();
+ llvm_as.stdin.as_mut().unwrap().write_all(filtered_output.as_bytes()).unwrap();
+ assert!(llvm_as.wait().unwrap().success())
+}
diff --git a/nac3core/src/codegen/expr.rs b/nac3core/src/codegen/expr.rs
index 29eb8dec..6c8af87d 100644
--- a/nac3core/src/codegen/expr.rs
+++ b/nac3core/src/codegen/expr.rs
@@ -3,7 +3,9 @@ use std::{collections::HashMap, convert::TryInto, iter::once};
use crate::{
codegen::{
concrete_type::{ConcreteFuncArg, ConcreteTypeEnum, ConcreteTypeStore},
- get_llvm_type, CodeGenContext, CodeGenTask,
+ get_llvm_type,
+ irrt::integer_power,
+ CodeGenContext, CodeGenTask,
},
symbol_resolver::{SymbolValue, ValueEnum},
toplevel::{DefinitionId, TopLevelDef},
@@ -186,8 +188,8 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
Operator::LShift => self.builder.build_left_shift(lhs, rhs, "lshift").into(),
Operator::RShift => self.builder.build_right_shift(lhs, rhs, true, "rshift").into(),
Operator::FloorDiv => self.builder.build_int_signed_div(lhs, rhs, "floordiv").into(),
+ Operator::Pow => integer_power(self, lhs, rhs).into(),
// special implementation?
- Operator::Pow => unimplemented!(),
Operator::MatMult => unreachable!(),
}
}
@@ -205,6 +207,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
} else {
unreachable!()
};
+ let float = self.ctx.f64_type();
match op {
Operator::Add => self.builder.build_float_add(lhs, rhs, "fadd").into(),
Operator::Sub => self.builder.build_float_sub(lhs, rhs, "fsub").into(),
@@ -215,7 +218,6 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
let div = self.builder.build_float_div(lhs, rhs, "fdiv");
let floor_intrinsic =
self.module.get_function("llvm.floor.f64").unwrap_or_else(|| {
- let float = self.ctx.f64_type();
let fn_type = float.fn_type(&[float.into()], false);
self.module.add_function("llvm.floor.f64", fn_type, None)
});
@@ -225,6 +227,16 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
.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")
+ .try_as_basic_value()
+ .unwrap_left()
+ }
// special implementation?
_ => unimplemented!(),
}
@@ -630,6 +642,47 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>(
}
}
+pub fn gen_binop_expr<'ctx, 'a, G: CodeGenerator>(
+ generator: &mut G,
+ ctx: &mut CodeGenContext<'ctx, 'a>,
+ left: &Expr