core: Update cargo dependencies

This commit is contained in:
David Mak 2024-02-19 19:30:25 +08:00
parent e1dbe2526a
commit 8492503af2
17 changed files with 1123 additions and 966 deletions

100
Cargo.lock generated
View File

@ -2,17 +2,6 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "ahash"
version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9"
dependencies = [
"getrandom",
"once_cell",
"version_check",
]
[[package]] [[package]]
name = "ahash" name = "ahash"
version = "0.8.9" version = "0.8.9"
@ -133,12 +122,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.83" version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" checksum = "7f9fa1897e4325be0d68d48df6aa1a71ac2ed4d27723887e7754192705350730"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
@ -371,15 +357,6 @@ dependencies = [
"wasi", "wasi",
] ]
[[package]]
name = "hashbrown"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
dependencies = [
"ahash 0.7.8",
]
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.12.3" version = "0.12.3"
@ -391,6 +368,9 @@ name = "hashbrown"
version = "0.14.3" version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
dependencies = [
"ahash",
]
[[package]] [[package]]
name = "heck" name = "heck"
@ -432,23 +412,23 @@ checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8"
[[package]] [[package]]
name = "inkwell" name = "inkwell"
version = "0.2.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f4fcb4a4fa0b8f7b4178e24e6317d6f8b95ab500d8e6e1bd4283b6860e369c1" checksum = "b597a7b2cdf279aeef6d7149071e35e4bc87c2cf05a5b7f2d731300bffe587ea"
dependencies = [ dependencies = [
"either", "either",
"inkwell_internals", "inkwell_internals",
"libc", "libc",
"llvm-sys", "llvm-sys",
"once_cell", "once_cell",
"parking_lot", "thiserror",
] ]
[[package]] [[package]]
name = "inkwell_internals" name = "inkwell_internals"
version = "0.8.0" version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b185e7d068d6820411502efa14d8fbf010750485399402156b72dd2a548ef8e9" checksum = "4fa4d8d74483041a882adaa9a29f633253a66dde85055f0495c121620ac484b2"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -676,7 +656,7 @@ dependencies = [
name = "nac3parser" name = "nac3parser"
version = "0.1.2" version = "0.1.2"
dependencies = [ dependencies = [
"ahash 0.8.9", "ahash",
"insta", "insta",
"lalrpop", "lalrpop",
"lalrpop-util", "lalrpop-util",
@ -1114,12 +1094,12 @@ checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
[[package]] [[package]]
name = "string-interner" name = "string-interner"
version = "0.14.0" version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91e2531d8525b29b514d25e275a43581320d587b86db302b9a7e464bac579648" checksum = "07f9fdfdd31a0ff38b59deb401be81b73913d76c9cc5b1aed4e1330a223420b9"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"hashbrown 0.11.2", "hashbrown 0.14.3",
"serde", "serde",
] ]
@ -1166,9 +1146,9 @@ dependencies = [
[[package]] [[package]]
name = "target-lexicon" name = "target-lexicon"
version = "0.12.13" version = "0.12.14"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69758bda2e78f098e4ccb393021a0963bb3442eac05f135c30f61b7370bbafae" checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f"
[[package]] [[package]]
name = "tempfile" name = "tempfile"
@ -1405,7 +1385,7 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [ dependencies = [
"windows-targets 0.52.0", "windows-targets 0.52.3",
] ]
[[package]] [[package]]
@ -1425,17 +1405,17 @@ dependencies = [
[[package]] [[package]]
name = "windows-targets" name = "windows-targets"
version = "0.52.0" version = "0.52.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" checksum = "d380ba1dc7187569a8a9e91ed34b8ccfc33123bbacb8c0aed2d1ad7f3ef2dc5f"
dependencies = [ dependencies = [
"windows_aarch64_gnullvm 0.52.0", "windows_aarch64_gnullvm 0.52.3",
"windows_aarch64_msvc 0.52.0", "windows_aarch64_msvc 0.52.3",
"windows_i686_gnu 0.52.0", "windows_i686_gnu 0.52.3",
"windows_i686_msvc 0.52.0", "windows_i686_msvc 0.52.3",
"windows_x86_64_gnu 0.52.0", "windows_x86_64_gnu 0.52.3",
"windows_x86_64_gnullvm 0.52.0", "windows_x86_64_gnullvm 0.52.3",
"windows_x86_64_msvc 0.52.0", "windows_x86_64_msvc 0.52.3",
] ]
[[package]] [[package]]
@ -1446,9 +1426,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]] [[package]]
name = "windows_aarch64_gnullvm" name = "windows_aarch64_gnullvm"
version = "0.52.0" version = "0.52.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" checksum = "68e5dcfb9413f53afd9c8f86e56a7b4d86d9a2fa26090ea2dc9e40fba56c6ec6"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
@ -1458,9 +1438,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.52.0" version = "0.52.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" checksum = "8dab469ebbc45798319e69eebf92308e541ce46760b49b18c6b3fe5e8965b30f"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
@ -1470,9 +1450,9 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.52.0" version = "0.52.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" checksum = "2a4e9b6a7cac734a8b4138a4e1044eac3404d8326b6c0f939276560687a033fb"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
@ -1482,9 +1462,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.52.0" version = "0.52.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" checksum = "28b0ec9c422ca95ff34a78755cfa6ad4a51371da2a5ace67500cf7ca5f232c58"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
@ -1494,9 +1474,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.52.0" version = "0.52.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" checksum = "704131571ba93e89d7cd43482277d6632589b18ecf4468f591fbae0a8b101614"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
@ -1506,9 +1486,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
version = "0.52.0" version = "0.52.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" checksum = "42079295511643151e98d61c38c0acc444e52dd42ab456f7ccfd5152e8ecf21c"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
@ -1518,9 +1498,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.52.0" version = "0.52.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" checksum = "0770833d60a970638e989b3fa9fd2bb1aaadcf88963d1659fd7d9990196ed2d6"
[[package]] [[package]]
name = "yaml-rust" name = "yaml-rust"

View File

@ -12,13 +12,13 @@ crate-type = ["cdylib"]
itertools = "0.12" itertools = "0.12"
pyo3 = { version = "0.20", features = ["extension-module"] } pyo3 = { version = "0.20", features = ["extension-module"] }
parking_lot = "0.12" parking_lot = "0.12"
tempfile = "3.8" tempfile = "3.10"
nac3parser = { path = "../nac3parser" } nac3parser = { path = "../nac3parser" }
nac3core = { path = "../nac3core" } nac3core = { path = "../nac3core" }
nac3ld = { path = "../nac3ld" } nac3ld = { path = "../nac3ld" }
[dependencies.inkwell] [dependencies.inkwell]
version = "0.2" version = "0.4"
default-features = false default-features = false
features = ["llvm14-0", "target-x86", "target-arm", "target-riscv", "no-libffi-linking"] features = ["llvm14-0", "target-x86", "target-arm", "target-riscv", "no-libffi-linking"]

View File

@ -12,7 +12,11 @@ use nac3core::{
use nac3parser::ast::{Expr, ExprKind, Located, Stmt, StmtKind, StrRef}; use nac3parser::ast::{Expr, ExprKind, Located, Stmt, StmtKind, StrRef};
use inkwell::{ use inkwell::{
context::Context, module::Linkage, types::IntType, values::BasicValueEnum, AddressSpace, context::Context,
module::Linkage,
types::IntType,
values::{BasicValueEnum, CallSiteValue},
AddressSpace,
}; };
use pyo3::{PyObject, PyResult, Python, types::{PyDict, PyList}}; use pyo3::{PyObject, PyResult, Python, types::{PyDict, PyList}};
@ -25,6 +29,7 @@ use std::{
hash::{Hash, Hasher}, hash::{Hash, Hasher},
sync::Arc, sync::Arc,
}; };
use itertools::Either;
/// The parallelism mode within a block. /// The parallelism mode within a block.
#[derive(Copy, Clone, Eq, PartialEq)] #[derive(Copy, Clone, Eq, PartialEq)]
@ -139,15 +144,15 @@ impl<'a> ArtiqCodeGenerator<'a> {
let max = ctx let max = ctx
.builder .builder
.build_call(smax, &[old_end.into(), now.into()], "smax") .build_call(smax, &[old_end.into(), now.into()], "smax")
.try_as_basic_value() .map(CallSiteValue::try_as_basic_value)
.left() .map(Either::unwrap_left)
.unwrap(); .unwrap();
let end_store = self.gen_store_target( let end_store = self.gen_store_target(
ctx, ctx,
&end, &end,
store_name.map(|name| format!("{name}.addr")).as_deref())? store_name.map(|name| format!("{name}.addr")).as_deref())?
.unwrap(); .unwrap();
ctx.builder.build_store(end_store, max); ctx.builder.build_store(end_store, max).unwrap();
} }
Ok(()) Ok(())
@ -268,7 +273,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> {
let start = self let start = self
.gen_store_target(ctx, &start_expr, Some("start.addr"))? .gen_store_target(ctx, &start_expr, Some("start.addr"))?
.unwrap(); .unwrap();
ctx.builder.build_store(start, now); ctx.builder.build_store(start, now).unwrap();
Ok(Some(start_expr)) as Result<_, String> Ok(Some(start_expr)) as Result<_, String>
}, },
|v| Ok(Some(v)), |v| Ok(Some(v)),
@ -283,7 +288,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> {
let end = self let end = self
.gen_store_target(ctx, &end_expr, Some("end.addr"))? .gen_store_target(ctx, &end_expr, Some("end.addr"))?
.unwrap(); .unwrap();
ctx.builder.build_store(end, now); ctx.builder.build_store(end, now).unwrap();
self.end = Some(end_expr); self.end = Some(end_expr);
self.name_counter += 1; self.name_counter += 1;
self.parallel_mode = match id.to_string().as_str() { self.parallel_mode = match id.to_string().as_str() {
@ -477,12 +482,14 @@ fn rpc_codegen_callback_fn<'ctx>(
) )
}); });
let stackptr = ctx.builder.build_call(stacksave, &[], "rpc.stack"); let stackptr = ctx.builder.build_call(stacksave, &[], "rpc.stack").unwrap();
let args_ptr = ctx.builder.build_array_alloca( let args_ptr = ctx.builder
.build_array_alloca(
ptr_type, ptr_type,
ctx.ctx.i32_type().const_int(arg_length as u64, false), ctx.ctx.i32_type().const_int(arg_length as u64, false),
"argptr", "argptr",
); )
.unwrap();
// -- rpc args handling // -- rpc args handling
let mut keys = fun.0.args.clone(); let mut keys = fun.0.args.clone();
@ -515,16 +522,16 @@ fn rpc_codegen_callback_fn<'ctx>(
for (i, arg) in real_params.iter().enumerate() { for (i, arg) in real_params.iter().enumerate() {
let arg_slot = generator.gen_var_alloc(ctx, arg.get_type(), Some(&format!("rpc.arg{i}"))).unwrap(); let arg_slot = generator.gen_var_alloc(ctx, arg.get_type(), Some(&format!("rpc.arg{i}"))).unwrap();
ctx.builder.build_store(arg_slot, *arg); ctx.builder.build_store(arg_slot, *arg).unwrap();
let arg_slot = ctx.builder.build_bitcast(arg_slot, ptr_type, "rpc.arg"); let arg_slot = ctx.builder.build_bitcast(arg_slot, ptr_type, "rpc.arg").unwrap();
let arg_ptr = unsafe { let arg_ptr = unsafe {
ctx.builder.build_gep( ctx.builder.build_gep(
args_ptr, args_ptr,
&[int32.const_int(i as u64, false)], &[int32.const_int(i as u64, false)],
&format!("rpc.arg{i}"), &format!("rpc.arg{i}"),
) )
}; }.unwrap();
ctx.builder.build_store(arg_ptr, arg_slot); ctx.builder.build_store(arg_ptr, arg_slot).unwrap();
} }
// call // call
@ -542,18 +549,22 @@ fn rpc_codegen_callback_fn<'ctx>(
None, None,
) )
}); });
ctx.builder.build_call( ctx.builder
.build_call(
rpc_send, rpc_send,
&[service_id.into(), tag_ptr.into(), args_ptr.into()], &[service_id.into(), tag_ptr.into(), args_ptr.into()],
"rpc.send", "rpc.send",
); )
.unwrap();
// reclaim stack space used by arguments // reclaim stack space used by arguments
ctx.builder.build_call( ctx.builder
.build_call(
stackrestore, stackrestore,
&[stackptr.try_as_basic_value().unwrap_left().into()], &[stackptr.try_as_basic_value().unwrap_left().into()],
"rpc.stackrestore", "rpc.stackrestore",
); )
.unwrap();
// -- receive value: // -- receive value:
// T result = { // T result = {
@ -581,41 +592,45 @@ fn rpc_codegen_callback_fn<'ctx>(
let ret_ty = ctx.get_llvm_abi_type(generator, fun.0.ret); let ret_ty = ctx.get_llvm_abi_type(generator, fun.0.ret);
let need_load = !ret_ty.is_pointer_type(); let need_load = !ret_ty.is_pointer_type();
let slot = ctx.builder.build_alloca(ret_ty, "rpc.ret.slot"); let slot = ctx.builder.build_alloca(ret_ty, "rpc.ret.slot").unwrap();
let slotgen = ctx.builder.build_bitcast(slot, ptr_type, "rpc.ret.ptr"); let slotgen = ctx.builder.build_bitcast(slot, ptr_type, "rpc.ret.ptr").unwrap();
ctx.builder.build_unconditional_branch(head_bb); ctx.builder.build_unconditional_branch(head_bb).unwrap();
ctx.builder.position_at_end(head_bb); ctx.builder.position_at_end(head_bb);
let phi = ctx.builder.build_phi(ptr_type, "rpc.ptr"); let phi = ctx.builder.build_phi(ptr_type, "rpc.ptr").unwrap();
phi.add_incoming(&[(&slotgen, prehead_bb)]); phi.add_incoming(&[(&slotgen, prehead_bb)]);
let alloc_size = ctx let alloc_size = ctx
.build_call_or_invoke(rpc_recv, &[phi.as_basic_value()], "rpc.size.next") .build_call_or_invoke(rpc_recv, &[phi.as_basic_value()], "rpc.size.next")
.unwrap() .unwrap()
.into_int_value(); .into_int_value();
let is_done = ctx.builder.build_int_compare( let is_done = ctx.builder
.build_int_compare(
inkwell::IntPredicate::EQ, inkwell::IntPredicate::EQ,
int32.const_zero(), int32.const_zero(),
alloc_size, alloc_size,
"rpc.done", "rpc.done",
); )
.unwrap();
ctx.builder.build_conditional_branch(is_done, tail_bb, alloc_bb); ctx.builder.build_conditional_branch(is_done, tail_bb, alloc_bb).unwrap();
ctx.builder.position_at_end(alloc_bb); ctx.builder.position_at_end(alloc_bb);
let alloc_ptr = ctx.builder.build_array_alloca(ptr_type, alloc_size, "rpc.alloc"); let alloc_ptr = ctx.builder.build_array_alloca(ptr_type, alloc_size, "rpc.alloc").unwrap();
let alloc_ptr = ctx.builder.build_bitcast(alloc_ptr, ptr_type, "rpc.alloc.ptr"); let alloc_ptr = ctx.builder.build_bitcast(alloc_ptr, ptr_type, "rpc.alloc.ptr").unwrap();
phi.add_incoming(&[(&alloc_ptr, alloc_bb)]); phi.add_incoming(&[(&alloc_ptr, alloc_bb)]);
ctx.builder.build_unconditional_branch(head_bb); ctx.builder.build_unconditional_branch(head_bb).unwrap();
ctx.builder.position_at_end(tail_bb); ctx.builder.position_at_end(tail_bb);
let result = ctx.builder.build_load(slot, "rpc.result"); let result = ctx.builder.build_load(slot, "rpc.result").unwrap();
if need_load { if need_load {
ctx.builder.build_call( ctx.builder
.build_call(
stackrestore, stackrestore,
&[stackptr.try_as_basic_value().unwrap_left().into()], &[stackptr.try_as_basic_value().unwrap_left().into()],
"rpc.stackrestore", "rpc.stackrestore",
); )
.unwrap();
} }
Ok(Some(result)) Ok(Some(result))
} }

View File

@ -642,7 +642,13 @@ impl Nac3 {
let builder = context.create_builder(); let builder = context.create_builder();
let modinit_return = main.get_function("__modinit__").unwrap().get_last_basic_block().unwrap().get_terminator().unwrap(); let modinit_return = main.get_function("__modinit__").unwrap().get_last_basic_block().unwrap().get_terminator().unwrap();
builder.position_before(&modinit_return); builder.position_before(&modinit_return);
builder.build_call(main.get_function("attributes_writeback").unwrap(), &[], "attributes_writeback"); builder
.build_call(
main.get_function("attributes_writeback").unwrap(),
&[],
"attributes_writeback",
)
.unwrap();
main.link_in_module(load_irrt(&context)) main.link_in_module(load_irrt(&context))
.map_err(|err| CompileError::new_err(err.to_string()))?; .map_err(|err| CompileError::new_err(err.to_string()))?;

View File

@ -1,4 +1,5 @@
use inkwell::{values::BasicValueEnum, AddressSpace, AtomicOrdering}; use inkwell::{values::{BasicValueEnum, CallSiteValue}, AddressSpace, AtomicOrdering};
use itertools::Either;
use nac3core::codegen::CodeGenContext; use nac3core::codegen::CodeGenContext;
/// Functions for manipulating the timeline. /// Functions for manipulating the timeline.
@ -26,32 +27,28 @@ impl TimeFns for NowPinningTimeFns64 {
.module .module
.get_global("now") .get_global("now")
.unwrap_or_else(|| ctx.module.add_global(i64_type, None, "now")); .unwrap_or_else(|| ctx.module.add_global(i64_type, None, "now"));
let now_hiptr = let now_hiptr = ctx.builder
ctx.builder.build_bitcast(now, i32_type.ptr_type(AddressSpace::default()), "now.hi.addr"); .build_bitcast(now, i32_type.ptr_type(AddressSpace::default()), "now.hi.addr")
.map(BasicValueEnum::into_pointer_value)
let BasicValueEnum::PointerValue(now_hiptr) = now_hiptr else { .unwrap();
unreachable!()
};
let now_loptr = unsafe { let now_loptr = unsafe {
ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(2, false)], "now.lo.addr") ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(2, false)], "now.lo.addr")
}; }.unwrap();
let (BasicValueEnum::IntValue(now_hi), BasicValueEnum::IntValue(now_lo)) = ( let now_hi = ctx.builder.build_load(now_hiptr, "now.hi")
ctx.builder.build_load(now_hiptr, "now.hi"), .map(BasicValueEnum::into_int_value)
ctx.builder.build_load(now_loptr, "now.lo"), .unwrap();
) else { let now_lo = ctx.builder.build_load(now_loptr, "now.lo")
unreachable!() .map(BasicValueEnum::into_int_value)
}; .unwrap();
let zext_hi = ctx.builder.build_int_z_extend(now_hi, i64_type, ""); let zext_hi = ctx.builder.build_int_z_extend(now_hi, i64_type, "").unwrap();
let shifted_hi = ctx.builder.build_left_shift( let shifted_hi = ctx.builder
zext_hi, .build_left_shift(zext_hi, i64_type.const_int(32, false), "")
i64_type.const_int(32, false), .unwrap();
"", let zext_lo = ctx.builder.build_int_z_extend(now_lo, i64_type, "").unwrap();
); ctx.builder.build_or(shifted_hi, zext_lo, "now_mu").map(Into::into).unwrap()
let zext_lo = ctx.builder.build_int_z_extend(now_lo, i64_type, "");
ctx.builder.build_or(shifted_hi, zext_lo, "now_mu").into()
} }
fn emit_at_mu<'ctx>(&self, ctx: &mut CodeGenContext<'ctx, '_>, t: BasicValueEnum<'ctx>) { fn emit_at_mu<'ctx>(&self, ctx: &mut CodeGenContext<'ctx, '_>, t: BasicValueEnum<'ctx>) {
@ -59,39 +56,36 @@ impl TimeFns for NowPinningTimeFns64 {
let i64_type = ctx.ctx.i64_type(); let i64_type = ctx.ctx.i64_type();
let i64_32 = i64_type.const_int(32, false); let i64_32 = i64_type.const_int(32, false);
let BasicValueEnum::IntValue(time) = t else { let time = t.into_int_value();
unreachable!()
};
let time_hi = ctx.builder.build_int_truncate( let time_hi = ctx.builder
ctx.builder.build_right_shift(time, i64_32, false, "time.hi"), .build_int_truncate(
ctx.builder.build_right_shift(time, i64_32, false, "time.hi").unwrap(),
i32_type, i32_type,
"", "",
); )
let time_lo = ctx.builder.build_int_truncate(time, i32_type, "time.lo"); .unwrap();
let time_lo = ctx.builder.build_int_truncate(time, i32_type, "time.lo").unwrap();
let now = ctx let now = ctx
.module .module
.get_global("now") .get_global("now")
.unwrap_or_else(|| ctx.module.add_global(i64_type, None, "now")); .unwrap_or_else(|| ctx.module.add_global(i64_type, None, "now"));
let now_hiptr = ctx.builder.build_bitcast( let now_hiptr = ctx.builder
now, .build_bitcast(now, i32_type.ptr_type(AddressSpace::default()), "now.hi.addr")
i32_type.ptr_type(AddressSpace::default()), .map(BasicValueEnum::into_pointer_value)
"now.hi.addr", .unwrap();
);
let BasicValueEnum::PointerValue(now_hiptr) = now_hiptr else {
unreachable!()
};
let now_loptr = unsafe { let now_loptr = unsafe {
ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(2, false)], "now.lo.addr") ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(2, false)], "now.lo.addr")
}; }.unwrap();
ctx.builder ctx.builder
.build_store(now_hiptr, time_hi) .build_store(now_hiptr, time_hi)
.unwrap()
.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent) .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
.unwrap(); .unwrap();
ctx.builder ctx.builder
.build_store(now_loptr, time_lo) .build_store(now_loptr, time_lo)
.unwrap()
.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent) .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
.unwrap(); .unwrap();
} }
@ -107,57 +101,53 @@ impl TimeFns for NowPinningTimeFns64 {
.module .module
.get_global("now") .get_global("now")
.unwrap_or_else(|| ctx.module.add_global(i64_type, None, "now")); .unwrap_or_else(|| ctx.module.add_global(i64_type, None, "now"));
let now_hiptr = let now_hiptr = ctx.builder
ctx.builder.build_bitcast(now, i32_type.ptr_type(AddressSpace::default()), "now.hi.addr"); .build_bitcast(now, i32_type.ptr_type(AddressSpace::default()), "now.hi.addr")
.map(BasicValueEnum::into_pointer_value)
let BasicValueEnum::PointerValue(now_hiptr) = now_hiptr else { .unwrap();
unreachable!()
};
let now_loptr = unsafe { let now_loptr = unsafe {
ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(2, false)], "now.lo.addr") ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(2, false)], "now.lo.addr")
}; }.unwrap();
let ( let now_hi = ctx.builder.build_load(now_hiptr, "now.hi")
BasicValueEnum::IntValue(now_hi), .map(BasicValueEnum::into_int_value)
BasicValueEnum::IntValue(now_lo), .unwrap();
BasicValueEnum::IntValue(dt), let now_lo = ctx.builder.build_load(now_loptr, "now.lo")
) = ( .map(BasicValueEnum::into_int_value)
ctx.builder.build_load(now_hiptr, "now.hi"), .unwrap();
ctx.builder.build_load(now_loptr, "now.lo"), let dt = dt.into_int_value();
dt,
) else {
unreachable!()
};
let zext_hi = ctx.builder.build_int_z_extend(now_hi, i64_type, ""); let zext_hi = ctx.builder.build_int_z_extend(now_hi, i64_type, "").unwrap();
let shifted_hi = ctx.builder.build_left_shift( let shifted_hi = ctx.builder
zext_hi, .build_left_shift(zext_hi, i64_type.const_int(32, false), "")
i64_type.const_int(32, false), .unwrap();
"", let zext_lo = ctx.builder.build_int_z_extend(now_lo, i64_type, "").unwrap();
); let now_val = ctx.builder.build_or(shifted_hi, zext_lo, "now").unwrap();
let zext_lo = ctx.builder.build_int_z_extend(now_lo, i64_type, "");
let now_val = ctx.builder.build_or(shifted_hi, zext_lo, "now");
let time = ctx.builder.build_int_add(now_val, dt, "time"); let time = ctx.builder.build_int_add(now_val, dt, "time").unwrap();
let time_hi = ctx.builder.build_int_truncate( let time_hi = ctx.builder
.build_int_truncate(
ctx.builder.build_right_shift( ctx.builder.build_right_shift(
time, time,
i64_type.const_int(32, false), i64_type.const_int(32, false),
false, false,
"", "",
), ).unwrap(),
i32_type, i32_type,
"time.hi", "time.hi",
); )
let time_lo = ctx.builder.build_int_truncate(time, i32_type, "time.lo"); .unwrap();
let time_lo = ctx.builder.build_int_truncate(time, i32_type, "time.lo").unwrap();
ctx.builder ctx.builder
.build_store(now_hiptr, time_hi) .build_store(now_hiptr, time_hi)
.unwrap()
.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent) .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
.unwrap(); .unwrap();
ctx.builder ctx.builder
.build_store(now_loptr, time_lo) .build_store(now_loptr, time_lo)
.unwrap()
.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent) .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
.unwrap(); .unwrap();
} }
@ -174,16 +164,16 @@ impl TimeFns for NowPinningTimeFns {
.module .module
.get_global("now") .get_global("now")
.unwrap_or_else(|| ctx.module.add_global(i64_type, None, "now")); .unwrap_or_else(|| ctx.module.add_global(i64_type, None, "now"));
let now_raw = ctx.builder.build_load(now.as_pointer_value(), "now"); let now_raw = ctx.builder.build_load(now.as_pointer_value(), "now")
.map(BasicValueEnum::into_int_value)
let BasicValueEnum::IntValue(now_raw) = now_raw else { .unwrap();
unreachable!()
};
let i64_32 = i64_type.const_int(32, false); let i64_32 = i64_type.const_int(32, false);
let now_lo = ctx.builder.build_left_shift(now_raw, i64_32, "now.lo"); let now_lo = ctx.builder.build_left_shift(now_raw, i64_32, "now.lo").unwrap();
let now_hi = ctx.builder.build_right_shift(now_raw, i64_32, false, "now.hi"); let now_hi = ctx.builder.build_right_shift(now_raw, i64_32, false, "now.hi").unwrap();
ctx.builder.build_or(now_lo, now_hi, "now_mu").into() ctx.builder.build_or(now_lo, now_hi, "now_mu")
.map(Into::into)
.unwrap()
} }
fn emit_at_mu<'ctx>(&self, ctx: &mut CodeGenContext<'ctx, '_>, t: BasicValueEnum<'ctx>) { fn emit_at_mu<'ctx>(&self, ctx: &mut CodeGenContext<'ctx, '_>, t: BasicValueEnum<'ctx>) {
@ -191,39 +181,36 @@ impl TimeFns for NowPinningTimeFns {
let i64_type = ctx.ctx.i64_type(); let i64_type = ctx.ctx.i64_type();
let i64_32 = i64_type.const_int(32, false); let i64_32 = i64_type.const_int(32, false);
let BasicValueEnum::IntValue(time) = t else { let time = t.into_int_value();
unreachable!()
};
let time_hi = ctx.builder.build_int_truncate( let time_hi = ctx.builder
ctx.builder.build_right_shift(time, i64_32, false, ""), .build_int_truncate(
ctx.builder.build_right_shift(time, i64_32, false, "").unwrap(),
i32_type, i32_type,
"time.hi", "time.hi",
); )
let time_lo = ctx.builder.build_int_truncate(time, i32_type, "now_trunc"); .unwrap();
let time_lo = ctx.builder.build_int_truncate(time, i32_type, "now_trunc").unwrap();
let now = ctx let now = ctx
.module .module
.get_global("now") .get_global("now")
.unwrap_or_else(|| ctx.module.add_global(i64_type, None, "now")); .unwrap_or_else(|| ctx.module.add_global(i64_type, None, "now"));
let now_hiptr = ctx.builder.build_bitcast( let now_hiptr = ctx.builder
now, .build_bitcast(now, i32_type.ptr_type(AddressSpace::default()), "now.hi.addr")
i32_type.ptr_type(AddressSpace::default()), .map(BasicValueEnum::into_pointer_value)
"now.hi.addr", .unwrap();
);
let BasicValueEnum::PointerValue(now_hiptr) = now_hiptr else {
unreachable!()
};
let now_loptr = unsafe { let now_loptr = unsafe {
ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(1, false)], "now.lo.addr") ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(1, false)], "now.lo.addr")
}; }.unwrap();
ctx.builder ctx.builder
.build_store(now_hiptr, time_hi) .build_store(now_hiptr, time_hi)
.unwrap()
.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent) .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
.unwrap(); .unwrap();
ctx.builder ctx.builder
.build_store(now_loptr, time_lo) .build_store(now_loptr, time_lo)
.unwrap()
.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent) .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
.unwrap(); .unwrap();
} }
@ -240,41 +227,41 @@ impl TimeFns for NowPinningTimeFns {
.module .module
.get_global("now") .get_global("now")
.unwrap_or_else(|| ctx.module.add_global(i64_type, None, "now")); .unwrap_or_else(|| ctx.module.add_global(i64_type, None, "now"));
let now_raw = ctx.builder.build_load(now.as_pointer_value(), ""); let now_raw = ctx.builder
.build_load(now.as_pointer_value(), "")
.map(BasicValueEnum::into_int_value)
.unwrap();
let (BasicValueEnum::IntValue(now_raw), BasicValueEnum::IntValue(dt)) = (now_raw, dt) else { let dt = dt.into_int_value();
unreachable!()
};
let now_lo = ctx.builder.build_left_shift(now_raw, i64_32, "now.lo"); let now_lo = ctx.builder.build_left_shift(now_raw, i64_32, "now.lo").unwrap();
let now_hi = ctx.builder.build_right_shift(now_raw, i64_32, false, "now.hi"); let now_hi = ctx.builder.build_right_shift(now_raw, i64_32, false, "now.hi").unwrap();
let now_val = ctx.builder.build_or(now_lo, now_hi, "now_val"); let now_val = ctx.builder.build_or(now_lo, now_hi, "now_val").unwrap();
let time = ctx.builder.build_int_add(now_val, dt, "time"); let time = ctx.builder.build_int_add(now_val, dt, "time").unwrap();
let time_hi = ctx.builder.build_int_truncate( let time_hi = ctx.builder
ctx.builder.build_right_shift(time, i64_32, false, "time.hi"), .build_int_truncate(
ctx.builder.build_right_shift(time, i64_32, false, "time.hi").unwrap(),
i32_type, i32_type,
"now_trunc", "now_trunc",
); )
let time_lo = ctx.builder.build_int_truncate(time, i32_type, "time.lo"); .unwrap();
let now_hiptr = ctx.builder.build_bitcast( let time_lo = ctx.builder.build_int_truncate(time, i32_type, "time.lo").unwrap();
now, let now_hiptr = ctx.builder
i32_type.ptr_type(AddressSpace::default()), .build_bitcast(now, i32_type.ptr_type(AddressSpace::default()), "now.hi.addr")
"now.hi.addr", .map(BasicValueEnum::into_pointer_value)
); .unwrap();
let BasicValueEnum::PointerValue(now_hiptr) = now_hiptr else {
unreachable!()
};
let now_loptr = unsafe { let now_loptr = unsafe {
ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(1, false)], "now.lo.addr") ctx.builder.build_gep(now_hiptr, &[i32_type.const_int(1, false)], "now.lo.addr")
}; }.unwrap();
ctx.builder ctx.builder
.build_store(now_hiptr, time_hi) .build_store(now_hiptr, time_hi)
.unwrap()
.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent) .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
.unwrap(); .unwrap();
ctx.builder ctx.builder
.build_store(now_loptr, time_lo) .build_store(now_loptr, time_lo)
.unwrap()
.set_atomic_ordering(AtomicOrdering::SequentiallyConsistent) .set_atomic_ordering(AtomicOrdering::SequentiallyConsistent)
.unwrap(); .unwrap();
} }
@ -289,7 +276,10 @@ impl TimeFns for ExternTimeFns {
let now_mu = ctx.module.get_function("now_mu").unwrap_or_else(|| { let now_mu = ctx.module.get_function("now_mu").unwrap_or_else(|| {
ctx.module.add_function("now_mu", ctx.ctx.i64_type().fn_type(&[], false), None) ctx.module.add_function("now_mu", ctx.ctx.i64_type().fn_type(&[], false), None)
}); });
ctx.builder.build_call(now_mu, &[], "now_mu").try_as_basic_value().left().unwrap() ctx.builder.build_call(now_mu, &[], "now_mu")
.map(CallSiteValue::try_as_basic_value)
.map(Either::unwrap_left)
.unwrap()
} }
fn emit_at_mu<'ctx>(&self, ctx: &mut CodeGenContext<'ctx, '_>, t: BasicValueEnum<'ctx>) { fn emit_at_mu<'ctx>(&self, ctx: &mut CodeGenContext<'ctx, '_>, t: BasicValueEnum<'ctx>) {
@ -300,7 +290,7 @@ impl TimeFns for ExternTimeFns {
None, None,
) )
}); });
ctx.builder.build_call(at_mu, &[t.into()], "at_mu"); ctx.builder.build_call(at_mu, &[t.into()], "at_mu").unwrap();
} }
fn emit_delay_mu<'ctx>( fn emit_delay_mu<'ctx>(
@ -315,7 +305,7 @@ impl TimeFns for ExternTimeFns {
None, None,
) )
}); });
ctx.builder.build_call(delay_mu, &[dt.into()], "delay_mu"); ctx.builder.build_call(delay_mu, &[dt.into()], "delay_mu").unwrap();
} }
} }

