feat: migrate to cranelift (WIP)

This commit is contained in:
2025-06-27 22:40:53 +08:00
parent e26789f3b7
commit 5625f28e9b
13 changed files with 720 additions and 732 deletions

421
Cargo.lock generated
View File

@@ -23,12 +23,24 @@ version = "1.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
[[package]]
name = "arbitrary"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223"
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.1.0" version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.9.0" version = "2.9.0"
@@ -36,12 +48,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
[[package]] [[package]]
name = "cc" name = "bumpalo"
version = "1.2.21" version = "3.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8691782945451c1c383942c4874dbe63814f61cb57ef773cda2972682b7bb3c0" checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
dependencies = [ dependencies = [
"shlex", "allocator-api2",
] ]
[[package]] [[package]]
@@ -80,6 +92,177 @@ version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636" checksum = "7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636"
[[package]]
name = "cranelift"
version = "0.121.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94c4a83217cefee80a63921d524b7c98c4dc0c9913bd876fcdfa76a4fcef9b62"
dependencies = [
"cranelift-codegen",
"cranelift-frontend",
"cranelift-module",
]
[[package]]
name = "cranelift-assembler-x64"
version = "0.121.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "226b7077389885873ffad5d778e8512742580a6e11b0f723072f41f305d3652f"
dependencies = [
"cranelift-assembler-x64-meta",
]
[[package]]
name = "cranelift-assembler-x64-meta"
version = "0.121.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e9cfeae5a23c8cf9c43381f49211f3ce6dc1da1d46f1c5d06966e6258cc483fa"
dependencies = [
"cranelift-srcgen",
]
[[package]]
name = "cranelift-bforest"
version = "0.121.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c88c577c6af92b550cb83455c331cf8e1bc89fe0ccc3e7eb0fa617ed1d63056"
dependencies = [
"cranelift-entity",
]
[[package]]
name = "cranelift-bitset"
version = "0.121.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "370f0aa7f1816bf0f838048d69b72d6cf12ef2fc3b37f6997fe494ffb9feb3ad"
[[package]]
name = "cranelift-codegen"
version = "0.121.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d1a10a8a2958b68ecd261e565eef285249e242a8447ac959978319eabbb4a55"
dependencies = [
"bumpalo",
"cranelift-assembler-x64",
"cranelift-bforest",
"cranelift-bitset",
"cranelift-codegen-meta",
"cranelift-codegen-shared",
"cranelift-control",
"cranelift-entity",
"cranelift-isle",
"gimli",
"hashbrown 0.15.3",
"log",
"regalloc2",
"rustc-hash 2.1.1",
"serde",
"smallvec",
"target-lexicon",
"wasmtime-math",
]
[[package]]
name = "cranelift-codegen-meta"
version = "0.121.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f319986d5ae1386cfec625c70f8c01e52dc1f910aa6aaee7740bf8842d4e19c7"
dependencies = [
"cranelift-assembler-x64-meta",
"cranelift-codegen-shared",
"cranelift-srcgen",
]
[[package]]
name = "cranelift-codegen-shared"
version = "0.121.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed52f5660397039c3c741c3acf18746445f4e20629b7280d9f2ccfe57e2b1efd"
[[package]]
name = "cranelift-control"
version = "0.121.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79bde8d48e1840702574e28c5d7d4499441435af71e6c47450881f84ce2b60a5"
dependencies = [
"arbitrary",
]
[[package]]
name = "cranelift-entity"
version = "0.121.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0335ac187211ac94c254826b6e78d23b8654ae09ebf0830506a827a2647162f"
dependencies = [
"cranelift-bitset",
]
[[package]]
name = "cranelift-frontend"
version = "0.121.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4fce5fcf93c1fece95d0175b15fbaf0808b187430bc06c8ecde80db0ed58c5e"
dependencies = [
"cranelift-codegen",
"log",
"smallvec",
"target-lexicon",
]
[[package]]
name = "cranelift-isle"
version = "0.121.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13fc8d838a2bf28438dbaf6ccdbc34531b6a972054f43fd23be7f124121ce6e0"
[[package]]
name = "cranelift-jit"
version = "0.121.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e50932cee220b782812b728c0e63adf2b8eef63e823df8e5fea84c18f3fff99"
dependencies = [
"anyhow",
"cranelift-codegen",
"cranelift-control",
"cranelift-entity",
"cranelift-module",
"cranelift-native",
"libc",
"log",
"region",
"target-lexicon",
"wasmtime-jit-icache-coherence",
"windows-sys 0.59.0",
]
[[package]]
name = "cranelift-module"
version = "0.121.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2707466bd2c786bd637e6b6375ebb472a158be35b6efbe85d2a744ec82e16356"
dependencies = [
"anyhow",
"cranelift-codegen",
"cranelift-control",
]
[[package]]
name = "cranelift-native"
version = "0.121.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0975ce66adcf2e0729d06b1d3efea0398d793d1f39c2e0a6f52a347537836693"
dependencies = [
"cranelift-codegen",
"libc",
"target-lexicon",
]
[[package]]
name = "cranelift-srcgen"
version = "0.121.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4493a9b500bb02837ea2fb7d4b58c1c21c37a470ae33c92659f4e637aad14c9"
[[package]] [[package]]
name = "derive_more" name = "derive_more"
version = "2.0.1" version = "2.0.1"
@@ -133,7 +316,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e"
dependencies = [ dependencies = [
"libc", "libc",
"windows-sys", "windows-sys 0.59.0",
] ]
[[package]] [[package]]
@@ -142,6 +325,12 @@ version = "3.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5d9305ccc6942a704f4335694ecd3de2ea531b114ac2d51f5f843750787a92f" checksum = "a5d9305ccc6942a704f4335694ecd3de2ea531b114ac2d51f5f843750787a92f"
[[package]]
name = "fallible-iterator"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
[[package]] [[package]]
name = "fd-lock" name = "fd-lock"
version = "4.0.4" version = "4.0.4"
@@ -150,7 +339,7 @@ checksum = "0ce92ff622d6dadf7349484f42c93271a0d49b7cc4d466a936405bacbe10aa78"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"rustix", "rustix",
"windows-sys", "windows-sys 0.59.0",
] ]
[[package]] [[package]]
@@ -159,6 +348,17 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
[[package]]
name = "gimli"
version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
dependencies = [
"fallible-iterator",
"indexmap",
"stable_deref_trait",
]
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.14.3" version = "0.14.3"
@@ -182,7 +382,7 @@ version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf"
dependencies = [ dependencies = [
"windows-sys", "windows-sys 0.59.0",
] ]
[[package]] [[package]]
@@ -195,31 +395,6 @@ dependencies = [
"hashbrown 0.15.3", "hashbrown 0.15.3",
] ]
[[package]]
name = "inkwell"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e67349bd7578d4afebbe15eaa642a80b884e8623db74b1716611b131feb1deef"
dependencies = [
"either",
"inkwell_internals",
"libc",
"llvm-sys",
"once_cell",
"thiserror 1.0.69",
]
[[package]]
name = "inkwell_internals"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f365c8de536236cfdebd0ba2130de22acefed18b1fb99c32783b3840aec5fb46"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "itertools" name = "itertools"
version = "0.14.0" version = "0.14.0"
@@ -229,38 +404,24 @@ dependencies = [
"either", "either",
] ]
[[package]]
name = "lazy_static"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.172" version = "0.2.172"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
[[package]]
name = "libm"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
[[package]] [[package]]
name = "linux-raw-sys" name = "linux-raw-sys"
version = "0.9.4" version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
[[package]]
name = "llvm-sys"
version = "181.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d320f9d2723c97d4b78f9190a61ed25cc7cfbe456668c08e6e7dd8e50ceb8500"
dependencies = [
"anyhow",
"cc",
"lazy_static",
"libc",
"regex-lite",
"semver",
]
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.27" version = "0.4.27"
@@ -276,6 +437,15 @@ dependencies = [
"hashbrown 0.15.3", "hashbrown 0.15.3",
] ]
[[package]]
name = "mach2"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d640282b302c0bb0a2a8e0233ead9035e3bed871f0b7e81fe4a1ec829765db44"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.7.4" version = "2.7.4"
@@ -306,7 +476,7 @@ version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
dependencies = [ dependencies = [
"bitflags", "bitflags 2.9.0",
"cfg-if", "cfg-if",
"cfg_aliases", "cfg_aliases",
"libc", "libc",
@@ -316,10 +486,13 @@ dependencies = [
name = "nixjit" name = "nixjit"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"cranelift",
"cranelift-jit",
"cranelift-module",
"cranelift-native",
"derive_more", "derive_more",
"ecow", "ecow",
"hashbrown 0.15.3", "hashbrown 0.15.3",
"inkwell",
"itertools", "itertools",
"lru", "lru",
"priority-queue", "priority-queue",
@@ -327,15 +500,9 @@ dependencies = [
"replace_with", "replace_with",
"rnix", "rnix",
"rustyline", "rustyline",
"thiserror 2.0.12", "thiserror",
] ]
[[package]]
name = "once_cell"
version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
[[package]] [[package]]
name = "priority-queue" name = "priority-queue"
version = "2.5.0" version = "2.5.0"
@@ -375,6 +542,20 @@ dependencies = [
"nibble_vec", "nibble_vec",
] ]
[[package]]
name = "regalloc2"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5216b1837de2149f8bc8e6d5f88a9326b63b8c836ed58ce4a0a29ec736a59734"
dependencies = [
"allocator-api2",
"bumpalo",
"hashbrown 0.15.3",
"log",
"rustc-hash 2.1.1",
"smallvec",
]
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.11.1" version = "1.11.1"
@@ -398,18 +579,24 @@ dependencies = [
"regex-syntax", "regex-syntax",
] ]
[[package]]
name = "regex-lite"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a"
[[package]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.8.5" version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "region"
version = "3.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6b6ebd13bc009aef9cd476c1310d49ac354d36e240cf1bd753290f3dc7199a7"
dependencies = [
"bitflags 1.3.2",
"libc",
"mach2",
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "replace_with" name = "replace_with"
version = "0.1.8" version = "0.1.8"
@@ -434,7 +621,7 @@ dependencies = [
"countme", "countme",
"hashbrown 0.14.3", "hashbrown 0.14.3",
"memoffset", "memoffset",
"rustc-hash", "rustc-hash 1.1.0",
"text-size", "text-size",
] ]
@@ -444,17 +631,23 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustc-hash"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "1.0.7" version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266"
dependencies = [ dependencies = [
"bitflags", "bitflags 2.9.0",
"errno", "errno",
"libc", "libc",
"linux-raw-sys", "linux-raw-sys",
"windows-sys", "windows-sys 0.59.0",
] ]
[[package]] [[package]]
@@ -463,7 +656,7 @@ version = "15.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ee1e066dc922e513bda599c6ccb5f3bb2b0ea5870a579448f2622993f0a9a2f" checksum = "2ee1e066dc922e513bda599c6ccb5f3bb2b0ea5870a579448f2622993f0a9a2f"
dependencies = [ dependencies = [
"bitflags", "bitflags 2.9.0",
"cfg-if", "cfg-if",
"clipboard-win", "clipboard-win",
"fd-lock", "fd-lock",
@@ -476,20 +669,28 @@ dependencies = [
"unicode-segmentation", "unicode-segmentation",
"unicode-width", "unicode-width",
"utf8parse", "utf8parse",
"windows-sys", "windows-sys 0.59.0",
] ]
[[package]] [[package]]
name = "semver" name = "serde"
version = "1.0.26" version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
dependencies = [
"serde_derive",
]
[[package]] [[package]]
name = "shlex" name = "serde_derive"
version = "1.3.0" version = "1.0.219"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "smallvec" name = "smallvec"
@@ -497,6 +698,12 @@ version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.101" version = "2.0.101"
@@ -508,39 +715,25 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "target-lexicon"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e502f78cdbb8ba4718f566c418c52bc729126ffd16baee5baa718cf25dd5a69a"
[[package]] [[package]]
name = "text-size" name = "text-size"
version = "1.1.1" version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233" checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233"
[[package]]
name = "thiserror"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
dependencies = [
"thiserror-impl 1.0.69",
]
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "2.0.12" version = "2.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
dependencies = [ dependencies = [
"thiserror-impl 2.0.12", "thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn",
] ]
[[package]] [[package]]
@@ -584,6 +777,36 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "wasmtime-jit-icache-coherence"
version = "34.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44c71d64e8ebe132cd45e9d299a4d0daf261d66bd05cf50a204a1bf8cf96ff1f"
dependencies = [
"anyhow",
"cfg-if",
"libc",
"windows-sys 0.59.0",
]
[[package]]
name = "wasmtime-math"
version = "34.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "222bfa4769c6931c985711eb49a92748ea0acc4ca85fcd24e945a2f1bacda0c1"
dependencies = [
"libm",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
]
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.59.0" version = "0.59.0"

View File

@@ -34,6 +34,9 @@ hashbrown = "0.15"
priority-queue = "2.5" priority-queue = "2.5"
lru = "0.14" lru = "0.14"
replace_with = "0.1" replace_with = "0.1"
inkwell = { version = "0.6.0", features = ["llvm18-1"] } cranelift = "0.121"
cranelift-module = "0.121"
cranelift-jit = "0.121"
cranelift-native = "0.121"
rustyline = { version = "15.0", optional = true } rustyline = { version = "15.0", optional = true }

View File

@@ -1,4 +1,5 @@
use std::cell::OnceCell; use std::cell::OnceCell;
use core::mem::MaybeUninit;
use std::rc::Rc; use std::rc::Rc;
use hashbrown::HashSet; use hashbrown::HashSet;
@@ -7,7 +8,7 @@ use priority_queue::PriorityQueue;
use crate::env::Env; use crate::env::Env;
use crate::error::Result; use crate::error::Result;
use crate::eval::jit::{JITContext, JITFunc}; use crate::eval::jit::{JITContext, JITFunc, JITValue};
use crate::eval::Evaluate; use crate::eval::Evaluate;
use crate::ir::{Dep, Downgraded, Ir, SccNode}; use crate::ir::{Dep, Downgraded, Ir, SccNode};
use crate::ty::internal as i; use crate::ty::internal as i;
@@ -19,12 +20,12 @@ mod test;
type ThunkIdx = usize; type ThunkIdx = usize;
type EnvIdx = usize; type EnvIdx = usize;
pub struct Engine<'ctx: 'exec, 'exec> { pub struct Engine<'exec> {
pub thunks: Box<[Ir]>, pub thunks: Box<[Ir]>,
pub func_offset: usize, pub func_offset: usize,
pub func_deps: Vec<HashSet<Dep>>, pub func_deps: Vec<HashSet<Dep>>,
jit: &'exec JITContext<'ctx>, jit: &'exec JITContext,
compiled: Box<[OnceCell<JITFunc<'ctx, 'exec>>]>, compiled: Box<[OnceCell<JITFunc<'exec>>]>,
tasks: PriorityQueue<CompileTask, usize>, tasks: PriorityQueue<CompileTask, usize>,
} }
@@ -79,8 +80,12 @@ impl<'ctx, 'exec> Engine<'ctx, 'exec> {
} }
pub fn eval_thunk(&mut self, idx: usize, env: &mut Env) -> Result<i::Value> { pub fn eval_thunk(&mut self, idx: usize, env: &mut Env) -> Result<i::Value> {
let func = self.compiled[idx].get_or_init(|| self.jit.compile(&self.thunks[idx])); let func = self.compiled[idx].get_or_init(|| self.jit.compile(&self.thunks[idx], idx));
Ok(unsafe { func(self as *const Engine, env as *const Env).into() }) let mut ret: MaybeUninit<JITValue> = MaybeUninit::uninit();
unsafe {
func(self as *const Engine, env as *const Env, core::mem::transmute::<*mut MaybeUninit<JITValue>, *mut JITValue>(&mut ret as *mut _));
Ok(ret.assume_init().into())
}
} }
pub fn eval_func_deps(&mut self, idx: usize, env: &mut Env) -> Result<()> { pub fn eval_func_deps(&mut self, idx: usize, env: &mut Env) -> Result<()> {

View File

@@ -1,4 +1,4 @@
use std::fmt::Debug; use core::fmt::Debug;
use std::rc::Rc; use std::rc::Rc;
use ecow::EcoString; use ecow::EcoString;
@@ -12,7 +12,6 @@ pub struct Env {
cache: Vec<HashMap<usize, Value>>, cache: Vec<HashMap<usize, Value>>,
with: Vec<Rc<HashMap<EcoString, Value>>>, with: Vec<Rc<HashMap<EcoString, Value>>>,
args: Vec<Value>, args: Vec<Value>,
pub args_len: usize,
} }
impl Env { impl Env {
@@ -21,7 +20,6 @@ impl Env {
cache: Vec::from([HashMap::new()]), cache: Vec::from([HashMap::new()]),
with: Vec::new(), with: Vec::new(),
args: Vec::new(), args: Vec::new(),
args_len: 0,
} }
} }
@@ -89,7 +87,7 @@ impl Env {
} }
pub fn enter_arg(&mut self, arg: Value) { pub fn enter_arg(&mut self, arg: Value) {
self.args.push(arg) self.args.push(arg);
} }
pub fn pop_args(&mut self, len: usize) -> Vec<Value> { pub fn pop_args(&mut self, len: usize) -> Vec<Value> {

View File

@@ -10,8 +10,8 @@ pub enum Error {
DowngradeError(String), DowngradeError(String),
#[error("error occurred during evaluation stage: {0}")] #[error("error occurred during evaluation stage: {0}")]
EvalError(String), EvalError(String),
#[error("error occurred during JIT compile stage: {0}")] // #[error("error occurred during JIT compile stage: {0}")]
CompileError(#[from] inkwell::builder::BuilderError), // CompileError(#[from] inkwell::builder::BuilderError),
#[error("unknown error")] #[error("unknown error")]
Unknown, Unknown,
} }

View File

@@ -1,70 +1,71 @@
use std::{alloc::Layout, ffi::CStr}; use std::{alloc::Layout, ffi::CStr};
use inkwell::values::{FunctionValue, StructValue}; use cranelift::prelude::*;
use cranelift::codegen::ir;
use crate::eval::jit::JITValue;
use crate::ir::*;
use crate::ty::common as c; use crate::ty::common as c;
use crate::ty::internal::Value; use crate::ty::internal::Value;
use crate::{eval::jit::JITValue, ir::*};
use super::{JITContext, ValueTag}; use super::{JITContext, ValueTag};
pub trait JITCompile { pub trait JITCompile {
fn compile<'gc>( fn compile(
&self, &self,
ctx: &JITContext<'gc>, ctx: &mut JITContext,
func: FunctionValue<'gc>, builder: &mut FunctionBuilder,
values: &mut Vec<Value>, block: Block,
) -> StructValue<'gc>; ) -> ir::Value;
} }
impl JITCompile for Attrs { impl JITCompile for Attrs {
fn compile<'gc>( fn compile(
&self, &self,
ctx: &JITContext<'gc>, ctx: &mut JITContext,
func: FunctionValue<'gc>, builder: &mut FunctionBuilder,
values: &mut Vec<Value>, block: Block,
) -> StructValue<'gc> { ) -> ir::Value {
todo!() todo!()
} }
} }
impl JITCompile for List { impl JITCompile for List {
fn compile<'gc>( fn compile(
&self, &self,
ctx: &JITContext<'gc>, ctx: &mut JITContext,
func: FunctionValue<'gc>, builder: &mut FunctionBuilder,
values: &mut Vec<Value>, block: Block,
) -> StructValue<'gc> { ) -> ir::Value {
todo!() todo!()
} }
} }
impl JITCompile for HasAttr { impl JITCompile for HasAttr {
fn compile<'gc>( fn compile(
&self, &self,
ctx: &JITContext<'gc>, ctx: &mut JITContext,
func: FunctionValue<'gc>, builder: &mut FunctionBuilder,
values: &mut Vec<Value>, block: Block,
) -> StructValue<'gc> { ) -> ir::Value {
todo!() todo!()
} }
} }
impl JITCompile for BinOp { impl JITCompile for BinOp {
fn compile<'gc>( fn compile(
&self, &self,
ctx: &JITContext<'gc>, ctx: &mut JITContext,
func: FunctionValue<'gc>, builder: &mut FunctionBuilder,
values: &mut Vec<Value>, block: Block,
) -> StructValue<'gc> { ) -> ir::Value {
use BinOpKind::*; use BinOpKind::*;
use ValueTag::*; let lhs = self.lhs.compile(ctx, builder, block);
let lhs = self.lhs.compile(ctx, func, values); let rhs = self.rhs.compile(ctx, builder, block);
let rhs = self.rhs.compile(ctx, func, values);
let lhs_tag = ctx.get_tag(lhs); let lhs_tag = ctx.get_tag(lhs);
let rhs_tag = ctx.get_tag(rhs); let rhs_tag = ctx.get_tag(rhs);
let tag = ctx let tag = ctx
.builder .func_builder
.build_int_add( .build_int_add(
lhs_tag.const_shl(ctx.helpers.const_int(8)), lhs_tag.const_shl(ctx.helpers.const_int(8)),
rhs_tag, rhs_tag,
@@ -73,7 +74,7 @@ impl JITCompile for BinOp {
.unwrap(); .unwrap();
let ret = ctx.context.append_basic_block(func, "fallback"); let ret = ctx.context.append_basic_block(func, "fallback");
let res = ctx let res = ctx
.builder .func_builder
.build_alloca(ctx.helpers.value_type, "res_alloca") .build_alloca(ctx.helpers.value_type, "res_alloca")
.unwrap(); .unwrap();
match self.kind { match self.kind {
@@ -83,7 +84,7 @@ impl JITCompile for BinOp {
let float_int = ctx.context.append_basic_block(func, "float_int"); let float_int = ctx.context.append_basic_block(func, "float_int");
let float_float = ctx.context.append_basic_block(func, "float_float"); let float_float = ctx.context.append_basic_block(func, "float_float");
let fallback = ctx.context.append_basic_block(func, "fallback"); let fallback = ctx.context.append_basic_block(func, "fallback");
ctx.builder ctx.func_builder
.build_switch( .build_switch(
tag, tag,
fallback, fallback,
@@ -107,19 +108,19 @@ impl JITCompile for BinOp {
], ],
) )
.unwrap(); .unwrap();
ctx.builder.position_at_end(int_int); ctx.func_builder.position_at_end(int_int);
let val = ctx let val = ctx
.builder .func_builder
.build_int_add(ctx.get_int(lhs), ctx.get_int(rhs), "add") .build_int_add(ctx.get_int(lhs), ctx.get_int(rhs), "add")
.unwrap(); .unwrap();
ctx.builder ctx.func_builder
.build_store(res, ctx.helpers.new_value(Int, val.into())) .build_store(res, ctx.helpers.new_value(Int, val.into()))
.unwrap(); .unwrap();
ctx.builder.position_at_end(int_float); ctx.func_builder.position_at_end(int_float);
let val = ctx let val = ctx
.builder .func_builder
.build_float_add( .build_float_add(
ctx.builder ctx.func_builder
.build_signed_int_to_float( .build_signed_int_to_float(
ctx.get_int(lhs), ctx.get_int(lhs),
ctx.helpers.float_type, ctx.helpers.float_type,
@@ -130,15 +131,15 @@ impl JITCompile for BinOp {
"add", "add",
) )
.unwrap(); .unwrap();
ctx.builder ctx.func_builder
.build_store(res, ctx.helpers.new_value(Float, val.into())) .build_store(res, ctx.helpers.new_value(Float, val.into()))
.unwrap(); .unwrap();
ctx.builder.position_at_end(float_int); ctx.func_builder.position_at_end(float_int);
let val = ctx let val = ctx
.builder .func_builder
.build_float_add( .build_float_add(
ctx.get_float(lhs), ctx.get_float(lhs),
ctx.builder ctx.func_builder
.build_signed_int_to_float( .build_signed_int_to_float(
ctx.get_int(rhs), ctx.get_int(rhs),
ctx.helpers.float_type, ctx.helpers.float_type,
@@ -148,23 +149,23 @@ impl JITCompile for BinOp {
"add", "add",
) )
.unwrap(); .unwrap();
ctx.builder ctx.func_builder
.build_store(res, ctx.helpers.new_value(Float, val.into())) .build_store(res, ctx.helpers.new_value(Float, val.into()))
.unwrap(); .unwrap();
ctx.builder.position_at_end(int_int); ctx.func_builder.position_at_end(int_int);
let val = ctx let val = ctx
.builder .func_builder
.build_float_add(ctx.get_float(lhs), ctx.get_float(rhs), "add") .build_float_add(ctx.get_float(lhs), ctx.get_float(rhs), "add")
.unwrap(); .unwrap();
ctx.builder ctx.func_builder
.build_store(res, ctx.helpers.new_value(Float, val.into())) .build_store(res, ctx.helpers.new_value(Float, val.into()))
.unwrap(); .unwrap();
ctx.builder.position_at_end(fallback); ctx.func_builder.position_at_end(fallback);
} }
Or => { Or => {
let bool_bool = ctx.context.append_basic_block(func, "int_int"); let bool_bool = ctx.context.append_basic_block(func, "int_int");
let fallback = ctx.context.append_basic_block(func, "fallback"); let fallback = ctx.context.append_basic_block(func, "fallback");
ctx.builder ctx.func_builder
.build_switch( .build_switch(
tag, tag,
fallback, fallback,
@@ -174,20 +175,20 @@ impl JITCompile for BinOp {
)], )],
) )
.unwrap(); .unwrap();
ctx.builder.position_at_end(bool_bool); ctx.func_builder.position_at_end(bool_bool);
let val = ctx let val = ctx
.builder .func_builder
.build_or(ctx.get_bool(lhs), ctx.get_bool(rhs), "or") .build_or(ctx.get_bool(lhs), ctx.get_bool(rhs), "or")
.unwrap(); .unwrap();
ctx.builder ctx.func_builder
.build_store(res, ctx.helpers.new_value(Bool, val.into())) .build_store(res, ctx.helpers.new_value(Bool, val.into()))
.unwrap(); .unwrap();
ctx.builder.position_at_end(fallback); ctx.func_builder.position_at_end(fallback);
} }
_ => todo!(), _ => todo!(),
} }
ctx.builder.position_at_end(ret); ctx.func_builder.position_at_end(ret);
ctx.builder ctx.func_builder
.build_load(ctx.helpers.value_type, res, "load_res") .build_load(ctx.helpers.value_type, res, "load_res")
.unwrap() .unwrap()
.try_into() .try_into()
@@ -196,25 +197,25 @@ impl JITCompile for BinOp {
} }
impl JITCompile for UnOp { impl JITCompile for UnOp {
fn compile<'gc>( fn compile(
&self, &self,
ctx: &JITContext<'gc>, ctx: &mut JITContext,
func: FunctionValue<'gc>, builder: &mut FunctionBuilder,
values: &mut Vec<Value>, block: Block,
) -> StructValue<'gc> { ) -> ir::Value {
todo!(); todo!();
let rhs = self.rhs.compile(ctx, func, values); let rhs = self.rhs.compile(ctx, builder, block);
let tag = ctx.get_tag(rhs); let tag = ctx.get_tag(rhs);
let fallback = ctx.context.append_basic_block(func, "fallback"); let fallback = ctx.context.append_basic_block(func, "fallback");
let ret = ctx.context.append_basic_block(func, "fallback"); let ret = ctx.context.append_basic_block(func, "fallback");
let res = ctx let res = ctx
.builder .func_builder
.build_alloca(ctx.helpers.value_type, "res_alloca") .build_alloca(ctx.helpers.value_type, "res_alloca")
.unwrap(); .unwrap();
ctx.builder.build_switch(tag, fallback, &[]).unwrap(); ctx.func_builder.build_switch(tag, fallback, &[]).unwrap();
ctx.builder.position_at_end(fallback); ctx.func_builder.position_at_end(fallback);
ctx.builder.position_at_end(ret); ctx.func_builder.position_at_end(ret);
ctx.builder ctx.func_builder
.build_load(ctx.helpers.value_type, res, "load_res") .build_load(ctx.helpers.value_type, res, "load_res")
.unwrap() .unwrap()
.try_into() .try_into()
@@ -223,34 +224,34 @@ impl JITCompile for UnOp {
} }
impl JITCompile for Select { impl JITCompile for Select {
fn compile<'gc>( fn compile(
&self, &self,
ctx: &JITContext<'gc>, ctx: &mut JITContext,
func: FunctionValue<'gc>, builder: &mut FunctionBuilder,
values: &mut Vec<Value>, block: Block,
) -> StructValue<'gc> { ) -> ir::Value {
todo!() todo!()
} }
} }
impl JITCompile for If { impl JITCompile for If {
fn compile<'gc>( fn compile(
&self, &self,
ctx: &JITContext<'gc>, ctx: &mut JITContext,
func: FunctionValue<'gc>, builder: &mut FunctionBuilder,
values: &mut Vec<Value>, block: Block,
) -> StructValue<'gc> { ) -> ir::Value {
todo!() todo!()
} }
} }
impl JITCompile for LoadFunc { impl JITCompile for LoadFunc {
fn compile<'gc>( fn compile(
&self, &self,
ctx: &JITContext<'gc>, ctx: &mut JITContext,
_: FunctionValue<'gc>, builder: &mut FunctionBuilder,
values: &mut Vec<Value>, block: Block,
) -> StructValue<'gc> { ) -> ir::Value {
ctx.helpers.new_value( ctx.helpers.new_value(
ValueTag::Function, ValueTag::Function,
ctx.helpers.const_int(self.idx as i64).into(), ctx.helpers.const_int(self.idx as i64).into(),
@@ -259,14 +260,18 @@ impl JITCompile for LoadFunc {
} }
impl JITCompile for Call { impl JITCompile for Call {
fn compile<'gc>( fn compile(
&self, &self,
ctx: &JITContext<'gc>, ctx: &mut JITContext,
func: FunctionValue<'gc>, builder: &mut FunctionBuilder,
values: &mut Vec<Value>, block: Block,
) -> StructValue<'gc> { ) -> ir::Value {
let ret = ctx
.func_builder
.build_alloca(ctx.helpers.value_type, "ret")
.unwrap();
let args = ctx let args = ctx
.builder .func_builder
.build_call( .build_call(
ctx.helpers.alloc_array, ctx.helpers.alloc_array,
&[ctx.helpers.const_ptr_int(self.args.len()).into()], &[ctx.helpers.const_ptr_int(self.args.len()).into()],
@@ -277,89 +282,93 @@ impl JITCompile for Call {
.unwrap_left() .unwrap_left()
.into_pointer_value(); .into_pointer_value();
for (i, arg) in self.args.iter().enumerate() { for (i, arg) in self.args.iter().enumerate() {
ctx.builder let arg_ptr = unsafe {
.build_store( ctx.func_builder
unsafe { .build_gep(
args.const_in_bounds_gep( ctx.helpers.value_type,
ctx.helpers.value_type, args,
&[ctx.helpers.const_ptr_int(i)], &[ctx.helpers.const_ptr_int(i)],
) "args_gep",
}, )
arg.compile(ctx, func, values), .unwrap()
) };
ctx.func_builder
.build_store(arg_ptr, arg.compile(ctx, builder, block))
.unwrap(); .unwrap();
} }
ctx.builder ctx.func_builder
.build_call( .build_call(
ctx.helpers.call, ctx.helpers.call,
&[ &[
self.func.compile(ctx, func, values).into(), self.func.compile(ctx, builder, block).into(),
args.into(), args.into(),
ctx.helpers.const_ptr_int(self.args.len()).into(), ctx.helpers.const_ptr_int(self.args.len()).into(),
func.get_first_param().unwrap().into(), func.get_nth_param(0).unwrap().into(),
func.get_last_param().unwrap().into(), func.get_nth_param(1).unwrap().into(),
ret.into(),
], ],
"call", "call",
) )
.unwrap();
ctx.func_builder
.build_load(ctx.helpers.value_type, ret, "load_ret")
.unwrap() .unwrap()
.try_as_basic_value() .into_struct_value()
.unwrap_left()
.try_into()
.unwrap()
} }
} }
impl JITCompile for Let { impl JITCompile for Let {
fn compile<'gc>( fn compile(
&self, &self,
ctx: &JITContext<'gc>, ctx: &mut JITContext,
func: FunctionValue<'gc>, builder: &mut FunctionBuilder,
values: &mut Vec<Value>, block: Block,
) -> StructValue<'gc> { ) -> ir::Value {
unreachable!() unreachable!()
} }
} }
impl JITCompile for With { impl JITCompile for With {
fn compile<'gc>( fn compile(
&self, &self,
ctx: &JITContext<'gc>, ctx: &mut JITContext,
func: FunctionValue<'gc>, builder: &mut FunctionBuilder,
values: &mut Vec<Value>, block: Block,
) -> StructValue<'gc> { ) -> ir::Value {
todo!()
todo!() todo!()
} }
} }
impl JITCompile for Assert { impl JITCompile for Assert {
fn compile<'gc>( fn compile(
&self, &self,
ctx: &JITContext<'gc>, ctx: &mut JITContext,
func: FunctionValue<'gc>, builder: &mut FunctionBuilder,
values: &mut Vec<Value>, block: Block,
) -> StructValue<'gc> { ) -> ir::Value {
todo!() todo!()
} }
} }
impl JITCompile for ConcatStrings { impl JITCompile for ConcatStrings {
fn compile<'gc>( fn compile(
&self, &self,
ctx: &JITContext<'gc>, ctx: &mut JITContext,
func: FunctionValue<'gc>, builder: &mut FunctionBuilder,
values: &mut Vec<Value>, block: Block,
) -> StructValue<'gc> { ) -> ir::Value {
todo!() todo!()
} }
} }
impl JITCompile for Const { impl JITCompile for Const {
fn compile<'gc>( fn compile(
&self, &self,
ctx: &JITContext<'gc>, ctx: &mut JITContext,
func: FunctionValue<'gc>, builder: &mut FunctionBuilder,
values: &mut Vec<Value>, block: Block,
) -> StructValue<'gc> { ) -> ir::Value {
use c::Const::*; use c::Const::*;
match self.val { match self.val {
Bool(x) => ctx.helpers.new_bool(x), Bool(x) => ctx.helpers.new_bool(x),
@@ -371,28 +380,27 @@ impl JITCompile for Const {
} }
impl JITCompile for String { impl JITCompile for String {
fn compile<'gc>( fn compile(
&self, &self,
ctx: &JITContext<'gc>, ctx: &mut JITContext,
func: FunctionValue<'gc>, builder: &mut FunctionBuilder,
values: &mut Vec<Value>, block: Block,
) -> StructValue<'gc> { ) -> ir::Value {
todo!() todo!()
} }
} }
impl JITCompile for Var { impl JITCompile for Var {
fn compile<'gc>( fn compile(
&self, &self,
ctx: &JITContext<'gc>, ctx: &mut JITContext,
func: FunctionValue<'gc>, builder: &mut FunctionBuilder,
values: &mut Vec<Value>, block: Block,
) -> StructValue<'gc> { ) -> ir::Value {
let env = func.get_nth_param(1).unwrap(); let env = func.get_nth_param(1).unwrap();
let ptr = self.sym.as_ptr(); let ptr = self.sym.as_ptr();
let len = self.sym.len(); let len = self.sym.len();
// values.push(Value::String(self.sym.clone())); ctx.func_builder
ctx.builder
.build_direct_call( .build_direct_call(
ctx.helpers.lookup, ctx.helpers.lookup,
&[ &[
@@ -411,43 +419,54 @@ impl JITCompile for Var {
} }
impl JITCompile for Arg { impl JITCompile for Arg {
fn compile<'gc>( fn compile(
&self, &self,
ctx: &JITContext<'gc>, ctx: &mut JITContext,
func: FunctionValue<'gc>, builder: &mut FunctionBuilder,
values: &mut Vec<Value>, block: Block,
) -> StructValue<'gc> { ) -> ir::Value {
let env = func.get_last_param().unwrap(); let env = builder.block_params(block)[];
let ret = ctx.builder.build_alloca(ctx.helpers.value_type, "alloca_ret").unwrap(); let env = func.get_nth_param(1).unwrap();
ctx.builder let arg = ctx
.func_builder
.build_alloca(ctx.helpers.value_type, "alloca_arg")
.unwrap();
ctx.func_builder
.build_direct_call( .build_direct_call(
ctx.helpers.lookup_arg, ctx.helpers.lookup_arg,
&[env.into(), ctx.helpers.const_ptr_int(self.level).into(), ret.into()], &[
env.into(),
ctx.helpers.const_ptr_int(self.level).into(),
arg.into(),
],
"lookup_arg", "lookup_arg",
) )
.unwrap(); .unwrap();
ctx.builder.build_load(ctx.helpers.value_type,ret, "load_ret").unwrap().into_struct_value() ctx.func_builder
.build_load(ctx.helpers.value_type, arg, "load_arg")
.unwrap()
.into_struct_value()
} }
} }
impl JITCompile for LetVar { impl JITCompile for LetVar {
fn compile<'gc>( fn compile(
&self, &self,
ctx: &JITContext<'gc>, ctx: &mut JITContext,
func: FunctionValue<'gc>, builder: &mut FunctionBuilder,
values: &mut Vec<Value>, block: Block,
) -> StructValue<'gc> { ) -> ir::Value {
unreachable!() unreachable!()
} }
} }
impl JITCompile for Thunk { impl JITCompile for Thunk {
fn compile<'gc>( fn compile(
&self, &self,
ctx: &JITContext<'gc>, ctx: &mut JITContext,
_: FunctionValue<'gc>, builder: &mut FunctionBuilder,
values: &mut Vec<Value>, block: Block,
) -> StructValue<'gc> { ) -> ir::Value {
ctx.helpers.new_value( ctx.helpers.new_value(
ValueTag::Thunk, ValueTag::Thunk,
ctx.helpers.const_int(self.idx as i64).into(), ctx.helpers.const_int(self.idx as i64).into(),
@@ -456,12 +475,12 @@ impl JITCompile for Thunk {
} }
impl JITCompile for Path { impl JITCompile for Path {
fn compile<'gc>( fn compile(
&self, &self,
ctx: &JITContext<'gc>, ctx: &mut JITContext,
func: FunctionValue<'gc>, builder: &mut FunctionBuilder,
values: &mut Vec<Value>, block: Block,
) -> StructValue<'gc> { ) -> ir::Value {
todo!() todo!()
} }
} }

