forked from M-Labs/nac3
core: Update cargo dependencies
This commit is contained in:
parent
e1dbe2526a
commit
8492503af2
|
@ -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"
|
||||||
|
|
|
@ -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"]
|
||||||
|
|
||||||
|
|
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()))?;
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"]
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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, ¶ms, then_block, target, call_name)
|
.build_invoke(fun, ¶ms, 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, ¶m, call_name).try_as_basic_value().left()
|
self.builder.build_call(fun, ¶m, 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,
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)?,
|
||||||
|
|
|
@ -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()))
|
||||||
},
|
},
|
||||||
)))),
|
)))),
|
||||||
|
|
|
@ -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)
|
||||||
},
|
},
|
||||||
|
|
|
@ -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"
|
||||||
|
|
||||||
|
|
|
@ -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"]
|
||||||
|
|
Loading…
Reference in New Issue