View File

@ -12,5 +12,5 @@ fold = []
[dependencies] [dependencies]
lazy_static = "1.4" lazy_static = "1.4"
parking_lot = "0.12" parking_lot = "0.12"
string-interner = "0.14" string-interner = "0.15"
fxhash = "0.2" fxhash = "0.2"

View File

@ -5,10 +5,10 @@ pub use crate::constant::*;
use std::{fmt, collections::HashMap, cell::RefCell}; use std::{fmt, collections::HashMap, cell::RefCell};
use parking_lot::{Mutex, MutexGuard}; use parking_lot::{Mutex, MutexGuard};
use string_interner::{DefaultBackend, DefaultSymbol, StringInterner, symbol::SymbolU32}; use string_interner::{DefaultBackend, StringInterner, symbol::SymbolU32};
use fxhash::FxBuildHasher; use fxhash::FxBuildHasher;
pub type Interner = StringInterner<DefaultBackend<DefaultSymbol>, FxBuildHasher>; pub type Interner = StringInterner<DefaultBackend, FxBuildHasher>;
lazy_static! { lazy_static! {
static ref INTERNER: Mutex<Interner> = Mutex::new(StringInterner::with_hasher(FxBuildHasher::default())); static ref INTERNER: Mutex<Interner> = Mutex::new(StringInterner::with_hasher(FxBuildHasher::default()));
} }

View File

@ -8,11 +8,11 @@ edition = "2021"
itertools = "0.12" itertools = "0.12"
crossbeam = "0.8" crossbeam = "0.8"
parking_lot = "0.12" parking_lot = "0.12"
rayon = "1.5" rayon = "1.8"
nac3parser = { path = "../nac3parser" } nac3parser = { path = "../nac3parser" }
[dependencies.inkwell] [dependencies.inkwell]
version = "0.2" version = "0.4"
default-features = false default-features = false
features = ["llvm14-0", "target-x86", "target-arm", "target-riscv", "no-libffi-linking"] features = ["llvm14-0", "target-x86", "target-arm", "target-riscv", "no-libffi-linking"]

View File

