Compare commits
10 Commits
6a2da69317
...
899c0d8cd3
Author | SHA1 | Date |
---|---|---|
David Mak | 899c0d8cd3 | |
David Mak | 49743995b3 | |
David Mak | 8bef0ab8f2 | |
David Mak | 806f65815f | |
David Mak | 2e6a64a1de | |
David Mak | 20aa094b1f | |
David Mak | 5ab8d751ed | |
David Mak | c7d5d75014 | |
David Mak | 72570fbb16 | |
David Mak | 9e57498958 |
|
@ -27,9 +27,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.0.2"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41"
|
||||
checksum = "0f2135563fb5c609d2b2b87c1e8ce7bc41b0b45430fa9661f457981503dd5bf0"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
@ -120,9 +120,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.3.3"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42"
|
||||
checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
|
@ -132,9 +132,12 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
|||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.79"
|
||||
version = "1.0.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
|
||||
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
|
@ -144,9 +147,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.4.2"
|
||||
version = "4.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a13b88d2c62ff462f88e4a121f17a82c1af05693a2f192b5c38d14de73c19f6"
|
||||
checksum = "b1d7b8d5ec32af0fadc644bf1fd509a688c2103b185644bb1e29d164e0703136"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
|
@ -154,9 +157,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.4.2"
|
||||
version = "4.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bb9faaa7c2ef94b2743a21f5a29e6f0010dff4caa69ac8e9d6cf8b6fa74da08"
|
||||
checksum = "5179bb514e4d7c2051749d8fcefa2ed6d06a9f4e6d69faf3805f5d80b8cf8d56"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
|
@ -173,7 +176,7 @@ dependencies = [
|
|||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.29",
|
||||
"syn 2.0.37",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -308,9 +311,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.8.1"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
|
||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
|
||||
[[package]]
|
||||
name = "ena"
|
||||
|
@ -328,10 +331,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.1"
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd"
|
||||
dependencies = [
|
||||
"errno-dragonfly",
|
||||
"libc",
|
||||
|
@ -350,12 +359,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "1.9.0"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
|
||||
dependencies = [
|
||||
"instant",
|
||||
]
|
||||
checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764"
|
||||
|
||||
[[package]]
|
||||
name = "fixedbitset"
|
||||
|
@ -407,6 +413,12 @@ version = "0.12.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.1"
|
||||
|
@ -429,6 +441,16 @@ dependencies = [
|
|||
"hashbrown 0.12.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.14.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indoc"
|
||||
version = "1.0.9"
|
||||
|
@ -437,9 +459,9 @@ checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306"
|
|||
|
||||
[[package]]
|
||||
name = "indoc"
|
||||
version = "2.0.3"
|
||||
version = "2.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c785eefb63ebd0e33416dfcb8d6da0bf27ce752843a45632a67bf10d4d4b5c4"
|
||||
checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8"
|
||||
|
||||
[[package]]
|
||||
name = "inkwell"
|
||||
|
@ -463,7 +485,7 @@ checksum = "b185e7d068d6820411502efa14d8fbf010750485399402156b72dd2a548ef8e9"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.29",
|
||||
"syn 2.0.37",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -480,26 +502,6 @@ dependencies = [
|
|||
"similar",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "io-lifetimes"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.9"
|
||||
|
@ -507,7 +509,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"rustix 0.38.4",
|
||||
"rustix",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
|
@ -575,9 +577,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.147"
|
||||
version = "0.2.148"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
|
||||
checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
|
@ -597,21 +599,15 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
|
|||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.3.8"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0"
|
||||
checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128"
|
||||
|
||||
[[package]]
|
||||
name = "llvm-sys"
|
||||
version = "140.1.1"
|
||||
version = "140.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe48b87b95ad1b3eeca563010aadbb427b3d3e89c1f78fe21acd39846be5c7d4"
|
||||
checksum = "69b285f8682531b9b394dd9891977a2a28c47006e491bda944e1ca62ebab2664"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"lazy_static",
|
||||
|
@ -632,15 +628,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.19"
|
||||
version = "0.4.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
|
||||
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.5.0"
|
||||
version = "2.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
|
@ -679,7 +675,7 @@ name = "nac3core"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"crossbeam",
|
||||
"indoc 2.0.3",
|
||||
"indoc 2.0.4",
|
||||
"inkwell",
|
||||
"insta",
|
||||
"itertools 0.11.0",
|
||||
|
@ -767,17 +763,17 @@ dependencies = [
|
|||
"libc",
|
||||
"redox_syscall 0.3.5",
|
||||
"smallvec",
|
||||
"windows-targets 0.48.1",
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "petgraph"
|
||||
version = "0.6.3"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4"
|
||||
checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9"
|
||||
dependencies = [
|
||||
"fixedbitset",
|
||||
"indexmap",
|
||||
"indexmap 2.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -810,7 +806,7 @@ dependencies = [
|
|||
"phf_shared 0.11.2",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.29",
|
||||
"syn 2.0.37",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -851,9 +847,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.64"
|
||||
version = "1.0.67"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78803b62cbf1f46fde80d7c0e803111524b9877184cfe7c3033659490ac7a7da"
|
||||
checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
@ -920,9 +916,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.29"
|
||||
version = "1.0.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105"
|
||||
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
@ -1010,9 +1006,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.9.1"
|
||||
version = "1.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575"
|
||||
checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
|
@ -1022,9 +1018,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.3.3"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310"
|
||||
checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
|
@ -1033,9 +1029,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.7.4"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2"
|
||||
checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
|
||||
|
||||
[[package]]
|
||||
name = "runkernel"
|
||||
|
@ -1046,36 +1042,22 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.37.23"
|
||||
version = "0.38.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06"
|
||||
checksum = "d7db8590df6dfcd144d22afd1b83b36c21a18d7cbc1dc4bb5295a8712e9eb662"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"errno",
|
||||
"io-lifetimes",
|
||||
"libc",
|
||||
"linux-raw-sys 0.3.8",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5"
|
||||
dependencies = [
|
||||
"bitflags 2.3.3",
|
||||
"bitflags 2.4.0",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.4.3",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.13"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc31bd9b61a32c31f9650d18add92aa83a49ba979c143eefd27fe7177b05bd5f"
|
||||
checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
|
@ -1085,15 +1067,15 @@ checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
|
|||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.17"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
|
||||
checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
|
@ -1112,14 +1094,14 @@ checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.29",
|
||||
"syn 2.0.37",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.105"
|
||||
version = "1.0.107"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360"
|
||||
checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
|
@ -1132,7 +1114,7 @@ version = "0.8.26"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"indexmap 1.9.3",
|
||||
"ryu",
|
||||
"serde",
|
||||
"yaml-rust",
|
||||
|
@ -1146,9 +1128,9 @@ checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf"
|
|||
|
||||
[[package]]
|
||||
name = "siphasher"
|
||||
version = "0.3.10"
|
||||
version = "0.3.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
|
||||
checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
|
@ -1199,9 +1181,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.29"
|
||||
version = "2.0.37"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a"
|
||||
checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1210,21 +1192,20 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "target-lexicon"
|
||||
version = "0.12.9"
|
||||
version = "0.12.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df8e77cb757a61f51b947ec4a7e3646efd825b73561db1c232a8ccb639e611a0"
|
||||
checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a"
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.6.0"
|
||||
version = "3.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6"
|
||||
checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
"fastrand",
|
||||
"redox_syscall 0.3.5",
|
||||
"rustix 0.37.23",
|
||||
"rustix",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
|
@ -1254,22 +1235,22 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.43"
|
||||
version = "1.0.48"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a35fc5b8971143ca348fa6df4f024d4d55264f3468c71ad1c2f365b0a4d58c42"
|
||||
checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.43"
|
||||
version = "1.0.48"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "463fe12d7993d3b327787537ce8dd4dfa058de32fc2b195ef3cde03dc4771e8f"
|
||||
checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.29",
|
||||
"syn 2.0.37",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1352,9 +1333,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.10"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
|
@ -1450,7 +1431,7 @@ version = "0.48.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets 0.48.1",
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1470,17 +1451,17 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.1"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.48.0",
|
||||
"windows_aarch64_msvc 0.48.0",
|
||||
"windows_i686_gnu 0.48.0",
|
||||
"windows_i686_msvc 0.48.0",
|
||||
"windows_x86_64_gnu 0.48.0",
|
||||
"windows_x86_64_gnullvm 0.48.0",
|
||||
"windows_x86_64_msvc 0.48.0",
|
||||
"windows_aarch64_gnullvm 0.48.5",
|
||||
"windows_aarch64_msvc 0.48.5",
|
||||
"windows_i686_gnu 0.48.5",
|
||||
"windows_i686_msvc 0.48.5",
|
||||
"windows_x86_64_gnu 0.48.5",
|
||||
"windows_x86_64_gnullvm 0.48.5",
|
||||
"windows_x86_64_msvc 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1491,9 +1472,9 @@ checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
|
|||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.0"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
|
@ -1503,9 +1484,9 @@ checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
|
|||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.0"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
|
@ -1515,9 +1496,9 @@ checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
|
|||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.0"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
|
@ -1527,9 +1508,9 @@ checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
|
|||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.0"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
|
@ -1539,9 +1520,9 @@ checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
|
|||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.0"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
|
@ -1551,9 +1532,9 @@ checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
|
|||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.0"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
|
@ -1563,9 +1544,9 @@ checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
|
|||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.0"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
||||
[[package]]
|
||||
name = "yaml-rust"
|
||||
|
|
|
@ -450,7 +450,7 @@ fn rpc_codegen_callback_fn<'ctx, 'a>(
|
|||
let alloc_bb = ctx.ctx.append_basic_block(current_function, "rpc.continue");
|
||||
let tail_bb = ctx.ctx.append_basic_block(current_function, "rpc.tail");
|
||||
|
||||
let ret_ty = ctx.get_llvm_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 slot = ctx.builder.build_alloca(ret_ty, "rpc.ret.slot");
|
||||
let slotgen = ctx.builder.build_bitcast(slot, ptr_type, "rpc.ret.ptr");
|
||||
|
@ -529,7 +529,7 @@ pub fn attributes_writeback<'ctx, 'a>(
|
|||
let index = ctx.get_attr_index(ty, *name);
|
||||
values.push((*field_ty, ctx.build_gep_and_load(
|
||||
obj.into_pointer_value(),
|
||||
&[zero, int32.const_int(index as u64, false)])));
|
||||
&[zero, int32.const_int(index as u64, false)], None)));
|
||||
}
|
||||
}
|
||||
if !attributes.is_empty() {
|
||||
|
|
|
@ -916,7 +916,6 @@ impl Nac3 {
|
|||
llvm_options: CodeGenLLVMOptions {
|
||||
opt_level: OptimizationLevel::Default,
|
||||
target: Nac3::get_llvm_target_options(isa),
|
||||
emit_llvm: false,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -134,9 +134,7 @@ impl StaticValue for PythonValue {
|
|||
PrimitiveValue::U32(val) => ctx.ctx.i32_type().const_int(*val as u64, false).into(),
|
||||
PrimitiveValue::U64(val) => ctx.ctx.i64_type().const_int(*val as u64, false).into(),
|
||||
PrimitiveValue::F64(val) => ctx.ctx.f64_type().const_float(*val).into(),
|
||||
PrimitiveValue::Bool(val) => {
|
||||
ctx.ctx.bool_type().const_int(*val as u64, false).into()
|
||||
}
|
||||
PrimitiveValue::Bool(val) => ctx.ctx.i8_type().const_int(*val as u64, false).into(),
|
||||
});
|
||||
}
|
||||
if let Some(global) = ctx.module.get_global(&self.id.to_string()) {
|
||||
|
@ -808,7 +806,7 @@ impl InnerResolver {
|
|||
} else if ty_id == self.primitive_ids.bool {
|
||||
let val: bool = obj.extract().unwrap();
|
||||
self.id_to_primitive.write().insert(id, PrimitiveValue::Bool(val));
|
||||
Ok(Some(ctx.ctx.bool_type().const_int(val as u64, false).into()))
|
||||
Ok(Some(ctx.ctx.i8_type().const_int(val as u64, false).into()))
|
||||
} else if ty_id == self.primitive_ids.float || ty_id == self.primitive_ids.float64 {
|
||||
let val: f64 = obj.extract().unwrap();
|
||||
self.id_to_primitive.write().insert(id, PrimitiveValue::F64(val));
|
||||
|
|
|
@ -4,6 +4,7 @@ use crate::{
|
|||
codegen::{
|
||||
concrete_type::{ConcreteFuncArg, ConcreteTypeEnum, ConcreteTypeStore},
|
||||
get_llvm_type,
|
||||
get_llvm_abi_type,
|
||||
irrt::*,
|
||||
stmt::gen_raise,
|
||||
CodeGenContext, CodeGenTask,
|
||||
|
@ -58,12 +59,15 @@ pub fn get_subst_key(
|
|||
}
|
||||
|
||||
impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
||||
/// Builds a sequence of `getelementptr` and `load` instructions which stores the value of a
|
||||
/// struct field into an LLVM value.
|
||||
pub fn build_gep_and_load(
|
||||
&mut self,
|
||||
ptr: PointerValue<'ctx>,
|
||||
index: &[IntValue<'ctx>],
|
||||
name: Option<&str>,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
unsafe { self.builder.build_load(self.builder.build_gep(ptr, index, "gep"), "load") }
|
||||
unsafe { self.builder.build_load(self.builder.build_gep(ptr, index, ""), name.unwrap_or_default()) }
|
||||
}
|
||||
|
||||
fn get_subst_key(
|
||||
|
@ -101,7 +105,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
|||
SymbolValue::I64(v) => self.ctx.i64_type().const_int(*v as u64, true).into(),
|
||||
SymbolValue::U32(v) => self.ctx.i32_type().const_int(*v as u64, false).into(),
|
||||
SymbolValue::U64(v) => self.ctx.i64_type().const_int(*v as u64, false).into(),
|
||||
SymbolValue::Bool(v) => self.ctx.bool_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::Str(v) => {
|
||||
let str_ptr =
|
||||
|
@ -158,6 +162,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// See [get_llvm_type].
|
||||
pub fn get_llvm_type(
|
||||
&mut self,
|
||||
generator: &mut dyn CodeGenerator,
|
||||
|
@ -175,6 +180,25 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
|||
)
|
||||
}
|
||||
|
||||
/// See [get_llvm_abi_type].
|
||||
pub fn get_llvm_abi_type(
|
||||
&mut self,
|
||||
generator: &mut dyn CodeGenerator,
|
||||
ty: Type,
|
||||
) -> BasicTypeEnum<'ctx> {
|
||||
get_llvm_abi_type(
|
||||
self.ctx,
|
||||
&self.module,
|
||||
generator,
|
||||
&mut self.unifier,
|
||||
self.top_level,
|
||||
&mut self.type_cache,
|
||||
&self.primitives,
|
||||
ty,
|
||||
)
|
||||
}
|
||||
|
||||
/// Generates an LLVM variable for a [constant value][value] with a given [type][ty].
|
||||
pub fn gen_const(
|
||||
&mut self,
|
||||
generator: &mut dyn CodeGenerator,
|
||||
|
@ -184,7 +208,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
|||
match value {
|
||||
Constant::Bool(v) => {
|
||||
assert!(self.unifier.unioned(ty, self.primitives.bool));
|
||||
let ty = self.ctx.bool_type();
|
||||
let ty = self.ctx.i8_type();
|
||||
ty.const_int(if *v { 1 } else { 0 }, false).into()
|
||||
}
|
||||
Constant::Int(val) => {
|
||||
|
@ -236,6 +260,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Generates a binary operation `op` between two integral operands `lhs` and `rhs`.
|
||||
pub fn gen_int_ops(
|
||||
&mut self,
|
||||
generator: &mut dyn CodeGenerator,
|
||||
|
@ -280,6 +305,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Generates a binary operation `op` between two floating-point operands `lhs` and `rhs`.
|
||||
pub fn gen_float_ops(
|
||||
&mut self,
|
||||
op: &Operator,
|
||||
|
@ -402,6 +428,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Helper function for generating a LLVM variable storing a [String].
|
||||
pub fn gen_string<S: Into<String>>(
|
||||
&mut self,
|
||||
generator: &mut dyn CodeGenerator,
|
||||
|
@ -501,6 +528,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// See [CodeGenerator::gen_constructor].
|
||||
pub fn gen_constructor<'ctx, 'a, G: CodeGenerator>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -532,6 +560,7 @@ pub fn gen_constructor<'ctx, 'a, G: CodeGenerator>(
|
|||
}
|
||||
}
|
||||
|
||||
/// See [CodeGenerator::gen_func_instance].
|
||||
pub fn gen_func_instance<'ctx, 'a>(
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
obj: Option<(Type, ValueEnum<'ctx>)>,
|
||||
|
@ -608,6 +637,7 @@ pub fn gen_func_instance<'ctx, 'a>(
|
|||
}
|
||||
}
|
||||
|
||||
/// See [CodeGenerator::gen_call].
|
||||
pub fn gen_call<'ctx, 'a, G: CodeGenerator>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -711,18 +741,19 @@ pub fn gen_call<'ctx, 'a, G: CodeGenerator>(
|
|||
let ret_type = if ctx.unifier.unioned(fun.0.ret, ctx.primitives.none) {
|
||||
None
|
||||
} else {
|
||||
Some(ctx.get_llvm_type(generator, fun.0.ret))
|
||||
Some(ctx.get_llvm_abi_type(generator, fun.0.ret))
|
||||
};
|
||||
let has_sret = ret_type.map_or(false, |ret_type| need_sret(ctx.ctx, ret_type));
|
||||
let mut byvals = Vec::new();
|
||||
let mut params =
|
||||
args.iter().enumerate().map(|(i, arg)| match ctx.get_llvm_type(generator, arg.ty) {
|
||||
let mut params = args.iter().enumerate()
|
||||
.map(|(i, arg)| match ctx.get_llvm_abi_type(generator, arg.ty) {
|
||||
BasicTypeEnum::StructType(ty) if is_extern => {
|
||||
byvals.push((i, ty));
|
||||
ty.ptr_type(AddressSpace::default()).into()
|
||||
},
|
||||
x => x
|
||||
}.into()).collect_vec();
|
||||
}.into())
|
||||
.collect_vec();
|
||||
if has_sret {
|
||||
params.insert(0, ret_type.unwrap().ptr_type(AddressSpace::default()).into());
|
||||
}
|
||||
|
@ -744,54 +775,99 @@ pub fn gen_call<'ctx, 'a, G: CodeGenerator>(
|
|||
}
|
||||
fun_val
|
||||
});
|
||||
|
||||
// Convert boolean parameter values into i1
|
||||
let param_vals = (&fun_val.get_params()).iter().zip(param_vals)
|
||||
.map(|(p, v)| {
|
||||
if p.is_int_value() && v.is_int_value() {
|
||||
let expected_ty = p.into_int_value().get_type();
|
||||
let param_val = v.into_int_value();
|
||||
|
||||
if expected_ty.get_bit_width() == 1 && param_val.get_type().get_bit_width() != 1 {
|
||||
generator.bool_to_i1(ctx, param_val)
|
||||
} else {
|
||||
param_val
|
||||
}.into()
|
||||
} else {
|
||||
v
|
||||
}
|
||||
})
|
||||
.collect_vec();
|
||||
|
||||
Ok(ctx.build_call_or_invoke(fun_val, ¶m_vals, "call"))
|
||||
}
|
||||
|
||||
/// Generates three LLVM variables representing the start, stop, and step values of a [range] class
|
||||
/// respectively.
|
||||
pub fn destructure_range<'ctx, 'a>(
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
range: PointerValue<'ctx>,
|
||||
) -> (IntValue<'ctx>, IntValue<'ctx>, IntValue<'ctx>) {
|
||||
let int32 = ctx.ctx.i32_type();
|
||||
let start = ctx
|
||||
.build_gep_and_load(range, &[int32.const_zero(), int32.const_int(0, false)])
|
||||
.build_gep_and_load(range, &[int32.const_zero(), int32.const_int(0, false)], Some("range.start"))
|
||||
.into_int_value();
|
||||
let end = ctx
|
||||
.build_gep_and_load(range, &[int32.const_zero(), int32.const_int(1, false)])
|
||||
.build_gep_and_load(range, &[int32.const_zero(), int32.const_int(1, false)], Some("range.stop"))
|
||||
.into_int_value();
|
||||
let step = ctx
|
||||
.build_gep_and_load(range, &[int32.const_zero(), int32.const_int(2, false)])
|
||||
.build_gep_and_load(range, &[int32.const_zero(), int32.const_int(2, false)], Some("range.step"))
|
||||
.into_int_value();
|
||||
(start, end, step)
|
||||
}
|
||||
|
||||
/// Allocates a List structure with the given [type][ty] and [length]. The name of the resulting
|
||||
/// LLVM value is `{name}.addr`, or `list.addr` if [name] is not specified.
|
||||
///
|
||||
/// Returns an instance of [PointerValue] pointing to the List structure. The List structure is
|
||||
/// defined as `type { ty*, size_t }` in LLVM, where the first element stores the pointer to the
|
||||
/// data, and the second element stores the size of the List.
|
||||
pub fn allocate_list<'ctx, 'a, G: CodeGenerator>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
ty: BasicTypeEnum<'ctx>,
|
||||
length: IntValue<'ctx>,
|
||||
name: Option<&str>,
|
||||
) -> PointerValue<'ctx> {
|
||||
let arr_ptr = ctx.builder.build_array_alloca(ty, length, "tmparr");
|
||||
let size_t = generator.get_size_type(ctx.ctx);
|
||||
let i32_t = ctx.ctx.i32_type();
|
||||
let arr_ty =
|
||||
ctx.ctx.struct_type(&[ty.ptr_type(AddressSpace::default()).into(), size_t.into()], false);
|
||||
// List structure; type { ty*, size_t }
|
||||
let arr_ty = ctx.ctx
|
||||
.struct_type(&[ty.ptr_type(AddressSpace::default()).into(), size_t.into()], false);
|
||||
let zero = ctx.ctx.i32_type().const_zero();
|
||||
let arr_str_ptr = ctx.builder.build_alloca(arr_ty, "tmparrstr");
|
||||
|
||||
let arr_str_ptr = ctx.builder.build_alloca(
|
||||
arr_ty, format!("{}.addr", name.unwrap_or("list")).as_str()
|
||||
);
|
||||
|
||||
unsafe {
|
||||
// Pointer to the `length` element of the list structure
|
||||
let len_ptr = ctx.builder.build_in_bounds_gep(
|
||||
arr_str_ptr,
|
||||
&[zero, i32_t.const_int(1, false)],
|
||||
"len_ptr",
|
||||
""
|
||||
);
|
||||
let length = ctx.builder.build_int_z_extend(
|
||||
length,
|
||||
size_t,
|
||||
""
|
||||
);
|
||||
let length = ctx.builder.build_int_z_extend(length, size_t, "zext");
|
||||
ctx.builder.build_store(len_ptr, length);
|
||||
let ptr_to_arr =
|
||||
ctx.builder.build_in_bounds_gep(arr_str_ptr, &[zero, i32_t.const_zero()], "ptr_to_arr");
|
||||
|
||||
// Pointer to the `data` element of the list structure
|
||||
let arr_ptr = ctx.builder.build_array_alloca(ty, length, "");
|
||||
let ptr_to_arr = ctx.builder.build_in_bounds_gep(
|
||||
arr_str_ptr,
|
||||
&[zero, i32_t.const_zero()],
|
||||
""
|
||||
);
|
||||
ctx.builder.build_store(ptr_to_arr, arr_ptr);
|
||||
arr_str_ptr
|
||||
}
|
||||
|
||||
arr_str_ptr
|
||||
}
|
||||
|
||||
/// Generates LLVM IR for a [list comprehension expression][expr].
|
||||
pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -799,9 +875,15 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>(
|
|||
) -> Result<BasicValueEnum<'ctx>, String> {
|
||||
if let ExprKind::ListComp { elt, generators } = &expr.node {
|
||||
let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap();
|
||||
let test_bb = ctx.ctx.append_basic_block(current, "test");
|
||||
let body_bb = ctx.ctx.append_basic_block(current, "body");
|
||||
let cont_bb = ctx.ctx.append_basic_block(current, "cont");
|
||||
|
||||
let init_bb = ctx.ctx.append_basic_block(current, "listcomp.init");
|
||||
let test_bb = ctx.ctx.append_basic_block(current, "listcomp.test");
|
||||
let body_bb = ctx.ctx.append_basic_block(current, "listcomp.body");
|
||||
let cont_bb = ctx.ctx.append_basic_block(current, "listcomp.cont");
|
||||
|
||||
ctx.builder.build_unconditional_branch(init_bb);
|
||||
|
||||
ctx.builder.position_at_end(init_bb);
|
||||
|
||||
let Comprehension { target, iter, ifs, .. } = &generators[0];
|
||||
let iter_val = generator.gen_expr(ctx, iter)?.unwrap().to_basic_value_enum(ctx, generator, iter.custom.unwrap())?;
|
||||
|
@ -830,10 +912,11 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>(
|
|||
// in case length is non-positive
|
||||
let is_valid =
|
||||
ctx.builder.build_int_compare(inkwell::IntPredicate::SGT, length, zero_32, "check");
|
||||
let normal = ctx.ctx.append_basic_block(current, "normal_list");
|
||||
let empty = ctx.ctx.append_basic_block(current, "empty_list");
|
||||
let list_init = ctx.ctx.append_basic_block(current, "list_init");
|
||||
let normal = ctx.ctx.append_basic_block(current, "listcomp.normal_list");
|
||||
let empty = ctx.ctx.append_basic_block(current, "listcomp.empty_list");
|
||||
let list_init = ctx.ctx.append_basic_block(current, "listcomp.list_init");
|
||||
ctx.builder.build_conditional_branch(is_valid, normal, empty);
|
||||
|
||||
// normal: allocate a list
|
||||
ctx.builder.position_at_end(normal);
|
||||
let list_a = allocate_list(
|
||||
|
@ -841,21 +924,31 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>(
|
|||
ctx,
|
||||
elem_ty,
|
||||
ctx.builder.build_int_z_extend_or_bit_cast(length, size_t, "z_ext_len"),
|
||||
Some("listcomp"),
|
||||
);
|
||||
ctx.builder.build_unconditional_branch(list_init);
|
||||
|
||||
ctx.builder.position_at_end(empty);
|
||||
let list_b = allocate_list(generator, ctx, elem_ty, zero_size_t);
|
||||
let list_b = allocate_list(
|
||||
generator,
|
||||
ctx,
|
||||
elem_ty,
|
||||
zero_size_t,
|
||||
Some("list_b")
|
||||
);
|
||||
ctx.builder.build_unconditional_branch(list_init);
|
||||
|
||||
ctx.builder.position_at_end(list_init);
|
||||
let phi = ctx.builder.build_phi(list_a.get_type(), "phi");
|
||||
phi.add_incoming(&[(&list_a, normal), (&list_b, empty)]);
|
||||
list = phi.as_basic_value().into_pointer_value();
|
||||
list_content =
|
||||
ctx.build_gep_and_load(list, &[zero_size_t, zero_32]).into_pointer_value();
|
||||
list_content = ctx.build_gep_and_load(list, &[zero_size_t, zero_32], Some("list_content"))
|
||||
.into_pointer_value();
|
||||
|
||||
let i = generator.gen_store_target(ctx, target, Some("i.addr"))?;
|
||||
ctx.builder.build_store(i, ctx.builder.build_int_sub(start, step, "start_init"));
|
||||
ctx.builder.build_unconditional_branch(test_bb);
|
||||
|
||||
ctx.builder.position_at_end(test_bb);
|
||||
let sign =
|
||||
ctx.builder.build_int_compare(inkwell::IntPredicate::SGT, step, zero_32, "sign");
|
||||
|
@ -877,44 +970,52 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>(
|
|||
body_bb,
|
||||
cont_bb,
|
||||
);
|
||||
|
||||
ctx.builder.position_at_end(body_bb);
|
||||
} else {
|
||||
let length = ctx
|
||||
.build_gep_and_load(
|
||||
iter_val.into_pointer_value(),
|
||||
&[zero_size_t, int32.const_int(1, false)],
|
||||
Some("length"),
|
||||
)
|
||||
.into_int_value();
|
||||
list = allocate_list(generator, ctx, elem_ty, length);
|
||||
list = allocate_list(generator, ctx, elem_ty, length, Some("listcomp"));
|
||||
list_content =
|
||||
ctx.build_gep_and_load(list, &[zero_size_t, zero_32]).into_pointer_value();
|
||||
ctx.build_gep_and_load(list, &[zero_size_t, zero_32], Some("list_content")).into_pointer_value();
|
||||
let counter = generator.gen_var_alloc(ctx, size_t.into(), Some("counter.addr"))?;
|
||||
// counter = -1
|
||||
ctx.builder.build_store(counter, size_t.const_int(u64::max_value(), true));
|
||||
ctx.builder.build_unconditional_branch(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_int_add(tmp, size_t.const_int(1, false), "inc");
|
||||
ctx.builder.build_store(counter, tmp);
|
||||
let cmp = ctx.builder.build_int_compare(inkwell::IntPredicate::SLT, tmp, length, "cmp");
|
||||
ctx.builder.build_conditional_branch(cmp, body_bb, cont_bb);
|
||||
|
||||
ctx.builder.position_at_end(body_bb);
|
||||
let arr_ptr = ctx
|
||||
.build_gep_and_load(iter_val.into_pointer_value(), &[zero_size_t, zero_32])
|
||||
.build_gep_and_load(iter_val.into_pointer_value(), &[zero_size_t, zero_32], Some("arr.addr"))
|
||||
.into_pointer_value();
|
||||
let val = ctx.build_gep_and_load(arr_ptr, &[tmp]);
|
||||
let val = ctx.build_gep_and_load(arr_ptr, &[tmp], Some("val"));
|
||||
generator.gen_assign(ctx, target, val.into())?;
|
||||
}
|
||||
|
||||
for cond in ifs.iter() {
|
||||
let result = generator
|
||||
.gen_expr(ctx, cond)?
|
||||
.unwrap()
|
||||
.to_basic_value_enum(ctx, generator, cond.custom.unwrap())?
|
||||
.into_int_value();
|
||||
let result = generator.bool_to_i1(ctx, result);
|
||||
let succ = ctx.ctx.append_basic_block(current, "then");
|
||||
ctx.builder.build_conditional_branch(result, succ, test_bb);
|
||||
|
||||
ctx.builder.position_at_end(succ);
|
||||
}
|
||||
|
||||
let elem = generator.gen_expr(ctx, elt)?.unwrap();
|
||||
let i = ctx.builder.build_load(index, "i").into_int_value();
|
||||
let elem_ptr = unsafe { ctx.builder.build_gep(list_content, &[i], "elem_ptr") };
|
||||
|
@ -923,17 +1024,26 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>(
|
|||
ctx.builder
|
||||
.build_store(index, ctx.builder.build_int_add(i, size_t.const_int(1, false), "inc"));
|
||||
ctx.builder.build_unconditional_branch(test_bb);
|
||||
|
||||
ctx.builder.position_at_end(cont_bb);
|
||||
let len_ptr = unsafe {
|
||||
ctx.builder.build_gep(list, &[zero_size_t, int32.const_int(1, false)], "length")
|
||||
};
|
||||
ctx.builder.build_store(len_ptr, ctx.builder.build_load(index, "index"));
|
||||
|
||||
Ok(list.into())
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates LLVM IR for a [binary operator expression][expr].
|
||||
///
|
||||
/// * `left` - The left-hand side of the binary operator.
|
||||
/// * `op` - The operator applied on the operands.
|
||||
/// * `right` - The right-hand side of the binary operator.
|
||||
/// * `loc` - The location of the full expression.
|
||||
/// * `is_aug_assign` - Whether the binary operator expression is also an assignment operator.
|
||||
pub fn gen_binop_expr<'ctx, 'a, G: CodeGenerator>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -1030,6 +1140,7 @@ pub fn gen_binop_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
}
|
||||
}
|
||||
|
||||
/// See [CodeGenerator::gen_expr].
|
||||
pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -1070,7 +1181,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
}
|
||||
}
|
||||
ExprKind::Name { id, .. } => match ctx.var_assignment.get(id) {
|
||||
Some((ptr, None, _)) => ctx.builder.build_load(*ptr, "load").into(),
|
||||
Some((ptr, None, _)) => ctx.builder.build_load(*ptr, id.to_string().as_str()).into(),
|
||||
Some((_, Some(static_value), _)) => ValueEnum::Static(static_value.clone()),
|
||||
None => {
|
||||
let resolver = ctx.resolver.clone();
|
||||
|
@ -1101,8 +1212,9 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
elements[0].get_type()
|
||||
};
|
||||
let length = generator.get_size_type(ctx.ctx).const_int(elements.len() as u64, false);
|
||||
let arr_str_ptr = allocate_list(generator, ctx, ty, length);
|
||||
let arr_ptr = ctx.build_gep_and_load(arr_str_ptr, &[zero, zero]).into_pointer_value();
|
||||
let arr_str_ptr = allocate_list(generator, ctx, ty, length, Some("list"));
|
||||
let arr_ptr = ctx.build_gep_and_load(arr_str_ptr, &[zero, zero], Some("list.ptr.addr"))
|
||||
.into_pointer_value();
|
||||
unsafe {
|
||||
for (i, v) in elements.iter().enumerate() {
|
||||
let elem_ptr = ctx.builder.build_gep(
|
||||
|
@ -1148,6 +1260,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
Ok(ValueEnum::Dynamic(ctx.build_gep_and_load(
|
||||
v.into_pointer_value(),
|
||||
&[zero, int32.const_int(index as u64, false)],
|
||||
None,
|
||||
))) as Result<_, String>
|
||||
}, Ok)?,
|
||||
ValueEnum::Dynamic(v) => {
|
||||
|
@ -1155,6 +1268,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
ValueEnum::Dynamic(ctx.build_gep_and_load(
|
||||
v.into_pointer_value(),
|
||||
&[zero, int32.const_int(index as u64, false)],
|
||||
None,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
@ -1170,11 +1284,11 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
let a_bb = ctx.ctx.append_basic_block(current, "a");
|
||||
let b_bb = ctx.ctx.append_basic_block(current, "b");
|
||||
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(generator.bool_to_i1(ctx, left), a_bb, b_bb);
|
||||
let (a, b) = match op {
|
||||
Boolop::Or => {
|
||||
ctx.builder.position_at_end(a_bb);
|
||||
let a = ctx.ctx.bool_type().const_int(1, false);
|
||||
let a = ctx.ctx.i8_type().const_int(1, false);
|
||||
ctx.builder.build_unconditional_branch(cont_bb);
|
||||
ctx.builder.position_at_end(b_bb);
|
||||
let b = generator
|
||||
|
@ -1182,6 +1296,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
.unwrap()
|
||||
.to_basic_value_enum(ctx, generator, values[1].custom.unwrap())?
|
||||
.into_int_value();
|
||||
let b = generator.bool_to_i8(ctx, b);
|
||||
ctx.builder.build_unconditional_branch(cont_bb);
|
||||
(a, b)
|
||||
}
|
||||
|
@ -1192,15 +1307,16 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
.unwrap()
|
||||
.to_basic_value_enum(ctx, generator, values[1].custom.unwrap())?
|
||||
.into_int_value();
|
||||
let a = generator.bool_to_i8(ctx, a);
|
||||
ctx.builder.build_unconditional_branch(cont_bb);
|
||||
ctx.builder.position_at_end(b_bb);
|
||||
let b = ctx.ctx.bool_type().const_int(0, false);
|
||||
let b = ctx.ctx.i8_type().const_zero();
|
||||
ctx.builder.build_unconditional_branch(cont_bb);
|
||||
(a, b)
|
||||
}
|
||||
};
|
||||
ctx.builder.position_at_end(cont_bb);
|
||||
let phi = ctx.builder.build_phi(ctx.ctx.bool_type(), "phi");
|
||||
let phi = ctx.builder.build_phi(ctx.ctx.i8_type(), "");
|
||||
phi.add_incoming(&[(&a, a_bb), (&b, b_bb)]);
|
||||
phi.as_basic_value().into()
|
||||
}
|
||||
|
@ -1511,7 +1627,8 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
.to_basic_value_enum(ctx, generator, value.custom.unwrap())?
|
||||
.into_pointer_value();
|
||||
let ty = ctx.get_llvm_type(generator, *ty);
|
||||
let arr_ptr = ctx.build_gep_and_load(v, &[zero, zero]).into_pointer_value();
|
||||
let arr_ptr = ctx.build_gep_and_load(v, &[zero, zero], Some("arr.addr"))
|
||||
.into_pointer_value();
|
||||
if let ExprKind::Slice { lower, upper, step } = &slice.node {
|
||||
let one = int32.const_int(1, false);
|
||||
let (start, end, step) =
|
||||
|
@ -1535,7 +1652,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
.into_int_value(),
|
||||
step,
|
||||
);
|
||||
let res_array_ret = allocate_list(generator, ctx, ty, length);
|
||||
let res_array_ret = allocate_list(generator, ctx, ty, length, Some("ret"));
|
||||
let res_ind =
|
||||
handle_slice_indices(&None, &None, &None, ctx, generator, res_array_ret)?;
|
||||
list_slice_assignment(
|
||||
|
@ -1550,7 +1667,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
res_array_ret.into()
|
||||
} else {
|
||||
let len = ctx
|
||||
.build_gep_and_load(v, &[zero, int32.const_int(1, false)])
|
||||
.build_gep_and_load(v, &[zero, int32.const_int(1, false)], Some("len"))
|
||||
.into_int_value();
|
||||
let raw_index = generator
|
||||
.gen_expr(ctx, slice)?
|
||||
|
@ -1590,7 +1707,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
|
|||
[Some(raw_index), Some(len), None],
|
||||
expr.location,
|
||||
);
|
||||
ctx.build_gep_and_load(arr_ptr, &[index]).into()
|
||||
ctx.build_gep_and_load(arr_ptr, &[index], None).into()
|
||||
}
|
||||
} else if let TypeEnum::TTuple { .. } = &*ctx.unifier.get_ty(value.custom.unwrap()) {
|
||||
let index: u32 =
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{
|
||||
codegen::{expr::*, stmt::*, CodeGenContext},
|
||||
codegen::{expr::*, stmt::*, bool_to_i1, bool_to_i8, CodeGenContext},
|
||||
symbol_resolver::ValueEnum,
|
||||
toplevel::{DefinitionId, TopLevelDef},
|
||||
typecheck::typedef::{FunSignature, Type},
|
||||
|
@ -7,7 +7,7 @@ use crate::{
|
|||
use inkwell::{
|
||||
context::Context,
|
||||
types::{BasicTypeEnum, IntType},
|
||||
values::{BasicValueEnum, PointerValue},
|
||||
values::{BasicValueEnum, IntValue, PointerValue},
|
||||
};
|
||||
use nac3parser::ast::{Expr, Stmt, StrRef};
|
||||
|
||||
|
@ -180,6 +180,24 @@ pub trait CodeGenerator {
|
|||
{
|
||||
gen_stmt(self, ctx, stmt)
|
||||
}
|
||||
|
||||
/// See [bool_to_i1].
|
||||
fn bool_to_i1<'ctx, 'a>(
|
||||
&self,
|
||||
ctx: &CodeGenContext<'ctx, 'a>,
|
||||
bool_value: IntValue<'ctx>
|
||||
) -> IntValue<'ctx> {
|
||||
bool_to_i1(&ctx.builder, bool_value)
|
||||
}
|
||||
|
||||
/// See [bool_to_i8].
|
||||
fn bool_to_i8<'ctx, 'a>(
|
||||
&self,
|
||||
ctx: &CodeGenContext<'ctx, 'a>,
|
||||
bool_value: IntValue<'ctx>
|
||||
) -> IntValue<'ctx> {
|
||||
bool_to_i8(&ctx.builder, &ctx.ctx, bool_value)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DefaultCodeGenerator {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
typedef _ExtInt(8) int8_t;
|
||||
typedef unsigned _ExtInt(8) uint8_t;
|
||||
typedef _ExtInt(32) int32_t;
|
||||
typedef unsigned _ExtInt(32) uint32_t;
|
||||
typedef _ExtInt(64) int64_t;
|
||||
typedef unsigned _ExtInt(64) uint64_t;
|
||||
typedef _BitInt(8) int8_t;
|
||||
typedef unsigned _BitInt(8) uint8_t;
|
||||
typedef _BitInt(32) int32_t;
|
||||
typedef unsigned _BitInt(32) uint32_t;
|
||||
typedef _BitInt(64) int64_t;
|
||||
typedef unsigned _BitInt(64) uint64_t;
|
||||
|
||||
# define MAX(a, b) (a > b ? a : b)
|
||||
# define MIN(a, b) (a > b ? b : a)
|
||||
|
|
|
@ -162,7 +162,7 @@ pub fn handle_slice_indices<'a, 'ctx, G: CodeGenerator>(
|
|||
let int32 = ctx.ctx.i32_type();
|
||||
let zero = int32.const_zero();
|
||||
let one = int32.const_int(1, false);
|
||||
let length = ctx.build_gep_and_load(list, &[zero, one]).into_int_value();
|
||||
let length = ctx.build_gep_and_load(list, &[zero, one], Some("length")).into_int_value();
|
||||
let length = ctx.builder.build_int_truncate_or_bit_cast(length, int32, "leni32");
|
||||
Ok(match (start, end, step) {
|
||||
(s, e, None) => (
|
||||
|
@ -309,21 +309,21 @@ pub fn list_slice_assignment<'ctx, 'a>(
|
|||
|
||||
let zero = int32.const_zero();
|
||||
let one = int32.const_int(1, false);
|
||||
let dest_arr_ptr = ctx.build_gep_and_load(dest_arr, &[zero, zero]);
|
||||
let dest_arr_ptr = ctx.build_gep_and_load(dest_arr, &[zero, zero], Some("dest.addr"));
|
||||
let dest_arr_ptr = ctx.builder.build_pointer_cast(
|
||||
dest_arr_ptr.into_pointer_value(),
|
||||
elem_ptr_type,
|
||||
"dest_arr_ptr_cast",
|
||||
);
|
||||
let dest_len = ctx.build_gep_and_load(dest_arr, &[zero, one]).into_int_value();
|
||||
let dest_len = ctx.build_gep_and_load(dest_arr, &[zero, one], Some("dest.len")).into_int_value();
|
||||
let dest_len = ctx.builder.build_int_truncate_or_bit_cast(dest_len, int32, "srclen32");
|
||||
let src_arr_ptr = ctx.build_gep_and_load(src_arr, &[zero, zero]);
|
||||
let src_arr_ptr = ctx.build_gep_and_load(src_arr, &[zero, zero], Some("src.addr"));
|
||||
let src_arr_ptr = ctx.builder.build_pointer_cast(
|
||||
src_arr_ptr.into_pointer_value(),
|
||||
elem_ptr_type,
|
||||
"src_arr_ptr_cast",
|
||||
);
|
||||
let src_len = ctx.build_gep_and_load(src_arr, &[zero, one]).into_int_value();
|
||||
let src_len = ctx.build_gep_and_load(src_arr, &[zero, one], Some("src.len")).into_int_value();
|
||||
let src_len = ctx.builder.build_int_truncate_or_bit_cast(src_len, int32, "srclen32");
|
||||
|
||||
// index in bound and positive should be done
|
||||
|
|
|
@ -9,6 +9,7 @@ use crate::{
|
|||
use crossbeam::channel::{unbounded, Receiver, Sender};
|
||||
use inkwell::{
|
||||
AddressSpace,
|
||||
IntPredicate,
|
||||
OptimizationLevel,
|
||||
attributes::{Attribute, AttributeLoc},
|
||||
basic_block::BasicBlock,
|
||||
|
@ -18,7 +19,7 @@ use inkwell::{
|
|||
passes::PassBuilderOptions,
|
||||
targets::{CodeModel, RelocMode, Target, TargetMachine, TargetTriple},
|
||||
types::{AnyType, BasicType, BasicTypeEnum},
|
||||
values::{BasicValueEnum, FunctionValue, PhiValue, PointerValue},
|
||||
values::{BasicValueEnum, FunctionValue, IntValue, PhiValue, PointerValue},
|
||||
debug_info::{
|
||||
DebugInfoBuilder, DICompileUnit, DISubprogram, AsDIScope, DIFlagsConstants, DIScope
|
||||
},
|
||||
|
@ -61,9 +62,6 @@ pub struct CodeGenLLVMOptions {
|
|||
|
||||
/// Options related to the target machine.
|
||||
pub target: CodeGenTargetMachineOptions,
|
||||
|
||||
/// Whether to output the LLVM IR after generation is complete.
|
||||
pub emit_llvm: bool,
|
||||
}
|
||||
|
||||
/// Additional options for code generation for the target machine.
|
||||
|
@ -322,8 +320,7 @@ impl WorkerRegistry {
|
|||
let result = module.verify();
|
||||
if let Err(err) = result {
|
||||
println!("{}", module.print_to_string().to_str().unwrap());
|
||||
println!("{}", err.to_string());
|
||||
panic!()
|
||||
panic!("{}", err.to_string())
|
||||
}
|
||||
|
||||
let pass_options = PassBuilderOptions::create();
|
||||
|
@ -339,11 +336,6 @@ impl WorkerRegistry {
|
|||
err.to_string());
|
||||
}
|
||||
|
||||
if self.llvm_options.emit_llvm {
|
||||
println!("LLVM IR for {}\n{}", module.get_name().to_str().unwrap(), module.to_string());
|
||||
println!();
|
||||
}
|
||||
|
||||
f.run(&module);
|
||||
let mut lock = self.task_count.lock();
|
||||
*lock += 1;
|
||||
|
@ -363,6 +355,10 @@ pub struct CodeGenTask {
|
|||
pub id: usize,
|
||||
}
|
||||
|
||||
/// Retrieves the [LLVM type][BasicTypeEnum] corresponding to the [Type].
|
||||
///
|
||||
/// This function is used to obtain the in-memory representation of `ty`, e.g. a `bool` variable
|
||||
/// would be represented by an `i8`.
|
||||
fn get_llvm_type<'ctx>(
|
||||
ctx: &'ctx Context,
|
||||
module: &Module<'ctx>,
|
||||
|
@ -474,6 +470,34 @@ fn get_llvm_type<'ctx>(
|
|||
})
|
||||
}
|
||||
|
||||
/// Retrieves the [LLVM type][BasicTypeEnum] corresponding to the [Type].
|
||||
///
|
||||
/// This function is used mainly to obtain the ABI representation of `ty`, e.g. a `bool` is
|
||||
/// would be represented by an `i1`.
|
||||
///
|
||||
/// The difference between the in-memory representation (as returned by [get_llvm_type]) and the
|
||||
/// ABI representation is that the in-memory representation must be at least byte-sized and must
|
||||
/// be byte-aligned for the variable to be addressable in memory, whereas there is no such
|
||||
/// restriction for ABI representations.
|
||||
fn get_llvm_abi_type<'ctx>(
|
||||
ctx: &'ctx Context,
|
||||
module: &Module<'ctx>,
|
||||
generator: &mut dyn CodeGenerator,
|
||||
unifier: &mut Unifier,
|
||||
top_level: &TopLevelContext,
|
||||
type_cache: &mut HashMap<Type, BasicTypeEnum<'ctx>>,
|
||||
primitives: &PrimitiveStore,
|
||||
ty: Type,
|
||||
) -> BasicTypeEnum<'ctx> {
|
||||
// If the type is used in the definition of a function, return `i1` instead of `i8` for ABI
|
||||
// consistency.
|
||||
return if unifier.unioned(ty, primitives.bool) {
|
||||
ctx.bool_type().into()
|
||||
} else {
|
||||
get_llvm_type(ctx, module, generator, unifier, top_level, type_cache, primitives, ty)
|
||||
}
|
||||
}
|
||||
|
||||
fn need_sret<'ctx>(ctx: &'ctx Context, ty: BasicTypeEnum<'ctx>) -> bool {
|
||||
fn need_sret_impl<'ctx>(ctx: &'ctx Context, ty: BasicTypeEnum<'ctx>, maybe_large: bool) -> bool {
|
||||
match ty {
|
||||
|
@ -487,6 +511,7 @@ fn need_sret<'ctx>(ctx: &'ctx Context, ty: BasicTypeEnum<'ctx>) -> bool {
|
|||
need_sret_impl(ctx, ty, true)
|
||||
}
|
||||
|
||||
/// Implementation for generating LLVM IR for a function.
|
||||
pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenContext) -> Result<(), String>> (
|
||||
context: &'ctx Context,
|
||||
generator: &mut G,
|
||||
|
@ -543,7 +568,7 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte
|
|||
(primitives.uint32, context.i32_type().into()),
|
||||
(primitives.uint64, context.i64_type().into()),
|
||||
(primitives.float, context.f64_type().into()),
|
||||
(primitives.bool, context.bool_type().into()),
|
||||
(primitives.bool, context.i8_type().into()),
|
||||
(primitives.str, {
|
||||
let name = "str";
|
||||
match module.get_struct_type(name) {
|
||||
|
@ -601,14 +626,14 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte
|
|||
let ret_type = if unifier.unioned(ret, primitives.none) {
|
||||
None
|
||||
} else {
|
||||
Some(get_llvm_type(context, &module, generator, &mut unifier, top_level_ctx.as_ref(), &mut type_cache, &primitives, ret))
|
||||
Some(get_llvm_abi_type(context, &module, generator, &mut unifier, top_level_ctx.as_ref(), &mut type_cache, &primitives, ret))
|
||||
};
|
||||
|
||||
let has_sret = ret_type.map_or(false, |ty| need_sret(context, ty));
|
||||
let mut params = args
|
||||
.iter()
|
||||
.map(|arg| {
|
||||
get_llvm_type(
|
||||
get_llvm_abi_type(
|
||||
context,
|
||||
&module,
|
||||
generator,
|
||||
|
@ -656,19 +681,35 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte
|
|||
let offset = if has_sret { 1 } else { 0 };
|
||||
for (n, arg) in args.iter().enumerate() {
|
||||
let param = fn_val.get_nth_param((n as u32) + offset).unwrap();
|
||||
let alloca = builder.build_alloca(
|
||||
get_llvm_type(
|
||||
context,
|
||||
&module,
|
||||
generator,
|
||||
&mut unifier,
|
||||
top_level_ctx.as_ref(),
|
||||
&mut type_cache,
|
||||
&primitives,
|
||||
arg.ty,
|
||||
),
|
||||
&arg.name.to_string(),
|
||||
let local_type = get_llvm_type(
|
||||
context,
|
||||
&module,
|
||||
generator,
|
||||
&mut unifier,
|
||||
top_level_ctx.as_ref(),
|
||||
&mut type_cache,
|
||||
&primitives,
|
||||
arg.ty,
|
||||
);
|
||||
let alloca = builder.build_alloca(
|
||||
local_type,
|
||||
&format!("{}.addr", &arg.name.to_string()),
|
||||
);
|
||||
|
||||
// Remap boolean parameters into i8
|
||||
let param = if local_type.is_int_type() && param.is_int_value() {
|
||||
let expected_ty = local_type.into_int_type();
|
||||
let param_val = param.into_int_value();
|
||||
|
||||
if expected_ty.get_bit_width() == 8 && param_val.get_type().get_bit_width() == 1 {
|
||||
bool_to_i8(&builder, &context, param_val)
|
||||
} else {
|
||||
param_val
|
||||
}.into()
|
||||
} else {
|
||||
param
|
||||
};
|
||||
|
||||
builder.build_store(alloca, param);
|
||||
var_assignment.insert(arg.name, (alloca, None, 0));
|
||||
}
|
||||
|
@ -795,6 +836,15 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte
|
|||
Ok((builder, module, fn_val))
|
||||
}
|
||||
|
||||
/// Generates LLVM IR for a function.
|
||||
///
|
||||
/// * `context` - The [LLVM Context][Context] used in generating the function body.
|
||||
/// * `generator` - The [CodeGenerator] for generating various program constructs.
|
||||
/// * `registry` - The [WorkerRegistry] responsible for monitoring this function generation task.
|
||||
/// * `builder` - The [Builder] used for generating LLVM IR.
|
||||
/// * `module` - The [Module] of which the generated LLVM function will be inserted into.
|
||||
/// * `task` - The [CodeGenTask] associated with this function generation task.
|
||||
///
|
||||
pub fn gen_func<'ctx, G: CodeGenerator>(
|
||||
context: &'ctx Context,
|
||||
generator: &mut G,
|
||||
|
@ -811,3 +861,40 @@ pub fn gen_func<'ctx, G: CodeGenerator>(
|
|||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
/// Converts the value of a boolean-like value `bool_value` into an `i1`.
|
||||
fn bool_to_i1<'ctx>(builder: &Builder<'ctx>, bool_value: IntValue<'ctx>) -> IntValue<'ctx> {
|
||||
if bool_value.get_type().get_bit_width() != 1 {
|
||||
builder.build_int_compare(
|
||||
IntPredicate::NE,
|
||||
bool_value,
|
||||
bool_value.get_type().const_zero(),
|
||||
"tobool"
|
||||
)
|
||||
} else {
|
||||
bool_value
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts the value of a boolean-like value `bool_value` into an `i8`.
|
||||
fn bool_to_i8<'ctx>(
|
||||
builder: &Builder<'ctx>,
|
||||
ctx: &'ctx Context,
|
||||
bool_value: IntValue<'ctx>
|
||||
) -> IntValue<'ctx> {
|
||||
let value_bits = bool_value.get_type().get_bit_width();
|
||||
match value_bits {
|
||||
8 => bool_value,
|
||||
1 => builder.build_int_z_extend(bool_value, ctx.i8_type(), "frombool"),
|
||||
_ => bool_to_i8(
|
||||
builder,
|
||||
ctx,
|
||||
builder.build_int_compare(
|
||||
IntPredicate::NE,
|
||||
bool_value,
|
||||
bool_value.get_type().const_zero(),
|
||||
""
|
||||
)
|
||||
),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ use nac3parser::ast::{
|
|||
};
|
||||
use std::convert::TryFrom;
|
||||
|
||||
/// See [CodeGenerator::gen_var_alloc].
|
||||
pub fn gen_var<'ctx, 'a>(
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
ty: BasicTypeEnum<'ctx>,
|
||||
|
@ -35,6 +36,7 @@ pub fn gen_var<'ctx, 'a>(
|
|||
Ok(ptr)
|
||||
}
|
||||
|
||||
/// See [CodeGenerator::gen_store_target].
|
||||
pub fn gen_store_target<'ctx, 'a, G: CodeGenerator>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -93,7 +95,7 @@ pub fn gen_store_target<'ctx, 'a, G: CodeGenerator>(
|
|||
.to_basic_value_enum(ctx, generator, value.custom.unwrap())?
|
||||
.into_pointer_value();
|
||||
let len = ctx
|
||||
.build_gep_and_load(v, &[zero, i32_type.const_int(1, false)])
|
||||
.build_gep_and_load(v, &[zero, i32_type.const_int(1, false)], Some("len"))
|
||||
.into_int_value();
|
||||
let raw_index = generator
|
||||
.gen_expr(ctx, slice)?
|
||||
|
@ -135,7 +137,7 @@ pub fn gen_store_target<'ctx, 'a, G: CodeGenerator>(
|
|||
);
|
||||
unsafe {
|
||||
let arr_ptr = ctx
|
||||
.build_gep_and_load(v, &[i32_type.const_zero(), i32_type.const_zero()])
|
||||
.build_gep_and_load(v, &[i32_type.const_zero(), i32_type.const_zero()], Some("arr.addr"))
|
||||
.into_pointer_value();
|
||||
ctx.builder.build_gep(arr_ptr, &[index], name.unwrap_or(""))
|
||||
}
|
||||
|
@ -144,6 +146,7 @@ pub fn gen_store_target<'ctx, 'a, G: CodeGenerator>(
|
|||
})
|
||||
}
|
||||
|
||||
/// See [CodeGenerator::gen_assign].
|
||||
pub fn gen_assign<'ctx, 'a, G: CodeGenerator>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -214,13 +217,21 @@ pub fn gen_assign<'ctx, 'a, G: CodeGenerator>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Generates a sequence of IR which checks whether [value] does not exceed the upper bound of the
|
||||
/// range as defined by [stop] and [step].
|
||||
/// Generates a sequence of IR which checks whether `value` does not exceed the upper bound of the
|
||||
/// range as defined by `stop` and `step`.
|
||||
///
|
||||
/// Note that the generated IR will **not** check whether value is part of the range or whether
|
||||
/// value exceeds the lower bound of the range (as evident by the missing `start` argument).
|
||||
///
|
||||
/// Returns an [IntValue] representing the result of whether the [value] is in the range.
|
||||
/// The generated IR is equivalent to the following Rust code:
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// let sign = step > 0;
|
||||
/// let (lo, hi) = if sign { (value, stop) } else { (stop, value) };
|
||||
/// let cmp = lo < hi;
|
||||
/// ```
|
||||
///
|
||||
/// Returns an `i1` [IntValue] representing the result of whether the `value` is in the range.
|
||||
fn gen_in_range_check<'ctx, 'a>(
|
||||
ctx: &CodeGenContext<'ctx, 'a>,
|
||||
value: IntValue<'ctx>,
|
||||
|
@ -234,6 +245,7 @@ fn gen_in_range_check<'ctx, 'a>(
|
|||
ctx.builder.build_int_compare(IntPredicate::SLT, lo, hi, "cmp")
|
||||
}
|
||||
|
||||
/// See [CodeGenerator::gen_for].
|
||||
pub fn gen_for<'ctx, 'a, G: CodeGenerator>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -327,6 +339,7 @@ pub fn gen_for<'ctx, 'a, G: CodeGenerator>(
|
|||
.build_gep_and_load(
|
||||
iter_val.into_pointer_value(),
|
||||
&[zero, int32.const_int(1, false)],
|
||||
Some("len")
|
||||
)
|
||||
.into_int_value();
|
||||
ctx.builder.build_unconditional_branch(test_bb);
|
||||
|
@ -338,9 +351,9 @@ pub fn gen_for<'ctx, 'a, G: CodeGenerator>(
|
|||
|
||||
ctx.builder.position_at_end(body_bb);
|
||||
let arr_ptr = ctx
|
||||
.build_gep_and_load(iter_val.into_pointer_value(), &[zero, zero])
|
||||
.build_gep_and_load(iter_val.into_pointer_value(), &[zero, zero], Some("arr.addr"))
|
||||
.into_pointer_value();
|
||||
let val = ctx.build_gep_and_load(arr_ptr, &[index]);
|
||||
let val = ctx.build_gep_and_load(arr_ptr, &[index], Some("val"));
|
||||
generator.gen_assign(ctx, target, val.into())?;
|
||||
gen_block(generator, ctx, body.iter())?;
|
||||
|
||||
|
@ -383,6 +396,7 @@ pub fn gen_for<'ctx, 'a, G: CodeGenerator>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// See [CodeGenerator::gen_while].
|
||||
pub fn gen_while<'ctx, 'a, G: CodeGenerator>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -410,7 +424,7 @@ pub fn gen_while<'ctx, 'a, G: CodeGenerator>(
|
|||
test.custom.unwrap(),
|
||||
)?;
|
||||
if let BasicValueEnum::IntValue(test) = test {
|
||||
ctx.builder.build_conditional_branch(test, body_bb, orelse_bb);
|
||||
ctx.builder.build_conditional_branch(generator.bool_to_i1(ctx, test), body_bb, orelse_bb);
|
||||
} else {
|
||||
unreachable!()
|
||||
};
|
||||
|
@ -446,6 +460,7 @@ pub fn gen_while<'ctx, 'a, G: CodeGenerator>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// See [CodeGenerator::gen_if].
|
||||
pub fn gen_if<'ctx, 'a, G: CodeGenerator>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -469,13 +484,11 @@ pub fn gen_if<'ctx, 'a, G: CodeGenerator>(
|
|||
};
|
||||
ctx.builder.build_unconditional_branch(test_bb);
|
||||
ctx.builder.position_at_end(test_bb);
|
||||
let test = generator.gen_expr(ctx, test)?.unwrap().to_basic_value_enum(
|
||||
ctx,
|
||||
generator,
|
||||
test.custom.unwrap(),
|
||||
)?;
|
||||
let test = generator.gen_expr(ctx, test)?
|
||||
.unwrap()
|
||||
.to_basic_value_enum(ctx, generator, test.custom.unwrap())?;
|
||||
if let BasicValueEnum::IntValue(test) = test {
|
||||
ctx.builder.build_conditional_branch(test, body_bb, orelse_bb);
|
||||
ctx.builder.build_conditional_branch(generator.bool_to_i1(ctx, test), body_bb, orelse_bb);
|
||||
} else {
|
||||
unreachable!()
|
||||
};
|
||||
|
@ -536,6 +549,8 @@ pub fn final_proxy<'ctx, 'a>(
|
|||
final_paths.push(block);
|
||||
}
|
||||
|
||||
/// Inserts the declaration of the builtin function with the specified `symbol` name, and returns
|
||||
/// the function.
|
||||
pub fn get_builtins<'ctx, 'a>(
|
||||
generator: &mut dyn CodeGenerator,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -633,6 +648,10 @@ pub fn exn_constructor<'ctx, 'a>(
|
|||
Ok(Some(zelf.into()))
|
||||
}
|
||||
|
||||
/// Generates IR for a `raise` statement.
|
||||
///
|
||||
/// * `exception` - The exception thrown by the `raise` statement.
|
||||
/// * `loc` - The location where the exception is raised from.
|
||||
pub fn gen_raise<'ctx, 'a>(
|
||||
generator: &mut dyn CodeGenerator,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -684,6 +703,7 @@ pub fn gen_raise<'ctx, 'a>(
|
|||
ctx.builder.build_unreachable();
|
||||
}
|
||||
|
||||
/// Generates IR for a `try` statement.
|
||||
pub fn gen_try<'ctx, 'a, G: CodeGenerator>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -1006,6 +1026,7 @@ pub fn gen_try<'ctx, 'a, G: CodeGenerator>(
|
|||
}
|
||||
}
|
||||
|
||||
/// See [CodeGenerator::gen_with].
|
||||
pub fn gen_with<'ctx, 'a, G: CodeGenerator>(
|
||||
_: &mut G,
|
||||
_: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -1015,11 +1036,13 @@ pub fn gen_with<'ctx, 'a, G: CodeGenerator>(
|
|||
Err(format!("With statement with custom types is not yet supported (at {})", stmt.location))
|
||||
}
|
||||
|
||||
/// Generates IR for a `return` statement.
|
||||
pub fn gen_return<'ctx, 'a, G: CodeGenerator>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
value: &Option<Box<Expr<Option<Type>>>>,
|
||||
) -> Result<(), String> {
|
||||
let func = ctx.builder.get_insert_block().and_then(|bb| bb.get_parent()).unwrap();
|
||||
let value = value
|
||||
.as_ref()
|
||||
.map(|v_expr| {
|
||||
|
@ -1038,12 +1061,31 @@ pub fn gen_return<'ctx, 'a, G: CodeGenerator>(
|
|||
ctx.builder.build_store(ctx.return_buffer.unwrap(), value.unwrap());
|
||||
ctx.builder.build_return(None);
|
||||
} else {
|
||||
// Remap boolean return type into i1
|
||||
let value = value.map(|v| {
|
||||
let expected_ty = func.get_type().get_return_type().unwrap();
|
||||
let ret_val = v.as_basic_value_enum();
|
||||
|
||||
if expected_ty.is_int_type() && ret_val.is_int_value() {
|
||||
let ret_type = expected_ty.into_int_type();
|
||||
let ret_val = ret_val.into_int_value();
|
||||
|
||||
if ret_type.get_bit_width() == 1 && ret_val.get_type().get_bit_width() != 1 {
|
||||
generator.bool_to_i1(ctx, ret_val)
|
||||
} else {
|
||||
ret_val
|
||||
}.into()
|
||||
} else {
|
||||
ret_val
|
||||
}
|
||||
});
|
||||
let value = value.as_ref().map(|v| v as &dyn BasicValue);
|
||||
ctx.builder.build_return(value);
|
||||
ctx.builder.build_return(value.into());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// See [CodeGenerator::gen_stmt].
|
||||
pub fn gen_stmt<'ctx, 'a, G: CodeGenerator>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -1135,6 +1177,7 @@ pub fn gen_stmt<'ctx, 'a, G: CodeGenerator>(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Generates IR for a block statement contains `stmts`.
|
||||
pub fn gen_block<'ctx, 'a, 'b, G: CodeGenerator, I: Iterator<Item = &'b Stmt<Option<Type>>>>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
|
|
@ -21,6 +21,7 @@ use nac3parser::{
|
|||
use parking_lot::RwLock;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::sync::Arc;
|
||||
use inkwell::targets::{InitializationConfig, Target};
|
||||
|
||||
struct Resolver {
|
||||
id_to_type: HashMap<StrRef, Type>,
|
||||
|
@ -181,24 +182,18 @@ fn test_primitives() {
|
|||
let expected = indoc! {"
|
||||
; ModuleID = 'test'
|
||||
source_filename = \"test\"
|
||||
|
||||
define i32 @testing(i32 %0, i32 %1) !dbg !4 {
|
||||
|
||||
; Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn
|
||||
define i32 @testing(i32 %0, i32 %1) local_unnamed_addr #0 !dbg !4 {
|
||||
init:
|
||||
%add = add i32 %0, %1, !dbg !9
|
||||
%add = add i32 %1, %0, !dbg !9
|
||||
%cmp = icmp eq i32 %add, 1, !dbg !10
|
||||
br i1 %cmp, label %then, label %else, !dbg !10
|
||||
|
||||
then: ; preds = %init
|
||||
br label %cont, !dbg !11
|
||||
|
||||
else: ; preds = %init
|
||||
br label %cont, !dbg !12
|
||||
|
||||
cont: ; preds = %else, %then
|
||||
%if_exp_result.0 = phi i32 [ %0, %then ], [ 0, %else ], !dbg !13
|
||||
ret i32 %if_exp_result.0, !dbg !14
|
||||
%. = select i1 %cmp, i32 %0, i32 0, !dbg !11
|
||||
ret i32 %., !dbg !12
|
||||
}
|
||||
|
||||
attributes #0 = { mustprogress nofree norecurse nosync nounwind readnone willreturn }
|
||||
|
||||
!llvm.module.flags = !{!0, !1}
|
||||
!llvm.dbg.cu = !{!2}
|
||||
|
||||
|
@ -213,19 +208,18 @@ fn test_primitives() {
|
|||
!8 = !{}
|
||||
!9 = !DILocation(line: 1, column: 9, scope: !4)
|
||||
!10 = !DILocation(line: 2, column: 15, scope: !4)
|
||||
!11 = !DILocation(line: 2, column: 5, scope: !4)
|
||||
!12 = !DILocation(line: 2, column: 22, scope: !4)
|
||||
!13 = !DILocation(line: 0, scope: !4)
|
||||
!14 = !DILocation(line: 3, column: 8, scope: !4)
|
||||
!11 = !DILocation(line: 0, scope: !4)
|
||||
!12 = !DILocation(line: 3, column: 8, scope: !4)
|
||||
"}
|
||||
.trim();
|
||||
assert_eq!(expected, module.print_to_string().to_str().unwrap().trim());
|
||||
})));
|
||||
|
||||
Target::initialize_all(&InitializationConfig::default());
|
||||
|
||||
let llvm_options = CodeGenLLVMOptions {
|
||||
opt_level: OptimizationLevel::Default,
|
||||
target: CodeGenTargetMachineOptions::from_host_triple(),
|
||||
emit_llvm: false,
|
||||
};
|
||||
let (registry, handles) = WorkerRegistry::create_workers(
|
||||
threads,
|
||||
|
@ -373,22 +367,26 @@ fn test_simple_call() {
|
|||
; ModuleID = 'test'
|
||||
source_filename = \"test\"
|
||||
|
||||
define i32 @testing(i32 %0) !dbg !5 {
|
||||
; Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn
|
||||
define i32 @testing(i32 %0) local_unnamed_addr #0 !dbg !5 {
|
||||
init:
|
||||
%call = call i32 @foo.0(i32 %0), !dbg !10
|
||||
%mul = mul i32 %call, 2, !dbg !11
|
||||
ret i32 %mul, !dbg !11
|
||||
%add.i = shl i32 %0, 1, !dbg !10
|
||||
%mul = add i32 %add.i, 2, !dbg !10
|
||||
ret i32 %mul, !dbg !10
|
||||
}
|
||||
|
||||
define i32 @foo.0(i32 %0) !dbg !12 {
|
||||
|
||||
; Function Attrs: mustprogress nofree norecurse nosync nounwind readnone willreturn
|
||||
define i32 @foo.0(i32 %0) local_unnamed_addr #0 !dbg !11 {
|
||||
init:
|
||||
%add = add i32 %0, 1, !dbg !13
|
||||
ret i32 %add, !dbg !13
|
||||
%add = add i32 %0, 1, !dbg !12
|
||||
ret i32 %add, !dbg !12
|
||||
}
|
||||
|
||||
|
||||
attributes #0 = { mustprogress nofree norecurse nosync nounwind readnone willreturn }
|
||||
|
||||
!llvm.module.flags = !{!0, !1}
|
||||
!llvm.dbg.cu = !{!2, !4}
|
||||
|
||||
|
||||
!0 = !{i32 2, !\"Debug Info Version\", i32 3}
|
||||
!1 = !{i32 2, !\"Dwarf Version\", i32 4}
|
||||
!2 = distinct !DICompileUnit(language: DW_LANG_Python, file: !3, producer: \"NAC3\", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug)
|
||||
|
@ -399,19 +397,19 @@ fn test_simple_call() {
|
|||
!7 = !{!8}
|
||||
!8 = !DIBasicType(name: \"_\", flags: DIFlagPublic)
|
||||
!9 = !{}
|
||||
!10 = !DILocation(line: 1, column: 9, scope: !5)
|
||||
!11 = !DILocation(line: 2, column: 12, scope: !5)
|
||||
!12 = distinct !DISubprogram(name: \"foo.0\", linkageName: \"foo.0\", scope: null, file: !3, line: 1, type: !6, scopeLine: 1, flags: DIFlagPublic, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !4, retainedNodes: !9)
|
||||
!13 = !DILocation(line: 1, column: 12, scope: !12)
|
||||
!10 = !DILocation(line: 2, column: 12, scope: !5)
|
||||
!11 = distinct !DISubprogram(name: \"foo.0\", linkageName: \"foo.0\", scope: null, file: !3, line: 1, type: !6, scopeLine: 1, flags: DIFlagPublic, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !4, retainedNodes: !9)
|
||||
!12 = !DILocation(line: 1, column: 12, scope: !11)
|
||||
"}
|
||||
.trim();
|
||||
assert_eq!(expected, module.print_to_string().to_str().unwrap().trim());
|
||||
})));
|
||||
|
||||
Target::initialize_all(&InitializationConfig::default());
|
||||
|
||||
let llvm_options = CodeGenLLVMOptions {
|
||||
opt_level: OptimizationLevel::Default,
|
||||
target: CodeGenTargetMachineOptions::from_host_triple(),
|
||||
emit_llvm: false,
|
||||
};
|
||||
let (registry, handles) = WorkerRegistry::create_workers(
|
||||
threads,
|
||||
|
|
|
@ -59,6 +59,7 @@ impl Display for SymbolValue {
|
|||
}
|
||||
|
||||
pub trait StaticValue {
|
||||
/// Returns a unique identifier for this value.
|
||||
fn get_unique_identifier(&self) -> u64;
|
||||
|
||||
fn get_const_obj<'ctx, 'a>(
|
||||
|
@ -67,6 +68,7 @@ pub trait StaticValue {
|
|||
generator: &mut dyn CodeGenerator,
|
||||
) -> BasicValueEnum<'ctx>;
|
||||
|
||||
/// Converts this value to a LLVM [BasicValueEnum].
|
||||
fn to_basic_value_enum<'ctx, 'a>(
|
||||
&self,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
|
@ -74,12 +76,14 @@ pub trait StaticValue {
|
|||
expected_ty: Type,
|
||||
) -> Result<BasicValueEnum<'ctx>, String>;
|
||||
|
||||
/// Returns a field within this value.
|
||||
fn get_field<'ctx, 'a>(
|
||||
&self,
|
||||
name: StrRef,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
) -> Option<ValueEnum<'ctx>>;
|
||||
|
||||
/// Returns a single element of this tuple.
|
||||
fn get_tuple_element<'ctx>(&self, index: u32) -> Option<ValueEnum<'ctx>>;
|
||||
}
|
||||
|
||||
|
|
|
@ -1013,6 +1013,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||
.build_gep_and_load(
|
||||
arg.into_pointer_value(),
|
||||
&[zero, int32.const_int(1, false)],
|
||||
None,
|
||||
)
|
||||
.into_int_value();
|
||||
if len.get_type().get_bit_width() != 32 {
|
||||
|
@ -1049,7 +1050,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||
let uint32 = ctx.primitives.uint32;
|
||||
let uint64 = ctx.primitives.uint64;
|
||||
let float = ctx.primitives.float;
|
||||
let llvm_i1 = ctx.ctx.bool_type().as_basic_type_enum();
|
||||
let llvm_i8 = ctx.ctx.i8_type().as_basic_type_enum();
|
||||
let llvm_i32 = ctx.ctx.i32_type().as_basic_type_enum();
|
||||
let llvm_i64 = ctx.ctx.i64_type().as_basic_type_enum();
|
||||
let llvm_f64 = ctx.ctx.f64_type().as_basic_type_enum();
|
||||
|
@ -1059,7 +1060,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||
let n_val = args[1].1.clone().to_basic_value_enum(ctx, generator, n_ty)?;
|
||||
let mut is_type = |a: Type, b: Type| ctx.unifier.unioned(a, b);
|
||||
let (fun_name, arg_ty) = if is_type(m_ty, n_ty) && is_type(n_ty, boolean) {
|
||||
("llvm.umin.i1", llvm_i1)
|
||||
("llvm.umin.i8", llvm_i8)
|
||||
} else if is_type(m_ty, n_ty) && is_type(n_ty, int32) {
|
||||
("llvm.smin.i32", llvm_i32)
|
||||
} else if is_type(m_ty, n_ty) && is_type(n_ty, int64) {
|
||||
|
@ -1111,7 +1112,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||
let uint32 = ctx.primitives.uint32;
|
||||
let uint64 = ctx.primitives.uint64;
|
||||
let float = ctx.primitives.float;
|
||||
let llvm_i1 = ctx.ctx.bool_type().as_basic_type_enum();
|
||||
let llvm_i8 = ctx.ctx.i8_type().as_basic_type_enum();
|
||||
let llvm_i32 = ctx.ctx.i32_type().as_basic_type_enum();
|
||||
let llvm_i64 = ctx.ctx.i64_type().as_basic_type_enum();
|
||||
let llvm_f64 = ctx.ctx.f64_type().as_basic_type_enum();
|
||||
|
@ -1121,7 +1122,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||
let n_val = args[1].1.clone().to_basic_value_enum(ctx, generator, n_ty)?;
|
||||
let mut is_type = |a: Type, b: Type| ctx.unifier.unioned(a, b);
|
||||
let (fun_name, arg_ty) = if is_type(m_ty, n_ty) && is_type(n_ty, boolean) {
|
||||
("llvm.umax.i1", llvm_i1)
|
||||
("llvm.umax.i8", llvm_i8)
|
||||
} else if is_type(m_ty, n_ty) && is_type(n_ty, int32) {
|
||||
("llvm.smax.i32", llvm_i32)
|
||||
} else if is_type(m_ty, n_ty) && is_type(n_ty, int64) {
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define min(a, b) \
|
||||
({ \
|
||||
__typeof__(a) _a = (a); \
|
||||
__typeof__(b) _b = (b); \
|
||||
_a < _b ? _a : _b; \
|
||||
})
|
||||
|
||||
#if __SIZEOF_POINTER__ == 8
|
||||
#define usize uint64_t
|
||||
#elif __SIZEOF_POINTER__ == 4
|
||||
#define usize uint32_t
|
||||
#elif __SIZEOF_POINTER__ == 2
|
||||
#define usize uint16_t
|
||||
#endif
|
||||
|
||||
void output_int32(const int32_t x) {
|
||||
printf("%d\n", x);
|
||||
}
|
||||
|
||||
void output_int64(const int64_t x) {
|
||||
printf("%ld\n", x);
|
||||
}
|
||||
|
||||
void output_uint32(const uint32_t x) {
|
||||
printf("%d\n", x);
|
||||
}
|
||||
|
||||
void output_uint64(const uint64_t x) {
|
||||
printf("%ld\n", x);
|
||||
}
|
||||
|
||||
void output_asciiart(const int32_t x) {
|
||||
const char* chars = " .,-:;i+hHM$*#@ ";
|
||||
if (x < 0) {
|
||||
fputc('\n', stdout);
|
||||
} else {
|
||||
fputc(chars[x], stdout);
|
||||
}
|
||||
}
|
||||
|
||||
struct cslice_int32 {
|
||||
const int32_t* data;
|
||||
usize len;
|
||||
};
|
||||
|
||||
void output_int32_list(struct cslice_int32* slice) {
|
||||
fputc('[', stdout);
|
||||
for (usize i = 0; i < slice->len; ++i) {
|
||||
if (i == slice->len - 1) {
|
||||
printf("%d", slice->data[i]);
|
||||
} else {
|
||||
printf("%d, ", slice->data[i]);
|
||||
}
|
||||
}
|
||||
puts("]");
|
||||
}
|
||||
|
||||
uint32_t __nac3_personality(
|
||||
__attribute__((unused)) uint32_t state,
|
||||
__attribute__((unused)) uint32_t exception_object,
|
||||
__attribute__((unused)) uint32_t context) {
|
||||
assert(false && "__nac3_personality not implemented");
|
||||
exit(101);
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
uint32_t __nac3_raise(uint32_t state, uint32_t exception_object, uint32_t context) {
|
||||
printf("__nac3_raise(state: %x, exception_object: %x, context: %x\n", state, exception_object, context);
|
||||
exit(101);
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
extern int32_t run();
|
||||
|
||||
int main() {
|
||||
run();
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
echo "No argument supplied"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -e ../../target/release/nac3standalone ]; then
|
||||
nac3standalone=../../target/release/nac3standalone
|
||||
else
|
||||
# used by Nix builds
|
||||
nac3standalone=../../target/x86_64-unknown-linux-gnu/release/nac3standalone
|
||||
fi
|
||||
|
||||
rm -f *.o *.bc
|
||||
$nac3standalone --emit-llvm "$@"
|
||||
gcc -c -std=c11 -Wall -Wextra -pedantic-errors -Werror=pedantic -O3 -o demo.o demo.c
|
||||
clang -S -Wall -Wextra -O3 -emit-llvm -o irrt.bc ../../nac3core/src/codegen/irrt/irrt.c
|
||||
lli --extra-object demo.o --extra-module irrt.bc main.bc
|
|
@ -0,0 +1,30 @@
|
|||
# Different cases for using boolean variables in boolean contexts.
|
||||
# Tests whether all boolean variables (expressed as i8s) are lowered into i1s before used in branching instruction (`br`)
|
||||
|
||||
def bfunc(b: bool) -> bool:
|
||||
return not b
|
||||
|
||||
def run() -> int32:
|
||||
b1 = True
|
||||
b2 = False
|
||||
|
||||
if b1:
|
||||
pass
|
||||
|
||||
if not b2:
|
||||
pass
|
||||
|
||||
while b2:
|
||||
pass
|
||||
|
||||
l = [i for i in range(10) if b2]
|
||||
|
||||
b_and = True and False
|
||||
b_or = True or False
|
||||
|
||||
b_and = b1 and b2
|
||||
b_or = b1 or b2
|
||||
|
||||
bfunc(b1)
|
||||
|
||||
return 0
|
|
@ -0,0 +1,17 @@
|
|||
@extern
|
||||
def output_int32(x: int32):
|
||||
...
|
||||
|
||||
@extern
|
||||
def output_int32_list(x: list[int32]):
|
||||
...
|
||||
|
||||
def run() -> int32:
|
||||
bl = [True, False]
|
||||
|
||||
bl1 = bl[:]
|
||||
bl1[1:] = [True]
|
||||
output_int32_list([int32(b) for b in bl1])
|
||||
output_int32_list([int32(b) for b in bl1])
|
||||
|
||||
return 0
|
|
@ -305,7 +305,6 @@ fn main() {
|
|||
features: target_features,
|
||||
..host_target_machine
|
||||
},
|
||||
emit_llvm,
|
||||
};
|
||||
|
||||
let task = CodeGenTask {
|
||||
|
@ -340,11 +339,19 @@ fn main() {
|
|||
let main = context
|
||||
.create_module_from_ir(MemoryBuffer::create_from_memory_range(&buffers[0], "main"))
|
||||
.unwrap();
|
||||
for buffer in buffers.iter().skip(1) {
|
||||
if emit_llvm {
|
||||
main.write_bitcode_to_path(Path::new("main.bc"));
|
||||
}
|
||||
|
||||
for (idx, buffer) in buffers.iter().skip(1).enumerate() {
|
||||
let other = context
|
||||
.create_module_from_ir(MemoryBuffer::create_from_memory_range(buffer, "main"))
|
||||
.unwrap();
|
||||
|
||||
if emit_llvm {
|
||||
other.write_bitcode_to_path(Path::new(&format!("module{}.bc", idx)));
|
||||
}
|
||||
|
||||
main.link_in_module(other).unwrap();
|
||||
}
|
||||
main.link_in_module(load_irrt(&context)).unwrap();
|
||||
|
|
Loading…
Reference in New Issue