View File

@@ -1,14 +1,14 @@
use std::alloc::Layout; use std::alloc::Layout;
use std::ffi::CStr; use std::alloc::alloc;
use std::ptr::NonNull; use core::ptr::NonNull;
use std::{slice, str}; use core::{slice, str};
use inkwell::AddressSpace; use cranelift::codegen::ir::ArgumentExtension;
use inkwell::context::Context; use cranelift::codegen::ir::ArgumentPurpose;
use inkwell::execution_engine::ExecutionEngine; use cranelift::prelude::*;
use inkwell::module::Module; use cranelift_module::FuncId;
use inkwell::types::{FloatType, FunctionType, IntType, PointerType, StructType}; use cranelift_module::Linkage;
use inkwell::values::{BasicValueEnum, FloatValue, FunctionValue, IntValue, StructValue}; use cranelift_module::Module;
use crate::env::Env; use crate::env::Env;
use crate::eval::Engine; use crate::eval::Engine;
@@ -16,153 +16,71 @@ use crate::ty::internal::Value;
use super::{JITContext, JITValue, JITValueData, ValueTag}; use super::{JITContext, JITValue, JITValueData, ValueTag};
pub struct Helpers<'ctx> { pub struct Helpers {
pub int_type: IntType<'ctx>, pub int_type: Type,
pub float_type: FloatType<'ctx>, pub float_type: Type,
pub bool_type: IntType<'ctx>, pub bool_type: Type,
pub ptr_int_type: IntType<'ctx>, pub ptr_int_type: Type,
pub ptr_type: PointerType<'ctx>, pub ptr_type: Type,
pub value_type: StructType<'ctx>, pub value_type: Type,
pub func_type: FunctionType<'ctx>, pub func_sig: Signature,
pub new_thunk: FunctionValue<'ctx>,
pub debug: FunctionValue<'ctx>, pub call: FuncId,
pub capture_env: FunctionValue<'ctx>, pub lookup_arg: FuncId,
pub neg: FunctionValue<'ctx>, pub lookup: FuncId,
pub not: FunctionValue<'ctx>, pub force: FuncId,
pub add: FunctionValue<'ctx>,
pub sub: FunctionValue<'ctx>,
pub eq: FunctionValue<'ctx>,
pub or: FunctionValue<'ctx>,
pub call: FunctionValue<'ctx>,
pub lookup_arg: FunctionValue<'ctx>,
pub lookup: FunctionValue<'ctx>,
pub force: FunctionValue<'ctx>,
pub alloc_array: FunctionValue<'ctx>, pub alloc_array: FuncId,
} }
impl<'ctx> Helpers<'ctx> { impl Helpers {
pub fn new( pub fn new(
ctx: &'ctx Context, ctx: &codegen::Context,
module: &Module<'ctx>, module: &mut dyn Module,
execution_engine: &ExecutionEngine<'ctx>,
) -> Self { ) -> Self {
let int_type = ctx.i64_type(); let int_type = types::I64;
let float_type = ctx.f64_type(); let float_type = types::F64;
let bool_type = ctx.bool_type(); let bool_type = types::I8;
let ptr_int_type = ctx.ptr_sized_int_type(execution_engine.get_target_data(), None); // let ptr_type = ctx.ptr_type(AddressSpace::default());
let ptr_type = ctx.ptr_type(AddressSpace::default()); let ptr_type = module.target_config().pointer_type();
let value_type = let ptr_int_type = ptr_type;
ctx.struct_type(&[int_type.into(), int_type.into(), int_type.into()], false); let value_type = types::I128;
let func_type = value_type.fn_type(&[ptr_type.into(), ptr_type.into()], false); // let func_sig = ctx.void_type().fn_type(&[ptr_type.into(), ptr_type.into(), ptr_type.into()], false);
let mut func_sig = Signature::new(isa::CallConv::SystemV);
func_sig.params.push(AbiParam { value_type: ptr_type, purpose: ArgumentPurpose::Normal, extension: ArgumentExtension::None });
func_sig.params.push(AbiParam { value_type: ptr_type, purpose: ArgumentPurpose::Normal, extension: ArgumentExtension::None });
func_sig.returns.push(AbiParam { value_type, purpose: ArgumentPurpose::StructReturn, extension: ArgumentExtension::None });
let new_thunk = module.add_function( let mut call_sig = Signature::new(isa::CallConv::SystemV);
"new_thunk", call_sig.params.push(AbiParam { value_type, purpose: ArgumentPurpose::StructArgument(24), extension: ArgumentExtension::None });
value_type.fn_type(&[ptr_type.into(), ptr_type.into()], false), call_sig.params.push(AbiParam { value_type: ptr_type, purpose: ArgumentPurpose::Normal, extension: ArgumentExtension::None });
None, call_sig.params.push(AbiParam { value_type: ptr_int_type, purpose: ArgumentPurpose::Normal, extension: ArgumentExtension::None });
); call_sig.params.push(AbiParam { value_type: ptr_type, purpose: ArgumentPurpose::Normal, extension: ArgumentExtension::None });
let capture_env = module.add_function( call_sig.params.push(AbiParam { value_type: ptr_type, purpose: ArgumentPurpose::Normal, extension: ArgumentExtension::None });
"capture_env", let call = module.declare_function("helper_call", Linkage::Import, &call_sig).unwrap();
ctx
.void_type()
.fn_type(&[value_type.into(), ptr_type.into()], false),
None,
);
let neg = module.add_function(
"neg",
value_type.fn_type(&[value_type.into(), ptr_type.into()], false),
None,
);
let not = module.add_function(
"not",
value_type.fn_type(&[value_type.into(), ptr_type.into()], false),
None,
);
let add = module.add_function(
"add",
value_type.fn_type(&[value_type.into(), value_type.into()], false),
None,
);
let sub = module.add_function(
"sub",
value_type.fn_type(&[value_type.into(), value_type.into()], false),
None,
);
let eq = module.add_function(
"eq",
value_type.fn_type(&[value_type.into(), value_type.into()], false),
None,
);
let or = module.add_function(
"or",
value_type.fn_type(&[value_type.into(), value_type.into()], false),
None,
);
let call = module.add_function(
"call",
value_type.fn_type(
&[
value_type.into(),
ptr_type.into(),
ptr_int_type.into(),
ptr_type.into(),
ptr_type.into(),
],
false,
),
None,
);
let debug = module.add_function(
"debug",
ctx
.void_type()
.fn_type(&[ptr_type.into(), int_type.into()], false),
None,
);
let lookup_arg = module.add_function(
"lookup_arg",
// value_type.fn_type(&[ptr_type.into(), int_type.into()], false),
ctx.void_type().fn_type(&[ptr_type.into(), int_type.into(), ptr_type.into()], false),
None,
);
let lookup = module.add_function(
"lookup",
value_type.fn_type(
&[ptr_int_type.into(), ptr_type.into(), ptr_int_type.into()],
false,
),
None,
);
let force = module.add_function(
"force",
value_type.fn_type(
&[value_type.into(), ptr_type.into(), ptr_type.into()],
false,
),
None,
);
let alloc_array = module.add_function(
"alloc_array",
value_type.fn_type(&[ptr_int_type.into()], false),
None,
);
execution_engine.add_global_mapping(&new_thunk, helper_new_thunk as _); let mut lookup_arg_sig = Signature::new(isa::CallConv::SystemV);
execution_engine.add_global_mapping(&debug, helper_debug as _); lookup_arg_sig.params.push(AbiParam { value_type: ptr_type, purpose: ArgumentPurpose::Normal, extension: ArgumentExtension::None });
execution_engine.add_global_mapping(&capture_env, helper_capture_env as _); lookup_arg_sig.params.push(AbiParam { value_type: ptr_type, purpose: ArgumentPurpose::Normal, extension: ArgumentExtension::None });
execution_engine.add_global_mapping(&neg, helper_neg as _); let lookup_arg = module.declare_function("helper_lookup_arg", Linkage::Import, &call_sig).unwrap();
execution_engine.add_global_mapping(&not, helper_not as _);
execution_engine.add_global_mapping(&add, helper_add as _); let mut lookup_sig = Signature::new(isa::CallConv::SystemV);
execution_engine.add_global_mapping(&sub, helper_sub as _); lookup_sig.params.push(AbiParam { value_type: ptr_type, purpose: ArgumentPurpose::Normal, extension: ArgumentExtension::None });
execution_engine.add_global_mapping(&eq, helper_eq as _); lookup_sig.params.push(AbiParam { value_type: ptr_type, purpose: ArgumentPurpose::Normal, extension: ArgumentExtension::None });
execution_engine.add_global_mapping(&or, helper_or as _); lookup_sig.params.push(AbiParam { value_type: ptr_type, purpose: ArgumentPurpose::Normal, extension: ArgumentExtension::None });
execution_engine.add_global_mapping(&call, helper_call as _); lookup_sig.params.push(AbiParam { value_type: ptr_int_type, purpose: ArgumentPurpose::Normal, extension: ArgumentExtension::None });
execution_engine.add_global_mapping(&lookup_arg, helper_lookup_arg as _); let lookup = module.declare_function("helper_lookup", Linkage::Import, &call_sig).unwrap();
execution_engine.add_global_mapping(&lookup, helper_lookup as _);
execution_engine.add_global_mapping(&force, helper_force as _); let mut force_sig = Signature::new(isa::CallConv::SystemV);
execution_engine.add_global_mapping(&alloc_array, helper_alloc_array as _); force_sig.params.push(AbiParam { value_type, purpose: ArgumentPurpose::StructArgument(24), extension: ArgumentExtension::None });
force_sig.params.push(AbiParam { value_type: ptr_type, purpose: ArgumentPurpose::Normal, extension: ArgumentExtension::None });
force_sig.params.push(AbiParam { value_type: ptr_type, purpose: ArgumentPurpose::Normal, extension: ArgumentExtension::None });
let force = module.declare_function("helper_force", Linkage::Import, &call_sig).unwrap();
let mut alloc_array_sig = Signature::new(isa::CallConv::SystemV);
alloc_array_sig.params.push(AbiParam { value_type: ptr_int_type, purpose: ArgumentPurpose::Normal, extension: ArgumentExtension::None });
let alloc_array = module.declare_function("helper_alloc_array", Linkage::Import, &call_sig).unwrap();
Helpers { Helpers {
int_type, int_type,
@@ -171,18 +89,8 @@ impl<'ctx> Helpers<'ctx> {
ptr_int_type, ptr_int_type,
ptr_type, ptr_type,
value_type, value_type,
func_type, func_sig,
new_thunk,
debug,
capture_env,
neg,
not,
add,
sub,
eq,
or,
call, call,
lookup_arg, lookup_arg,
lookup, lookup,
@@ -192,7 +100,7 @@ impl<'ctx> Helpers<'ctx> {
} }
} }
pub fn new_value(&self, tag: ValueTag, data: BasicValueEnum<'ctx>) -> StructValue<'ctx> { pub fn new_value(&self, tag: ValueTag, data: BasicValueEnum) -> StructValue {
self.value_type.const_named_struct(&[ self.value_type.const_named_struct(&[
self.const_int(tag as i64).into(), self.const_int(tag as i64).into(),
data, data,
@@ -200,143 +108,39 @@ impl<'ctx> Helpers<'ctx> {
]) ])
} }
pub fn const_ptr_int(&self, int: usize) -> IntValue<'ctx> { pub fn const_ptr_int(&self, int: usize) -> IntValue {
self.ptr_int_type.const_int(int as _, false) self.ptr_int_type.const_int(int as _, false)
} }
pub fn const_int(&self, int: i64) -> IntValue<'ctx> { pub fn const_int(&self, int: i64) -> IntValue {
self.int_type.const_int(int as _, false) self.int_type.const_int(int as _, false)
} }
pub fn new_int(&self, int: i64) -> StructValue<'ctx> { pub fn new_int(&self, int: i64) -> StructValue {
self.new_value(ValueTag::Int, self.const_int(int).into()) self.new_value(ValueTag::Int, self.const_int(int).into())
} }
pub fn const_float(&self, float: f64) -> FloatValue<'ctx> { pub fn const_float(&self, float: f64) -> FloatValue {
self.float_type.const_float(float) self.float_type.const_float(float)
} }
pub fn new_float(&self, float: f64) -> StructValue<'ctx> { pub fn new_float(&self, float: f64) -> StructValue {
self.new_value(ValueTag::Float, self.const_float(float).into()) self.new_value(ValueTag::Float, self.const_float(float).into())
} }
pub fn const_bool(&self, bool: bool) -> IntValue<'ctx> { pub fn const_bool(&self, bool: bool) -> IntValue {
self.bool_type.const_int(bool as _, false) self.bool_type.const_int(bool as _, false)
} }
pub fn new_bool(&self, bool: bool) -> StructValue<'ctx> { pub fn new_bool(&self, bool: bool) -> StructValue {
self.new_value(ValueTag::Bool, self.const_bool(bool).into()) self.new_value(ValueTag::Bool, self.const_bool(bool).into())
} }
pub fn new_null(&self) -> StructValue<'ctx> { pub fn new_null(&self) -> StructValue {
self.new_value(ValueTag::Null, self.int_type.const_zero().into()) self.new_value(ValueTag::Null, self.int_type.const_zero().into())
} }
} }
extern "C" fn helper_capture_env(thunk: JITValue, env: *const Env) {
todo!()
}
extern "C" fn helper_neg(rhs: JITValue, _env: *const Env) -> JITValue {
use ValueTag::*;
match rhs.tag {
Int => JITValue {
tag: Int,
data: JITValueData {
int: -unsafe { rhs.data.int },
},
},
Float => JITValue {
tag: Float,
data: JITValueData {
float: -unsafe { rhs.data.float },
},
},
_ => todo!(),
}
}
extern "C" fn helper_not(rhs: JITValue, _env: *const Env) -> JITValue {
use ValueTag::*;
match rhs.tag {
Bool => JITValue {
tag: Bool,
data: JITValueData {
bool: !unsafe { rhs.data.bool },
},
},
_ => todo!(),
}
}
extern "C" fn helper_add(lhs: JITValue, rhs: JITValue) -> JITValue {
use ValueTag::*;
match (lhs.tag, rhs.tag) {
(Int, Int) => JITValue {
tag: Int,
data: JITValueData {
int: unsafe { lhs.data.int + rhs.data.int },
},
},
_ => todo!(
"Addition not implemented for {:?} and {:?}",
lhs.tag,
rhs.tag
),
}
}
extern "C" fn helper_sub(lhs: JITValue, rhs: JITValue) -> JITValue {
use ValueTag::*;
match (lhs.tag, rhs.tag) {
(Int, Int) => JITValue {
tag: Int,
data: JITValueData {
int: unsafe { lhs.data.int - rhs.data.int },
},
},
_ => todo!(
"Substruction not implemented for {:?} and {:?}",
lhs.tag,
rhs.tag
),
}
}
extern "C" fn helper_eq(lhs: JITValue, rhs: JITValue) -> JITValue {
use ValueTag::*;
match (lhs.tag, rhs.tag) {
(Int, Int) => JITValue {
tag: Bool,
data: JITValueData {
bool: unsafe { lhs.data.int == rhs.data.int },
},
},
_ => todo!(
"Equation not implemented for {:?} and {:?}",
lhs.tag,
rhs.tag
),
}
}
extern "C" fn helper_or(lhs: JITValue, rhs: JITValue) -> JITValue {
use ValueTag::*;
match (lhs.tag, rhs.tag) {
(Bool, Bool) => JITValue {
tag: Bool,
data: JITValueData {
bool: unsafe { lhs.data.bool || rhs.data.bool },
},
},
_ => todo!(
"Substraction not implemented for {:?} and {:?}",
lhs.tag,
rhs.tag
),
}
}
extern "C" fn helper_call( extern "C" fn helper_call(
func: JITValue, func: JITValue,
args: *mut JITValue, args: *mut JITValue,
@@ -354,19 +158,12 @@ extern "C" fn helper_call(
unsafe { env.as_mut() }, unsafe { env.as_mut() },
) )
.unwrap(); .unwrap();
todo!() func.into()
} }
extern "C" fn helper_debug(env: NonNull<Env>, level: u64) { extern "C" fn helper_lookup_arg(env: NonNull<Env>, level: u64) -> JITValue {
dbg!(env, level); let env_ref = unsafe { env.as_ref() };
dbg!(unsafe { env.as_ref() }.lookup_arg(level as usize)); env_ref.lookup_arg(level as usize).into()
}
extern "C" fn helper_lookup_arg(env_ptr: NonNull<Env>, level: u64, ret: NonNull<JITValue>) {
dbg!(env_ptr, level);
let env_ref = unsafe { env_ptr.as_ref() };
let val: JITValue = env_ref.lookup_arg(level as usize).into();
unsafe { ret.write(val) }
} }
extern "C" fn helper_lookup(env: NonNull<Env>, ptr: *const u8, len: usize) -> JITValue { extern "C" fn helper_lookup(env: NonNull<Env>, ptr: *const u8, len: usize) -> JITValue {
@@ -391,10 +188,6 @@ extern "C" fn helper_force(
todo!() todo!()
} }
extern "C" fn helper_new_thunk(opcodes: *const ()) -> JITValue {
todo!()
}
unsafe extern "C" fn helper_alloc_array(len: usize) -> *mut u8 { unsafe extern "C" fn helper_alloc_array(len: usize) -> *mut u8 {
unsafe { std::alloc::alloc(Layout::array::<JITValue>(len).unwrap()) } unsafe { alloc(Layout::array::<JITValue>(len).unwrap()) }
} }

View File

@@ -2,14 +2,11 @@ use std::marker::PhantomData;
use std::ops::Deref; use std::ops::Deref;
use std::rc::Rc; use std::rc::Rc;
use inkwell::OptimizationLevel; use cranelift::codegen::ir::Function;
use inkwell::builder::Builder; use cranelift::prelude::*;
use inkwell::context::Context; use cranelift::codegen::ir;
use inkwell::execution_engine::ExecutionEngine; use cranelift_module::{DataDescription, Linkage, Module};
use inkwell::module::Module; use cranelift_jit::{JITModule, JITBuilder};
use inkwell::values::{
AnyValue, BasicMetadataValueEnum, FloatValue, IntValue, PointerValue, StructValue,
};
use crate::engine::Engine; use crate::engine::Engine;
use crate::env::Env; use crate::env::Env;
@@ -22,19 +19,30 @@ mod helpers;
pub use compile::JITCompile; pub use compile::JITCompile;
use helpers::Helpers; use helpers::Helpers;
#[repr(u64)] #[repr(transparent)]
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ValueTag { pub struct ValueTag(u64);
Null,
Int, #[allow(non_upper_case_globals)]
Float, #[allow(non_snake_case)]
String, impl ValueTag {
Bool, const Null: Self = Self(0);
AttrSet, const Int: Self = Self(1);
List, const Float: Self = Self(2);
Function, const Path: Self = Self(3);
Thunk, const Bool: Self = Self(4);
Path, const AttrSet: Self = Self(5);
const List: Self = Self(6);
const Function: Self = Self(7);
const Thunk: Self = Self(8);
pub fn String(len: usize) -> Self {
Self(len as u64 ^ (1 << 31))
}
pub fn is_str(&self) -> bool {
self.0 >> 31 != 0
}
} }
#[repr(C)] #[repr(C)]
@@ -51,24 +59,15 @@ pub union JITValueData {
float: f64, float: f64,
bool: bool, bool: bool,
ptr: *const (), ptr: *const (),
slice: Slice,
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct Slice {
ptr: *const (),
len: usize,
} }
impl From<JITValue> for Value { impl From<JITValue> for Value {
fn from(value: JITValue) -> Self { fn from(value: JITValue) -> Self {
use ValueTag::*;
match value.tag { match value.tag {
Int => Value::Int(unsafe { value.data.int }), ValueTag::Int => Value::Int(unsafe { value.data.int }),
Null => Value::Null, ValueTag::Null => Value::Null,
Function => Value::Func(unsafe { value.data.int as usize }), ValueTag::Function => Value::Func(unsafe { value.data.int as usize }),
Thunk => Value::Thunk(unsafe { value.data.int as usize }), ValueTag::Thunk => Value::Thunk(unsafe { value.data.int as usize }),
_ => todo!("not implemented for {:?}", value.tag), _ => todo!("not implemented for {:?}", value.tag),
} }
} }
@@ -84,10 +83,7 @@ impl From<Value> for JITValue {
Value::List(list) => JITValue { Value::List(list) => JITValue {
tag: ValueTag::List, tag: ValueTag::List,
data: JITValueData { data: JITValueData {
slice: Slice { ptr: list.as_ptr() as *const (),
ptr: list.as_ptr() as *const (),
len: list.len(),
},
}, },
}, },
Value::Func(idx) => JITValue { Value::Func(idx) => JITValue {
@@ -103,69 +99,82 @@ impl From<Value> for JITValue {
} }
} }
pub struct JITFunc<'ctx, 'exec>(F<'ctx, 'exec>, PhantomData<&'exec mut ()>); pub struct JITFunc<'exec>(F<'exec>, PhantomData<&'exec mut ()>);
type F<'ctx, 'exec> = unsafe extern "C" fn(*const Engine<'ctx, 'exec>, *const Env) -> JITValue; type F<'exec> = unsafe extern "C" fn(*const Engine<'exec>, *const Env, *mut JITValue);
impl<'ctx, 'exec> From<F<'ctx, 'exec>> for JITFunc<'ctx, 'exec> { impl<'exec> From<F<'exec>> for JITFunc<'exec> {
fn from(value: F<'ctx, 'exec>) -> Self { fn from(value: F<'exec>) -> Self {
Self(value, PhantomData) Self(value, PhantomData)
} }
} }
impl<'ctx: 'exec, 'exec> Deref for JITFunc<'ctx, 'exec> { impl<'exec> Deref for JITFunc<'exec> {
type Target = F<'ctx, 'exec>; type Target = F<'exec>;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&self.0 &self.0
} }
} }
pub struct JITContext<'ctx> { pub struct JITContext {
context: &'ctx Context, func_builder: FunctionBuilderContext,
module: Module<'ctx>,
builder: Builder<'ctx>,
execution_engine: ExecutionEngine<'ctx>,
helpers: Helpers<'ctx>, ctx: codegen::Context,
data_description: DataDescription,
module: JITModule,
func: Function,
helpers: Helpers,
} }
impl<'ctx> JITContext<'ctx> { impl JITContext {
pub fn new(context: &'ctx Context) -> Self { pub fn new() -> Self {
// force linker to link JIT engine let mut flag_builder = settings::builder();
unsafe { flag_builder.set("use_colocated_libcalls", "false").unwrap();
inkwell::llvm_sys::execution_engine::LLVMLinkInMCJIT(); flag_builder.set("is_pic", "false").unwrap();
} let isa_builder = cranelift_native::builder().unwrap_or_else(|msg| {
let module = context.create_module("nixjit"); panic!("host machine is not supported: {}", msg);
let execution_engine = module });
.create_jit_execution_engine(OptimizationLevel::Aggressive) let isa = isa_builder
.finish(settings::Flags::new(flag_builder))
.unwrap(); .unwrap();
let helpers = Helpers::new(context, &module, &execution_engine); let builder = JITBuilder::with_isa(isa, cranelift_module::default_libcall_names());
JITContext { let mut module = JITModule::new(builder);
execution_engine, let ctx = module.make_context();
builder: context.create_builder(),
context, Self {
func_builder: FunctionBuilderContext::new(),
helpers: Helpers::new(&ctx, &mut module),
data_description: DataDescription::new(),
func: Function::new(),
ctx,
module, module,
helpers,
} }
} }
pub fn compile<'exec>(&'exec self, ir: &Ir) -> JITFunc<'ctx, 'exec> { pub fn compile<'exec>(&'exec mut self, ir: &Ir, id: usize) -> JITFunc<'exec> {
let func = self let func_id = self.module.declare_function(format!("nixjit_thunk{id}").as_str(), Linkage::Local, &self.helpers.func_sig).unwrap();
.module let mut func = Function::new();
.add_function("nixjit_func", self.helpers.func_type, None); let builder = FunctionBuilder::new(&mut func, &mut self.func_builder);
let entry = self.context.append_basic_block(func, "entry"); let entry = builder.create_block();
self.builder.position_at_end(entry); builder.switch_to_block(entry);
// TODO: // TODO:
let ret = ir.compile(self, func, &mut Vec::new()); let ret = ir.compile(self, func_id, &mut Vec::new());
self.builder.build_return(Some(&ret)).unwrap(); self.func_builder
if func.verify(true) { .build_store(func_id.get_nth_param(2).unwrap().into_pointer_value(), ret)
.unwrap();
self.func_builder.build_return(None).unwrap();
self.module.print_to_stderr();
let _ = self.execution_engine.remove_module(&self.module);
let _ = self.execution_engine.add_module(&self.module);
if func_id.verify(true) {
unsafe { unsafe {
JITFunc( JITFunc(
self.execution_engine std::mem::transmute(
.get_function(func.get_name().to_str().unwrap()) self.execution_engine
.unwrap() .get_function_address(func_id.get_name().to_str().unwrap())
.into_raw(), .unwrap(),
),
PhantomData, PhantomData,
) )
} }
@@ -174,80 +183,18 @@ impl<'ctx> JITContext<'ctx> {
} }
} }
pub fn get_float(&self, val: StructValue<'ctx>) -> FloatValue<'ctx> { pub fn get_value(&self, builder: &mut FunctionBuilder, val: ir::Value) -> ir::Value {
let alloca = self let offset = builder.ins().iconst(types::I8, 64);
.builder builder.ins().rotl(val, offset)
.build_alloca(self.helpers.int_type, "get_value_alloca")
.unwrap();
self.builder.build_store(alloca, val).unwrap();
self.builder
.build_load(
self.helpers.float_type,
self.builder
.build_struct_gep(self.helpers.value_type, alloca, 1, "get_value_gep")
.unwrap(),
"get_value",
)
.unwrap()
.into_float_value()
} }
pub fn get_int(&self, val: StructValue<'ctx>) -> IntValue<'ctx> { pub fn get_tag(&self, builder: &mut FunctionBuilder, val: ir::Value) -> ir::Value {
let alloca = self let offset = builder.ins().iconst(types::I8, 64);
.builder builder.ins().rotl(val, offset)
.build_alloca(self.helpers.int_type, "get_value_alloca")
.unwrap();
self.builder.build_store(alloca, val).unwrap();
self.builder
.build_load(
self.helpers.int_type,
self.builder
.build_struct_gep(self.helpers.value_type, alloca, 1, "get_value_gep")
.unwrap(),
"get_value",
)
.unwrap()
.into_int_value()
} }
pub fn get_bool(&self, val: StructValue<'ctx>) -> IntValue<'ctx> { pub fn const_ptr(&self, ptr: *const ()) -> PointerValue {
let alloca = self self.func_builder
.builder
.build_alloca(self.helpers.bool_type, "get_value_alloca")
.unwrap();
self.builder.build_store(alloca, val).unwrap();
self.builder
.build_load(
self.helpers.bool_type,
self.builder
.build_struct_gep(self.helpers.value_type, alloca, 1, "get_value_gep")
.unwrap(),
"get_value",
)
.unwrap()
.into_int_value()
}
pub fn get_tag(&self, val: StructValue<'ctx>) -> IntValue<'ctx> {
let alloca = self
.builder
.build_alloca(self.helpers.value_type, "get_tag_alloca")
.unwrap();
self.builder.build_store(alloca, val).unwrap();
self.builder
.build_load(
self.helpers.int_type,
self.builder
.build_struct_gep(self.helpers.value_type, alloca, 0, "get_tag_gep")
.unwrap(),
"get_tag",
)
.unwrap()
.into_int_value()
}
pub fn const_ptr(&self, ptr: *const ()) -> PointerValue<'ctx> {
self.builder
.build_int_to_ptr( .build_int_to_ptr(
self.helpers.int_type.const_int(ptr as _, false), self.helpers.int_type.const_int(ptr as _, false),
self.helpers.ptr_type, self.helpers.ptr_type,

View File

@@ -195,11 +195,11 @@ impl DowngradeContext {
|| unreachable!(), || unreachable!(),
|func| { |func| {
unsafe { unsafe {
let old = std::ptr::read(func); let old = core::ptr::read(func);
match old.resolve(Index::Func(idx), self_ptr.as_mut().unwrap(), env) { match old.resolve(Index::Func(idx), self_ptr.as_mut().unwrap(), env) {
Ok(ok) => std::ptr::write(func, ok), Ok(ok) => core::ptr::write(func, ok),
Err(err) => { Err(err) => {
std::ptr::write( core::ptr::write(
func, func,
Func { Func {
param: crate::ir::Param::Ident(EcoString::new()), param: crate::ir::Param::Ident(EcoString::new()),
@@ -225,11 +225,11 @@ impl DowngradeContext {
|| unreachable!(), || unreachable!(),
|thunk| { |thunk| {
unsafe { unsafe {
let (old, _) = std::ptr::read(thunk); let (old, _) = core::ptr::read(thunk);
match old.resolve(Index::Thunk(idx), self_ptr.as_mut().unwrap(), env) { match old.resolve(Index::Thunk(idx), self_ptr.as_mut().unwrap(), env) {
Ok(ok) => std::ptr::write(&mut thunk.0, ok), Ok(ok) => core::ptr::write(&mut thunk.0, ok),
Err(err) => { Err(err) => {
std::ptr::write( core::ptr::write(
&mut thunk.0, &mut thunk.0,
Ir::Const(super::Const { val: Const::Null }), Ir::Const(super::Const { val: Const::Null }),
); );

View File

@@ -1,7 +1,7 @@
use derive_more::{IsVariant, TryUnwrap, Unwrap}; use derive_more::{IsVariant, TryUnwrap, Unwrap};
use ecow::EcoString; use ecow::EcoString;
use hashbrown::HashMap; use hashbrown::HashMap;
use inkwell::values::{FunctionValue, StructValue}; use cranelift::codegen;
use itertools::Itertools; use itertools::Itertools;
use rnix::ast::HasEntry; use rnix::ast::HasEntry;
use rnix::ast::{self, Expr}; use rnix::ast::{self, Expr};
@@ -90,9 +90,9 @@ macro_rules! ir {
} }
impl JITCompile for Ir { impl JITCompile for Ir {
fn compile<'ctx>(&self, ctx: &JITContext<'ctx>, func: FunctionValue<'ctx>, values: &mut Vec<Value>) -> StructValue<'ctx>{ fn compile(&self, ctx: &mut JITContext, builder: &mut FunctionBuilder) -> StructValue{
match self { match self {
$(Ir::$ty(ir) => ir.compile(ctx, func, values),)* $(Ir::$ty(ir) => ir.compile(ctx, builder),)*
} }
} }
} }

View File

@@ -1,5 +1,5 @@
use std::mem::{MaybeUninit, replace, transmute}; use core::mem::{MaybeUninit, replace, transmute};
use std::ops::{Deref, DerefMut}; use core::ops::{Deref, DerefMut};
use crate::error::*; use crate::error::*;

View File

@@ -1,5 +1,5 @@
use std::fmt::{Display, Formatter, Result as FmtResult}; use core::fmt::{Display, Formatter, Result as FmtResult};
use std::hash::Hash; use core::hash::Hash;
use derive_more::{Constructor, IsVariant, Unwrap}; use derive_more::{Constructor, IsVariant, Unwrap};
use ecow::EcoString; use ecow::EcoString;
@@ -30,9 +30,9 @@ pub enum Const {
} }
impl Hash for Const { impl Hash for Const {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) { fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
use Const::*; use Const::*;
std::mem::discriminant(self).hash(state); core::mem::discriminant(self).hash(state);
match self { match self {
Int(x) => x.hash(state), Int(x) => x.hash(state),
Float(x) => x.to_bits().hash(state), Float(x) => x.to_bits().hash(state),

View File

@@ -1,4 +1,4 @@
use std::ops::Deref; use core::ops::Deref;
use std::rc::Rc; use std::rc::Rc;
use derive_more::Constructor; use derive_more::Constructor;
@@ -99,7 +99,7 @@ impl AttrSet {
} }
pub fn into_inner(self: Rc<Self>) -> Rc<HashMap<EcoString, Value>> { pub fn into_inner(self: Rc<Self>) -> Rc<HashMap<EcoString, Value>> {
unsafe { std::mem::transmute(self) } unsafe { core::mem::transmute(self) }
} }
pub fn from_inner(data: HashMap<EcoString, Value>) -> Self { pub fn from_inner(data: HashMap<EcoString, Value>) -> Self {