@ -1,8 +1,9 @@
use inkwell::{ use inkwell::{
IntPredicate, IntPredicate,
types::{AnyTypeEnum, BasicTypeEnum, IntType, PointerType}, types::{AnyTypeEnum, BasicTypeEnum, IntType, PointerType},
values::{ArrayValue, BasicValueEnum, IntValue, PointerValue}, values::{ArrayValue, BasicValueEnum, CallSiteValue, IntValue, PointerValue},
}; };
use itertools::Either;
use crate::codegen::{ use crate::codegen::{
CodeGenContext, CodeGenContext,
CodeGenerator, CodeGenerator,
@ -79,7 +80,7 @@ impl<'ctx> ListValue<'ctx> {
self.get_ptr(), self.get_ptr(),
&[llvm_i32.const_zero(), llvm_i32.const_zero()], &[llvm_i32.const_zero(), llvm_i32.const_zero()],
var_name.as_str(), var_name.as_str(),
) ).unwrap()
} }
} }
@ -93,13 +94,13 @@ impl<'ctx> ListValue<'ctx> {
self.0, self.0,
&[llvm_i32.const_zero(), llvm_i32.const_int(1, true)], &[llvm_i32.const_zero(), llvm_i32.const_int(1, true)],
var_name.as_str(), var_name.as_str(),
) ).unwrap()
} }
} }
/// Stores the array of data elements `data` into this instance. /// Stores the array of data elements `data` into this instance.
fn store_data(&self, ctx: &CodeGenContext<'ctx, '_>, data: PointerValue<'ctx>) { fn store_data(&self, ctx: &CodeGenContext<'ctx, '_>, data: PointerValue<'ctx>) {
ctx.builder.build_store(self.get_data_pptr(ctx), data); ctx.builder.build_store(self.get_data_pptr(ctx), data).unwrap();
} }
/// Convenience method for creating a new array storing data elements with the given element /// Convenience method for creating a new array storing data elements with the given element
@ -113,7 +114,7 @@ impl<'ctx> ListValue<'ctx> {
size: Option<IntValue<'ctx>>, size: Option<IntValue<'ctx>>,
) { ) {
let size = size.unwrap_or_else(|| self.load_size(ctx, None)); let size = size.unwrap_or_else(|| self.load_size(ctx, None));
self.store_data(ctx, ctx.builder.build_array_alloca(elem_ty, size, "")); self.store_data(ctx, ctx.builder.build_array_alloca(elem_ty, size, "").unwrap());
} }
/// Returns the double-indirection pointer to the `data` array, as if by calling `getelementptr` /// Returns the double-indirection pointer to the `data` array, as if by calling `getelementptr`
@ -132,7 +133,7 @@ impl<'ctx> ListValue<'ctx> {
debug_assert_eq!(size.get_type(), generator.get_size_type(ctx.ctx)); debug_assert_eq!(size.get_type(), generator.get_size_type(ctx.ctx));
let psize = self.get_size_ptr(ctx); let psize = self.get_size_ptr(ctx);
ctx.builder.build_store(psize, size); ctx.builder.build_store(psize, size).unwrap();
} }
/// Returns the size of this `list` as a value. /// Returns the size of this `list` as a value.
@ -143,7 +144,9 @@ impl<'ctx> ListValue<'ctx> {
.or_else(|| self.1.map(|v| format!("{v}.size"))) .or_else(|| self.1.map(|v| format!("{v}.size")))
.unwrap_or_default(); .unwrap_or_default();
ctx.builder.build_load(psize, var_name.as_str()).into_int_value() ctx.builder.build_load(psize, var_name.as_str())
.map(BasicValueEnum::into_int_value)
.unwrap()
} }
} }
@ -156,7 +159,9 @@ impl<'ctx> ListDataProxy<'ctx> {
pub fn get_ptr(&self, ctx: &CodeGenContext<'ctx, '_>) -> PointerValue<'ctx> { pub fn get_ptr(&self, ctx: &CodeGenContext<'ctx, '_>) -> PointerValue<'ctx> {
let var_name = self.0.1.map(|v| format!("{v}.data")).unwrap_or_default(); let var_name = self.0.1.map(|v| format!("{v}.data")).unwrap_or_default();
ctx.builder.build_load(self.0.get_data_pptr(ctx), var_name.as_str()).into_pointer_value() ctx.builder.build_load(self.0.get_data_pptr(ctx), var_name.as_str())
.map(BasicValueEnum::into_pointer_value)
.unwrap()
} }
pub unsafe fn ptr_offset_unchecked( pub unsafe fn ptr_offset_unchecked(
@ -173,7 +178,7 @@ impl<'ctx> ListDataProxy<'ctx> {
self.get_ptr(ctx), self.get_ptr(ctx),
&[idx], &[idx],
var_name.as_str(), var_name.as_str(),
) ).unwrap()
} }
/// Returns the pointer to the data at the `idx`-th index. /// Returns the pointer to the data at the `idx`-th index.
@ -191,7 +196,7 @@ impl<'ctx> ListDataProxy<'ctx> {
idx, idx,
self.0.load_size(ctx, None), self.0.load_size(ctx, None),
"" ""
); ).unwrap();
ctx.make_assert( ctx.make_assert(
generator, generator,
in_range, in_range,
@ -213,7 +218,7 @@ impl<'ctx> ListDataProxy<'ctx> {
name: Option<&str>, name: Option<&str>,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
let ptr = self.ptr_offset_unchecked(ctx, idx, name); let ptr = self.ptr_offset_unchecked(ctx, idx, name);
ctx.builder.build_load(ptr, name.unwrap_or_default()) ctx.builder.build_load(ptr, name.unwrap_or_default()).unwrap()
} }
/// Returns the data at the `idx`-th flattened index. /// Returns the data at the `idx`-th flattened index.
@ -225,7 +230,7 @@ impl<'ctx> ListDataProxy<'ctx> {
name: Option<&str>, name: Option<&str>,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
let ptr = self.ptr_offset(ctx, generator, idx, name); let ptr = self.ptr_offset(ctx, generator, idx, name);
ctx.builder.build_load(ptr, name.unwrap_or_default()) ctx.builder.build_load(ptr, name.unwrap_or_default()).unwrap()
} }
} }
@ -286,7 +291,7 @@ impl<'ctx> RangeValue<'ctx> {
self.0, self.0,
&[llvm_i32.const_zero(), llvm_i32.const_int(0, false)], &[llvm_i32.const_zero(), llvm_i32.const_int(0, false)],
var_name.as_str(), var_name.as_str(),
) ).unwrap()
} }
} }
@ -299,7 +304,7 @@ impl<'ctx> RangeValue<'ctx> {
self.0, self.0,
&[llvm_i32.const_zero(), llvm_i32.const_int(1, false)], &[llvm_i32.const_zero(), llvm_i32.const_int(1, false)],
var_name.as_str(), var_name.as_str(),
) ).unwrap()
} }
} }
@ -312,7 +317,7 @@ impl<'ctx> RangeValue<'ctx> {
self.0, self.0,
&[llvm_i32.const_zero(), llvm_i32.const_int(2, false)], &[llvm_i32.const_zero(), llvm_i32.const_int(2, false)],
var_name.as_str(), var_name.as_str(),
) ).unwrap()
} }
} }
@ -325,7 +330,7 @@ impl<'ctx> RangeValue<'ctx> {
debug_assert_eq!(start.get_type().get_bit_width(), 32); debug_assert_eq!(start.get_type().get_bit_width(), 32);
let pstart = self.get_start_ptr(ctx); let pstart = self.get_start_ptr(ctx);
ctx.builder.build_store(pstart, start); ctx.builder.build_store(pstart, start).unwrap();
} }
/// Returns the `start` value of this `range`. /// Returns the `start` value of this `range`.
@ -336,7 +341,9 @@ impl<'ctx> RangeValue<'ctx> {
.or_else(|| self.1.map(|v| format!("{v}.start"))) .or_else(|| self.1.map(|v| format!("{v}.start")))
.unwrap_or_default(); .unwrap_or_default();
ctx.builder.build_load(pstart, var_name.as_str()).into_int_value() ctx.builder.build_load(pstart, var_name.as_str())
.map(BasicValueEnum::into_int_value)
.unwrap()
} }
/// Stores the `end` value into this instance. /// Stores the `end` value into this instance.
@ -348,7 +355,7 @@ impl<'ctx> RangeValue<'ctx> {
debug_assert_eq!(end.get_type().get_bit_width(), 32); debug_assert_eq!(end.get_type().get_bit_width(), 32);
let pend = self.get_start_ptr(ctx); let pend = self.get_start_ptr(ctx);
ctx.builder.build_store(pend, end); ctx.builder.build_store(pend, end).unwrap();
} }
/// Returns the `end` value of this `range`. /// Returns the `end` value of this `range`.
@ -359,7 +366,9 @@ impl<'ctx> RangeValue<'ctx> {
.or_else(|| self.1.map(|v| format!("{v}.end"))) .or_else(|| self.1.map(|v| format!("{v}.end")))
.unwrap_or_default(); .unwrap_or_default();
ctx.builder.build_load(pend, var_name.as_str()).into_int_value() ctx.builder.build_load(pend, var_name.as_str())
.map(BasicValueEnum::into_int_value)
.unwrap()
} }
/// Stores the `step` value into this instance. /// Stores the `step` value into this instance.
@ -371,7 +380,7 @@ impl<'ctx> RangeValue<'ctx> {
debug_assert_eq!(step.get_type().get_bit_width(), 32); debug_assert_eq!(step.get_type().get_bit_width(), 32);
let pstep = self.get_start_ptr(ctx); let pstep = self.get_start_ptr(ctx);
ctx.builder.build_store(pstep, step); ctx.builder.build_store(pstep, step).unwrap();
} }
/// Returns the `step` value of this `range`. /// Returns the `step` value of this `range`.
@ -382,7 +391,9 @@ impl<'ctx> RangeValue<'ctx> {
.or_else(|| self.1.map(|v| format!("{v}.step"))) .or_else(|| self.1.map(|v| format!("{v}.step")))
.unwrap_or_default(); .unwrap_or_default();
ctx.builder.build_load(pstep, var_name.as_str()).into_int_value() ctx.builder.build_load(pstep, var_name.as_str())
.map(BasicValueEnum::into_int_value)
.unwrap()
} }
} }
@ -472,7 +483,7 @@ impl<'ctx> NDArrayValue<'ctx> {
self.0, self.0,
&[llvm_i32.const_zero(), llvm_i32.const_zero()], &[llvm_i32.const_zero(), llvm_i32.const_zero()],
var_name.as_str(), var_name.as_str(),
) ).unwrap()
} }
} }
@ -486,13 +497,15 @@ impl<'ctx> NDArrayValue<'ctx> {
debug_assert_eq!(ndims.get_type(), generator.get_size_type(ctx.ctx)); debug_assert_eq!(ndims.get_type(), generator.get_size_type(ctx.ctx));
let pndims = self.get_ndims(ctx); let pndims = self.get_ndims(ctx);
ctx.builder.build_store(pndims, ndims); ctx.builder.build_store(pndims, ndims).unwrap();
} }
/// Returns the number of dimensions of this `NDArray` as a value. /// Returns the number of dimensions of this `NDArray` as a value.
pub fn load_ndims(&self, ctx: &CodeGenContext<'ctx, '_>) -> IntValue<'ctx> { pub fn load_ndims(&self, ctx: &CodeGenContext<'ctx, '_>) -> IntValue<'ctx> {
let pndims = self.get_ndims(ctx); let pndims = self.get_ndims(ctx);
ctx.builder.build_load(pndims, "").into_int_value() ctx.builder.build_load(pndims, "")
.map(BasicValueEnum::into_int_value)
.unwrap()
} }
/// Returns the double-indirection pointer to the `dims` array, as if by calling `getelementptr` /// Returns the double-indirection pointer to the `dims` array, as if by calling `getelementptr`
@ -506,13 +519,13 @@ impl<'ctx> NDArrayValue<'ctx> {
self.get_ptr(), self.get_ptr(),
&[llvm_i32.const_zero(), llvm_i32.const_int(1, true)], &[llvm_i32.const_zero(), llvm_i32.const_int(1, true)],
var_name.as_str(), var_name.as_str(),
) ).unwrap()
} }
} }
/// Stores the array of dimension sizes `dims` into this instance. /// Stores the array of dimension sizes `dims` into this instance.
fn store_dims(&self, ctx: &CodeGenContext<'ctx, '_>, dims: PointerValue<'ctx>) { fn store_dims(&self, ctx: &CodeGenContext<'ctx, '_>, dims: PointerValue<'ctx>) {
ctx.builder.build_store(self.get_dims_ptr(ctx), dims); ctx.builder.build_store(self.get_dims_ptr(ctx), dims).unwrap();
} }
/// Convenience method for creating a new array storing dimension sizes with the given `size`. /// Convenience method for creating a new array storing dimension sizes with the given `size`.
@ -522,7 +535,7 @@ impl<'ctx> NDArrayValue<'ctx> {
llvm_usize: IntType<'ctx>, llvm_usize: IntType<'ctx>,
size: IntValue<'ctx>, size: IntValue<'ctx>,
) { ) {
self.store_dims(ctx, ctx.builder.build_array_alloca(llvm_usize, size, "")); self.store_dims(ctx, ctx.builder.build_array_alloca(llvm_usize, size, "").unwrap());
} }
/// Returns a proxy object to the field storing the size of each dimension of this `NDArray`. /// Returns a proxy object to the field storing the size of each dimension of this `NDArray`.
@ -541,25 +554,24 @@ impl<'ctx> NDArrayValue<'ctx> {
self.get_ptr(), self.get_ptr(),
&[llvm_i32.const_zero(), llvm_i32.const_int(2, true)], &[llvm_i32.const_zero(), llvm_i32.const_int(2, true)],
var_name.as_str(), var_name.as_str(),
) ).unwrap()
} }
} }
/// Stores the array of data elements `data` into this instance. /// Stores the array of data elements `data` into this instance.
fn store_data(&self, ctx: &CodeGenContext<'ctx, '_>, data: PointerValue<'ctx>) { fn store_data(&self, ctx: &CodeGenContext<'ctx, '_>, data: PointerValue<'ctx>) {
ctx.builder.build_store(self.get_data_ptr(ctx), data); ctx.builder.build_store(self.get_data_ptr(ctx), data).unwrap();
} }
/// Convenience method for creating a new array storing data elements with the given element /// Convenience method for creating a new array storing data elements with the given element
/// type `elem_ty` and /// type `elem_ty` and `size`.
/// `size`.
pub fn create_data( pub fn create_data(
&self, &self,
ctx: &CodeGenContext<'ctx, '_>, ctx: &CodeGenContext<'ctx, '_>,
elem_ty: BasicTypeEnum<'ctx>, elem_ty: BasicTypeEnum<'ctx>,
size: IntValue<'ctx>, size: IntValue<'ctx>,
) { ) {
self.store_data(ctx, ctx.builder.build_array_alloca(elem_ty, size, "")); self.store_data(ctx, ctx.builder.build_array_alloca(elem_ty, size, "").unwrap());
} }
/// Returns a proxy object to the field storing the data of this `NDArray`. /// Returns a proxy object to the field storing the data of this `NDArray`.
@ -583,7 +595,9 @@ impl<'ctx> NDArrayDimsProxy<'ctx> {
pub fn get_ptr(&self, ctx: &CodeGenContext<'ctx, '_>) -> PointerValue<'ctx> { pub fn get_ptr(&self, ctx: &CodeGenContext<'ctx, '_>) -> PointerValue<'ctx> {
let var_name = self.0.1.map(|v| format!("{v}.dims")).unwrap_or_default(); let var_name = self.0.1.map(|v| format!("{v}.dims")).unwrap_or_default();
ctx.builder.build_load(self.0.get_dims_ptr(ctx), var_name.as_str()).into_pointer_value() ctx.builder.build_load(self.0.get_dims_ptr(ctx), var_name.as_str())
.map(BasicValueEnum::into_pointer_value)
.unwrap()
} }
/// Returns the pointer to the size of the `idx`-th dimension. /// Returns the pointer to the size of the `idx`-th dimension.
@ -599,7 +613,7 @@ impl<'ctx> NDArrayDimsProxy<'ctx> {
idx, idx,
self.0.load_ndims(ctx), self.0.load_ndims(ctx),
"" ""
); ).unwrap();
ctx.make_assert( ctx.make_assert(
generator, generator,
in_range, in_range,
@ -618,7 +632,7 @@ impl<'ctx> NDArrayDimsProxy<'ctx> {
self.get_ptr(ctx), self.get_ptr(ctx),
&[idx], &[idx],
var_name.as_str(), var_name.as_str(),
) ).unwrap()
} }
} }
@ -631,7 +645,9 @@ impl<'ctx> NDArrayDimsProxy<'ctx> {
name: Option<&str>, name: Option<&str>,
) -> IntValue<'ctx> { ) -> IntValue<'ctx> {
let ptr = self.ptr_offset(ctx, generator, idx, name); let ptr = self.ptr_offset(ctx, generator, idx, name);
ctx.builder.build_load(ptr, name.unwrap_or_default()).into_int_value() ctx.builder.build_load(ptr, name.unwrap_or_default())
.map(BasicValueEnum::into_int_value)
.unwrap()
} }
} }
@ -644,7 +660,9 @@ impl<'ctx> NDArrayDataProxy<'ctx> {
pub fn get_ptr(&self, ctx: &CodeGenContext<'ctx, '_>) -> PointerValue<'ctx> { pub fn get_ptr(&self, ctx: &CodeGenContext<'ctx, '_>) -> PointerValue<'ctx> {
let var_name = self.0.1.map(|v| format!("{v}.data")).unwrap_or_default(); let var_name = self.0.1.map(|v| format!("{v}.data")).unwrap_or_default();
ctx.builder.build_load(self.0.get_data_ptr(ctx), var_name.as_str()).into_pointer_value() ctx.builder.build_load(self.0.get_data_ptr(ctx), var_name.as_str())
.map(BasicValueEnum::into_pointer_value)
.unwrap()
} }
pub unsafe fn ptr_to_data_flattened_unchecked( pub unsafe fn ptr_to_data_flattened_unchecked(
@ -657,7 +675,7 @@ impl<'ctx> NDArrayDataProxy<'ctx> {
self.get_ptr(ctx), self.get_ptr(ctx),
&[idx], &[idx],
name.unwrap_or_default(), name.unwrap_or_default(),
) ).unwrap()
} }
/// Returns the pointer to the data at the `idx`-th flattened index. /// Returns the pointer to the data at the `idx`-th flattened index.
@ -677,7 +695,7 @@ impl<'ctx> NDArrayDataProxy<'ctx> {
idx, idx,
data_sz, data_sz,
"" ""
); ).unwrap();
ctx.make_assert( ctx.make_assert(
generator, generator,
in_range, in_range,
@ -699,7 +717,7 @@ impl<'ctx> NDArrayDataProxy<'ctx> {
name: Option<&str>, name: Option<&str>,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
let ptr = self.ptr_to_data_flattened_unchecked(ctx, idx, name); let ptr = self.ptr_to_data_flattened_unchecked(ctx, idx, name);
ctx.builder.build_load(ptr, name.unwrap_or_default()) ctx.builder.build_load(ptr, name.unwrap_or_default()).unwrap()
} }
/// Returns the data at the `idx`-th flattened index. /// Returns the data at the `idx`-th flattened index.
@ -711,7 +729,7 @@ impl<'ctx> NDArrayDataProxy<'ctx> {
name: Option<&str>, name: Option<&str>,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
let ptr = self.ptr_to_data_flattened(ctx, generator, idx, name); let ptr = self.ptr_to_data_flattened(ctx, generator, idx, name);
ctx.builder.build_load(ptr, name.unwrap_or_default()) ctx.builder.build_load(ptr, name.unwrap_or_default()).unwrap()
} }
pub unsafe fn ptr_offset_unchecked( pub unsafe fn ptr_offset_unchecked(
@ -725,7 +743,7 @@ impl<'ctx> NDArrayDataProxy<'ctx> {
let Ok(indices_elem_ty) = IntType::try_from(indices_elem_ty) else { let Ok(indices_elem_ty) = IntType::try_from(indices_elem_ty) else {
panic!("Expected list[int32] but got {indices_elem_ty}") panic!("Expected list[int32] but got {indices_elem_ty}")
}; };
debug_assert_eq!(indices_elem_ty.get_bit_width(), 32, "Expected list[int32] but got {indices_elem_ty}"); assert_eq!(indices_elem_ty.get_bit_width(), 32, "Expected list[int32] but got {indices_elem_ty}");
let index = call_ndarray_flatten_index( let index = call_ndarray_flatten_index(
generator, generator,
@ -739,7 +757,7 @@ impl<'ctx> NDArrayDataProxy<'ctx> {
self.get_ptr(ctx), self.get_ptr(ctx),
&[index], &[index],
name.unwrap_or_default(), name.unwrap_or_default(),
) ).unwrap()
} }
} }
@ -763,7 +781,7 @@ impl<'ctx> NDArrayDataProxy<'ctx> {
&[index], &[index],
name.unwrap_or_default(), name.unwrap_or_default(),
) )
} }.unwrap()
} }
/// Returns the pointer to the data at the index specified by `indices`. /// Returns the pointer to the data at the index specified by `indices`.
@ -787,7 +805,7 @@ impl<'ctx> NDArrayDataProxy<'ctx> {
llvm_usize.const_int(indices.get_type().len() as u64, false), llvm_usize.const_int(indices.get_type().len() as u64, false),
self.0.load_ndims(ctx), self.0.load_ndims(ctx),
"" ""
); ).unwrap();
ctx.make_assert( ctx.make_assert(
generator, generator,
nidx_leq_ndims, nidx_leq_ndims,
@ -802,8 +820,8 @@ impl<'ctx> NDArrayDataProxy<'ctx> {
let dim_idx = ctx.builder let dim_idx = ctx.builder
.build_extract_value(indices, idx, "") .build_extract_value(indices, idx, "")
.map(|v| v.into_int_value()) .map(BasicValueEnum::into_int_value)
.map(|v| ctx.builder.build_int_z_extend_or_bit_cast(v, llvm_usize, "")) .map(|v| ctx.builder.build_int_z_extend_or_bit_cast(v, llvm_usize, "").unwrap())
.unwrap(); .unwrap();
let dim_sz = self.0.get_dims().get(ctx, generator, i, None); let dim_sz = self.0.get_dims().get(ctx, generator, i, None);
@ -812,7 +830,7 @@ impl<'ctx> NDArrayDataProxy<'ctx> {
dim_idx, dim_idx,
dim_sz, dim_sz,
"" ""
); ).unwrap();
ctx.make_assert( ctx.make_assert(
generator, generator,
@ -844,7 +862,7 @@ impl<'ctx> NDArrayDataProxy<'ctx> {
indices.load_size(ctx, None), indices.load_size(ctx, None),
self.0.load_ndims(ctx), self.0.load_ndims(ctx),
"" ""
); ).unwrap();
ctx.make_assert( ctx.make_assert(
generator, generator,
nidx_leq_ndims, nidx_leq_ndims,
@ -859,7 +877,7 @@ impl<'ctx> NDArrayDataProxy<'ctx> {
ctx, ctx,
|generator, ctx| { |generator, ctx| {
let i = generator.gen_var_alloc(ctx, llvm_usize.into(), None)?; let i = generator.gen_var_alloc(ctx, llvm_usize.into(), None)?;
ctx.builder.build_store(i, llvm_usize.const_zero()); ctx.builder.build_store(i, llvm_usize.const_zero()).unwrap();
Ok(i) Ok(i)
}, },
@ -879,16 +897,20 @@ impl<'ctx> NDArrayDataProxy<'ctx> {
let len = ctx let len = ctx
.builder .builder
.build_call(min_fn, &[indices_len.into(), ndarray_len.into()], "") .build_call(min_fn, &[indices_len.into(), ndarray_len.into()], "")
.try_as_basic_value() .map(CallSiteValue::try_as_basic_value)
.map_left(|v| v.into_int_value()) .map(|v| v.map_left(BasicValueEnum::into_int_value))
.left() .map(Either::unwrap_left)
.unwrap(); .unwrap();
let i = ctx.builder.build_load(i_addr, "").into_int_value(); let i = ctx.builder.build_load(i_addr, "")
Ok(ctx.builder.build_int_compare(IntPredicate::SLT, i, len, "")) .map(BasicValueEnum::into_int_value)
.unwrap();
Ok(ctx.builder.build_int_compare(IntPredicate::SLT, i, len, "").unwrap())
}, },
|generator, ctx, i_addr| { |generator, ctx, i_addr| {
let i = ctx.builder.build_load(i_addr, "").into_int_value(); let i = ctx.builder.build_load(i_addr, "")
.map(BasicValueEnum::into_int_value)
.unwrap();
let (dim_idx, dim_sz) = unsafe { let (dim_idx, dim_sz) = unsafe {
( (
indices.get_data().get_unchecked(ctx, i, None).into_int_value(), indices.get_data().get_unchecked(ctx, i, None).into_int_value(),
@ -901,7 +923,7 @@ impl<'ctx> NDArrayDataProxy<'ctx> {
dim_idx, dim_idx,
dim_sz, dim_sz,
"" ""
); ).unwrap();
ctx.make_assert( ctx.make_assert(
generator, generator,
@ -917,9 +939,10 @@ impl<'ctx> NDArrayDataProxy<'ctx> {
|_, ctx, i_addr| { |_, ctx, i_addr| {
let i = ctx.builder let i = ctx.builder
.build_load(i_addr, "") .build_load(i_addr, "")
.into_int_value(); .map(BasicValueEnum::into_int_value)
let i = ctx.builder.build_int_add(i, llvm_usize.const_int(1, true), ""); .unwrap();
ctx.builder.build_store(i_addr, i); let i = ctx.builder.build_int_add(i, llvm_usize.const_int(1, true), "").unwrap();
ctx.builder.build_store(i_addr, i).unwrap();
Ok(()) Ok(())
}, },
@ -938,7 +961,7 @@ impl<'ctx> NDArrayDataProxy<'ctx> {
name: Option<&str>, name: Option<&str>,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
let ptr = self.ptr_offset_unchecked_const(ctx, generator, indices, name); let ptr = self.ptr_offset_unchecked_const(ctx, generator, indices, name);
ctx.builder.build_load(ptr, name.unwrap_or_default()) ctx.builder.build_load(ptr, name.unwrap_or_default()).unwrap()
} }
pub unsafe fn get_unsafe( pub unsafe fn get_unsafe(
@ -949,7 +972,7 @@ impl<'ctx> NDArrayDataProxy<'ctx> {
name: Option<&str>, name: Option<&str>,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
let ptr = self.ptr_offset_unchecked(ctx, generator, indices, name); let ptr = self.ptr_offset_unchecked(ctx, generator, indices, name);
ctx.builder.build_load(ptr, name.unwrap_or_default()) ctx.builder.build_load(ptr, name.unwrap_or_default()).unwrap()
} }
/// Returns the data at the index specified by `indices`. /// Returns the data at the index specified by `indices`.
@ -961,7 +984,7 @@ impl<'ctx> NDArrayDataProxy<'ctx> {
name: Option<&str>, name: Option<&str>,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
let ptr = self.ptr_offset_const(ctx, generator, indices, name); let ptr = self.ptr_offset_const(ctx, generator, indices, name);
ctx.builder.build_load(ptr, name.unwrap_or_default()) ctx.builder.build_load(ptr, name.unwrap_or_default()).unwrap()
} }
/// Returns the data at the index specified by `indices`. /// Returns the data at the index specified by `indices`.
@ -973,6 +996,6 @@ impl<'ctx> NDArrayDataProxy<'ctx> {
name: Option<&str>, name: Option<&str>,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
let ptr = self.ptr_offset(ctx, generator, indices, name); let ptr = self.ptr_offset(ctx, generator, indices, name);
ctx.builder.build_load(ptr, name.unwrap_or_default()) ctx.builder.build_load(ptr, name.unwrap_or_default()).unwrap()
} }
} }

View File

@ -23,9 +23,9 @@ use inkwell::{
attributes::{Attribute, AttributeLoc}, attributes::{Attribute, AttributeLoc},
IntPredicate, IntPredicate,
types::{AnyType, BasicType, BasicTypeEnum}, types::{AnyType, BasicType, BasicTypeEnum},
values::{BasicValueEnum, FunctionValue, IntValue, PointerValue} values::{BasicValueEnum, CallSiteValue, FunctionValue, IntValue, PointerValue}
}; };
use itertools::{chain, izip, Itertools}; use itertools::{chain, izip, Itertools, Either};
use nac3parser::ast::{ use nac3parser::ast::{
self, Boolop, Comprehension, Constant, Expr, ExprKind, Location, Operator, StrRef, self, Boolop, Comprehension, Constant, Expr, ExprKind, Location, Operator, StrRef,
}; };
@ -69,8 +69,8 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
index: &[IntValue<'ctx>], index: &[IntValue<'ctx>],
name: Option<&str>, name: Option<&str>,
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
let gep = unsafe { self.builder.build_gep(ptr, index, "") }; let gep = unsafe { self.builder.build_gep(ptr, index, "") }.unwrap();
self.builder.build_load(gep, name.unwrap_or_default()) self.builder.build_load(gep, name.unwrap_or_default()).unwrap()
} }
fn get_subst_key( fn get_subst_key(
@ -111,8 +111,10 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
SymbolValue::Bool(v) => self.ctx.i8_type().const_int(*v as u64, true).into(), SymbolValue::Bool(v) => self.ctx.i8_type().const_int(*v as u64, true).into(),
SymbolValue::Double(v) => self.ctx.f64_type().const_float(*v).into(), SymbolValue::Double(v) => self.ctx.f64_type().const_float(*v).into(),
SymbolValue::Str(v) => { SymbolValue::Str(v) => {
let str_ptr = let str_ptr = self.builder
self.builder.build_global_string_ptr(v, "const").as_pointer_value().into(); .build_global_string_ptr(v, "const")
.map(|v| v.as_pointer_value().into())
.unwrap();
let size = generator.get_size_type(self.ctx).const_int(v.len() as u64, false); let size = generator.get_size_type(self.ctx).const_int(v.len() as u64, false);
let ty = self.get_llvm_type(generator, self.primitives.str).into_struct_type(); let ty = self.get_llvm_type(generator, self.primitives.str).into_struct_type();
ty.const_named_struct(&[str_ptr, size.into()]).into() ty.const_named_struct(&[str_ptr, size.into()]).into()
@ -129,11 +131,11 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
ptr, ptr,
&[zero, self.ctx.i32_type().const_int(i as u64, false)], &[zero, self.ctx.i32_type().const_int(i as u64, false)],
"elemptr", "elemptr",
); ).unwrap();
self.builder.build_store(p, val); self.builder.build_store(p, val).unwrap();
} }
} }
self.builder.build_load(ptr, "tup_val") self.builder.build_load(ptr, "tup_val").unwrap()
} }
SymbolValue::OptionSome(v) => { SymbolValue::OptionSome(v) => {
let ty = match self.unifier.get_ty_immutable(ty).as_ref() { let ty = match self.unifier.get_ty_immutable(ty).as_ref() {
@ -146,7 +148,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
}; };
let val = self.gen_symbol_val(generator, v, ty); let val = self.gen_symbol_val(generator, v, ty);
let ptr = generator.gen_var_alloc(self, val.get_type(), Some("default_opt_some")).unwrap(); let ptr = generator.gen_var_alloc(self, val.get_type(), Some("default_opt_some")).unwrap();
self.builder.build_store(ptr, val); self.builder.build_store(ptr, val).unwrap();
ptr.into() ptr.into()
} }
SymbolValue::OptionNone => { SymbolValue::OptionNone => {
@ -254,8 +256,10 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
if let Some(v) = self.const_strings.get(v) { if let Some(v) = self.const_strings.get(v) {
Some(*v) Some(*v)
} else { } else {
let str_ptr = let str_ptr = self.builder
self.builder.build_global_string_ptr(v, "const").as_pointer_value().into(); .build_global_string_ptr(v, "const")
.map(|v| v.as_pointer_value().into())
.unwrap();
let size = generator.get_size_type(self.ctx).const_int(v.len() as u64, false); let size = generator.get_size_type(self.ctx).const_int(v.len() as u64, false);
let ty = self.get_llvm_type(generator, self.primitives.str); let ty = self.get_llvm_type(generator, self.primitives.str);
let val = let val =
@ -295,24 +299,24 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
}; };
let float = self.ctx.f64_type(); let float = self.ctx.f64_type();
match (op, signed) { match (op, signed) {
(Operator::Add, _) => self.builder.build_int_add(lhs, rhs, "add").into(), (Operator::Add, _) => self.builder.build_int_add(lhs, rhs, "add").map(Into::into).unwrap(),
(Operator::Sub, _) => self.builder.build_int_sub(lhs, rhs, "sub").into(), (Operator::Sub, _) => self.builder.build_int_sub(lhs, rhs, "sub").map(Into::into).unwrap(),
(Operator::Mult, _) => self.builder.build_int_mul(lhs, rhs, "mul").into(), (Operator::Mult, _) => self.builder.build_int_mul(lhs, rhs, "mul").map(Into::into).unwrap(),
(Operator::Div, true) => { (Operator::Div, true) => {
let left = self.builder.build_signed_int_to_float(lhs, float, "i2f"); let left = self.builder.build_signed_int_to_float(lhs, float, "i2f").unwrap();
let right = self.builder.build_signed_int_to_float(rhs, float, "i2f"); let right = self.builder.build_signed_int_to_float(rhs, float, "i2f").unwrap();
self.builder.build_float_div(left, right, "fdiv").into() self.builder.build_float_div(left, right, "fdiv").map(Into::into).unwrap()
} }
(Operator::Div, false) => { (Operator::Div, false) => {
let left = self.builder.build_unsigned_int_to_float(lhs, float, "i2f"); let left = self.builder.build_unsigned_int_to_float(lhs, float, "i2f").unwrap();
let right = self.builder.build_unsigned_int_to_float(rhs, float, "i2f"); let right = self.builder.build_unsigned_int_to_float(rhs, float, "i2f").unwrap();
self.builder.build_float_div(left, right, "fdiv").into() self.builder.build_float_div(left, right, "fdiv").map(Into::into).unwrap()
} }
(Operator::Mod, true) => self.builder.build_int_signed_rem(lhs, rhs, "mod").into(), (Operator::Mod, true) => self.builder.build_int_signed_rem(lhs, rhs, "mod").map(Into::into).unwrap(),
(Operator::Mod, false) => self.builder.build_int_unsigned_rem(lhs, rhs, "mod").into(), (Operator::Mod, false) => self.builder.build_int_unsigned_rem(lhs, rhs, "mod").map(Into::into).unwrap(),
(Operator::BitOr, _) => self.builder.build_or(lhs, rhs, "or").into(), (Operator::BitOr, _) => self.builder.build_or(lhs, rhs, "or").map(Into::into).unwrap(),
(Operator::BitXor, _) => self.builder.build_xor(lhs, rhs, "xor").into(), (Operator::BitXor, _) => self.builder.build_xor(lhs, rhs, "xor").map(Into::into).unwrap(),
(Operator::BitAnd, _) => self.builder.build_and(lhs, rhs, "and").into(), (Operator::BitAnd, _) => self.builder.build_and(lhs, rhs, "and").map(Into::into).unwrap(),
// Sign-ness of bitshift operators are always determined by the left operand // Sign-ness of bitshift operators are always determined by the left operand
(Operator::LShift | Operator::RShift, signed) => { (Operator::LShift | Operator::RShift, signed) => {
@ -322,15 +326,17 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
let common_type = lhs.get_type(); let common_type = lhs.get_type();
let rhs = if common_type.get_bit_width() > 32 { let rhs = if common_type.get_bit_width() > 32 {
if signed { if signed {
self.builder.build_int_s_extend(rhs, common_type, "") self.builder.build_int_s_extend(rhs, common_type, "").unwrap()
} else { } else {
self.builder.build_int_z_extend(rhs, common_type, "") self.builder.build_int_z_extend(rhs, common_type, "").unwrap()
} }
} else { } else {
rhs rhs
}; };
let rhs_gez = self.builder.build_int_compare(IntPredicate::SGE, rhs, common_type.const_zero(), ""); let rhs_gez = self.builder
.build_int_compare(IntPredicate::SGE, rhs, common_type.const_zero(), "")
.unwrap();
self.make_assert( self.make_assert(
generator, generator,
rhs_gez, rhs_gez,
@ -341,14 +347,14 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
); );
match *op { match *op {
Operator::LShift => self.builder.build_left_shift(lhs, rhs, "lshift").into(), Operator::LShift => self.builder.build_left_shift(lhs, rhs, "lshift").map(Into::into).unwrap(),
Operator::RShift => self.builder.build_right_shift(lhs, rhs, signed, "rshift").into(), Operator::RShift => self.builder.build_right_shift(lhs, rhs, signed, "rshift").map(Into::into).unwrap(),
_ => unreachable!() _ => unreachable!()
} }
} }
(Operator::FloorDiv, true) => self.builder.build_int_signed_div(lhs, rhs, "floordiv").into(), (Operator::FloorDiv, true) => self.builder.build_int_signed_div(lhs, rhs, "floordiv").map(Into::into).unwrap(),
(Operator::FloorDiv, false) => self.builder.build_int_unsigned_div(lhs, rhs, "floordiv").into(), (Operator::FloorDiv, false) => self.builder.build_int_unsigned_div(lhs, rhs, "floordiv").map(Into::into).unwrap(),
(Operator::Pow, s) => integer_power(generator, self, lhs, rhs, s).into(), (Operator::Pow, s) => integer_power(generator, self, lhs, rhs, s).into(),
// special implementation? // special implementation?
(Operator::MatMult, _) => unreachable!(), (Operator::MatMult, _) => unreachable!(),
@ -367,13 +373,13 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
}; };
let float = self.ctx.f64_type(); let float = self.ctx.f64_type();
match op { match op {
Operator::Add => self.builder.build_float_add(lhs, rhs, "fadd").into(), Operator::Add => self.builder.build_float_add(lhs, rhs, "fadd").map(Into::into).unwrap(),
Operator::Sub => self.builder.build_float_sub(lhs, rhs, "fsub").into(), Operator::Sub => self.builder.build_float_sub(lhs, rhs, "fsub").map(Into::into).unwrap(),
Operator::Mult => self.builder.build_float_mul(lhs, rhs, "fmul").into(), Operator::Mult => self.builder.build_float_mul(lhs, rhs, "fmul").map(Into::into).unwrap(),
Operator::Div => self.builder.build_float_div(lhs, rhs, "fdiv").into(), Operator::Div => self.builder.build_float_div(lhs, rhs, "fdiv").map(Into::into).unwrap(),
Operator::Mod => self.builder.build_float_rem(lhs, rhs, "fmod").into(), Operator::Mod => self.builder.build_float_rem(lhs, rhs, "fmod").map(Into::into).unwrap(),
Operator::FloorDiv => { Operator::FloorDiv => {
let div = self.builder.build_float_div(lhs, rhs, "fdiv"); let div = self.builder.build_float_div(lhs, rhs, "fdiv").unwrap();
let floor_intrinsic = let floor_intrinsic =
self.module.get_function("llvm.floor.f64").unwrap_or_else(|| { self.module.get_function("llvm.floor.f64").unwrap_or_else(|| {
let fn_type = float.fn_type(&[float.into()], false); let fn_type = float.fn_type(&[float.into()], false);
@ -381,8 +387,8 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
}); });
self.builder self.builder
.build_call(floor_intrinsic, &[div.into()], "floor") .build_call(floor_intrinsic, &[div.into()], "floor")
.try_as_basic_value() .map(CallSiteValue::try_as_basic_value)
.left() .map(Either::unwrap_left)
.unwrap() .unwrap()
} }
Operator::Pow => { Operator::Pow => {
@ -392,8 +398,9 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
}); });
self.builder self.builder
.build_call(pow_intrinsic, &[lhs.into(), rhs.into()], "f_pow") .build_call(pow_intrinsic, &[lhs.into(), rhs.into()], "f_pow")
.try_as_basic_value() .map(CallSiteValue::try_as_basic_value)
.unwrap_left() .map(Either::unwrap_left)
.unwrap()
} }
// special implementation? // special implementation?
_ => unimplemented!(), _ => unimplemented!(),
@ -424,8 +431,17 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
let byval_id = Attribute::get_named_enum_kind_id("byval"); let byval_id = Attribute::get_named_enum_kind_id("byval");
let offset = if fun.get_enum_attribute(AttributeLoc::Param(0), sret_id).is_some() { let offset = if fun.get_enum_attribute(AttributeLoc::Param(0), sret_id).is_some() {
return_slot = Some(self.builder.build_alloca(fun.get_type().get_param_types()[0] return_slot = Some(self.builder
.into_pointer_type().get_element_type().into_struct_type(), call_name)); .build_alloca(
fun.get_type()
.get_param_types()[0]
.into_pointer_type()
.get_element_type()
.into_struct_type(),
call_name
)
.unwrap()
);
loc_params.push((*return_slot.as_ref().unwrap()).into()); loc_params.push((*return_slot.as_ref().unwrap()).into());
1 1
} else { } else {
@ -440,7 +456,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
} }
let slot = gen_var(self, param.get_type(), Some(call_name)).unwrap(); let slot = gen_var(self, param.get_type(), Some(call_name)).unwrap();
loc_params.push(slot.into()); loc_params.push(slot.into());
self.builder.build_store(slot, *param); self.builder.build_store(slot, *param).unwrap();
} else if !loc_params.is_empty() { } else if !loc_params.is_empty() {
loc_params.push(*param); loc_params.push(*param);
} }
@ -460,7 +476,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
&& val_ty.get_element_type().is_struct_type() && val_ty.get_element_type().is_struct_type()
} => } =>
{ {
self.builder.build_bitcast(*val, arg_ty, "call_arg_cast") self.builder.build_bitcast(*val, arg_ty, "call_arg_cast").unwrap()
} }
_ => *val, _ => *val,
}) })
@ -471,16 +487,20 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
let result = self let result = self
.builder .builder
.build_invoke(fun, &params, then_block, target, call_name) .build_invoke(fun, &params, then_block, target, call_name)
.try_as_basic_value() .map(CallSiteValue::try_as_basic_value)
.left(); .map(Either::left)
.unwrap();
self.builder.position_at_end(then_block); self.builder.position_at_end(then_block);
result result
} else { } else {
let param: Vec<_> = params.iter().map(|v| (*v).into()).collect(); let param: Vec<_> = params.iter().map(|v| (*v).into()).collect();
self.builder.build_call(fun, &param, call_name).try_as_basic_value().left() self.builder.build_call(fun, &param, call_name)
.map(CallSiteValue::try_as_basic_value)
.map(Either::left)
.unwrap()
}; };
if let Some(slot) = return_slot { if let Some(slot) = return_slot {
Some(self.builder.build_load(slot, call_name)) Some(self.builder.build_load(slot, call_name).unwrap())
} else { } else {
result result
} }
@ -514,26 +534,28 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
let int32 = self.ctx.i32_type(); let int32 = self.ctx.i32_type();
let zero = int32.const_zero(); let zero = int32.const_zero();
unsafe { unsafe {
let id_ptr = self.builder.build_in_bounds_gep(zelf, &[zero, zero], "exn.id"); let id_ptr = self.builder
.build_in_bounds_gep(zelf, &[zero, zero], "exn.id")
.unwrap();
let id = self.resolver.get_string_id(name); let id = self.resolver.get_string_id(name);
self.builder.build_store(id_ptr, int32.const_int(id as u64, false)); self.builder.build_store(id_ptr, int32.const_int(id as u64, false)).unwrap();
let ptr = self.builder.build_in_bounds_gep( let ptr = self.builder.build_in_bounds_gep(
zelf, zelf,
&[zero, int32.const_int(5, false)], &[zero, int32.const_int(5, false)],
"exn.msg", "exn.msg",
); ).unwrap();
self.builder.build_store(ptr, msg); self.builder.build_store(ptr, msg).unwrap();
let i64_zero = self.ctx.i64_type().const_zero(); let i64_zero = self.ctx.i64_type().const_zero();
for (i, attr_ind) in [6, 7, 8].iter().enumerate() { for (i, attr_ind) in [6, 7, 8].iter().enumerate() {
let ptr = self.builder.build_in_bounds_gep( let ptr = self.builder.build_in_bounds_gep(
zelf, zelf,
&[zero, int32.const_int(*attr_ind, false)], &[zero, int32.const_int(*attr_ind, false)],
"exn.param", "exn.param",
); ).unwrap();
let val = params[i].map_or(i64_zero, |v| { let val = params[i].map_or(i64_zero, |v| {
self.builder.build_int_s_extend(v, self.ctx.i64_type(), "sext") self.builder.build_int_s_extend(v, self.ctx.i64_type(), "sext").unwrap()
}); });
self.builder.build_store(ptr, val); self.builder.build_store(ptr, val).unwrap();
} }
} }
gen_raise(generator, self, Some(&zelf.into()), loc); gen_raise(generator, self, Some(&zelf.into()), loc);
@ -577,14 +599,14 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
let cond = self let cond = self
.builder .builder
.build_call(expect_fun, &[cond.into(), i1_true.into()], "expect") .build_call(expect_fun, &[cond.into(), i1_true.into()], "expect")
.try_as_basic_value() .map(CallSiteValue::try_as_basic_value)
.left() .map(|v| v.map_left(BasicValueEnum::into_int_value))
.unwrap() .map(Either::unwrap_left)
.into_int_value(); .unwrap();
let current_fun = self.builder.get_insert_block().unwrap().get_parent().unwrap(); let current_fun = self.builder.get_insert_block().unwrap().get_parent().unwrap();
let then_block = self.ctx.append_basic_block(current_fun, "succ"); let then_block = self.ctx.append_basic_block(current_fun, "succ");
let exn_block = self.ctx.append_basic_block(current_fun, "fail"); let exn_block = self.ctx.append_basic_block(current_fun, "fail");
self.builder.build_conditional_branch(cond, then_block, exn_block); self.builder.build_conditional_branch(cond, then_block, exn_block).unwrap();
self.builder.position_at_end(exn_block); self.builder.position_at_end(exn_block);
self.raise_exn(generator, err_name, err_msg, params, loc); self.raise_exn(generator, err_name, err_msg, params, loc);
self.builder.position_at_end(then_block); self.builder.position_at_end(then_block);
@ -607,7 +629,7 @@ pub fn gen_constructor<'ctx, 'a, G: CodeGenerator>(
let fun_id = methods.iter().find(|method| method.0 == "__init__".into()).map(|method| method.2); let fun_id = methods.iter().find(|method| method.0 == "__init__".into()).map(|method| method.2);
let ty = ctx.get_llvm_type(generator, signature.ret).into_pointer_type(); let ty = ctx.get_llvm_type(generator, signature.ret).into_pointer_type();
let zelf_ty: BasicTypeEnum = ty.get_element_type().try_into().unwrap(); let zelf_ty: BasicTypeEnum = ty.get_element_type().try_into().unwrap();
let zelf: BasicValueEnum<'ctx> = ctx.builder.build_alloca(zelf_ty, "alloca").into(); let zelf: BasicValueEnum<'ctx> = ctx.builder.build_alloca(zelf_ty, "alloca").map(Into::into).unwrap();
// call `__init__` if there is one // call `__init__` if there is one
if let Some(fun_id) = fun_id { if let Some(fun_id) = fun_id {
let mut sign = signature.clone(); let mut sign = signature.clone();
@ -898,14 +920,14 @@ pub fn allocate_list<'ctx, G: CodeGenerator>(
let arr_str_ptr = ctx.builder.build_alloca( let arr_str_ptr = ctx.builder.build_alloca(
arr_ty, format!("{}.addr", name.unwrap_or("list")).as_str() arr_ty, format!("{}.addr", name.unwrap_or("list")).as_str()
); ).unwrap();
let list = ListValue::from_ptr_val(arr_str_ptr, size_t, Some("list")); let list = ListValue::from_ptr_val(arr_str_ptr, size_t, Some("list"));
let length = ctx.builder.build_int_z_extend( let length = ctx.builder.build_int_z_extend(
length, length,
size_t, size_t,
"" ""
); ).unwrap();
list.store_size(ctx, generator, length); list.store_size(ctx, generator, length);
list.create_data(ctx, ty, None); list.create_data(ctx, ty, None);
@ -929,7 +951,7 @@ pub fn gen_comprehension<'ctx, G: CodeGenerator>(
let body_bb = ctx.ctx.append_basic_block(current, "listcomp.body"); let body_bb = ctx.ctx.append_basic_block(current, "listcomp.body");
let cont_bb = ctx.ctx.append_basic_block(current, "listcomp.cont"); let cont_bb = ctx.ctx.append_basic_block(current, "listcomp.cont");
ctx.builder.build_unconditional_branch(init_bb); ctx.builder.build_unconditional_branch(init_bb).unwrap();
ctx.builder.position_at_end(init_bb); ctx.builder.position_at_end(init_bb);
@ -939,7 +961,7 @@ pub fn gen_comprehension<'ctx, G: CodeGenerator>(
} else { } else {
for bb in [test_bb, body_bb, cont_bb] { for bb in [test_bb, body_bb, cont_bb] {
ctx.builder.position_at_end(bb); ctx.builder.position_at_end(bb);
ctx.builder.build_unreachable(); ctx.builder.build_unreachable().unwrap();
} }
return Ok(None) return Ok(None)
@ -950,7 +972,7 @@ pub fn gen_comprehension<'ctx, G: CodeGenerator>(
let zero_32 = int32.const_zero(); let zero_32 = int32.const_zero();
let index = generator.gen_var_alloc(ctx, size_t.into(), Some("index.addr"))?; let index = generator.gen_var_alloc(ctx, size_t.into(), Some("index.addr"))?;
ctx.builder.build_store(index, zero_size_t); ctx.builder.build_store(index, zero_size_t).unwrap();
let elem_ty = ctx.get_llvm_type(generator, elt.custom.unwrap()); let elem_ty = ctx.get_llvm_type(generator, elt.custom.unwrap());
let is_range = ctx.unifier.unioned(iter.custom.unwrap(), ctx.primitives.range); let is_range = ctx.unifier.unioned(iter.custom.unwrap(), ctx.primitives.range);
@ -960,22 +982,23 @@ pub fn gen_comprehension<'ctx, G: CodeGenerator>(
if is_range { if is_range {
let iter_val = RangeValue::from_ptr_val(iter_val.into_pointer_value(), Some("range")); let iter_val = RangeValue::from_ptr_val(iter_val.into_pointer_value(), Some("range"));
let (start, stop, step) = destructure_range(ctx, iter_val); let (start, stop, step) = destructure_range(ctx, iter_val);
let diff = ctx.builder.build_int_sub(stop, start, "diff"); let diff = ctx.builder.build_int_sub(stop, start, "diff").unwrap();
// add 1 to the length as the value is rounded to zero // add 1 to the length as the value is rounded to zero
// the length may be 1 more than the actual length if the division is exact, but the // the length may be 1 more than the actual length if the division is exact, but the
// length is a upper bound only anyway so it does not matter. // length is a upper bound only anyway so it does not matter.
let length = ctx.builder.build_int_signed_div(diff, step, "div"); let length = ctx.builder.build_int_signed_div(diff, step, "div").unwrap();
let length = ctx.builder.build_int_add(length, int32.const_int(1, false), "add1"); let length = ctx.builder.build_int_add(length, int32.const_int(1, false), "add1").unwrap();
// in case length is non-positive // in case length is non-positive
let is_valid = let is_valid = ctx.builder
ctx.builder.build_int_compare(IntPredicate::SGT, length, zero_32, "check"); .build_int_compare(IntPredicate::SGT, length, zero_32, "check")
.unwrap();
let list_alloc_size = ctx.builder.build_select( let list_alloc_size = ctx.builder.build_select(
is_valid, is_valid,
ctx.builder.build_int_z_extend_or_bit_cast(length, size_t, "z_ext_len"), ctx.builder.build_int_z_extend_or_bit_cast(length, size_t, "z_ext_len").unwrap(),
zero_size_t, zero_size_t,
"listcomp.alloc_size" "listcomp.alloc_size"
); ).unwrap();
list = allocate_list( list = allocate_list(
generator, generator,
ctx, ctx,
@ -986,27 +1009,25 @@ pub fn gen_comprehension<'ctx, G: CodeGenerator>(
list_content = list.get_data().get_ptr(ctx); list_content = list.get_data().get_ptr(ctx);
let i = generator.gen_store_target(ctx, target, Some("i.addr"))?.unwrap(); let i = generator.gen_store_target(ctx, target, Some("i.addr"))?.unwrap();
ctx.builder.build_store(i, ctx.builder.build_int_sub(start, step, "start_init")); ctx.builder
.build_store(i, ctx.builder.build_int_sub(start, step, "start_init").unwrap())
.unwrap();
ctx.builder.build_conditional_branch( ctx.builder
gen_in_range_check(ctx, start, stop, step), .build_conditional_branch(gen_in_range_check(ctx, start, stop, step), test_bb, cont_bb)
test_bb, .unwrap();
cont_bb,
);
ctx.builder.position_at_end(test_bb); ctx.builder.position_at_end(test_bb);
// add and test // add and test
let tmp = ctx.builder.build_int_add( let tmp = ctx.builder.build_int_add(
ctx.builder.build_load(i, "i").into_int_value(), ctx.builder.build_load(i, "i").map(BasicValueEnum::into_int_value).unwrap(),
step, step,
"start_loop", "start_loop",
); ).unwrap();
ctx.builder.build_store(i, tmp); ctx.builder.build_store(i, tmp).unwrap();
ctx.builder.build_conditional_branch( ctx.builder
gen_in_range_check(ctx, tmp, stop, step), .build_conditional_branch(gen_in_range_check(ctx, tmp, stop, step), body_bb, cont_bb)
body_bb, .unwrap();
cont_bb,
);
ctx.builder.position_at_end(body_bb); ctx.builder.position_at_end(body_bb);
} else { } else {
@ -1021,15 +1042,15 @@ pub fn gen_comprehension<'ctx, G: CodeGenerator>(
list_content = list.get_data().get_ptr(ctx); list_content = list.get_data().get_ptr(ctx);
let counter = generator.gen_var_alloc(ctx, size_t.into(), Some("counter.addr"))?; let counter = generator.gen_var_alloc(ctx, size_t.into(), Some("counter.addr"))?;
// counter = -1 // counter = -1
ctx.builder.build_store(counter, size_t.const_int(u64::MAX, true)); ctx.builder.build_store(counter, size_t.const_int(u64::MAX, true)).unwrap();
ctx.builder.build_unconditional_branch(test_bb); ctx.builder.build_unconditional_branch(test_bb).unwrap();
ctx.builder.position_at_end(test_bb); ctx.builder.position_at_end(test_bb);
let tmp = ctx.builder.build_load(counter, "i").into_int_value(); let tmp = ctx.builder.build_load(counter, "i").map(BasicValueEnum::into_int_value).unwrap();
let tmp = ctx.builder.build_int_add(tmp, size_t.const_int(1, false), "inc"); let tmp = ctx.builder.build_int_add(tmp, size_t.const_int(1, false), "inc").unwrap();
ctx.builder.build_store(counter, tmp); ctx.builder.build_store(counter, tmp).unwrap();
let cmp = ctx.builder.build_int_compare(IntPredicate::SLT, tmp, length, "cmp"); let cmp = ctx.builder.build_int_compare(IntPredicate::SLT, tmp, length, "cmp").unwrap();
ctx.builder.build_conditional_branch(cmp, body_bb, cont_bb); ctx.builder.build_conditional_branch(cmp, body_bb, cont_bb).unwrap();
ctx.builder.position_at_end(body_bb); ctx.builder.position_at_end(body_bb);
let arr_ptr = ctx let arr_ptr = ctx
@ -1042,7 +1063,7 @@ pub fn gen_comprehension<'ctx, G: CodeGenerator>(
// Emits the content of `cont_bb` // Emits the content of `cont_bb`
let emit_cont_bb = |ctx: &CodeGenContext<'ctx, '_>, generator: &dyn CodeGenerator, list: ListValue<'ctx>| { let emit_cont_bb = |ctx: &CodeGenContext<'ctx, '_>, generator: &dyn CodeGenerator, list: ListValue<'ctx>| {
ctx.builder.position_at_end(cont_bb); ctx.builder.position_at_end(cont_bb);
list.store_size(ctx, generator, ctx.builder.build_load(index, "index").into_int_value()); list.store_size(ctx, generator, ctx.builder.build_load(index, "index").map(BasicValueEnum::into_int_value).unwrap());
}; };
for cond in ifs { for cond in ifs {
@ -1057,7 +1078,7 @@ pub fn gen_comprehension<'ctx, G: CodeGenerator>(
}; };
let result = generator.bool_to_i1(ctx, result); let result = generator.bool_to_i1(ctx, result);
let succ = ctx.ctx.append_basic_block(current, "then"); let succ = ctx.ctx.append_basic_block(current, "then");
ctx.builder.build_conditional_branch(result, succ, test_bb); ctx.builder.build_conditional_branch(result, succ, test_bb).unwrap();
ctx.builder.position_at_end(succ); ctx.builder.position_at_end(succ);
} }
@ -1068,13 +1089,17 @@ pub fn gen_comprehension<'ctx, G: CodeGenerator>(
return Ok(None) return Ok(None)
}; };
let i = ctx.builder.build_load(index, "i").into_int_value(); let i = ctx.builder.build_load(index, "i").map(BasicValueEnum::into_int_value).unwrap();
let elem_ptr = unsafe { ctx.builder.build_gep(list_content, &[i], "elem_ptr") }; let elem_ptr = unsafe { ctx.builder.build_gep(list_content, &[i], "elem_ptr") }.unwrap();
let val = elem.to_basic_value_enum(ctx, generator, elt.custom.unwrap())?; let val = elem.to_basic_value_enum(ctx, generator, elt.custom.unwrap())?;
ctx.builder.build_store(elem_ptr, val); ctx.builder.build_store(elem_ptr, val).unwrap();
ctx.builder ctx.builder
.build_store(index, ctx.builder.build_int_add(i, size_t.const_int(1, false), "inc")); .build_store(
ctx.builder.build_unconditional_branch(test_bb); index,
ctx.builder.build_int_add(i, size_t.const_int(1, false), "inc").unwrap(),
)
.unwrap();
ctx.builder.build_unconditional_branch(test_bb).unwrap();
emit_cont_bb(ctx, generator, list); emit_cont_bb(ctx, generator, list);
@ -1133,8 +1158,9 @@ pub fn gen_binop_expr<'ctx, G: CodeGenerator>(
}); });
let res = ctx.builder let res = ctx.builder
.build_call(pow_intr, &[left_val.into(), right_val.into()], "f_pow_i") .build_call(pow_intr, &[left_val.into(), right_val.into()], "f_pow_i")
.try_as_basic_value() .map(CallSiteValue::try_as_basic_value)
.unwrap_left(); .map(Either::unwrap_left)
.unwrap();
Ok(Some(res.into())) Ok(Some(res.into()))
} else { } else {
let left_ty_enum = ctx.unifier.get_ty_immutable(left.custom.unwrap()); let left_ty_enum = ctx.unifier.get_ty_immutable(left.custom.unwrap());
@ -1244,7 +1270,7 @@ fn gen_ndarray_subscript_expr<'ctx, G: CodeGenerator>(
let len = v.load_ndims(ctx); let len = v.load_ndims(ctx);
ctx.make_assert( ctx.make_assert(
generator, generator,
ctx.builder.build_int_compare(IntPredicate::SGT, len, llvm_usize.const_zero(), ""), ctx.builder.build_int_compare(IntPredicate::SGT, len, llvm_usize.const_zero(), "").unwrap(),
"0:IndexError", "0:IndexError",
"too many indices for array: array is {0}-dimensional but 1 were indexed", "too many indices for array: array is {0}-dimensional but 1 were indexed",
[Some(len), None, None], [Some(len), None, None],
@ -1302,7 +1328,7 @@ fn gen_ndarray_subscript_expr<'ctx, G: CodeGenerator>(
ndarray.store_ndims( ndarray.store_ndims(
ctx, ctx,
generator, generator,
ctx.builder.build_int_sub(num_dims, llvm_usize.const_int(1, false), ""), ctx.builder.build_int_sub(num_dims, llvm_usize.const_int(1, false), "").unwrap(),
); );
let ndarray_num_dims = ndarray.load_ndims(ctx); let ndarray_num_dims = ndarray.load_ndims(ctx);
@ -1336,25 +1362,34 @@ fn gen_ndarray_subscript_expr<'ctx, G: CodeGenerator>(
ctx.builder.build_call( ctx.builder.build_call(
memcpy_fn, memcpy_fn,
&[ &[
ctx.builder.build_bitcast( ctx.builder
.build_bitcast(
ndarray.get_dims().get_ptr(ctx), ndarray.get_dims().get_ptr(ctx),
llvm_pi8, llvm_pi8,
"", "",
).into(), )
ctx.builder.build_bitcast( .map(Into::into)
.unwrap(),
ctx.builder
.build_bitcast(
v_dims_src_ptr, v_dims_src_ptr,
llvm_pi8, llvm_pi8,
"", "",
).into(), )
ctx.builder.build_int_mul( .map(Into::into)
.unwrap(),
ctx.builder
.build_int_mul(
ndarray_num_dims.into(), ndarray_num_dims.into(),
llvm_usize.size_of(), llvm_usize.size_of(),
"", "",
).into(), )
.map(Into::into)
.unwrap(),
llvm_i1.const_zero().into(), llvm_i1.const_zero().into(),
], ],
"", "",
); ).unwrap();
let ndarray_num_elems = call_ndarray_calc_size( let ndarray_num_elems = call_ndarray_calc_size(
generator, generator,
@ -1373,25 +1408,34 @@ fn gen_ndarray_subscript_expr<'ctx, G: CodeGenerator>(
ctx.builder.build_call( ctx.builder.build_call(
memcpy_fn, memcpy_fn,
&[ &[
ctx.builder.build_bitcast( ctx.builder
.build_bitcast(
ndarray.get_data().get_ptr(ctx), ndarray.get_data().get_ptr(ctx),
llvm_pi8, llvm_pi8,
"", "",
).into(), )
ctx.builder.build_bitcast( .map(Into::into)
.unwrap(),
ctx.builder
.build_bitcast(
v_data_src_ptr, v_data_src_ptr,
llvm_pi8, llvm_pi8,
"", "",
).into(), )
ctx.builder.build_int_mul( .map(Into::into)
.unwrap(),
ctx.builder
.build_int_mul(
ndarray_num_elems.into(), ndarray_num_elems.into(),
llvm_ndarray_data_t.size_of().unwrap(), llvm_ndarray_data_t.size_of().unwrap(),
"", "",
).into(), )
.map(Into::into)
.unwrap(),
llvm_i1.const_zero().into(), llvm_i1.const_zero().into(),
], ],
"", "",
); ).unwrap();
Ok(Some(v.get_ptr().into())) Ok(Some(v.get_ptr().into()))
} }
@ -1442,7 +1486,7 @@ pub fn gen_expr<'ctx, G: CodeGenerator>(
} }
} }
ExprKind::Name { id, .. } => match ctx.var_assignment.get(id) { ExprKind::Name { id, .. } => match ctx.var_assignment.get(id) {
Some((ptr, None, _)) => ctx.builder.build_load(*ptr, id.to_string().as_str()).into(), Some((ptr, None, _)) => ctx.builder.build_load(*ptr, id.to_string().as_str()).map(Into::into).unwrap(),
Some((_, Some(static_value), _)) => ValueEnum::Static(static_value.clone()), Some((_, Some(static_value), _)) => ValueEnum::Static(static_value.clone()),
None => { None => {
let resolver = ctx.resolver.clone(); let resolver = ctx.resolver.clone();
@ -1480,7 +1524,7 @@ pub fn gen_expr<'ctx, G: CodeGenerator>(
for (i, v) in elements.iter().enumerate() { for (i, v) in elements.iter().enumerate() {
let elem_ptr = arr_ptr let elem_ptr = arr_ptr
.ptr_offset(ctx, generator, usize.const_int(i as u64, false), Some("elem_ptr")); .ptr_offset(ctx, generator, usize.const_int(i as u64, false), Some("elem_ptr"));
ctx.builder.build_store(elem_ptr, *v); ctx.builder.build_store(elem_ptr, *v).unwrap();
} }
arr_str_ptr.get_ptr().into() arr_str_ptr.get_ptr().into()
} }
@ -1500,18 +1544,18 @@ pub fn gen_expr<'ctx, G: CodeGenerator>(
let element_ty = element_val.iter().map(BasicValueEnum::get_type).collect_vec(); let element_ty = element_val.iter().map(BasicValueEnum::get_type).collect_vec();
let tuple_ty = ctx.ctx.struct_type(&element_ty, false); let tuple_ty = ctx.ctx.struct_type(&element_ty, false);
let tuple_ptr = ctx.builder.build_alloca(tuple_ty, "tuple"); let tuple_ptr = ctx.builder.build_alloca(tuple_ty, "tuple").unwrap();
for (i, v) in element_val.into_iter().enumerate() { for (i, v) in element_val.into_iter().enumerate() {
unsafe { unsafe {
let ptr = ctx.builder.build_in_bounds_gep( let ptr = ctx.builder.build_in_bounds_gep(
tuple_ptr, tuple_ptr,
&[zero, int32.const_int(i as u64, false)], &[zero, int32.const_int(i as u64, false)],
"ptr", "ptr",
); ).unwrap();
ctx.builder.build_store(ptr, v); ctx.builder.build_store(ptr, v).unwrap();
} }
} }
ctx.builder.build_load(tuple_ptr, "tup_val").into() ctx.builder.build_load(tuple_ptr, "tup_val").map(Into::into).unwrap()
} }
ExprKind::Attribute { value, attr, .. } => { ExprKind::Attribute { value, attr, .. } => {
// note that we would handle class methods directly in calls // note that we would handle class methods directly in calls
@ -1548,18 +1592,18 @@ pub fn gen_expr<'ctx, G: CodeGenerator>(
let a_bb = ctx.ctx.append_basic_block(current, "a"); let a_bb = ctx.ctx.append_basic_block(current, "a");
let b_bb = ctx.ctx.append_basic_block(current, "b"); let b_bb = ctx.ctx.append_basic_block(current, "b");
let cont_bb = ctx.ctx.append_basic_block(current, "cont"); let cont_bb = ctx.ctx.append_basic_block(current, "cont");
ctx.builder.build_conditional_branch(left, a_bb, b_bb); ctx.builder.build_conditional_branch(left, a_bb, b_bb).unwrap();
let (a, b) = match op { let (a, b) = match op {
Boolop::Or => { Boolop::Or => {
ctx.builder.position_at_end(a_bb); ctx.builder.position_at_end(a_bb);
let a = ctx.ctx.i8_type().const_int(1, false); let a = ctx.ctx.i8_type().const_int(1, false);
ctx.builder.build_unconditional_branch(cont_bb); ctx.builder.build_unconditional_branch(cont_bb).unwrap();
ctx.builder.position_at_end(b_bb); ctx.builder.position_at_end(b_bb);
let b = if let Some(v) = generator.gen_expr(ctx, &values[1])? { let b = if let Some(v) = generator.gen_expr(ctx, &values[1])? {
let b = v.to_basic_value_enum(ctx, generator, values[1].custom.unwrap())?.into_int_value(); let b = v.to_basic_value_enum(ctx, generator, values[1].custom.unwrap())?.into_int_value();
let b = generator.bool_to_i8(ctx, b); let b = generator.bool_to_i8(ctx, b);
ctx.builder.build_unconditional_branch(cont_bb); ctx.builder.build_unconditional_branch(cont_bb).unwrap();
Some(b) Some(b)
} else { } else {
@ -1573,7 +1617,7 @@ pub fn gen_expr<'ctx, G: CodeGenerator>(
let a = if let Some(v) = generator.gen_expr(ctx, &values[1])? { let a = if let Some(v) = generator.gen_expr(ctx, &values[1])? {
let a = v.to_basic_value_enum(ctx, generator, values[1].custom.unwrap())?.into_int_value(); let a = v.to_basic_value_enum(ctx, generator, values[1].custom.unwrap())?.into_int_value();
let a = generator.bool_to_i8(ctx, a); let a = generator.bool_to_i8(ctx, a);
ctx.builder.build_unconditional_branch(cont_bb); ctx.builder.build_unconditional_branch(cont_bb).unwrap();
Some(a) Some(a)
} else { } else {
@ -1582,7 +1626,7 @@ pub fn gen_expr<'ctx, G: CodeGenerator>(
ctx.builder.position_at_end(b_bb); ctx.builder.position_at_end(b_bb);
let b = ctx.ctx.i8_type().const_zero(); let b = ctx.ctx.i8_type().const_zero();
ctx.builder.build_unconditional_branch(cont_bb); ctx.builder.build_unconditional_branch(cont_bb).unwrap();
(a, Some(b)) (a, Some(b))
} }
@ -1591,7 +1635,7 @@ pub fn gen_expr<'ctx, G: CodeGenerator>(
ctx.builder.position_at_end(cont_bb); ctx.builder.position_at_end(cont_bb);
match (a, b) { match (a, b) {
(Some(a), Some(b)) => { (Some(a), Some(b)) => {
let phi = ctx.builder.build_phi(ctx.ctx.i8_type(), ""); let phi = ctx.builder.build_phi(ctx.ctx.i8_type(), "").unwrap();
phi.add_incoming(&[(&a, a_bb), (&b, b_bb)]); phi.add_incoming(&[(&a, a_bb), (&b, b_bb)]);
phi.as_basic_value().into() phi.as_basic_value().into()
} }
@ -1614,22 +1658,22 @@ pub fn gen_expr<'ctx, G: CodeGenerator>(
let val = val.into_int_value(); let val = val.into_int_value();
match op { match op {
ast::Unaryop::Invert | ast::Unaryop::Not => { ast::Unaryop::Invert | ast::Unaryop::Not => {
ctx.builder.build_not(val, "not").into() ctx.builder.build_not(val, "not").map(Into::into).unwrap()
} }
_ => val.into(), _ => val.into(),
} }
} else if [ctx.primitives.int32, ctx.primitives.int64, ctx.primitives.uint32, ctx.primitives.uint64].contains(&ty) { } else if [ctx.primitives.int32, ctx.primitives.int64, ctx.primitives.uint32, ctx.primitives.uint64].contains(&ty) {
let val = val.into_int_value(); let val = val.into_int_value();
match op { match op {
ast::Unaryop::USub => ctx.builder.build_int_neg(val, "neg").into(), ast::Unaryop::USub => ctx.builder.build_int_neg(val, "neg").map(Into::into).unwrap(),
ast::Unaryop::Invert => ctx.builder.build_not(val, "not").into(), ast::Unaryop::Invert => ctx.builder.build_not(val, "not").map(Into::into).unwrap(),
ast::Unaryop::Not => ctx.builder.build_xor(val, val.get_type().const_all_ones(), "not").into(), ast::Unaryop::Not => ctx.builder.build_xor(val, val.get_type().const_all_ones(), "not").map(Into::into).unwrap(),
ast::Unaryop::UAdd => val.into(), ast::Unaryop::UAdd => val.into(),
} }
} else if ty == ctx.primitives.float { } else if ty == ctx.primitives.float {
let val = val.into_float_value(); let val = val.into_float_value();
match op { match op {
ast::Unaryop::USub => ctx.builder.build_float_neg(val, "neg").into(), ast::Unaryop::USub => ctx.builder.build_float_neg(val, "neg").map(Into::into).unwrap(),
ast::Unaryop::Not => ctx ast::Unaryop::Not => ctx
.builder .builder
.build_float_compare( .build_float_compare(
@ -1638,7 +1682,8 @@ pub fn gen_expr<'ctx, G: CodeGenerator>(
val.get_type().const_zero(), val.get_type().const_zero(),
"not", "not",
) )
.into(), .map(Into::into)
.unwrap(),
_ => val.into(), _ => val.into(),
} }
} else { } else {
@ -1695,7 +1740,7 @@ pub fn gen_expr<'ctx, G: CodeGenerator>(
_ => unreachable!(), _ => unreachable!(),
}; };
ctx.builder.build_int_compare(op, lhs, rhs, "cmp") ctx.builder.build_int_compare(op, lhs, rhs, "cmp").unwrap()
} else if ty == ctx.primitives.float { } else if ty == ctx.primitives.float {
let BasicValueEnum::FloatValue(lhs) = (match generator.gen_expr(ctx, lhs)? { let BasicValueEnum::FloatValue(lhs) = (match generator.gen_expr(ctx, lhs)? {
Some(v) => v.to_basic_value_enum(ctx, generator, lhs.custom.unwrap())?, Some(v) => v.to_basic_value_enum(ctx, generator, lhs.custom.unwrap())?,
@ -1716,11 +1761,11 @@ pub fn gen_expr<'ctx, G: CodeGenerator>(
ast::Cmpop::GtE => inkwell::FloatPredicate::OGE, ast::Cmpop::GtE => inkwell::FloatPredicate::OGE,
_ => unreachable!(), _ => unreachable!(),
}; };
ctx.builder.build_float_compare(op, lhs, rhs, "cmp") ctx.builder.build_float_compare(op, lhs, rhs, "cmp").unwrap()
} else { } else {
unimplemented!() unimplemented!()
}; };
Ok(prev?.map(|v| ctx.builder.build_and(v, current, "cmp")).or(Some(current))) Ok(prev?.map(|v| ctx.builder.build_and(v, current, "cmp").unwrap()).or(Some(current)))
})?; })?;
match cmp_val { match cmp_val {
@ -1740,13 +1785,13 @@ pub fn gen_expr<'ctx, G: CodeGenerator>(
None None
} else { } else {
let llvm_ty = ctx.get_llvm_type(generator, body_ty); let llvm_ty = ctx.get_llvm_type(generator, body_ty);
Some(ctx.builder.build_alloca(llvm_ty, "if_exp_result")) Some(ctx.builder.build_alloca(llvm_ty, "if_exp_result").unwrap())
}; };
let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap(); let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap();
let then_bb = ctx.ctx.append_basic_block(current, "then"); let then_bb = ctx.ctx.append_basic_block(current, "then");
let else_bb = ctx.ctx.append_basic_block(current, "else"); let else_bb = ctx.ctx.append_basic_block(current, "else");
let cont_bb = ctx.ctx.append_basic_block(current, "cont"); let cont_bb = ctx.ctx.append_basic_block(current, "cont");
ctx.builder.build_conditional_branch(test, then_bb, else_bb); ctx.builder.build_conditional_branch(test, then_bb, else_bb).unwrap();
ctx.builder.position_at_end(then_bb); ctx.builder.position_at_end(then_bb);
let a = generator.gen_expr(ctx, body)?; let a = generator.gen_expr(ctx, body)?;
@ -1758,7 +1803,7 @@ pub fn gen_expr<'ctx, G: CodeGenerator>(
Some(ctx.builder.build_store(v, a)) Some(ctx.builder.build_store(v, a))
} }
}; };
ctx.builder.build_unconditional_branch(cont_bb); ctx.builder.build_unconditional_branch(cont_bb).unwrap();
} }
ctx.builder.position_at_end(else_bb); ctx.builder.position_at_end(else_bb);
@ -1771,12 +1816,12 @@ pub fn gen_expr<'ctx, G: CodeGenerator>(
Some(ctx.builder.build_store(v, b)) Some(ctx.builder.build_store(v, b))
} }
}; };
ctx.builder.build_unconditional_branch(cont_bb); ctx.builder.build_unconditional_branch(cont_bb).unwrap();
} }
ctx.builder.position_at_end(cont_bb); ctx.builder.position_at_end(cont_bb);
if let Some(v) = result { if let Some(v) = result {
ctx.builder.build_load(v, "if_exp_val_load").into() ctx.builder.build_load(v, "if_exp_val_load").map(Into::into).unwrap()
} else { } else {
return Ok(None) return Ok(None)
} }
@ -1869,7 +1914,7 @@ pub fn gen_expr<'ctx, G: CodeGenerator>(
current_fun, current_fun,
"unwrap_none_exception" "unwrap_none_exception"
); );
ctx.builder.build_unconditional_branch(exn_block); ctx.builder.build_unconditional_branch(exn_block).unwrap();
ctx.builder.position_at_end(exn_block); ctx.builder.position_at_end(exn_block);
ctx.raise_exn( ctx.raise_exn(
generator, generator,
@ -1886,12 +1931,12 @@ pub fn gen_expr<'ctx, G: CodeGenerator>(
Ok(Some(ctx.builder.build_load( Ok(Some(ctx.builder.build_load(
ptr, ptr,
"unwrap_none_unreachable_load" "unwrap_none_unreachable_load"
).into())) ).map(Into::into).unwrap()))
} }
Some(v) => Ok(Some(v)), Some(v) => Ok(Some(v)),
}, },
ValueEnum::Dynamic(BasicValueEnum::PointerValue(ptr)) => { ValueEnum::Dynamic(BasicValueEnum::PointerValue(ptr)) => {
let not_null = ctx.builder.build_is_not_null(ptr, "unwrap_not_null"); let not_null = ctx.builder.build_is_not_null(ptr, "unwrap_not_null").unwrap();
ctx.make_assert( ctx.make_assert(
generator, generator,
not_null, not_null,
@ -1903,7 +1948,7 @@ pub fn gen_expr<'ctx, G: CodeGenerator>(
return Ok(Some(ctx.builder.build_load( return Ok(Some(ctx.builder.build_load(
ptr, ptr,
"unwrap_some_load" "unwrap_some_load"
).into())) ).map(Into::into).unwrap()))
} }
ValueEnum::Dynamic(_) => unreachable!("option must be static or ptr") ValueEnum::Dynamic(_) => unreachable!("option must be static or ptr")
} }
@ -1951,12 +1996,13 @@ pub fn gen_expr<'ctx, G: CodeGenerator>(
step, step,
zero, zero,
"is_neg", "is_neg",
), ).unwrap(),
ctx.builder.build_int_sub(end, one, "e_min_one"), ctx.builder.build_int_sub(end, one, "e_min_one").unwrap(),
ctx.builder.build_int_add(end, one, "e_add_one"), ctx.builder.build_int_add(end, one, "e_add_one").unwrap(),
"final_e", "final_e",
) )
.into_int_value(), .map(BasicValueEnum::into_int_value)
.unwrap(),
step, step,
); );
let res_array_ret = allocate_list(generator, ctx, ty, length, Some("ret")); let res_array_ret = allocate_list(generator, ctx, ty, length, Some("ret"));
@ -1985,19 +2031,20 @@ pub fn gen_expr<'ctx, G: CodeGenerator>(
raw_index, raw_index,
generator.get_size_type(ctx.ctx), generator.get_size_type(ctx.ctx),
"sext", "sext",
); ).unwrap();
// handle negative index // handle negative index
let is_negative = ctx.builder.build_int_compare( let is_negative = ctx.builder.build_int_compare(
IntPredicate::SLT, IntPredicate::SLT,
raw_index, raw_index,
generator.get_size_type(ctx.ctx).const_zero(), generator.get_size_type(ctx.ctx).const_zero(),
"is_neg", "is_neg",
); ).unwrap();
let adjusted = ctx.builder.build_int_add(raw_index, len, "adjusted"); let adjusted = ctx.builder.build_int_add(raw_index, len, "adjusted").unwrap();
let index = ctx let index = ctx
.builder .builder
.build_select(is_negative, adjusted, raw_index, "index") .build_select(is_negative, adjusted, raw_index, "index")
.into_int_value(); .map(BasicValueEnum::into_int_value)
.unwrap();
// unsigned less than is enough, because negative index after adjustment is // unsigned less than is enough, because negative index after adjustment is
// bigger than the length (for unsigned cmp) // bigger than the length (for unsigned cmp)
let bound_check = ctx.builder.build_int_compare( let bound_check = ctx.builder.build_int_compare(
@ -2005,7 +2052,7 @@ pub fn gen_expr<'ctx, G: CodeGenerator>(
index, index,
len, len,
"inbound", "inbound",
); ).unwrap();
ctx.make_assert( ctx.make_assert(
generator, generator,
bound_check, bound_check,

View File

@ -11,9 +11,10 @@ use inkwell::{
memory_buffer::MemoryBuffer, memory_buffer::MemoryBuffer,
module::Module, module::Module,
types::{BasicTypeEnum, IntType}, types::{BasicTypeEnum, IntType},
values::{ArrayValue, FloatValue, IntValue, PointerValue}, values::{ArrayValue, BasicValueEnum, CallSiteValue, FloatValue, IntValue, PointerValue},
AddressSpace, IntPredicate, AddressSpace, IntPredicate,
}; };
use itertools::Either;
use nac3parser::ast::Expr; use nac3parser::ast::Expr;
#[must_use] #[must_use]
@ -63,7 +64,7 @@ pub fn integer_power<'ctx>(
exp, exp,
exp.get_type().const_zero(), exp.get_type().const_zero(),
"assert_int_pow_ge_0", "assert_int_pow_ge_0",
); ).unwrap();
ctx.make_assert( ctx.make_assert(
generator, generator,
ge_zero, ge_zero,
@ -74,9 +75,10 @@ pub fn integer_power<'ctx>(
); );
ctx.builder ctx.builder
.build_call(pow_fun, &[base.into(), exp.into()], "call_int_pow") .build_call(pow_fun, &[base.into(), exp.into()], "call_int_pow")
.try_as_basic_value() .map(CallSiteValue::try_as_basic_value)
.unwrap_left() .map(|v| v.map_left(BasicValueEnum::into_int_value))
.into_int_value() .map(Either::unwrap_left)
.unwrap()
} }
pub fn calculate_len_for_slice_range<'ctx>( pub fn calculate_len_for_slice_range<'ctx>(
@ -99,7 +101,7 @@ pub fn calculate_len_for_slice_range<'ctx>(
step, step,
step.get_type().const_zero(), step.get_type().const_zero(),
"range_step_ne", "range_step_ne",
); ).unwrap();
ctx.make_assert( ctx.make_assert(
generator, generator,
not_zero, not_zero,
@ -110,10 +112,10 @@ pub fn calculate_len_for_slice_range<'ctx>(
); );
ctx.builder ctx.builder
.build_call(len_func, &[start.into(), end.into(), step.into()], "calc_len") .build_call(len_func, &[start.into(), end.into(), step.into()], "calc_len")
.try_as_basic_value() .map(CallSiteValue::try_as_basic_value)
.left() .map(|v| v.map_left(BasicValueEnum::into_int_value))
.map(Either::unwrap_left)
.unwrap() .unwrap()
.into_int_value()
} }
/// NOTE: the output value of the end index of this function should be compared ***inclusively***, /// NOTE: the output value of the end index of this function should be compared ***inclusively***,
@ -168,7 +170,7 @@ pub fn handle_slice_indices<'ctx, G: CodeGenerator>(
let zero = int32.const_zero(); let zero = int32.const_zero();
let one = int32.const_int(1, false); let one = int32.const_int(1, false);
let length = list.load_size(ctx, Some("length")); let length = list.load_size(ctx, Some("length"));
let length = ctx.builder.build_int_truncate_or_bit_cast(length, int32, "leni32"); let length = ctx.builder.build_int_truncate_or_bit_cast(length, int32, "leni32").unwrap();
Ok(Some(match (start, end, step) { Ok(Some(match (start, end, step) {
(s, e, None) => ( (s, e, None) => (
if let Some(s) = s.as_ref() { if let Some(s) = s.as_ref() {
@ -188,7 +190,7 @@ pub fn handle_slice_indices<'ctx, G: CodeGenerator>(
} else { } else {
length length
}; };
ctx.builder.build_int_sub(e, one, "final_end") ctx.builder.build_int_sub(e, one, "final_end").unwrap()
}, },
one, one,
), ),
@ -204,7 +206,7 @@ pub fn handle_slice_indices<'ctx, G: CodeGenerator>(
step, step,
step.get_type().const_zero(), step.get_type().const_zero(),
"range_step_ne", "range_step_ne",
); ).unwrap();
ctx.make_assert( ctx.make_assert(
generator, generator,
not_zero, not_zero,
@ -213,8 +215,8 @@ pub fn handle_slice_indices<'ctx, G: CodeGenerator>(
[None, None, None], [None, None, None],
ctx.current_loc, ctx.current_loc,
); );
let len_id = ctx.builder.build_int_sub(length, one, "lenmin1"); let len_id = ctx.builder.build_int_sub(length, one, "lenmin1").unwrap();
let neg = ctx.builder.build_int_compare(IntPredicate::SLT, step, zero, "step_is_neg"); let neg = ctx.builder.build_int_compare(IntPredicate::SLT, step, zero, "step_is_neg").unwrap();
( (
match s { match s {
Some(s) => { Some(s) => {
@ -229,17 +231,20 @@ pub fn handle_slice_indices<'ctx, G: CodeGenerator>(
s, s,
length, length,
"s_eq_len", "s_eq_len",
), ).unwrap(),
neg, neg,
"should_minus_one", "should_minus_one",
), ).unwrap(),
ctx.builder.build_int_sub(s, one, "s_min"), ctx.builder.build_int_sub(s, one, "s_min").unwrap(),
s, s,
"final_start", "final_start",
) )
.into_int_value() .map(BasicValueEnum::into_int_value)
.unwrap()
} }
None => ctx.builder.build_select(neg, len_id, zero, "stt").into_int_value(), None => ctx.builder.build_select(neg, len_id, zero, "stt")
.map(BasicValueEnum::into_int_value)
.unwrap(),
}, },
match e { match e {
Some(e) => { Some(e) => {
@ -249,13 +254,16 @@ pub fn handle_slice_indices<'ctx, G: CodeGenerator>(
ctx.builder ctx.builder
.build_select( .build_select(
neg, neg,
ctx.builder.build_int_add(e, one, "end_add_one"), ctx.builder.build_int_add(e, one, "end_add_one").unwrap(),
ctx.builder.build_int_sub(e, one, "end_sub_one"), ctx.builder.build_int_sub(e, one, "end_sub_one").unwrap(),
"final_end", "final_end",
) )
.into_int_value() .map(BasicValueEnum::into_int_value)
.unwrap()
} }
None => ctx.builder.build_select(neg, zero, len_id, "end").into_int_value(), None => ctx.builder.build_select(neg, zero, len_id, "end")
.map(BasicValueEnum::into_int_value)
.unwrap(),
}, },
step, step,
) )
@ -286,10 +294,10 @@ pub fn handle_slice_index_bound<'ctx, G: CodeGenerator>(
Ok(Some(ctx Ok(Some(ctx
.builder .builder
.build_call(func, &[i.into(), length.into()], "bounded_ind") .build_call(func, &[i.into(), length.into()], "bounded_ind")
.try_as_basic_value() .map(CallSiteValue::try_as_basic_value)
.left() .map(|v| v.map_left(BasicValueEnum::into_int_value))
.unwrap() .map(Either::unwrap_left)
.into_int_value())) .unwrap()))
} }
/// This function handles 'end' **inclusively**. /// This function handles 'end' **inclusively**.
@ -335,17 +343,17 @@ pub fn list_slice_assignment<'ctx>(
dest_arr_ptr, dest_arr_ptr,
elem_ptr_type, elem_ptr_type,
"dest_arr_ptr_cast", "dest_arr_ptr_cast",
); ).unwrap();
let dest_len = dest_arr.load_size(ctx, Some("dest.len")); let dest_len = dest_arr.load_size(ctx, Some("dest.len"));
let dest_len = ctx.builder.build_int_truncate_or_bit_cast(dest_len, int32, "srclen32"); let dest_len = ctx.builder.build_int_truncate_or_bit_cast(dest_len, int32, "srclen32").unwrap();
let src_arr_ptr = src_arr.get_data().get_ptr(ctx); let src_arr_ptr = src_arr.get_data().get_ptr(ctx);
let src_arr_ptr = ctx.builder.build_pointer_cast( let src_arr_ptr = ctx.builder.build_pointer_cast(
src_arr_ptr, src_arr_ptr,
elem_ptr_type, elem_ptr_type,
"src_arr_ptr_cast", "src_arr_ptr_cast",
); ).unwrap();
let src_len = src_arr.load_size(ctx, Some("src.len")); let src_len = src_arr.load_size(ctx, Some("src.len"));
let src_len = ctx.builder.build_int_truncate_or_bit_cast(src_len, int32, "srclen32"); let src_len = ctx.builder.build_int_truncate_or_bit_cast(src_len, int32, "srclen32").unwrap();
// index in bound and positive should be done // index in bound and positive should be done
// assert if dest.step == 1 then len(src) <= len(dest) else len(src) == len(dest), and // assert if dest.step == 1 then len(src) <= len(dest) else len(src) == len(dest), and
@ -357,12 +365,13 @@ pub fn list_slice_assignment<'ctx>(
src_idx.2, src_idx.2,
zero, zero,
"is_neg", "is_neg",
), ).unwrap(),
ctx.builder.build_int_sub(src_idx.1, one, "e_min_one"), ctx.builder.build_int_sub(src_idx.1, one, "e_min_one").unwrap(),
ctx.builder.build_int_add(src_idx.1, one, "e_add_one"), ctx.builder.build_int_add(src_idx.1, one, "e_add_one").unwrap(),
"final_e", "final_e",
) )
.into_int_value(); .map(BasicValueEnum::into_int_value)
.unwrap();
let dest_end = ctx.builder let dest_end = ctx.builder
.build_select( .build_select(
ctx.builder.build_int_compare( ctx.builder.build_int_compare(
@ -370,12 +379,13 @@ pub fn list_slice_assignment<'ctx>(
dest_idx.2, dest_idx.2,
zero, zero,
"is_neg", "is_neg",
), ).unwrap(),
ctx.builder.build_int_sub(dest_idx.1, one, "e_min_one"), ctx.builder.build_int_sub(dest_idx.1, one, "e_min_one").unwrap(),
ctx.builder.build_int_add(dest_idx.1, one, "e_add_one"), ctx.builder.build_int_add(dest_idx.1, one, "e_add_one").unwrap(),
"final_e", "final_e",
) )
.into_int_value(); .map(BasicValueEnum::into_int_value)
.unwrap();
let src_slice_len = let src_slice_len =
calculate_len_for_slice_range(generator, ctx, src_idx.0, src_end, src_idx.2); calculate_len_for_slice_range(generator, ctx, src_idx.0, src_end, src_idx.2);
let dest_slice_len = let dest_slice_len =
@ -385,21 +395,21 @@ pub fn list_slice_assignment<'ctx>(
src_slice_len, src_slice_len,
dest_slice_len, dest_slice_len,
"slice_src_eq_dest", "slice_src_eq_dest",
); ).unwrap();
let src_slt_dest = ctx.builder.build_int_compare( let src_slt_dest = ctx.builder.build_int_compare(
IntPredicate::SLT, IntPredicate::SLT,
src_slice_len, src_slice_len,
dest_slice_len, dest_slice_len,
"slice_src_slt_dest", "slice_src_slt_dest",
); ).unwrap();
let dest_step_eq_one = ctx.builder.build_int_compare( let dest_step_eq_one = ctx.builder.build_int_compare(
IntPredicate::EQ, IntPredicate::EQ,
dest_idx.2, dest_idx.2,
dest_idx.2.get_type().const_int(1, false), dest_idx.2.get_type().const_int(1, false),
"slice_dest_step_eq_one", "slice_dest_step_eq_one",
); ).unwrap();
let cond_1 = ctx.builder.build_and(dest_step_eq_one, src_slt_dest, "slice_cond_1"); let cond_1 = ctx.builder.build_and(dest_step_eq_one, src_slt_dest, "slice_cond_1").unwrap();
let cond = ctx.builder.build_or(src_eq_dest, cond_1, "slice_cond"); let cond = ctx.builder.build_or(src_eq_dest, cond_1, "slice_cond").unwrap();
ctx.make_assert( ctx.make_assert(
generator, generator,
cond, cond,
@ -429,27 +439,31 @@ pub fn list_slice_assignment<'ctx>(
BasicTypeEnum::StructType(t) => t.size_of().unwrap(), BasicTypeEnum::StructType(t) => t.size_of().unwrap(),
_ => unreachable!(), _ => unreachable!(),
}; };
ctx.builder.build_int_truncate_or_bit_cast(s, int32, "size") ctx.builder.build_int_truncate_or_bit_cast(s, int32, "size").unwrap()
} }
.into(), .into(),
]; ];
ctx.builder ctx.builder
.build_call(slice_assign_fun, args.as_slice(), "slice_assign") .build_call(slice_assign_fun, args.as_slice(), "slice_assign")
.try_as_basic_value() .map(CallSiteValue::try_as_basic_value)
.unwrap_left() .map(|v| v.map_left(BasicValueEnum::into_int_value))
.into_int_value() .map(Either::unwrap_left)
.unwrap()
}; };
// update length // update length
let need_update = let need_update = ctx.builder
ctx.builder.build_int_compare(IntPredicate::NE, new_len, dest_len, "need_update"); .build_int_compare(IntPredicate::NE, new_len, dest_len, "need_update")
.unwrap();
let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap(); let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap();
let update_bb = ctx.ctx.append_basic_block(current, "update"); let update_bb = ctx.ctx.append_basic_block(current, "update");
let cont_bb = ctx.ctx.append_basic_block(current, "cont"); let cont_bb = ctx.ctx.append_basic_block(current, "cont");
ctx.builder.build_conditional_branch(need_update, update_bb, cont_bb); ctx.builder.build_conditional_branch(need_update, update_bb, cont_bb).unwrap();
ctx.builder.position_at_end(update_bb); ctx.builder.position_at_end(update_bb);
let new_len = ctx.builder.build_int_z_extend_or_bit_cast(new_len, size_ty, "new_len"); let new_len = ctx.builder
.build_int_z_extend_or_bit_cast(new_len, size_ty, "new_len")
.unwrap();
dest_arr.store_size(ctx, generator, new_len); dest_arr.store_size(ctx, generator, new_len);
ctx.builder.build_unconditional_branch(cont_bb); ctx.builder.build_unconditional_branch(cont_bb).unwrap();
ctx.builder.position_at_end(cont_bb); ctx.builder.position_at_end(cont_bb);
} }
@ -466,9 +480,10 @@ pub fn call_isinf<'ctx>(
let ret = ctx.builder let ret = ctx.builder
.build_call(intrinsic_fn, &[v.into()], "isinf") .build_call(intrinsic_fn, &[v.into()], "isinf")
.try_as_basic_value() .map(CallSiteValue::try_as_basic_value)
.unwrap_left() .map(|v| v.map_left(BasicValueEnum::into_int_value))
.into_int_value(); .map(Either::unwrap_left)
.unwrap();
generator.bool_to_i1(ctx, ret) generator.bool_to_i1(ctx, ret)
} }
@ -486,9 +501,10 @@ pub fn call_isnan<'ctx>(
let ret = ctx.builder let ret = ctx.builder
.build_call(intrinsic_fn, &[v.into()], "isnan") .build_call(intrinsic_fn, &[v.into()], "isnan")
.try_as_basic_value() .map(CallSiteValue::try_as_basic_value)
.unwrap_left() .map(|v| v.map_left(BasicValueEnum::into_int_value))
.into_int_value(); .map(Either::unwrap_left)
.unwrap();
generator.bool_to_i1(ctx, ret) generator.bool_to_i1(ctx, ret)
} }
@ -507,9 +523,10 @@ pub fn call_gamma<'ctx>(
ctx.builder ctx.builder
.build_call(intrinsic_fn, &[v.into()], "gamma") .build_call(intrinsic_fn, &[v.into()], "gamma")
.try_as_basic_value() .map(CallSiteValue::try_as_basic_value)
.unwrap_left() .map(|v| v.map_left(BasicValueEnum::into_float_value))
.into_float_value() .map(Either::unwrap_left)
.unwrap()
} }
/// Generates a call to `gammaln` in IR. Returns an `f64` representing the result. /// Generates a call to `gammaln` in IR. Returns an `f64` representing the result.
@ -526,9 +543,10 @@ pub fn call_gammaln<'ctx>(
ctx.builder ctx.builder
.build_call(intrinsic_fn, &[v.into()], "gammaln") .build_call(intrinsic_fn, &[v.into()], "gammaln")
.try_as_basic_value() .map(CallSiteValue::try_as_basic_value)
.unwrap_left() .map(|v| v.map_left(BasicValueEnum::into_float_value))
.into_float_value() .map(Either::unwrap_left)
.unwrap()
} }
/// Generates a call to `j0` in IR. Returns an `f64` representing the result. /// Generates a call to `j0` in IR. Returns an `f64` representing the result.
@ -545,9 +563,10 @@ pub fn call_j0<'ctx>(
ctx.builder ctx.builder
.build_call(intrinsic_fn, &[v.into()], "j0") .build_call(intrinsic_fn, &[v.into()], "j0")
.try_as_basic_value() .map(CallSiteValue::try_as_basic_value)
.unwrap_left() .map(|v| v.map_left(BasicValueEnum::into_float_value))
.into_float_value() .map(Either::unwrap_left)
.unwrap()
} }
/// Generates a call to `__nac3_ndarray_calc_size`. Returns an [IntValue] representing the /// Generates a call to `__nac3_ndarray_calc_size`. Returns an [IntValue] representing the
@ -592,9 +611,10 @@ pub fn call_ndarray_calc_size<'ctx>(
], ],
"", "",
) )
.try_as_basic_value() .map(CallSiteValue::try_as_basic_value)
.unwrap_left() .map(|v| v.map_left(BasicValueEnum::into_int_value))
.into_int_value() .map(Either::unwrap_left)
.unwrap()
} }
/// Generates a call to `__nac3_ndarray_init_dims`. /// Generates a call to `__nac3_ndarray_init_dims`.
@ -638,7 +658,8 @@ pub fn call_ndarray_init_dims<'ctx>(
let shape_data = shape.get_data(); let shape_data = shape.get_data();
let ndarray_num_dims = ndarray.load_ndims(ctx); let ndarray_num_dims = ndarray.load_ndims(ctx);
ctx.builder.build_call( ctx.builder
.build_call(
ndarray_init_dims_fn, ndarray_init_dims_fn,
&[ &[
ndarray_dims.get_ptr(ctx).into(), ndarray_dims.get_ptr(ctx).into(),
@ -646,7 +667,8 @@ pub fn call_ndarray_init_dims<'ctx>(
ndarray_num_dims.into(), ndarray_num_dims.into(),
], ],
"", "",
); )
.unwrap();
} }
/// Generates a call to `__nac3_ndarray_calc_nd_indices`. /// Generates a call to `__nac3_ndarray_calc_nd_indices`.
@ -691,9 +713,10 @@ pub fn call_ndarray_calc_nd_indices<'ctx>(
llvm_usize, llvm_usize,
ndarray_num_dims, ndarray_num_dims,
"", "",
); ).unwrap();
ctx.builder.build_call( ctx.builder
.build_call(
ndarray_calc_nd_indices_fn, ndarray_calc_nd_indices_fn,
&[ &[
index.into(), index.into(),
@ -702,7 +725,8 @@ pub fn call_ndarray_calc_nd_indices<'ctx>(
indices.into(), indices.into(),
], ],
"", "",
); )
.unwrap();
Ok(indices) Ok(indices)
} }
@ -766,9 +790,9 @@ fn call_ndarray_flatten_index_impl<'ctx>(
], ],
"", "",
) )
.try_as_basic_value() .map(CallSiteValue::try_as_basic_value)
.map_left(|v| v.into_int_value()) .map(|v| v.map_left(BasicValueEnum::into_int_value))
.left() .map(Either::unwrap_left)
.unwrap(); .unwrap();
Ok(index) Ok(index)
@ -828,8 +852,8 @@ pub fn call_ndarray_flatten_index_const<'ctx>(
&[ctx.ctx.i32_type().const_int(i as u64, false)], &[ctx.ctx.i32_type().const_int(i as u64, false)],
"" ""
) )
}; }.unwrap();
ctx.builder.build_store(elem_ptr, v); ctx.builder.build_store(elem_ptr, v).unwrap();
} }
call_ndarray_flatten_index_impl( call_ndarray_flatten_index_impl(

View File

@ -763,10 +763,9 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte
&primitives, &primitives,
arg.ty, arg.ty,
); );
let alloca = builder.build_alloca( let alloca = builder
local_type, .build_alloca(local_type, &format!("{}.addr", &arg.name.to_string()))
&format!("{}.addr", &arg.name.to_string()), .unwrap();
);
// Remap boolean parameters into i8 // Remap boolean parameters into i8
let param = if local_type.is_int_type() && param.is_int_value() { let param = if local_type.is_int_type() && param.is_int_value() {
@ -782,14 +781,14 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte
param param
}; };
builder.build_store(alloca, param); builder.build_store(alloca, param).unwrap();
var_assignment.insert(arg.name, (alloca, None, 0)); var_assignment.insert(arg.name, (alloca, None, 0));
} }
let return_buffer = if has_sret { let return_buffer = if has_sret {
Some(fn_val.get_nth_param(0).unwrap().into_pointer_value()) Some(fn_val.get_nth_param(0).unwrap().into_pointer_value())
} else { } else {
fn_type.get_return_type().map(|v| builder.build_alloca(v, "$ret")) fn_type.get_return_type().map(|v| builder.build_alloca(v, "$ret").unwrap())
}; };
let static_values = { let static_values = {
@ -801,7 +800,7 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte
*static_val = Some(v); *static_val = Some(v);
} }
builder.build_unconditional_branch(body_bb); builder.build_unconditional_branch(body_bb).unwrap();
builder.position_at_end(body_bb); builder.position_at_end(body_bb);
let (dibuilder, compile_unit) = module.create_debug_info_builder( let (dibuilder, compile_unit) = module.create_debug_info_builder(
@ -895,7 +894,7 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte
// after static analysis, only void functions can have no return at the end. // after static analysis, only void functions can have no return at the end.
if !code_gen_context.is_terminated() { if !code_gen_context.is_terminated() {
code_gen_context.builder.build_return(None); code_gen_context.builder.build_return(None).unwrap();
} }
code_gen_context.builder.unset_current_debug_location(); code_gen_context.builder.unset_current_debug_location();
@ -937,12 +936,14 @@ fn bool_to_i1<'ctx>(builder: &Builder<'ctx>, bool_value: IntValue<'ctx>) -> IntV
if bool_value.get_type().get_bit_width() == 1 { if bool_value.get_type().get_bit_width() == 1 {
bool_value bool_value
} else { } else {
builder.build_int_compare( builder
.build_int_compare(
IntPredicate::NE, IntPredicate::NE,
bool_value, bool_value,
bool_value.get_type().const_zero(), bool_value.get_type().const_zero(),
"tobool" "tobool",
) )
.unwrap()
} }
} }
@ -955,16 +956,18 @@ fn bool_to_i8<'ctx>(
let value_bits = bool_value.get_type().get_bit_width(); let value_bits = bool_value.get_type().get_bit_width();
match value_bits { match value_bits {
8 => bool_value, 8 => bool_value,
1 => builder.build_int_z_extend(bool_value, ctx.i8_type(), "frombool"), 1 => builder.build_int_z_extend(bool_value, ctx.i8_type(), "frombool").unwrap(),
_ => bool_to_i8( _ => bool_to_i8(
builder, builder,
ctx, ctx,
builder.build_int_compare( builder
.build_int_compare(
IntPredicate::NE, IntPredicate::NE,
bool_value, bool_value,
bool_value.get_type().const_zero(), bool_value.get_type().const_zero(),
"" "",
) )
.unwrap()
), ),
} }
} }
@ -990,9 +993,13 @@ fn gen_in_range_check<'ctx>(
stop: IntValue<'ctx>, stop: IntValue<'ctx>,
step: IntValue<'ctx>, step: IntValue<'ctx>,
) -> IntValue<'ctx> { ) -> IntValue<'ctx> {
let sign = ctx.builder.build_int_compare(IntPredicate::SGT, step, ctx.ctx.i32_type().const_zero(), ""); let sign = ctx.builder.build_int_compare(IntPredicate::SGT, step, ctx.ctx.i32_type().const_zero(), "").unwrap();
let lo = ctx.builder.build_select(sign, value, stop, "").into_int_value(); let lo = ctx.builder.build_select(sign, value, stop, "")
let hi = ctx.builder.build_select(sign, stop, value, "").into_int_value(); .map(BasicValueEnum::into_int_value)
.unwrap();
let hi = ctx.builder.build_select(sign, stop, value, "")
.map(BasicValueEnum::into_int_value)
.unwrap();
ctx.builder.build_int_compare(IntPredicate::SLT, lo, hi, "cmp") ctx.builder.build_int_compare(IntPredicate::SLT, lo, hi, "cmp").unwrap()
} }

View File

@ -47,7 +47,7 @@ pub fn gen_var<'ctx>(
ctx.builder.position_before(&ctx.init_bb.get_last_instruction().unwrap()); ctx.builder.position_before(&ctx.init_bb.get_last_instruction().unwrap());
ctx.builder.set_current_debug_location(di_loc); ctx.builder.set_current_debug_location(di_loc);
let ptr = ctx.builder.build_alloca(ty, name.unwrap_or("")); let ptr = ctx.builder.build_alloca(ty, name.unwrap_or("")).unwrap();
ctx.builder.position_at_end(current); ctx.builder.position_at_end(current);
ctx.builder.set_current_debug_location(di_loc); ctx.builder.set_current_debug_location(di_loc);
@ -78,7 +78,7 @@ pub fn gen_array_var<'ctx, 'a, T: BasicType<'ctx>>(
ctx.builder.position_before(&ctx.init_bb.get_last_instruction().unwrap()); ctx.builder.position_before(&ctx.init_bb.get_last_instruction().unwrap());
ctx.builder.set_current_debug_location(di_loc); ctx.builder.set_current_debug_location(di_loc);
let ptr = ctx.builder.build_array_alloca(ty, size, name.unwrap_or("")); let ptr = ctx.builder.build_array_alloca(ty, size, name.unwrap_or("")).unwrap();
ctx.builder.position_at_end(current); ctx.builder.position_at_end(current);
ctx.builder.set_current_debug_location(di_loc); ctx.builder.set_current_debug_location(di_loc);
@ -130,7 +130,7 @@ pub fn gen_store_target<'ctx, G: CodeGenerator>(
], ],
name.unwrap_or(""), name.unwrap_or(""),
) )
} }.unwrap()
} }
ExprKind::Subscript { value, slice, .. } => { ExprKind::Subscript { value, slice, .. } => {
match ctx.unifier.get_ty_immutable(value.custom.unwrap()).as_ref() { match ctx.unifier.get_ty_immutable(value.custom.unwrap()).as_ref() {
@ -147,31 +147,34 @@ pub fn gen_store_target<'ctx, G: CodeGenerator>(
.unwrap() .unwrap()
.to_basic_value_enum(ctx, generator, slice.custom.unwrap())? .to_basic_value_enum(ctx, generator, slice.custom.unwrap())?
.into_int_value(); .into_int_value();
let raw_index = ctx.builder.build_int_s_extend( let raw_index = ctx.builder
raw_index, .build_int_s_extend(raw_index, generator.get_size_type(ctx.ctx), "sext")
generator.get_size_type(ctx.ctx), .unwrap();
"sext",
);
// handle negative index // handle negative index
let is_negative = ctx.builder.build_int_compare( let is_negative = ctx.builder
.build_int_compare(
IntPredicate::SLT, IntPredicate::SLT,
raw_index, raw_index,
generator.get_size_type(ctx.ctx).const_zero(), generator.get_size_type(ctx.ctx).const_zero(),
"is_neg", "is_neg",
); )
let adjusted = ctx.builder.build_int_add(raw_index, len, "adjusted"); .unwrap();
let adjusted = ctx.builder.build_int_add(raw_index, len, "adjusted").unwrap();
let index = ctx let index = ctx
.builder .builder
.build_select(is_negative, adjusted, raw_index, "index") .build_select(is_negative, adjusted, raw_index, "index")
.into_int_value(); .map(BasicValueEnum::into_int_value)
.unwrap();
// unsigned less than is enough, because negative index after adjustment is // unsigned less than is enough, because negative index after adjustment is
// bigger than the length (for unsigned cmp) // bigger than the length (for unsigned cmp)
let bound_check = ctx.builder.build_int_compare( let bound_check = ctx.builder
.build_int_compare(
IntPredicate::ULT, IntPredicate::ULT,
index, index,
len, len,
"inbound", "inbound",
); )
.unwrap();
ctx.make_assert( ctx.make_assert(
generator, generator,
bound_check, bound_check,
@ -267,7 +270,7 @@ pub fn gen_assign<'ctx, G: CodeGenerator>(
} }
} }
let val = value.to_basic_value_enum(ctx, generator, target.custom.unwrap())?; let val = value.to_basic_value_enum(ctx, generator, target.custom.unwrap())?;
ctx.builder.build_store(ptr, val); ctx.builder.build_store(ptr, val).unwrap();
} }
}; };
Ok(()) Ok(())
@ -330,10 +333,12 @@ pub fn gen_for<G: CodeGenerator>(
}; };
let (start, stop, step) = destructure_range(ctx, iter_val); let (start, stop, step) = destructure_range(ctx, iter_val);
ctx.builder.build_store(i, start); ctx.builder.build_store(i, start).unwrap();
// Check "If step is zero, ValueError is raised." // Check "If step is zero, ValueError is raised."
let rangenez = ctx.builder.build_int_compare(IntPredicate::NE, step, int32.const_zero(), ""); let rangenez = ctx.builder
.build_int_compare(IntPredicate::NE, step, int32.const_zero(), "")
.unwrap();
ctx.make_assert( ctx.make_assert(
generator, generator,
rangenez, rangenez,
@ -342,37 +347,46 @@ pub fn gen_for<G: CodeGenerator>(
[None, None, None], [None, None, None],
ctx.current_loc ctx.current_loc
); );
ctx.builder.build_unconditional_branch(cond_bb); ctx.builder.build_unconditional_branch(cond_bb).unwrap();
{ {
ctx.builder.position_at_end(cond_bb); ctx.builder.position_at_end(cond_bb);
ctx.builder.build_conditional_branch( ctx.builder
.build_conditional_branch(
gen_in_range_check( gen_in_range_check(
ctx, ctx,
ctx.builder.build_load(i, "").into_int_value(), ctx.builder.build_load(i, "").map(BasicValueEnum::into_int_value).unwrap(),
stop, stop,
step step,
), ),
body_bb, body_bb,
orelse_bb, orelse_bb,
); )
.unwrap();
} }
ctx.builder.position_at_end(incr_bb); ctx.builder.position_at_end(incr_bb);
let next_i = ctx.builder.build_int_add( let next_i = ctx.builder
ctx.builder.build_load(i, "").into_int_value(), .build_int_add(
ctx.builder.build_load(i, "").map(BasicValueEnum::into_int_value).unwrap(),
step, step,
"inc", "inc",
); )
ctx.builder.build_store(i, next_i); .unwrap();
ctx.builder.build_unconditional_branch(cond_bb); ctx.builder.build_store(i, next_i).unwrap();
ctx.builder.build_unconditional_branch(cond_bb).unwrap();
ctx.builder.position_at_end(body_bb); ctx.builder.position_at_end(body_bb);
ctx.builder.build_store(target_i, ctx.builder.build_load(i, "").into_int_value()); ctx.builder
.build_store(
target_i,
ctx.builder.build_load(i, "").map(BasicValueEnum::into_int_value).unwrap(),
)
.unwrap();
generator.gen_block(ctx, body.iter())?; generator.gen_block(ctx, body.iter())?;
} else { } else {
let index_addr = generator.gen_var_alloc(ctx, size_t.into(), Some("for.index.addr"))?; let index_addr = generator.gen_var_alloc(ctx, size_t.into(), Some("for.index.addr"))?;
ctx.builder.build_store(index_addr, size_t.const_zero()); ctx.builder.build_store(index_addr, size_t.const_zero()).unwrap();
let len = ctx let len = ctx
.build_gep_and_load( .build_gep_and_load(
iter_val.into_pointer_value(), iter_val.into_pointer_value(),
@ -380,24 +394,30 @@ pub fn gen_for<G: CodeGenerator>(
Some("len") Some("len")
) )
.into_int_value(); .into_int_value();
ctx.builder.build_unconditional_branch(cond_bb); ctx.builder.build_unconditional_branch(cond_bb).unwrap();
ctx.builder.position_at_end(cond_bb); ctx.builder.position_at_end(cond_bb);
let index = ctx.builder.build_load(index_addr, "for.index").into_int_value(); let index = ctx.builder
let cmp = ctx.builder.build_int_compare(IntPredicate::SLT, index, len, "cond"); .build_load(index_addr, "for.index")
ctx.builder.build_conditional_branch(cmp, body_bb, orelse_bb); .map(BasicValueEnum::into_int_value)
.unwrap();
let cmp = ctx.builder.build_int_compare(IntPredicate::SLT, index, len, "cond").unwrap();
ctx.builder.build_conditional_branch(cmp, body_bb, orelse_bb).unwrap();
ctx.builder.position_at_end(incr_bb); ctx.builder.position_at_end(incr_bb);
let index = ctx.builder.build_load(index_addr, "").into_int_value(); let index = ctx.builder.build_load(index_addr, "").map(BasicValueEnum::into_int_value).unwrap();
let inc = ctx.builder.build_int_add(index, size_t.const_int(1, true), "inc"); let inc = ctx.builder.build_int_add(index, size_t.const_int(1, true), "inc").unwrap();
ctx.builder.build_store(index_addr, inc); ctx.builder.build_store(index_addr, inc).unwrap();
ctx.builder.build_unconditional_branch(cond_bb); ctx.builder.build_unconditional_branch(cond_bb).unwrap();
ctx.builder.position_at_end(body_bb); ctx.builder.position_at_end(body_bb);
let arr_ptr = ctx let arr_ptr = ctx
.build_gep_and_load(iter_val.into_pointer_value(), &[zero, zero], Some("arr.addr")) .build_gep_and_load(iter_val.into_pointer_value(), &[zero, zero], Some("arr.addr"))
.into_pointer_value(); .into_pointer_value();
let index = ctx.builder.build_load(index_addr, "for.index").into_int_value(); let index = ctx.builder
.build_load(index_addr, "for.index")
.map(BasicValueEnum::into_int_value)
.unwrap();
let val = ctx.build_gep_and_load(arr_ptr, &[index], Some("val")); let val = ctx.build_gep_and_load(arr_ptr, &[index], Some("val"));
generator.gen_assign(ctx, target, val.into())?; generator.gen_assign(ctx, target, val.into())?;
generator.gen_block(ctx, body.iter())?; generator.gen_block(ctx, body.iter())?;
@ -411,14 +431,14 @@ pub fn gen_for<G: CodeGenerator>(
} }
if !ctx.is_terminated() { if !ctx.is_terminated() {
ctx.builder.build_unconditional_branch(incr_bb); ctx.builder.build_unconditional_branch(incr_bb).unwrap();
} }
if !orelse.is_empty() { if !orelse.is_empty() {
ctx.builder.position_at_end(orelse_bb); ctx.builder.position_at_end(orelse_bb);
generator.gen_block(ctx, orelse.iter())?; generator.gen_block(ctx, orelse.iter())?;
if !ctx.is_terminated() { if !ctx.is_terminated() {
ctx.builder.build_unconditional_branch(cont_bb); ctx.builder.build_unconditional_branch(cont_bb).unwrap();
} }
} }
@ -476,12 +496,12 @@ pub fn gen_for_callback<'ctx, 'a, I, InitFn, CondFn, BodyFn, UpdateFn>(
// store loop bb information and restore it later // store loop bb information and restore it later
let loop_bb = ctx.loop_target.replace((update_bb, cont_bb)); let loop_bb = ctx.loop_target.replace((update_bb, cont_bb));
ctx.builder.build_unconditional_branch(init_bb); ctx.builder.build_unconditional_branch(init_bb).unwrap();
let loop_var = { let loop_var = {
ctx.builder.position_at_end(init_bb); ctx.builder.position_at_end(init_bb);
let result = init(generator, ctx)?; let result = init(generator, ctx)?;
ctx.builder.build_unconditional_branch(cond_bb); ctx.builder.build_unconditional_branch(cond_bb).unwrap();
result result
}; };
@ -489,19 +509,17 @@ pub fn gen_for_callback<'ctx, 'a, I, InitFn, CondFn, BodyFn, UpdateFn>(
ctx.builder.position_at_end(cond_bb); ctx.builder.position_at_end(cond_bb);
let cond = cond(generator, ctx, loop_var.clone())?; let cond = cond(generator, ctx, loop_var.clone())?;
assert_eq!(cond.get_type().get_bit_width(), ctx.ctx.bool_type().get_bit_width()); assert_eq!(cond.get_type().get_bit_width(), ctx.ctx.bool_type().get_bit_width());
ctx.builder.build_conditional_branch( ctx.builder
cond, .build_conditional_branch(cond, body_bb, cont_bb)
body_bb, .unwrap();
cont_bb
);
ctx.builder.position_at_end(body_bb); ctx.builder.position_at_end(body_bb);
body(generator, ctx, loop_var.clone())?; body(generator, ctx, loop_var.clone())?;
ctx.builder.build_unconditional_branch(update_bb); ctx.builder.build_unconditional_branch(update_bb).unwrap();
ctx.builder.position_at_end(update_bb); ctx.builder.position_at_end(update_bb);
update(generator, ctx, loop_var)?; update(generator, ctx, loop_var)?;
ctx.builder.build_unconditional_branch(cond_bb); ctx.builder.build_unconditional_branch(cond_bb).unwrap();
ctx.builder.position_at_end(cont_bb); ctx.builder.position_at_end(cont_bb);
ctx.loop_target = loop_bb; ctx.loop_target = loop_bb;
@ -532,14 +550,14 @@ pub fn gen_while<G: CodeGenerator>(
if orelse.is_empty() { cont_bb } else { ctx.ctx.append_basic_block(current, "while.orelse") }; if orelse.is_empty() { cont_bb } else { ctx.ctx.append_basic_block(current, "while.orelse") };
// store loop bb information and restore it later // store loop bb information and restore it later
let loop_bb = ctx.loop_target.replace((test_bb, cont_bb)); let loop_bb = ctx.loop_target.replace((test_bb, cont_bb));
ctx.builder.build_unconditional_branch(test_bb); ctx.builder.build_unconditional_branch(test_bb).unwrap();
ctx.builder.position_at_end(test_bb); ctx.builder.position_at_end(test_bb);
let test = if let Some(v) = generator.gen_expr(ctx, test)? { let test = if let Some(v) = generator.gen_expr(ctx, test)? {
v.to_basic_value_enum(ctx, generator, test.custom.unwrap())? v.to_basic_value_enum(ctx, generator, test.custom.unwrap())?
} else { } else {
for bb in [body_bb, cont_bb] { for bb in [body_bb, cont_bb] {
ctx.builder.position_at_end(bb); ctx.builder.position_at_end(bb);
ctx.builder.build_unreachable(); ctx.builder.build_unreachable().unwrap();
} }
return Ok(()) return Ok(())
@ -548,7 +566,9 @@ pub fn gen_while<G: CodeGenerator>(
unreachable!() unreachable!()
}; };
ctx.builder.build_conditional_branch(generator.bool_to_i1(ctx, test), body_bb, orelse_bb); ctx.builder
.build_conditional_branch(generator.bool_to_i1(ctx, test), body_bb, orelse_bb)
.unwrap();
ctx.builder.position_at_end(body_bb); ctx.builder.position_at_end(body_bb);
generator.gen_block(ctx, body.iter())?; generator.gen_block(ctx, body.iter())?;
@ -559,13 +579,13 @@ pub fn gen_while<G: CodeGenerator>(
} }
} }
if !ctx.is_terminated() { if !ctx.is_terminated() {
ctx.builder.build_unconditional_branch(test_bb); ctx.builder.build_unconditional_branch(test_bb).unwrap();
} }
if !orelse.is_empty() { if !orelse.is_empty() {
ctx.builder.position_at_end(orelse_bb); ctx.builder.position_at_end(orelse_bb);
generator.gen_block(ctx, orelse.iter())?; generator.gen_block(ctx, orelse.iter())?;
if !ctx.is_terminated() { if !ctx.is_terminated() {
ctx.builder.build_unconditional_branch(cont_bb); ctx.builder.build_unconditional_branch(cont_bb).unwrap();
} }
} }
for (k, (_, _, counter)) in &var_assignment { for (k, (_, _, counter)) in &var_assignment {
@ -605,13 +625,15 @@ pub fn gen_if<G: CodeGenerator>(
} else { } else {
ctx.ctx.append_basic_block(current, "if.orelse") ctx.ctx.append_basic_block(current, "if.orelse")
}; };
ctx.builder.build_unconditional_branch(test_bb); ctx.builder.build_unconditional_branch(test_bb).unwrap();
ctx.builder.position_at_end(test_bb); ctx.builder.position_at_end(test_bb);
let test = generator let test = generator
.gen_expr(ctx, test) .gen_expr(ctx, test)
.and_then(|v| v.map(|v| v.to_basic_value_enum(ctx, generator, test.custom.unwrap())).transpose())?; .and_then(|v| v.map(|v| v.to_basic_value_enum(ctx, generator, test.custom.unwrap())).transpose())?;
if let Some(BasicValueEnum::IntValue(test)) = test { if let Some(BasicValueEnum::IntValue(test)) = test {
ctx.builder.build_conditional_branch(generator.bool_to_i1(ctx, test), body_bb, orelse_bb); ctx.builder
.build_conditional_branch(generator.bool_to_i1(ctx, test), body_bb, orelse_bb)
.unwrap();
}; };
ctx.builder.position_at_end(body_bb); ctx.builder.position_at_end(body_bb);
generator.gen_block(ctx, body.iter())?; generator.gen_block(ctx, body.iter())?;
@ -626,7 +648,7 @@ pub fn gen_if<G: CodeGenerator>(
if cont_bb.is_none() { if cont_bb.is_none() {
cont_bb = Some(ctx.ctx.append_basic_block(current, "cont")); cont_bb = Some(ctx.ctx.append_basic_block(current, "cont"));
} }
ctx.builder.build_unconditional_branch(cont_bb.unwrap()); ctx.builder.build_unconditional_branch(cont_bb.unwrap()).unwrap();
} }
if !orelse.is_empty() { if !orelse.is_empty() {
ctx.builder.position_at_end(orelse_bb); ctx.builder.position_at_end(orelse_bb);
@ -635,7 +657,7 @@ pub fn gen_if<G: CodeGenerator>(
if cont_bb.is_none() { if cont_bb.is_none() {
cont_bb = Some(ctx.ctx.append_basic_block(current, "cont")); cont_bb = Some(ctx.ctx.append_basic_block(current, "cont"));
} }
ctx.builder.build_unconditional_branch(cont_bb.unwrap()); ctx.builder.build_unconditional_branch(cont_bb.unwrap()).unwrap();
} }
} }
if let Some(cont_bb) = cont_bb { if let Some(cont_bb) = cont_bb {
@ -661,7 +683,7 @@ pub fn final_proxy<'ctx>(
let prev = ctx.builder.get_insert_block().unwrap(); let prev = ctx.builder.get_insert_block().unwrap();
ctx.builder.position_at_end(block); ctx.builder.position_at_end(block);
unsafe { unsafe {
ctx.builder.build_store(*final_state, target.get_address().unwrap()); ctx.builder.build_store(*final_state, target.get_address().unwrap()).unwrap();
} }
ctx.builder.position_at_end(prev); ctx.builder.position_at_end(prev);
final_targets.push(target); final_targets.push(target);
@ -718,48 +740,43 @@ pub fn exn_constructor<'ctx>(
}; };
let exception_name = format!("{}:{}", ctx.resolver.get_exception_id(zelf_id), zelf_name); let exception_name = format!("{}:{}", ctx.resolver.get_exception_id(zelf_id), zelf_name);
unsafe { unsafe {
let id_ptr = ctx.builder.build_in_bounds_gep(zelf, &[zero, zero], "exn.id"); let id_ptr = ctx.builder.build_in_bounds_gep(zelf, &[zero, zero], "exn.id").unwrap();
let id = ctx.resolver.get_string_id(&exception_name); let id = ctx.resolver.get_string_id(&exception_name);
ctx.builder.build_store(id_ptr, int32.const_int(id as u64, false)); ctx.builder.build_store(id_ptr, int32.const_int(id as u64, false)).unwrap();
let empty_string = ctx.gen_const(generator, &Constant::Str(String::new()), ctx.primitives.str); let empty_string = ctx.gen_const(generator, &Constant::Str(String::new()), ctx.primitives.str);
let ptr = let ptr = ctx.builder
ctx.builder.build_in_bounds_gep(zelf, &[zero, int32.const_int(5, false)], "exn.msg"); .build_in_bounds_gep(zelf, &[zero, int32.const_int(5, false)], "exn.msg")
.unwrap();
let msg = if args.is_empty() { let msg = if args.is_empty() {
empty_string.unwrap() empty_string.unwrap()
} else { } else {
args.remove(0).1.to_basic_value_enum(ctx, generator, ctx.primitives.str)? args.remove(0).1.to_basic_value_enum(ctx, generator, ctx.primitives.str)?
}; };
ctx.builder.build_store(ptr, msg); ctx.builder.build_store(ptr, msg).unwrap();
for i in &[6, 7, 8] { for i in &[6, 7, 8] {
let value = if args.is_empty() { let value = if args.is_empty() {
ctx.ctx.i64_type().const_zero().into() ctx.ctx.i64_type().const_zero().into()
} else { } else {
args.remove(0).1.to_basic_value_enum(ctx, generator, ctx.primitives.int64)? args.remove(0).1.to_basic_value_enum(ctx, generator, ctx.primitives.int64)?
}; };
let ptr = ctx.builder.build_in_bounds_gep( let ptr = ctx.builder
zelf, .build_in_bounds_gep(zelf, &[zero, int32.const_int(*i, false)], "exn.param")
&[zero, int32.const_int(*i, false)], .unwrap();
"exn.param", ctx.builder.build_store(ptr, value).unwrap();
);
ctx.builder.build_store(ptr, value);
} }
// set file, func to empty string // set file, func to empty string
for i in &[1, 4] { for i in &[1, 4] {
let ptr = ctx.builder.build_in_bounds_gep( let ptr = ctx.builder
zelf, .build_in_bounds_gep(zelf, &[zero, int32.const_int(*i, false)], "exn.str")
&[zero, int32.const_int(*i, false)], .unwrap();
"exn.str", ctx.builder.build_store(ptr, empty_string.unwrap()).unwrap();
);
ctx.builder.build_store(ptr, empty_string.unwrap());
} }
// set ints to zero // set ints to zero
for i in &[2, 3] { for i in &[2, 3] {
let ptr = ctx.builder.build_in_bounds_gep( let ptr = ctx.builder
zelf, .build_in_bounds_gep(zelf, &[zero, int32.const_int(*i, false)], "exn.ints")
&[zero, int32.const_int(*i, false)], .unwrap();
"exn.ints", ctx.builder.build_store(ptr, zero).unwrap();
);
ctx.builder.build_store(ptr, zero);
} }
} }
Ok(Some(zelf.into())) Ok(Some(zelf.into()))
@ -780,34 +797,26 @@ pub fn gen_raise<'ctx>(
let int32 = ctx.ctx.i32_type(); let int32 = ctx.ctx.i32_type();
let zero = int32.const_zero(); let zero = int32.const_zero();
let exception = exception.into_pointer_value(); let exception = exception.into_pointer_value();
let file_ptr = ctx.builder.build_in_bounds_gep( let file_ptr = ctx.builder
exception, .build_in_bounds_gep(exception, &[zero, int32.const_int(1, false)], "file_ptr")
&[zero, int32.const_int(1, false)], .unwrap();
"file_ptr",
);
let filename = ctx.gen_string(generator, loc.file.0); let filename = ctx.gen_string(generator, loc.file.0);
ctx.builder.build_store(file_ptr, filename); ctx.builder.build_store(file_ptr, filename).unwrap();
let row_ptr = ctx.builder.build_in_bounds_gep( let row_ptr = ctx.builder
exception, .build_in_bounds_gep(exception, &[zero, int32.const_int(2, false)], "row_ptr")
&[zero, int32.const_int(2, false)], .unwrap();
"row_ptr", ctx.builder.build_store(row_ptr, int32.const_int(loc.row as u64, false)).unwrap();
); let col_ptr = ctx.builder
ctx.builder.build_store(row_ptr, int32.const_int(loc.row as u64, false)); .build_in_bounds_gep(exception, &[zero, int32.const_int(3, false)], "col_ptr")
let col_ptr = ctx.builder.build_in_bounds_gep( .unwrap();
exception, ctx.builder.build_store(col_ptr, int32.const_int(loc.column as u64, false)).unwrap();
&[zero, int32.const_int(3, false)],
"col_ptr",
);
ctx.builder.build_store(col_ptr, int32.const_int(loc.column as u64, false));
let current_fun = ctx.builder.get_insert_block().unwrap().get_parent().unwrap(); let current_fun = ctx.builder.get_insert_block().unwrap().get_parent().unwrap();
let fun_name = ctx.gen_string(generator, current_fun.get_name().to_str().unwrap()); let fun_name = ctx.gen_string(generator, current_fun.get_name().to_str().unwrap());
let name_ptr = ctx.builder.build_in_bounds_gep( let name_ptr = ctx.builder
exception, .build_in_bounds_gep(exception, &[zero, int32.const_int(4, false)], "name_ptr")
&[zero, int32.const_int(4, false)], .unwrap();
"name_ptr", ctx.builder.build_store(name_ptr, fun_name).unwrap();
);
ctx.builder.build_store(name_ptr, fun_name);
} }
let raise = get_builtins(generator, ctx, "__nac3_raise"); let raise = get_builtins(generator, ctx, "__nac3_raise");
@ -817,7 +826,7 @@ pub fn gen_raise<'ctx>(
let resume = get_builtins(generator, ctx, "__nac3_resume"); let resume = get_builtins(generator, ctx, "__nac3_resume");
ctx.build_call_or_invoke(resume, &[], "resume"); ctx.build_call_or_invoke(resume, &[], "resume");
} }
ctx.builder.build_unreachable(); ctx.builder.build_unreachable().unwrap();
} }
/// Generates IR for a `try` statement. /// Generates IR for a `try` statement.
@ -844,7 +853,7 @@ pub fn gen_try<'ctx, 'a, G: CodeGenerator>(
let dispatcher = ctx.ctx.append_basic_block(current_fun, "try.dispatch"); let dispatcher = ctx.ctx.append_basic_block(current_fun, "try.dispatch");
let mut dispatcher_end = dispatcher; let mut dispatcher_end = dispatcher;
ctx.builder.position_at_end(dispatcher); ctx.builder.position_at_end(dispatcher);
let exn = ctx.builder.build_phi(exception_type, "exn"); let exn = ctx.builder.build_phi(exception_type, "exn").unwrap();
ctx.builder.position_at_end(current_block); ctx.builder.position_at_end(current_block);
let mut cleanup = None; let mut cleanup = None;
@ -868,8 +877,9 @@ pub fn gen_try<'ctx, 'a, G: CodeGenerator>(
} else { } else {
let return_target = ctx.ctx.append_basic_block(current_fun, "try.return_target"); let return_target = ctx.ctx.append_basic_block(current_fun, "try.return_target");
ctx.builder.position_at_end(return_target); ctx.builder.position_at_end(return_target);
let return_value = ctx.return_buffer.map(|v| ctx.builder.build_load(v, "$ret")); let return_value = ctx.return_buffer
ctx.builder.build_return(return_value.as_ref().map(|v| v as &dyn BasicValue)); .map(|v| ctx.builder.build_load(v, "$ret").unwrap());
ctx.builder.build_return(return_value.as_ref().map(|v| v as &dyn BasicValue)).unwrap();
ctx.builder.position_at_end(current_block); ctx.builder.position_at_end(current_block);
final_proxy(ctx, return_target, return_proxy, final_data.as_mut().unwrap()); final_proxy(ctx, return_target, return_proxy, final_data.as_mut().unwrap());
} }
@ -935,14 +945,16 @@ pub fn gen_try<'ctx, 'a, G: CodeGenerator>(
} else { } else {
let final_landingpad = ctx.ctx.append_basic_block(current_fun, "try.catch.final"); let final_landingpad = ctx.ctx.append_basic_block(current_fun, "try.catch.final");
ctx.builder.position_at_end(final_landingpad); ctx.builder.position_at_end(final_landingpad);
ctx.builder.build_landing_pad( ctx.builder
.build_landing_pad(
ctx.ctx.struct_type(&[ptr_type.into(), exception_type], false), ctx.ctx.struct_type(&[ptr_type.into(), exception_type], false),
personality, personality,
&[], &[],
true, true,
"try.catch.final", "try.catch.final",
); )
ctx.builder.build_unconditional_branch(cleanup.unwrap()); .unwrap();
ctx.builder.build_unconditional_branch(cleanup.unwrap()).unwrap();
ctx.builder.position_at_end(body); ctx.builder.position_at_end(body);
ctx.unwind_target.replace(final_landingpad) ctx.unwind_target.replace(final_landingpad)
}; };
@ -956,7 +968,7 @@ pub fn gen_try<'ctx, 'a, G: CodeGenerator>(
target: BasicBlock<'ctx>, target: BasicBlock<'ctx>,
block: BasicBlock<'ctx>| { block: BasicBlock<'ctx>| {
ctx.builder.position_at_end(block); ctx.builder.position_at_end(block);
ctx.builder.build_unconditional_branch(target); ctx.builder.build_unconditional_branch(target).unwrap();
ctx.builder.position_at_end(body); ctx.builder.position_at_end(body);
}; };
let redirect = if has_cleanup { let redirect = if has_cleanup {
@ -972,9 +984,9 @@ pub fn gen_try<'ctx, 'a, G: CodeGenerator>(
let break_proxy = ctx.ctx.append_basic_block(current_fun, "try.break"); let break_proxy = ctx.ctx.append_basic_block(current_fun, "try.break");
let continue_proxy = ctx.ctx.append_basic_block(current_fun, "try.continue"); let continue_proxy = ctx.ctx.append_basic_block(current_fun, "try.continue");
ctx.builder.position_at_end(break_proxy); ctx.builder.position_at_end(break_proxy);
ctx.builder.build_call(end_catch, &[], "end_catch"); ctx.builder.build_call(end_catch, &[], "end_catch").unwrap();
ctx.builder.position_at_end(continue_proxy); ctx.builder.position_at_end(continue_proxy);
ctx.builder.build_call(end_catch, &[], "end_catch"); ctx.builder.build_call(end_catch, &[], "end_catch").unwrap();
ctx.builder.position_at_end(body); ctx.builder.position_at_end(body);
redirect(ctx, break_target, break_proxy); redirect(ctx, break_target, break_proxy);
redirect(ctx, continue_target, continue_proxy); redirect(ctx, continue_target, continue_proxy);
@ -983,12 +995,12 @@ pub fn gen_try<'ctx, 'a, G: CodeGenerator>(
} }
let return_proxy = ctx.ctx.append_basic_block(current_fun, "try.return"); let return_proxy = ctx.ctx.append_basic_block(current_fun, "try.return");
ctx.builder.position_at_end(return_proxy); ctx.builder.position_at_end(return_proxy);
ctx.builder.build_call(end_catch, &[], "end_catch"); ctx.builder.build_call(end_catch, &[], "end_catch").unwrap();
let return_target = ctx.return_target.take().unwrap_or_else(|| { let return_target = ctx.return_target.take().unwrap_or_else(|| {
let doreturn = ctx.ctx.append_basic_block(current_fun, "try.doreturn"); let doreturn = ctx.ctx.append_basic_block(current_fun, "try.doreturn");
ctx.builder.position_at_end(doreturn); ctx.builder.position_at_end(doreturn);
let return_value = ctx.return_buffer.map(|v| ctx.builder.build_load(v, "$ret")); let return_value = ctx.return_buffer.map(|v| ctx.builder.build_load(v, "$ret").unwrap());
ctx.builder.build_return(return_value.as_ref().map(|v| v as &dyn BasicValue)); ctx.builder.build_return(return_value.as_ref().map(|v| v as &dyn BasicValue)).unwrap();
doreturn doreturn
}); });
redirect(ctx, return_target, return_proxy); redirect(ctx, return_target, return_proxy);
@ -1003,12 +1015,14 @@ pub fn gen_try<'ctx, 'a, G: CodeGenerator>(
ctx.builder.position_at_end(dispatcher); ctx.builder.position_at_end(dispatcher);
unsafe { unsafe {
let zero = ctx.ctx.i32_type().const_zero(); let zero = ctx.ctx.i32_type().const_zero();
let exnid_ptr = ctx.builder.build_gep( let exnid_ptr = ctx.builder
.build_gep(
exn.as_basic_value().into_pointer_value(), exn.as_basic_value().into_pointer_value(),
&[zero, zero], &[zero, zero],
"exnidptr", "exnidptr",
); )
Some(ctx.builder.build_load(exnid_ptr, "exnid")) .unwrap();
Some(ctx.builder.build_load(exnid_ptr, "exnid").unwrap())
} }
}; };
@ -1020,14 +1034,14 @@ pub fn gen_try<'ctx, 'a, G: CodeGenerator>(
let exn_ty = ctx.get_llvm_type(generator, type_.as_ref().unwrap().custom.unwrap()); let exn_ty = ctx.get_llvm_type(generator, type_.as_ref().unwrap().custom.unwrap());
let exn_store = generator.gen_var_alloc(ctx, exn_ty, Some("try.exn_store.addr"))?; let exn_store = generator.gen_var_alloc(ctx, exn_ty, Some("try.exn_store.addr"))?;
ctx.var_assignment.insert(*name, (exn_store, None, 0)); ctx.var_assignment.insert(*name, (exn_store, None, 0));
ctx.builder.build_store(exn_store, exn.as_basic_value()); ctx.builder.build_store(exn_store, exn.as_basic_value()).unwrap();
} }
generator.gen_block(ctx, body.iter())?; generator.gen_block(ctx, body.iter())?;
let current = ctx.builder.get_insert_block().unwrap(); let current = ctx.builder.get_insert_block().unwrap();
// only need to call end catch if not terminated // only need to call end catch if not terminated
// otherwise, we already handled in return/break/continue/raise // otherwise, we already handled in return/break/continue/raise
if current.get_terminator().is_none() { if current.get_terminator().is_none() {
ctx.builder.build_call(end_catch, &[], "end_catch"); ctx.builder.build_call(end_catch, &[], "end_catch").unwrap();
} }
post_handlers.push(current); post_handlers.push(current);
ctx.builder.position_at_end(dispatcher_end); ctx.builder.position_at_end(dispatcher_end);
@ -1038,12 +1052,15 @@ pub fn gen_try<'ctx, 'a, G: CodeGenerator>(
let expected_id = ctx let expected_id = ctx
.builder .builder
.build_load(exn_type.into_pointer_value(), "expected_id") .build_load(exn_type.into_pointer_value(), "expected_id")
.into_int_value(); .map(BasicValueEnum::into_int_value)
let result = ctx.builder.build_int_compare(IntPredicate::EQ, actual_id, expected_id, "exncheck"); .unwrap();
ctx.builder.build_conditional_branch(result, handler_bb, dispatcher_cont); let result = ctx.builder
.build_int_compare(IntPredicate::EQ, actual_id, expected_id, "exncheck")
.unwrap();
ctx.builder.build_conditional_branch(result, handler_bb, dispatcher_cont).unwrap();
dispatcher_end = dispatcher_cont; dispatcher_end = dispatcher_cont;
} else { } else {
ctx.builder.build_unconditional_branch(handler_bb); ctx.builder.build_unconditional_branch(handler_bb).unwrap();
break; break;
} }
} }
@ -1066,21 +1083,22 @@ pub fn gen_try<'ctx, 'a, G: CodeGenerator>(
has_cleanup, has_cleanup,
"try.landingpad", "try.landingpad",
) )
.into_struct_value(); .map(BasicValueEnum::into_struct_value)
.unwrap();
let exn_val = ctx.builder.build_extract_value(landingpad_value, 1, "exn").unwrap(); let exn_val = ctx.builder.build_extract_value(landingpad_value, 1, "exn").unwrap();
ctx.builder.build_unconditional_branch(dispatcher); ctx.builder.build_unconditional_branch(dispatcher).unwrap();
exn.add_incoming(&[(&exn_val, landingpad)]); exn.add_incoming(&[(&exn_val, landingpad)]);
if dispatcher_end.get_terminator().is_none() { if dispatcher_end.get_terminator().is_none() {
ctx.builder.position_at_end(dispatcher_end); ctx.builder.position_at_end(dispatcher_end);
if let Some(cleanup) = cleanup { if let Some(cleanup) = cleanup {
ctx.builder.build_unconditional_branch(cleanup); ctx.builder.build_unconditional_branch(cleanup).unwrap();
} else if let Some((_, outer_dispatcher, phi)) = ctx.outer_catch_clauses { } else if let Some((_, outer_dispatcher, phi)) = ctx.outer_catch_clauses {
phi.add_incoming(&[(&exn_val, dispatcher_end)]); phi.add_incoming(&[(&exn_val, dispatcher_end)]);
ctx.builder.build_unconditional_branch(outer_dispatcher); ctx.builder.build_unconditional_branch(outer_dispatcher).unwrap();
} else { } else {
ctx.build_call_or_invoke(resume, &[], "resume"); ctx.build_call_or_invoke(resume, &[], "resume");
ctx.builder.build_unreachable(); ctx.builder.build_unreachable().unwrap();
} }
} }
@ -1088,16 +1106,16 @@ pub fn gen_try<'ctx, 'a, G: CodeGenerator>(
let tail = ctx.ctx.append_basic_block(current_fun, "try.tail"); let tail = ctx.ctx.append_basic_block(current_fun, "try.tail");
if body.get_terminator().is_none() { if body.get_terminator().is_none() {
ctx.builder.position_at_end(body); ctx.builder.position_at_end(body);
ctx.builder.build_unconditional_branch(tail); ctx.builder.build_unconditional_branch(tail).unwrap();
} }
if matches!(cleanup, Some(cleanup) if cleanup.get_terminator().is_none()) { if matches!(cleanup, Some(cleanup) if cleanup.get_terminator().is_none()) {
ctx.builder.position_at_end(cleanup.unwrap()); ctx.builder.position_at_end(cleanup.unwrap());
ctx.builder.build_unconditional_branch(tail); ctx.builder.build_unconditional_branch(tail).unwrap();
} }
for post_handler in post_handlers { for post_handler in post_handlers {
if post_handler.get_terminator().is_none() { if post_handler.get_terminator().is_none() {
ctx.builder.position_at_end(post_handler); ctx.builder.position_at_end(post_handler);
ctx.builder.build_unconditional_branch(tail); ctx.builder.build_unconditional_branch(tail).unwrap();
} }
} }
ctx.builder.position_at_end(tail); ctx.builder.position_at_end(tail);
@ -1108,7 +1126,7 @@ pub fn gen_try<'ctx, 'a, G: CodeGenerator>(
generator.gen_block(ctx, finalbody.iter())?; generator.gen_block(ctx, finalbody.iter())?;
if !ctx.is_terminated() { if !ctx.is_terminated() {
ctx.build_call_or_invoke(resume, &[], "resume"); ctx.build_call_or_invoke(resume, &[], "resume");
ctx.builder.build_unreachable(); ctx.builder.build_unreachable().unwrap();
} }
// normal path // normal path
@ -1119,22 +1137,22 @@ pub fn gen_try<'ctx, 'a, G: CodeGenerator>(
ctx.builder.position_at_end(finalizer); ctx.builder.position_at_end(finalizer);
generator.gen_block(ctx, finalbody.iter())?; generator.gen_block(ctx, finalbody.iter())?;
if !ctx.is_terminated() { if !ctx.is_terminated() {
let dest = ctx.builder.build_load(final_state, "final_dest"); let dest = ctx.builder.build_load(final_state, "final_dest").unwrap();
ctx.builder.build_indirect_branch(dest, &final_targets); ctx.builder.build_indirect_branch(dest, &final_targets).unwrap();
} }
for block in &final_paths { for block in &final_paths {
if block.get_terminator().is_none() { if block.get_terminator().is_none() {
ctx.builder.position_at_end(*block); ctx.builder.position_at_end(*block);
ctx.builder.build_unconditional_branch(finalizer); ctx.builder.build_unconditional_branch(finalizer).unwrap();
} }
} }
for block in [body].iter().chain(post_handlers.iter()) { for block in [body].iter().chain(post_handlers.iter()) {
if block.get_terminator().is_none() { if block.get_terminator().is_none() {
ctx.builder.position_at_end(*block); ctx.builder.position_at_end(*block);
unsafe { unsafe {
ctx.builder.build_store(final_state, tail.get_address().unwrap()); ctx.builder.build_store(final_state, tail.get_address().unwrap()).unwrap();
} }
ctx.builder.build_unconditional_branch(finalizer); ctx.builder.build_unconditional_branch(finalizer).unwrap();
} }
} }
ctx.builder.position_at_end(tail); ctx.builder.position_at_end(tail);
@ -1173,13 +1191,13 @@ pub fn gen_return<G: CodeGenerator>(
}; };
if let Some(return_target) = ctx.return_target { if let Some(return_target) = ctx.return_target {
if let Some(value) = value { if let Some(value) = value {
ctx.builder.build_store(ctx.return_buffer.unwrap(), value); ctx.builder.build_store(ctx.return_buffer.unwrap(), value).unwrap();
} }
ctx.builder.build_unconditional_branch(return_target); ctx.builder.build_unconditional_branch(return_target).unwrap();
} else if ctx.need_sret { } else if ctx.need_sret {
// sret // sret
ctx.builder.build_store(ctx.return_buffer.unwrap(), value.unwrap()); ctx.builder.build_store(ctx.return_buffer.unwrap(), value.unwrap()).unwrap();
ctx.builder.build_return(None); ctx.builder.build_return(None).unwrap();
} else { } else {
// Remap boolean return type into i1 // Remap boolean return type into i1
let value = value.map(|v| { let value = value.map(|v| {
@ -1200,7 +1218,7 @@ pub fn gen_return<G: CodeGenerator>(
} }
}); });
let value = value.as_ref().map(|v| v as &dyn BasicValue); let value = value.as_ref().map(|v| v as &dyn BasicValue);
ctx.builder.build_return(value); ctx.builder.build_return(value).unwrap();
} }
Ok(()) Ok(())
} }
@ -1247,10 +1265,10 @@ pub fn gen_stmt<G: CodeGenerator>(
} }
} }
StmtKind::Continue { .. } => { StmtKind::Continue { .. } => {
ctx.builder.build_unconditional_branch(ctx.loop_target.unwrap().0); ctx.builder.build_unconditional_branch(ctx.loop_target.unwrap().0).unwrap();
} }
StmtKind::Break { .. } => { StmtKind::Break { .. } => {
ctx.builder.build_unconditional_branch(ctx.loop_target.unwrap().1); ctx.builder.build_unconditional_branch(ctx.loop_target.unwrap().1).unwrap();
} }
StmtKind::If { .. } => generator.gen_if(ctx, stmt)?, StmtKind::If { .. } => generator.gen_if(ctx, stmt)?,
StmtKind::While { .. } => generator.gen_while(ctx, stmt)?, StmtKind::While { .. } => generator.gen_while(ctx, stmt)?,

View File

@ -25,10 +25,11 @@ use crate::{
use inkwell::{ use inkwell::{
attributes::{Attribute, AttributeLoc}, attributes::{Attribute, AttributeLoc},
types::{BasicType, BasicMetadataTypeEnum}, types::{BasicType, BasicMetadataTypeEnum},
values::{BasicValue, BasicMetadataValueEnum}, values::{BasicValue, BasicMetadataValueEnum, CallSiteValue},
FloatPredicate, FloatPredicate,
IntPredicate IntPredicate
}; };
use itertools::Either;
use crate::toplevel::numpy::gen_ndarray_identity; use crate::toplevel::numpy::gen_ndarray_identity;
type BuiltinInfo = Vec<(Arc<RwLock<TopLevelDef>>, Option<Stmt>)>; type BuiltinInfo = Vec<(Arc<RwLock<TopLevelDef>>, Option<Stmt>)>;
@ -189,11 +190,10 @@ fn create_fn_by_intrinsic(
ctx.module.add_function(intrinsic_fn, fn_type, None) ctx.module.add_function(intrinsic_fn, fn_type, None)
}); });
let call = ctx.builder let val = ctx.builder
.build_call(intrinsic_fn, args_val.as_slice(), name); .build_call(intrinsic_fn, args_val.as_slice(), name)
.map(CallSiteValue::try_as_basic_value)
let val = call.try_as_basic_value() .map(Either::unwrap_left)
.left()
.unwrap(); .unwrap();
Ok(val.into()) Ok(val.into())
}), }),
@ -267,11 +267,10 @@ fn create_fn_by_extern(
func func
}); });
let call = ctx.builder let val = ctx.builder
.build_call(intrinsic_fn, &args_val, name); .build_call(intrinsic_fn, &args_val, name)
.map(CallSiteValue::try_as_basic_value)
let val = call.try_as_basic_value() .map(Either::unwrap_left)
.left()
.unwrap(); .unwrap();
Ok(val.into()) Ok(val.into())
}), }),
@ -459,7 +458,11 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
unreachable!("option must be ptr") unreachable!("option must be ptr")
}; };
Ok(Some(ctx.builder.build_is_not_null(ptr, "is_some").into())) Ok(Some(ctx.builder
.build_is_not_null(ptr, "is_some")
.map(Into::into)
.unwrap()
))
}, },
)))), )))),
loc: None, loc: None,
@ -484,7 +487,11 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
unreachable!("option must be ptr") unreachable!("option must be ptr")
}; };
Ok(Some(ctx.builder.build_is_null(ptr, "is_none").into())) Ok(Some(ctx.builder
.build_is_null(ptr, "is_none")
.map(Into::into)
.unwrap()
))
}, },
)))), )))),
loc: None, loc: None,
@ -554,7 +561,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
ctx.ctx.i32_type(), ctx.ctx.i32_type(),
"zext", "zext",
) )
.into(), .map(Into::into)
.unwrap(),
) )
} else if ctx.unifier.unioned(arg_ty, int32) } else if ctx.unifier.unioned(arg_ty, int32)
|| ctx.unifier.unioned(arg_ty, uint32) || ctx.unifier.unioned(arg_ty, uint32)
@ -570,7 +578,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
ctx.ctx.i32_type(), ctx.ctx.i32_type(),
"trunc", "trunc",
) )
.into(), .map(Into::into)
.unwrap(),
) )
} else if ctx.unifier.unioned(arg_ty, float) { } else if ctx.unifier.unioned(arg_ty, float) {
let to_int64 = ctx let to_int64 = ctx
@ -579,13 +588,11 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
arg.into_float_value(), arg.into_float_value(),
ctx.ctx.i64_type(), ctx.ctx.i64_type(),
"", "",
); )
.unwrap();
let val = ctx.builder let val = ctx.builder
.build_int_truncate( .build_int_truncate(to_int64, ctx.ctx.i32_type(), "conv")
to_int64, .unwrap();
ctx.ctx.i32_type(),
"conv",
);
Some(val.into()) Some(val.into())
} else { } else {
@ -632,7 +639,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
ctx.ctx.i64_type(), ctx.ctx.i64_type(),
"zext", "zext",
) )
.into(), .map(Into::into)
.unwrap(),
) )
} else if ctx.unifier.unioned(arg_ty, int32) { } else if ctx.unifier.unioned(arg_ty, int32) {
Some( Some(
@ -642,7 +650,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
ctx.ctx.i64_type(), ctx.ctx.i64_type(),
"sext", "sext",
) )
.into(), .map(Into::into)
.unwrap(),
) )
} else if ctx.unifier.unioned(arg_ty, int64) } else if ctx.unifier.unioned(arg_ty, int64)
|| ctx.unifier.unioned(arg_ty, uint64) || ctx.unifier.unioned(arg_ty, uint64)
@ -656,7 +665,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
ctx.ctx.i64_type(), ctx.ctx.i64_type(),
"fptosi", "fptosi",
) )
.into(); .map(Into::into)
.unwrap();
Some(val) Some(val)
} else { } else {
unreachable!() unreachable!()
@ -695,7 +705,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
let res = if ctx.unifier.unioned(arg_ty, boolean) { let res = if ctx.unifier.unioned(arg_ty, boolean) {
ctx.builder ctx.builder
.build_int_z_extend(arg.into_int_value(), ctx.ctx.i64_type(), "zext") .build_int_z_extend(arg.into_int_value(), ctx.ctx.i64_type(), "zext")
.into() .map(Into::into)
.unwrap()
} else if ctx.unifier.unioned(arg_ty, int32) } else if ctx.unifier.unioned(arg_ty, int32)
|| ctx.unifier.unioned(arg_ty, uint32) || ctx.unifier.unioned(arg_ty, uint32)
{ {
@ -705,34 +716,45 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
{ {
ctx.builder ctx.builder
.build_int_truncate(arg.into_int_value(), ctx.ctx.i32_type(), "trunc") .build_int_truncate(arg.into_int_value(), ctx.ctx.i32_type(), "trunc")
.into() .map(Into::into)
.unwrap()
} else if ctx.unifier.unioned(arg_ty, float) { } else if ctx.unifier.unioned(arg_ty, float) {
let llvm_i32 = ctx.ctx.i32_type(); let llvm_i32 = ctx.ctx.i32_type();
let llvm_i64 = ctx.ctx.i64_type(); let llvm_i64 = ctx.ctx.i64_type();
let arg = arg.into_float_value(); let arg = arg.into_float_value();
let arg_gez = ctx.builder let arg_gez = ctx.builder
.build_float_compare(FloatPredicate::OGE, arg, arg.get_type().const_zero(), ""); .build_float_compare(
FloatPredicate::OGE,
arg,
arg.get_type().const_zero(),
"",
)
.unwrap();
let to_int32 = ctx.builder let to_int32 = ctx.builder
.build_float_to_signed_int( .build_float_to_signed_int(
arg, arg,
llvm_i32, llvm_i32,
"" "",
); )
.unwrap();
let to_uint64 = ctx.builder let to_uint64 = ctx.builder
.build_float_to_unsigned_int( .build_float_to_unsigned_int(
arg, arg,
llvm_i64, llvm_i64,
"" "",
); )
.unwrap();
let val = ctx.builder.build_select( let val = ctx.builder
.build_select(
arg_gez, arg_gez,
ctx.builder.build_int_truncate(to_uint64, llvm_i32, ""), ctx.builder.build_int_truncate(to_uint64, llvm_i32, "").unwrap(),
to_int32, to_int32,
"conv" "conv",
); )
.unwrap();
val val
} else { } else {
@ -774,11 +796,13 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
{ {
ctx.builder ctx.builder
.build_int_z_extend(arg.into_int_value(), ctx.ctx.i64_type(), "zext") .build_int_z_extend(arg.into_int_value(), ctx.ctx.i64_type(), "zext")
.into() .map(Into::into)
.unwrap()
} else if ctx.unifier.unioned(arg_ty, int32) { } else if ctx.unifier.unioned(arg_ty, int32) {
ctx.builder ctx.builder
.build_int_s_extend(arg.into_int_value(), ctx.ctx.i64_type(), "sext") .build_int_s_extend(arg.into_int_value(), ctx.ctx.i64_type(), "sext")
.into() .map(Into::into)
.unwrap()
} else if ctx.unifier.unioned(arg_ty, int64) } else if ctx.unifier.unioned(arg_ty, int64)
|| ctx.unifier.unioned(arg_ty, uint64) || ctx.unifier.unioned(arg_ty, uint64)
{ {
@ -788,27 +812,24 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
let arg = arg.into_float_value(); let arg = arg.into_float_value();
let arg_gez = ctx.builder let arg_gez = ctx.builder
.build_float_compare(FloatPredicate::OGE, arg, arg.get_type().const_zero(), ""); .build_float_compare(
FloatPredicate::OGE,
arg,
arg.get_type().const_zero(),
"",
)
.unwrap();
let to_int64 = ctx.builder let to_int64 = ctx.builder
.build_float_to_signed_int( .build_float_to_signed_int(arg, llvm_i64, "")
arg, .unwrap();
llvm_i64,
""
);
let to_uint64 = ctx.builder let to_uint64 = ctx.builder
.build_float_to_unsigned_int( .build_float_to_unsigned_int(arg, llvm_i64, "")
arg, .unwrap();
llvm_i64,
""
);
let val = ctx.builder.build_select( let val = ctx.builder
arg_gez, .build_select(arg_gez, to_uint64, to_int64, "conv")
to_uint64, .unwrap();
to_int64,
"conv"
);
val val
} else { } else {
@ -852,14 +873,16 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
let val = ctx let val = ctx
.builder .builder
.build_signed_int_to_float(arg, ctx.ctx.f64_type(), "sitofp") .build_signed_int_to_float(arg, ctx.ctx.f64_type(), "sitofp")
.into(); .map(Into::into)
.unwrap();
Some(val) Some(val)
} else if [uint32, uint64].iter().any(|ty| ctx.unifier.unioned(arg_ty, *ty)) { } else if [uint32, uint64].iter().any(|ty| ctx.unifier.unioned(arg_ty, *ty)) {
let arg = arg.into_int_value(); let arg = arg.into_int_value();
let val = ctx let val = ctx
.builder .builder
.build_unsigned_int_to_float(arg, ctx.ctx.f64_type(), "uitofp") .build_unsigned_int_to_float(arg, ctx.ctx.f64_type(), "uitofp")
.into(); .map(Into::into)
.unwrap();
Some(val) Some(val)
} else if ctx.unifier.unioned(arg_ty, float) { } else if ctx.unifier.unioned(arg_ty, float) {
Some(arg) Some(arg)
@ -1002,11 +1025,12 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
let val = ctx let val = ctx
.builder .builder
.build_call(intrinsic_fn, &[arg.into()], "") .build_call(intrinsic_fn, &[arg.into()], "")
.try_as_basic_value() .map(CallSiteValue::try_as_basic_value)
.left() .map(Either::unwrap_left)
.unwrap(); .unwrap();
let val_toint = ctx.builder let val_toint = ctx.builder
.build_float_to_signed_int(val.into_float_value(), llvm_i32, "round"); .build_float_to_signed_int(val.into_float_value(), llvm_i32, "round")
.unwrap();
Ok(Some(val_toint.into())) Ok(Some(val_toint.into()))
}), }),
), ),
@ -1032,11 +1056,12 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
let val = ctx let val = ctx
.builder .builder
.build_call(intrinsic_fn, &[arg.into()], "") .build_call(intrinsic_fn, &[arg.into()], "")
.try_as_basic_value() .map(CallSiteValue::try_as_basic_value)
.left() .map(Either::unwrap_left)
.unwrap(); .unwrap();
let val_toint = ctx.builder let val_toint = ctx.builder
.build_float_to_signed_int(val.into_float_value(), llvm_i64, "round"); .build_float_to_signed_int(val.into_float_value(), llvm_i64, "round")
.unwrap();
Ok(Some(val_toint.into())) Ok(Some(val_toint.into()))
}), }),
), ),
@ -1061,8 +1086,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
let val = ctx let val = ctx
.builder .builder
.build_call(intrinsic_fn, &[arg.into()], "") .build_call(intrinsic_fn, &[arg.into()], "")
.try_as_basic_value() .map(CallSiteValue::try_as_basic_value)
.left() .map(Either::unwrap_left)
.unwrap(); .unwrap();
Ok(Some(val)) Ok(Some(val))
}), }),
@ -1119,12 +1144,14 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
Some(step) => { Some(step) => {
let step = step.into_int_value(); let step = step.into_int_value();
// assert step != 0, throw exception if not // assert step != 0, throw exception if not
let not_zero = ctx.builder.build_int_compare( let not_zero = ctx.builder
.build_int_compare(
IntPredicate::NE, IntPredicate::NE,
step, step,
step.get_type().const_zero(), step.get_type().const_zero(),
"range_step_ne", "range_step_ne",
); )
.unwrap();
ctx.make_assert( ctx.make_assert(
generator, generator,
not_zero, not_zero,
@ -1146,20 +1173,24 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
let ty = int32.array_type(3); let ty = int32.array_type(3);
let ptr = generator.gen_var_alloc(ctx, ty.into(), Some("range")).unwrap(); let ptr = generator.gen_var_alloc(ctx, ty.into(), Some("range")).unwrap();
unsafe { unsafe {
let a = ctx.builder.build_in_bounds_gep(ptr, &[zero, zero], "start"); let a = ctx.builder
let b = ctx.builder.build_in_bounds_gep( .build_in_bounds_gep(ptr, &[zero, zero], "start")
.unwrap();
let b = ctx.builder
.build_in_bounds_gep(
ptr, ptr,
&[zero, int32.const_int(1, false)], &[zero, int32.const_int(1, false)],
"end", "end",
); )
.unwrap();
let c = ctx.builder.build_in_bounds_gep( let c = ctx.builder.build_in_bounds_gep(
ptr, ptr,
&[zero, int32.const_int(2, false)], &[zero, int32.const_int(2, false)],
"step", "step",
); ).unwrap();
ctx.builder.build_store(a, start); ctx.builder.build_store(a, start).unwrap();
ctx.builder.build_store(b, stop); ctx.builder.build_store(b, stop).unwrap();
ctx.builder.build_store(c, step); ctx.builder.build_store(c, step).unwrap();
} }
Ok(Some(ptr.into())) Ok(Some(ptr.into()))
}, },
@ -1217,7 +1248,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
arg.into_int_value(), arg.into_int_value(),
"bool", "bool",
) )
.into(), .map(Into::into)
.unwrap(),
) )
} else if ctx.unifier.unioned(arg_ty, int64) { } else if ctx.unifier.unioned(arg_ty, int64) {
Some( Some(
@ -1228,7 +1260,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
arg.into_int_value(), arg.into_int_value(),
"bool", "bool",
) )
.into(), .map(Into::into)
.unwrap(),
) )
} else if ctx.unifier.unioned(arg_ty, float) { } else if ctx.unifier.unioned(arg_ty, float) {
let val = ctx let val = ctx
@ -1240,7 +1273,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
ctx.ctx.f64_type().const_zero(), ctx.ctx.f64_type().const_zero(),
"bool", "bool",
) )
.into(); .map(Into::into)
.unwrap();
Some(val) Some(val)
} else { } else {
unreachable!() unreachable!()
@ -1271,11 +1305,12 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
let val = ctx let val = ctx
.builder .builder
.build_call(intrinsic_fn, &[arg.into()], "") .build_call(intrinsic_fn, &[arg.into()], "")
.try_as_basic_value() .map(CallSiteValue::try_as_basic_value)
.left() .map(Either::unwrap_left)
.unwrap(); .unwrap();
let val_toint = ctx.builder let val_toint = ctx.builder
.build_float_to_signed_int(val.into_float_value(), llvm_i32, "floor"); .build_float_to_signed_int(val.into_float_value(), llvm_i32, "floor")
.unwrap();
Ok(Some(val_toint.into())) Ok(Some(val_toint.into()))
}), }),
), ),
@ -1301,11 +1336,12 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
let val = ctx let val = ctx
.builder .builder
.build_call(intrinsic_fn, &[arg.into()], "") .build_call(intrinsic_fn, &[arg.into()], "")
.try_as_basic_value() .map(CallSiteValue::try_as_basic_value)
.left() .map(Either::unwrap_left)
.unwrap(); .unwrap();
let val_toint = ctx.builder let val_toint = ctx.builder
.build_float_to_signed_int(val.into_float_value(), llvm_i64, "floor"); .build_float_to_signed_int(val.into_float_value(), llvm_i64, "floor")
.unwrap();
Ok(Some(val_toint.into())) Ok(Some(val_toint.into()))
}), }),
), ),
@ -1330,8 +1366,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
let val = ctx let val = ctx
.builder .builder
.build_call(intrinsic_fn, &[arg.into()], "") .build_call(intrinsic_fn, &[arg.into()], "")
.try_as_basic_value() .map(CallSiteValue::try_as_basic_value)
.left() .map(Either::unwrap_left)
.unwrap(); .unwrap();
Ok(Some(val)) Ok(Some(val))
}), }),
@ -1358,11 +1394,12 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
let val = ctx let val = ctx
.builder .builder
.build_call(intrinsic_fn, &[arg.into()], "") .build_call(intrinsic_fn, &[arg.into()], "")
.try_as_basic_value() .map(CallSiteValue::try_as_basic_value)
.left() .map(Either::unwrap_left)
.unwrap(); .unwrap();
let val_toint = ctx.builder let val_toint = ctx.builder
.build_float_to_signed_int(val.into_float_value(), llvm_i32, "ceil"); .build_float_to_signed_int(val.into_float_value(), llvm_i32, "ceil")
.unwrap();
Ok(Some(val_toint.into())) Ok(Some(val_toint.into()))
}), }),
), ),
@ -1388,11 +1425,12 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
let val = ctx let val = ctx
.builder .builder
.build_call(intrinsic_fn, &[arg.into()], "") .build_call(intrinsic_fn, &[arg.into()], "")
.try_as_basic_value() .map(CallSiteValue::try_as_basic_value)
.left() .map(Either::unwrap_left)
.unwrap(); .unwrap();
let val_toint = ctx.builder let val_toint = ctx.builder
.build_float_to_signed_int(val.into_float_value(), llvm_i64, "ceil"); .build_float_to_signed_int(val.into_float_value(), llvm_i64, "ceil")
.unwrap();
Ok(Some(val_toint.into())) Ok(Some(val_toint.into()))
}), }),
), ),
@ -1417,8 +1455,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
let val = ctx let val = ctx
.builder .builder
.build_call(intrinsic_fn, &[arg.into()], "") .build_call(intrinsic_fn, &[arg.into()], "")
.try_as_basic_value() .map(CallSiteValue::try_as_basic_value)
.left() .map(Either::unwrap_left)
.unwrap(); .unwrap();
Ok(Some(val)) Ok(Some(val))
}), }),
@ -1472,7 +1510,11 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
if len.get_type().get_bit_width() == 32 { if len.get_type().get_bit_width() == 32 {
Some(len.into()) Some(len.into())
} else { } else {
Some(ctx.builder.build_int_truncate(len, int32, "len2i32").into()) Some(ctx.builder
.build_int_truncate(len, int32, "len2i32")
.map(Into::into)
.unwrap()
)
} }
} }
TypeEnum::TNDArray { .. } => { TypeEnum::TNDArray { .. } => {
@ -1486,7 +1528,11 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
).into_int_value(); ).into_int_value();
if len.get_type().get_bit_width() != 32 { if len.get_type().get_bit_width() != 32 {
Some(ctx.builder.build_int_truncate(len, llvm_i32, "len").into()) Some(ctx.builder
.build_int_truncate(len, llvm_i32, "len")
.map(Into::into)
.unwrap()
)
} else { } else {
Some(len.into()) Some(len.into())
} }
@ -1553,8 +1599,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
let val = ctx let val = ctx
.builder .builder
.build_call(intrinsic, &[m_val.into(), n_val.into()], "min") .build_call(intrinsic, &[m_val.into(), n_val.into()], "min")
.try_as_basic_value() .map(CallSiteValue::try_as_basic_value)
.left() .map(Either::unwrap_left)
.unwrap(); .unwrap();
Ok(val.into()) Ok(val.into())
}, },
@ -1615,8 +1661,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
let val = ctx let val = ctx
.builder .builder
.build_call(intrinsic, &[m_val.into(), n_val.into()], "max") .build_call(intrinsic, &[m_val.into(), n_val.into()], "max")
.try_as_basic_value() .map(CallSiteValue::try_as_basic_value)
.left() .map(Either::unwrap_left)
.unwrap(); .unwrap();
Ok(val.into()) Ok(val.into())
}, },
@ -1684,8 +1730,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
}, },
"abs", "abs",
) )
.try_as_basic_value() .map(CallSiteValue::try_as_basic_value)
.left() .map(Either::unwrap_left)
.unwrap(); .unwrap();
Ok(val.into()) Ok(val.into())
}, },
@ -2079,7 +2125,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
let arg_ty = fun.0.args[0].ty; let arg_ty = fun.0.args[0].ty;
let arg_val = args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty)?; let arg_val = args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty)?;
let alloca = generator.gen_var_alloc(ctx, arg_val.get_type(), Some("alloca_some")).unwrap(); let alloca = generator.gen_var_alloc(ctx, arg_val.get_type(), Some("alloca_some")).unwrap();
ctx.builder.build_store(alloca, arg_val); ctx.builder.build_store(alloca, arg_val).unwrap();
Ok(Some(alloca.into())) Ok(Some(alloca.into()))
}, },
)))), )))),

View File

@ -1,5 +1,5 @@
use inkwell::{AddressSpace, IntPredicate, types::BasicType, values::{BasicValueEnum, PointerValue}}; use inkwell::{AddressSpace, IntPredicate, types::BasicType, values::{BasicValueEnum, PointerValue}};
use inkwell::values::{ArrayValue, IntValue}; use inkwell::values::{AggregateValueEnum, ArrayValue, IntValue};
use nac3parser::ast::StrRef; use nac3parser::ast::StrRef;
use crate::{ use crate::{
codegen::{ codegen::{
@ -39,18 +39,14 @@ fn create_ndarray_const_shape<'ctx, 'a>(
assert!(llvm_ndarray_data_t.is_sized()); assert!(llvm_ndarray_data_t.is_sized());
for i in 0..shape.get_type().len() { for i in 0..shape.get_type().len() {
let shape_dim = ctx.builder.build_extract_value( let shape_dim = ctx.builder
shape, .build_extract_value(shape, i, "")
i, .map(BasicValueEnum::into_int_value)
"", .unwrap();
).unwrap();
let shape_dim_gez = ctx.builder.build_int_compare( let shape_dim_gez = ctx.builder
IntPredicate::SGE, .build_int_compare(IntPredicate::SGE, shape_dim, llvm_usize.const_zero(), "")
shape_dim.into_int_value(), .unwrap();
llvm_usize.const_zero(),
""
);
ctx.make_assert( ctx.make_assert(
generator, generator,
@ -80,10 +76,10 @@ fn create_ndarray_const_shape<'ctx, 'a>(
.get_dims() .get_dims()
.ptr_offset(ctx, generator, llvm_usize.const_int(i as u64, true), None); .ptr_offset(ctx, generator, llvm_usize.const_int(i as u64, true), None);
let shape_dim = ctx.builder.build_extract_value(shape, i, "") let shape_dim = ctx.builder.build_extract_value(shape, i, "")
.map(|val| val.into_int_value()) .map(BasicValueEnum::into_int_value)
.unwrap(); .unwrap();
ctx.builder.build_store(ndarray_dim, shape_dim); ctx.builder.build_store(ndarray_dim, shape_dim).unwrap();
} }
let ndarray_dims = ndarray.get_dims().get_ptr(ctx); let ndarray_dims = ndarray.get_dims().get_ptr(ctx);
@ -167,30 +163,29 @@ fn call_ndarray_empty_impl<'ctx, 'a>(
ctx, ctx,
|generator, ctx| { |generator, ctx| {
let i = generator.gen_var_alloc(ctx, llvm_usize.into(), None)?; let i = generator.gen_var_alloc(ctx, llvm_usize.into(), None)?;
ctx.builder.build_store(i, llvm_usize.const_zero()); ctx.builder.build_store(i, llvm_usize.const_zero()).unwrap();
Ok(i) Ok(i)
}, },
|_, ctx, i_addr| { |_, ctx, i_addr| {
let i = ctx.builder let i = ctx.builder
.build_load(i_addr, "") .build_load(i_addr, "")
.into_int_value(); .map(BasicValueEnum::into_int_value)
.unwrap();
let shape_len = shape.load_size(ctx, None); let shape_len = shape.load_size(ctx, None);
Ok(ctx.builder.build_int_compare(IntPredicate::ULT, i, shape_len, "")) Ok(ctx.builder.build_int_compare(IntPredicate::ULT, i, shape_len, "").unwrap())
}, },
|generator, ctx, i_addr| { |generator, ctx, i_addr| {
let i = ctx.builder let i = ctx.builder
.build_load(i_addr, "") .build_load(i_addr, "")
.into_int_value(); .map(BasicValueEnum::into_int_value)
.unwrap();
let shape_dim = shape.get_data().get(ctx, generator, i, None).into_int_value(); let shape_dim = shape.get_data().get(ctx, generator, i, None).into_int_value();
let shape_dim_gez = ctx.builder.build_int_compare( let shape_dim_gez = ctx.builder
IntPredicate::SGE, .build_int_compare(IntPredicate::SGE, shape_dim, llvm_i32.const_zero(), "")
shape_dim, .unwrap();
llvm_i32.const_zero(),
""
);
ctx.make_assert( ctx.make_assert(
generator, generator,
@ -206,9 +201,10 @@ fn call_ndarray_empty_impl<'ctx, 'a>(
|_, ctx, i_addr| { |_, ctx, i_addr| {
let i = ctx.builder let i = ctx.builder
.build_load(i_addr, "") .build_load(i_addr, "")
.into_int_value(); .map(BasicValueEnum::into_int_value)
let i = ctx.builder.build_int_add(i, llvm_usize.const_int(1, true), ""); .unwrap();
ctx.builder.build_store(i_addr, i); let i = ctx.builder.build_int_add(i, llvm_usize.const_int(1, true), "").unwrap();
ctx.builder.build_store(i_addr, i).unwrap();
Ok(()) Ok(())
}, },
@ -268,36 +264,39 @@ fn ndarray_fill_flattened<'ctx, 'a, ValueFn>(
ctx, ctx,
|generator, ctx| { |generator, ctx| {
let i = generator.gen_var_alloc(ctx, llvm_usize.into(), None)?; let i = generator.gen_var_alloc(ctx, llvm_usize.into(), None)?;
ctx.builder.build_store(i, llvm_usize.const_zero()); ctx.builder.build_store(i, llvm_usize.const_zero()).unwrap();
Ok(i) Ok(i)
}, },
|_, ctx, i_addr| { |_, ctx, i_addr| {
let i = ctx.builder let i = ctx.builder
.build_load(i_addr, "") .build_load(i_addr, "")
.into_int_value(); .map(BasicValueEnum::into_int_value)
.unwrap();
Ok(ctx.builder.build_int_compare(IntPredicate::ULT, i, ndarray_num_elems, "")) Ok(ctx.builder.build_int_compare(IntPredicate::ULT, i, ndarray_num_elems, "").unwrap())
}, },
|generator, ctx, i_addr| { |generator, ctx, i_addr| {
let i = ctx.builder let i = ctx.builder
.build_load(i_addr, "") .build_load(i_addr, "")
.into_int_value(); .map(BasicValueEnum::into_int_value)
.unwrap();
let elem = unsafe { let elem = unsafe {
ndarray.get_data().ptr_to_data_flattened_unchecked(ctx, i, None) ndarray.get_data().ptr_to_data_flattened_unchecked(ctx, i, None)
}; };
let value = value_fn(generator, ctx, i)?; let value = value_fn(generator, ctx, i)?;
ctx.builder.build_store(elem, value); ctx.builder.build_store(elem, value).unwrap();
Ok(()) Ok(())
}, },
|_, ctx, i_addr| { |_, ctx, i_addr| {
let i = ctx.builder let i = ctx.builder
.build_load(i_addr, "") .build_load(i_addr, "")
.into_int_value(); .map(BasicValueEnum::into_int_value)
let i = ctx.builder.build_int_add(i, llvm_usize.const_int(1, true), ""); .unwrap();
ctx.builder.build_store(i_addr, i); let i = ctx.builder.build_int_add(i, llvm_usize.const_int(1, true), "").unwrap();
ctx.builder.build_store(i_addr, i).unwrap();
Ok(()) Ok(())
}, },
@ -451,7 +450,8 @@ fn call_ndarray_full_impl<'ctx, 'a>(
ctx.module.add_function(memcpy_fn_name.as_str(), fn_type, None) ctx.module.add_function(memcpy_fn_name.as_str(), fn_type, None)
}); });
ctx.builder.build_call( ctx.builder
.build_call(
memcpy_fn, memcpy_fn,
&[ &[
copy.into(), copy.into(),
@ -460,7 +460,8 @@ fn call_ndarray_full_impl<'ctx, 'a>(
llvm_i1.const_zero().into(), llvm_i1.const_zero().into(),
], ],
"", "",
); )
.unwrap();
copy.into() copy.into()
} else if fill_value.is_int_value() || fill_value.is_float_value() { } else if fill_value.is_int_value() || fill_value.is_float_value() {
@ -494,18 +495,19 @@ fn call_ndarray_eye_impl<'ctx, 'a>(
let shape_addr = generator.gen_var_alloc(ctx, llvm_usize_2.into(), None)?; let shape_addr = generator.gen_var_alloc(ctx, llvm_usize_2.into(), None)?;
let shape = ctx.builder.build_load(shape_addr, "") let shape = ctx.builder.build_load(shape_addr, "")
.into_array_value(); .map(BasicValueEnum::into_array_value)
let nrows = ctx.builder.build_int_z_extend_or_bit_cast(nrows, llvm_usize, "");
let shape = ctx.builder
.build_insert_value(shape, nrows, 0, "")
.map(|val| val.into_array_value())
.unwrap(); .unwrap();
let ncols = ctx.builder.build_int_z_extend_or_bit_cast(ncols, llvm_usize, ""); let nrows = ctx.builder.build_int_z_extend_or_bit_cast(nrows, llvm_usize, "").unwrap();
let shape = ctx.builder
.build_insert_value(shape, nrows, 0, "")
.map(AggregateValueEnum::into_array_value)
.unwrap();
let ncols = ctx.builder.build_int_z_extend_or_bit_cast(ncols, llvm_usize, "").unwrap();
let shape = ctx.builder let shape = ctx.builder
.build_insert_value(shape, ncols, 1, "") .build_insert_value(shape, ncols, 1, "")
.map(|val| val.into_array_value()) .map(AggregateValueEnum::into_array_value)
.unwrap(); .unwrap();
let ndarray = create_ndarray_const_shape(generator, ctx, elem_ty, shape)?; let ndarray = create_ndarray_const_shape(generator, ctx, elem_ty, shape)?;
@ -526,22 +528,21 @@ fn call_ndarray_eye_impl<'ctx, 'a>(
None, None,
).into_int_value(); ).into_int_value();
let col_with_offset = ctx.builder.build_int_add( let col_with_offset = ctx.builder
.build_int_add(
col, col,
ctx.builder.build_int_z_extend_or_bit_cast(offset, llvm_usize, ""), ctx.builder.build_int_z_extend_or_bit_cast(offset, llvm_usize, "").unwrap(),
"" "",
); )
let is_on_diag = ctx.builder.build_int_compare( .unwrap();
IntPredicate::EQ, let is_on_diag = ctx.builder
row, .build_int_compare(IntPredicate::EQ, row, col_with_offset, "")
col_with_offset, .unwrap();
""
);
let zero = ndarray_zero_value(generator, ctx, elem_ty); let zero = ndarray_zero_value(generator, ctx, elem_ty);
let one = ndarray_one_value(generator, ctx, elem_ty); let one = ndarray_one_value(generator, ctx, elem_ty);
let value = ctx.builder.build_select(is_on_diag, one, zero, ""); let value = ctx.builder.build_select(is_on_diag, one, zero, "").unwrap();
Ok(value) Ok(value)
}, },

View File

@ -16,7 +16,7 @@ lalrpop-util = "0.20"
log = "0.4" log = "0.4"
unic-emoji-char = "0.9" unic-emoji-char = "0.9"
unic-ucd-ident = "0.9" unic-ucd-ident = "0.9"
unicode_names2 = "1.0" unicode_names2 = "1.2"
phf = { version = "0.11", features = ["macros"] } phf = { version = "0.11", features = ["macros"] }
ahash = "0.8" ahash = "0.8"

View File

@ -10,10 +10,10 @@ nac3parser = { path = "../nac3parser" }
nac3core = { path = "../nac3core" } nac3core = { path = "../nac3core" }
[dependencies.clap] [dependencies.clap]
version = "4.4" version = "4.5"
features = ["derive"] features = ["derive"]
[dependencies.inkwell] [dependencies.inkwell]
version = "0.2" version = "0.4"
default-features = false default-features = false
features = ["llvm14-0", "target-x86", "target-arm", "target-riscv", "no-libffi-linking"] features = ["llvm14-0", "target-x86", "target-arm", "target-riscv", "no-libffi-linking"]