initial commit
This commit is contained in:
commit
38d2bc6e45
11 changed files with 1581 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/target
|
||||
603
Cargo.lock
generated
Normal file
603
Cargo.lock
generated
Normal file
|
|
@ -0,0 +1,603 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "allocator-api2"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon",
|
||||
"colorchoice",
|
||||
"is_terminal_polyfill",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "3.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"once_cell_polyfill",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.20.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"strsim",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9"
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-bitset"
|
||||
version = "0.130.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81fb5b134a12b559ff0c0f5af0fcd755ad380723b5016c4e0d36f74d39485340"
|
||||
dependencies = [
|
||||
"wasmtime-internal-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-entity"
|
||||
version = "0.130.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "463feed5d46cf8763f3ba3045284cf706dd161496e20ec9c14afbb4ba09b9e66"
|
||||
dependencies = [
|
||||
"cranelift-bitset",
|
||||
"wasmtime-internal-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||
|
||||
[[package]]
|
||||
name = "egg"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd40cfd4196d7a8f882ace95d623d4d6734588e502b4e188675a7c2f55eb4fb4"
|
||||
dependencies = [
|
||||
"env_logger",
|
||||
"hashbrown 0.15.5",
|
||||
"indexmap",
|
||||
"log",
|
||||
"num-bigint",
|
||||
"num-traits",
|
||||
"quanta",
|
||||
"rustc-hash",
|
||||
"smallvec",
|
||||
"symbol_table",
|
||||
"symbolic_expressions",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7"
|
||||
dependencies = [
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||
|
||||
[[package]]
|
||||
name = "fixedbitset"
|
||||
version = "0.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
|
||||
|
||||
[[package]]
|
||||
name = "foldhash"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
||||
|
||||
[[package]]
|
||||
name = "foldhash"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
|
||||
dependencies = [
|
||||
"allocator-api2",
|
||||
"equivalent",
|
||||
"foldhash 0.1.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.16.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
|
||||
dependencies = [
|
||||
"foldhash 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.16.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.70.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.94"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.184"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af"
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
|
||||
dependencies = [
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.46"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell_polyfill"
|
||||
version = "1.70.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
|
||||
|
||||
[[package]]
|
||||
name = "petgraph"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455"
|
||||
dependencies = [
|
||||
"fixedbitset",
|
||||
"hashbrown 0.15.5",
|
||||
"indexmap",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quanta"
|
||||
version = "0.12.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3ab5a9d756f0d97bdc89019bd2e4ea098cf9cde50ee7564dde6b81ccc8f06c7"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"raw-cpuid",
|
||||
"wasi",
|
||||
"web-sys",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "raw-cpuid"
|
||||
version = "11.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "2.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe"
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_core"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slonik"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"cranelift-entity",
|
||||
"egg",
|
||||
"petgraph",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.15.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "symbol_table"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f19bffd69fb182e684d14e3c71d04c0ef33d1641ac0b9e81c712c734e83703bc"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
"foldhash 0.1.5",
|
||||
"hashbrown 0.15.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "symbolic_expressions"
|
||||
version = "5.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c68d531d83ec6c531150584c42a4290911964d5f0d79132b193b67252a23b71"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
|
||||
dependencies = [
|
||||
"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]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.1+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"rustversion",
|
||||
"wasm-bindgen-macro",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasmtime-internal-core"
|
||||
version = "43.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e671917bb6856ae360cb59d7aaf26f1cfd042c7b924319dd06fd380739fc0b2e"
|
||||
dependencies = [
|
||||
"hashbrown 0.16.1",
|
||||
"libm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.94"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd70027e39b12f0849461e08ffc50b9cd7688d942c1c8e3c7b22273236b4dd0a"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
11
Cargo.toml
Normal file
11
Cargo.toml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "slonik"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.6.0", features = ["derive"] }
|
||||
cranelift-entity = "0.130.0"
|
||||
egg = "0.11.0"
|
||||
petgraph = "0.8.3"
|
||||
smallvec = "1.15.1"
|
||||
30
src/arch.rs
Normal file
30
src/arch.rs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// pub trait Architecture {
|
||||
// type Mode: Copy + Eq + Send + Sync + 'static;
|
||||
// type DecodedInstruction: Send + Sync + 'static;
|
||||
|
||||
// fn name(&self) -> &'static str;
|
||||
|
||||
// fn decode(
|
||||
// &self,
|
||||
// bytes: &[u8],
|
||||
// addr: u64,
|
||||
// mode: Self::Mode,
|
||||
// ) -> Result<(usize, Self::DecodedInstruction), DecodeError>;
|
||||
|
||||
// fn lift(
|
||||
// &self,
|
||||
// insn: &Self::DecodedInstruction,
|
||||
// addr: u64,
|
||||
// mode: Self::Mode,
|
||||
// b: &mut Builder,
|
||||
// ) -> Result<InstructionInfo, LiftError>;
|
||||
|
||||
// fn registers(&self) -> &'static [RegisterDesc];
|
||||
// fn flags(&self) -> &'static [FlagDesc];
|
||||
// }
|
||||
|
||||
// pub struct InsnInfo {
|
||||
// pub len: u8,
|
||||
// pub branches: smallvec::SmallVec<[Branch; 2]>,
|
||||
// pub terminates_block: bool,
|
||||
// }
|
||||
42
src/ir.rs
Normal file
42
src/ir.rs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
//! Slonik normalized SSA IR.
|
||||
|
||||
mod dfg;
|
||||
mod inst;
|
||||
mod ty;
|
||||
|
||||
pub use dfg::*;
|
||||
pub use inst::*;
|
||||
pub use ty::*;
|
||||
|
||||
/// Defines a thin `u32` entity handle.
|
||||
///
|
||||
/// Slonik uses dense numeric handles instead of pointer-heavy nodes. This keeps
|
||||
/// the IR compact, stable under mutation, and easy to store in `PrimaryMap` /
|
||||
/// `SecondaryMap`.
|
||||
macro_rules! entity {
|
||||
(
|
||||
$(
|
||||
$(#[$meta:meta])*
|
||||
$vis:vis struct $name:ident = $prefix:literal;
|
||||
)*
|
||||
) => {
|
||||
$(
|
||||
$(#[$meta])*
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
$vis struct $name(u32);
|
||||
|
||||
cranelift_entity::entity_impl!($name, $prefix);
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
entity! {
|
||||
/// A handle to a basic block in a `Body`.
|
||||
pub struct Block = "block";
|
||||
|
||||
/// A handle to an instruction in a `Body`.
|
||||
pub struct Inst = "inst";
|
||||
|
||||
/// A handle to an SSA value.
|
||||
pub struct Value = "v";
|
||||
}
|
||||
1
src/ir/dfg.rs
Normal file
1
src/ir/dfg.rs
Normal file
|
|
@ -0,0 +1 @@
|
|||
|
||||
413
src/ir/inst.rs
Normal file
413
src/ir/inst.rs
Normal file
|
|
@ -0,0 +1,413 @@
|
|||
//! Instruction opcodes and instruction data formats for Slonik.
|
||||
|
||||
use core::fmt;
|
||||
use cranelift_entity::EntityList;
|
||||
|
||||
use crate::ir::{Block, Inst, Type, Value};
|
||||
|
||||
/// A compact list of SSA values.
|
||||
///
|
||||
/// These lists are stored in a `ListPool` owned by the data-flow graph.
|
||||
pub type ValueList = EntityList<Value>;
|
||||
|
||||
/// A compact list of blocks.
|
||||
///
|
||||
/// This is primarily useful for generic control-flow helpers and side tables.
|
||||
pub type BlockList = EntityList<Block>;
|
||||
|
||||
/// A target block together with the SSA arguments passed to that block.
|
||||
///
|
||||
/// Slonik IR uses block arguments instead of phi nodes. A terminator that
|
||||
/// transfers control to a block also provides the values for that block's
|
||||
/// parameters.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct BlockCall {
|
||||
/// The destination block.
|
||||
pub block: Block,
|
||||
|
||||
/// The arguments passed to the destination block.
|
||||
pub args: ValueList,
|
||||
}
|
||||
|
||||
/// Integer comparison condition codes.
|
||||
///
|
||||
/// These are used by `Opcode::Icmp`.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum IntCC {
|
||||
/// Equal.
|
||||
Eq,
|
||||
|
||||
/// Not equal.
|
||||
Ne,
|
||||
|
||||
/// Unsigned less than.
|
||||
Ult,
|
||||
|
||||
/// Unsigned less than or equal.
|
||||
Ule,
|
||||
|
||||
/// Unsigned greater than.
|
||||
Ugt,
|
||||
|
||||
/// Unsigned greater than or equal.
|
||||
Uge,
|
||||
|
||||
/// Signed less than.
|
||||
Slt,
|
||||
|
||||
/// Signed less than or equal.
|
||||
Sle,
|
||||
|
||||
/// Signed greater than.
|
||||
Sgt,
|
||||
|
||||
/// Signed greater than or equal.
|
||||
Sge,
|
||||
}
|
||||
|
||||
impl IntCC {
|
||||
/// Returns the logical inverse of this condition code.
|
||||
pub const fn invert(self) -> Self {
|
||||
match self {
|
||||
Self::Eq => Self::Ne,
|
||||
Self::Ne => Self::Eq,
|
||||
Self::Ult => Self::Uge,
|
||||
Self::Ule => Self::Ugt,
|
||||
Self::Ugt => Self::Ule,
|
||||
Self::Uge => Self::Ult,
|
||||
Self::Slt => Self::Sge,
|
||||
Self::Sle => Self::Sgt,
|
||||
Self::Sgt => Self::Sle,
|
||||
Self::Sge => Self::Slt,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the condition code with operands swapped.
|
||||
pub const fn swap_args(self) -> Self {
|
||||
match self {
|
||||
Self::Eq => Self::Eq,
|
||||
Self::Ne => Self::Ne,
|
||||
Self::Ult => Self::Ugt,
|
||||
Self::Ule => Self::Uge,
|
||||
Self::Ugt => Self::Ult,
|
||||
Self::Uge => Self::Ule,
|
||||
Self::Slt => Self::Sgt,
|
||||
Self::Sle => Self::Sge,
|
||||
Self::Sgt => Self::Slt,
|
||||
Self::Sge => Self::Sle,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for IntCC {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let s = match self {
|
||||
Self::Eq => "eq",
|
||||
Self::Ne => "ne",
|
||||
Self::Ult => "ult",
|
||||
Self::Ule => "ule",
|
||||
Self::Ugt => "ugt",
|
||||
Self::Uge => "uge",
|
||||
Self::Slt => "slt",
|
||||
Self::Sle => "sle",
|
||||
Self::Sgt => "sgt",
|
||||
Self::Sge => "sge",
|
||||
};
|
||||
|
||||
f.write_str(s)
|
||||
}
|
||||
}
|
||||
|
||||
/// The set of operations that generic analysis and decompilation passes
|
||||
/// are expected to understand.
|
||||
///
|
||||
/// If a frontend encounters something that does not fit naturally here, that is
|
||||
/// a sign it should stay in the lifted IR longer or be lowered through a helper
|
||||
/// sequence before entering this IR.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum Opcode {
|
||||
Iconst,
|
||||
F32const,
|
||||
F64const,
|
||||
Bconst,
|
||||
|
||||
Zext,
|
||||
Sext,
|
||||
Trunc,
|
||||
Bitcast,
|
||||
|
||||
Iadd,
|
||||
Isub,
|
||||
Imul,
|
||||
Udiv,
|
||||
Sdiv,
|
||||
Urem,
|
||||
Srem,
|
||||
|
||||
And,
|
||||
Or,
|
||||
Xor,
|
||||
Not,
|
||||
|
||||
Shl,
|
||||
Lshr,
|
||||
Ashr,
|
||||
|
||||
Fadd,
|
||||
Fsub,
|
||||
Fmul,
|
||||
Fdiv,
|
||||
Fneg,
|
||||
|
||||
Icmp,
|
||||
Select,
|
||||
|
||||
Load,
|
||||
Store,
|
||||
|
||||
Jump,
|
||||
BrIf,
|
||||
Call,
|
||||
Return,
|
||||
}
|
||||
|
||||
impl Opcode {
|
||||
/// Returns the textual name of this opcode.
|
||||
pub const fn name(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Iconst => "iconst",
|
||||
Self::F32const => "f32const",
|
||||
Self::F64const => "f64const",
|
||||
Self::Bconst => "bconst",
|
||||
|
||||
Self::Zext => "zext",
|
||||
Self::Sext => "sext",
|
||||
Self::Trunc => "trunc",
|
||||
Self::Bitcast => "bitcast",
|
||||
|
||||
Self::Iadd => "iadd",
|
||||
Self::Isub => "isub",
|
||||
Self::Imul => "imul",
|
||||
Self::Udiv => "udiv",
|
||||
Self::Sdiv => "sdiv",
|
||||
Self::Urem => "urem",
|
||||
Self::Srem => "srem",
|
||||
|
||||
Self::And => "and",
|
||||
Self::Or => "or",
|
||||
Self::Xor => "xor",
|
||||
Self::Not => "not",
|
||||
|
||||
Self::Shl => "shl",
|
||||
Self::Lshr => "lshr",
|
||||
Self::Ashr => "ashr",
|
||||
|
||||
Self::Fadd => "fadd",
|
||||
Self::Fsub => "fsub",
|
||||
Self::Fmul => "fmul",
|
||||
Self::Fdiv => "fdiv",
|
||||
Self::Fneg => "fneg",
|
||||
|
||||
Self::Icmp => "icmp",
|
||||
Self::Select => "select",
|
||||
|
||||
Self::Load => "load",
|
||||
Self::Store => "store",
|
||||
|
||||
Self::Jump => "jump",
|
||||
Self::BrIf => "br_if",
|
||||
Self::Call => "call",
|
||||
Self::Return => "return",
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether this opcode is a terminator.
|
||||
pub const fn is_terminator(self) -> bool {
|
||||
matches!(self, Self::Jump | Self::BrIf | Self::Return)
|
||||
}
|
||||
|
||||
/// Returns whether this opcode may read memory.
|
||||
pub const fn may_read_memory(self) -> bool {
|
||||
matches!(self, Self::Load | Self::Call)
|
||||
}
|
||||
|
||||
/// Returns whether this opcode may write memory.
|
||||
pub const fn may_write_memory(self) -> bool {
|
||||
matches!(self, Self::Store | Self::Call)
|
||||
}
|
||||
|
||||
/// Returns whether this opcode is side-effecting.
|
||||
pub const fn has_side_effects(self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
Self::Store | Self::Jump | Self::BrIf | Self::Call | Self::Return
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Opcode {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(self.name())
|
||||
}
|
||||
}
|
||||
|
||||
/// A memory access size in bytes.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum MemSize {
|
||||
S1,
|
||||
S2,
|
||||
S4,
|
||||
S8,
|
||||
S16,
|
||||
}
|
||||
|
||||
impl MemSize {
|
||||
/// Returns the memory access width in bytes.
|
||||
pub const fn bytes(self) -> u8 {
|
||||
match self {
|
||||
Self::S1 => 1,
|
||||
Self::S2 => 2,
|
||||
Self::S4 => 4,
|
||||
Self::S8 => 8,
|
||||
Self::S16 => 16,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the memory access width in bits.
|
||||
pub const fn bits(self) -> u16 {
|
||||
// TODO: Some machines may have different byte sizes.
|
||||
(self.bytes() as u16) * 8
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for MemSize {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}B", self.bytes())
|
||||
}
|
||||
}
|
||||
|
||||
/// The payload of an instruction.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub enum InstructionData {
|
||||
/// A zero-operand instruction with no embedded immediate.
|
||||
Nullary { opcode: Opcode },
|
||||
|
||||
/// A constant instruction holding an `i64` immediate.
|
||||
Iconst { opcode: Opcode, imm: i64 },
|
||||
|
||||
/// A constant instruction holding a 32-bit floating-point bit pattern.
|
||||
///
|
||||
/// The value is stored as raw IEEE-754 bits.
|
||||
F32const { opcode: Opcode, bits: u32 },
|
||||
|
||||
/// A constant instruction holding a 64-bit floating-point bit pattern.
|
||||
///
|
||||
/// The value is stored as raw IEEE-754 bits.
|
||||
F64const { opcode: Opcode, bits: u64 },
|
||||
|
||||
/// A boolean constant.
|
||||
Bconst { opcode: Opcode, value: bool },
|
||||
|
||||
/// A one-argument instruction.
|
||||
Unary { opcode: Opcode, arg: Value },
|
||||
|
||||
/// A two-argument instruction.
|
||||
Binary { opcode: Opcode, args: [Value; 2] },
|
||||
|
||||
/// A three-argument instruction.
|
||||
///
|
||||
/// This is primarily useful for operations like `select`.
|
||||
Ternary { opcode: Opcode, args: [Value; 3] },
|
||||
|
||||
/// An integer comparison instruction.
|
||||
Icmp {
|
||||
opcode: Opcode,
|
||||
cc: IntCC,
|
||||
args: [Value; 2],
|
||||
},
|
||||
|
||||
/// A load from memory.
|
||||
Load {
|
||||
opcode: Opcode,
|
||||
addr: Value,
|
||||
size: MemSize,
|
||||
},
|
||||
|
||||
/// A store to memory.
|
||||
Store {
|
||||
opcode: Opcode,
|
||||
addr: Value,
|
||||
value: Value,
|
||||
size: MemSize,
|
||||
},
|
||||
|
||||
/// An unconditional branch to another block with block arguments.
|
||||
Jump { opcode: Opcode, dst: BlockCall },
|
||||
|
||||
/// A conditional branch with explicit true/false targets.
|
||||
// TODO: Introduce direct call references
|
||||
BrIf {
|
||||
opcode: Opcode,
|
||||
cond: Value,
|
||||
then_dst: BlockCall,
|
||||
else_dst: BlockCall,
|
||||
},
|
||||
|
||||
/// A call through a value.
|
||||
Call {
|
||||
opcode: Opcode,
|
||||
callee: Value,
|
||||
args: ValueList,
|
||||
},
|
||||
|
||||
/// A return from the current body.
|
||||
Return { opcode: Opcode, values: ValueList },
|
||||
}
|
||||
|
||||
impl InstructionData {
|
||||
/// Returns the opcode of this instruction.
|
||||
pub const fn opcode(&self) -> Opcode {
|
||||
match *self {
|
||||
Self::Nullary { opcode }
|
||||
| Self::Iconst { opcode, .. }
|
||||
| Self::F32const { opcode, .. }
|
||||
| Self::F64const { opcode, .. }
|
||||
| Self::Bconst { opcode, .. }
|
||||
| Self::Unary { opcode, .. }
|
||||
| Self::Binary { opcode, .. }
|
||||
| Self::Ternary { opcode, .. }
|
||||
| Self::Icmp { opcode, .. }
|
||||
| Self::Load { opcode, .. }
|
||||
| Self::Store { opcode, .. }
|
||||
| Self::Jump { opcode, .. }
|
||||
| Self::BrIf { opcode, .. }
|
||||
| Self::Call { opcode, .. }
|
||||
| Self::Return { opcode, .. } => opcode,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether this instruction is a terminator.
|
||||
pub const fn is_terminator(&self) -> bool {
|
||||
self.opcode().is_terminator()
|
||||
}
|
||||
}
|
||||
|
||||
/// The definition site of an SSA value.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum ValueDef {
|
||||
/// A value produced as result `index` of an instruction.
|
||||
Result(Inst, u16),
|
||||
|
||||
/// A block parameter at position `index`.
|
||||
Param(Block, u16),
|
||||
}
|
||||
|
||||
/// Type information attached to a value in the data-flow graph.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct ValueData {
|
||||
/// The semantic type of the value.
|
||||
pub ty: Type,
|
||||
|
||||
/// Where the value was defined.
|
||||
pub def: ValueDef,
|
||||
}
|
||||
451
src/ir/ty.rs
Normal file
451
src/ir/ty.rs
Normal file
|
|
@ -0,0 +1,451 @@
|
|||
//! Compact semantic types for Slonik IR.
|
||||
|
||||
use core::fmt;
|
||||
|
||||
/// A semantic type in Slonik.
|
||||
///
|
||||
/// `Type` describes the meaning and shape of an SSA value.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum Type {
|
||||
/// The absence of a value.
|
||||
///
|
||||
/// This should generally not appear as the type of an SSA `Value`.
|
||||
Void,
|
||||
|
||||
/// A one-bit boolean.
|
||||
Bool,
|
||||
|
||||
/// A signedness-agnostic integer bitvector.
|
||||
Int(IntType),
|
||||
|
||||
/// A floating-point scalar.
|
||||
Float(FloatType),
|
||||
|
||||
/// A raw bitvector with no numeric interpretation yet.
|
||||
Bits(BitsType),
|
||||
|
||||
/// A pointer value.
|
||||
Ptr(PtrType),
|
||||
|
||||
/// A fixed-length or scalable SIMD vector.
|
||||
Vector(VectorType),
|
||||
}
|
||||
|
||||
/// A fixed-width integer type.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct IntType {
|
||||
bits: u16,
|
||||
}
|
||||
|
||||
impl IntType {
|
||||
/// Creates a new integer type with the given width in bits.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `bits == 0`.
|
||||
pub const fn new(bits: u16) -> Self {
|
||||
assert!(bits != 0, "integer type must have nonzero width");
|
||||
Self { bits }
|
||||
}
|
||||
|
||||
/// Returns the integer width in bits.
|
||||
pub const fn bits(self) -> u16 {
|
||||
self.bits
|
||||
}
|
||||
}
|
||||
|
||||
/// A floating-point scalar type.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum FloatType {
|
||||
F16,
|
||||
F32,
|
||||
F64,
|
||||
F80,
|
||||
F128,
|
||||
}
|
||||
|
||||
impl FloatType {
|
||||
/// Returns the width of this floating-point type in bits.
|
||||
pub const fn bits(self) -> u16 {
|
||||
match self {
|
||||
Self::F16 => 16,
|
||||
Self::F32 => 32,
|
||||
Self::F64 => 64,
|
||||
Self::F80 => 80,
|
||||
Self::F128 => 128,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A raw uninterpreted bitvector type.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct BitsType {
|
||||
bits: u16,
|
||||
}
|
||||
|
||||
impl BitsType {
|
||||
/// Creates a new raw bitvector type with the given width.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `bits == 0`.
|
||||
pub const fn new(bits: u16) -> Self {
|
||||
assert!(bits != 0, "bitvector type must have nonzero width");
|
||||
Self { bits }
|
||||
}
|
||||
|
||||
/// Returns the width in bits.
|
||||
pub const fn bits(self) -> u16 {
|
||||
self.bits
|
||||
}
|
||||
}
|
||||
|
||||
/// A pointer type.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct PtrType {
|
||||
bits: u16,
|
||||
addr_space: u16,
|
||||
}
|
||||
|
||||
impl PtrType {
|
||||
/// Creates a new pointer type in address space 0.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `bits == 0`.
|
||||
pub const fn new(bits: u16) -> Self {
|
||||
Self::with_addr_space(bits, 0)
|
||||
}
|
||||
|
||||
/// Creates a new pointer type with an explicit address space.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `bits == 0`.
|
||||
pub const fn with_addr_space(bits: u16, addr_space: u16) -> Self {
|
||||
assert!(bits != 0, "pointer type must have nonzero width");
|
||||
Self { bits, addr_space }
|
||||
}
|
||||
|
||||
/// Returns the pointer width in bits.
|
||||
pub const fn bits(self) -> u16 {
|
||||
self.bits
|
||||
}
|
||||
|
||||
/// Returns the address space.
|
||||
pub const fn addr_space(self) -> u16 {
|
||||
self.addr_space
|
||||
}
|
||||
}
|
||||
|
||||
/// A scalar lane type for a vector.
|
||||
///
|
||||
/// Vector lanes are semantic scalar elements, not storage slots.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum LaneType {
|
||||
Bool,
|
||||
Int(IntType),
|
||||
Float(FloatType),
|
||||
Bits(BitsType),
|
||||
Ptr(PtrType),
|
||||
}
|
||||
|
||||
impl LaneType {
|
||||
/// Returns the width of one lane in bits.
|
||||
pub const fn bits(self) -> u16 {
|
||||
match self {
|
||||
Self::Bool => 1,
|
||||
Self::Int(ty) => ty.bits(),
|
||||
Self::Float(ty) => ty.bits(),
|
||||
Self::Bits(ty) => ty.bits(),
|
||||
Self::Ptr(ty) => ty.bits(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts this lane type into the corresponding scalar `Type`.
|
||||
pub const fn as_type(self) -> Type {
|
||||
match self {
|
||||
Self::Bool => Type::Bool,
|
||||
Self::Int(ty) => Type::Int(ty),
|
||||
Self::Float(ty) => Type::Float(ty),
|
||||
Self::Bits(ty) => Type::Bits(ty),
|
||||
Self::Ptr(ty) => Type::Ptr(ty),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A SIMD vector type.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct VectorType {
|
||||
lanes: u16,
|
||||
lane: LaneType,
|
||||
scalable: bool,
|
||||
}
|
||||
|
||||
impl VectorType {
|
||||
/// Creates a new fixed-length vector type.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `lanes == 0`.
|
||||
pub const fn new(lane: LaneType, lanes: u16) -> Self {
|
||||
assert!(lanes != 0, "vector type must have at least one lane");
|
||||
Self {
|
||||
lanes,
|
||||
lane,
|
||||
scalable: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new vector type with explicit scalability.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `lanes == 0`.
|
||||
pub const fn with_scalable(lane: LaneType, lanes: u16, scalable: bool) -> Self {
|
||||
assert!(lanes != 0, "vector type must have at least one lane");
|
||||
Self {
|
||||
lanes,
|
||||
lane,
|
||||
scalable,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the number of lanes.
|
||||
pub const fn lanes(self) -> u16 {
|
||||
self.lanes
|
||||
}
|
||||
|
||||
/// Returns the lane type.
|
||||
pub const fn lane(self) -> LaneType {
|
||||
self.lane
|
||||
}
|
||||
|
||||
/// Returns whether this is a scalable vector.
|
||||
pub const fn scalable(self) -> bool {
|
||||
self.scalable
|
||||
}
|
||||
|
||||
/// Returns the width of one lane in bits.
|
||||
pub const fn lane_bits(self) -> u16 {
|
||||
self.lane.bits()
|
||||
}
|
||||
|
||||
/// Returns the minimum number of bits in the vector.
|
||||
///
|
||||
/// For scalable vectors, this is the known minimum width.
|
||||
pub const fn min_bits(self) -> u32 {
|
||||
(self.lanes as u32) * (self.lane.bits() as u32)
|
||||
}
|
||||
}
|
||||
|
||||
impl Type {
|
||||
/// Returns `void`.
|
||||
pub const fn void() -> Self {
|
||||
Self::Void
|
||||
}
|
||||
|
||||
/// Returns `bool`.
|
||||
pub const fn bool() -> Self {
|
||||
Self::Bool
|
||||
}
|
||||
|
||||
/// Returns an integer type with the given width.
|
||||
pub const fn int(bits: u16) -> Self {
|
||||
Self::Int(IntType::new(bits))
|
||||
}
|
||||
|
||||
/// Returns a floating-point type.
|
||||
pub const fn float(kind: FloatType) -> Self {
|
||||
Self::Float(kind)
|
||||
}
|
||||
|
||||
/// Returns a raw bitvector type with the given width.
|
||||
pub const fn bits(bits: u16) -> Self {
|
||||
Self::Bits(BitsType::new(bits))
|
||||
}
|
||||
|
||||
/// Returns a pointer type in address space 0.
|
||||
pub const fn ptr(bits: u16) -> Self {
|
||||
Self::Ptr(PtrType::new(bits))
|
||||
}
|
||||
|
||||
/// Returns a pointer type with an explicit address space.
|
||||
pub const fn ptr_in(bits: u16, addr_space: u16) -> Self {
|
||||
Self::Ptr(PtrType::with_addr_space(bits, addr_space))
|
||||
}
|
||||
|
||||
/// Returns a fixed-length vector type.
|
||||
pub const fn vector(lane: LaneType, lanes: u16) -> Self {
|
||||
Self::Vector(VectorType::new(lane, lanes))
|
||||
}
|
||||
|
||||
/// Returns a vector type with explicit scalability.
|
||||
pub const fn vector_with_scalable(lane: LaneType, lanes: u16, scalable: bool) -> Self {
|
||||
Self::Vector(VectorType::with_scalable(lane, lanes, scalable))
|
||||
}
|
||||
|
||||
/// Returns whether this is `void`.
|
||||
pub const fn is_void(self) -> bool {
|
||||
matches!(self, Self::Void)
|
||||
}
|
||||
|
||||
/// Returns whether this is `bool`.
|
||||
pub const fn is_bool(self) -> bool {
|
||||
matches!(self, Self::Bool)
|
||||
}
|
||||
|
||||
/// Returns whether this is an integer.
|
||||
pub const fn is_int(self) -> bool {
|
||||
matches!(self, Self::Int(_))
|
||||
}
|
||||
|
||||
/// Returns whether this is a float.
|
||||
pub const fn is_float(self) -> bool {
|
||||
matches!(self, Self::Float(_))
|
||||
}
|
||||
|
||||
/// Returns whether this is a raw bitvector.
|
||||
pub const fn is_bits(self) -> bool {
|
||||
matches!(self, Self::Bits(_))
|
||||
}
|
||||
|
||||
/// Returns whether this is a pointer.
|
||||
pub const fn is_ptr(self) -> bool {
|
||||
matches!(self, Self::Ptr(_))
|
||||
}
|
||||
|
||||
/// Returns whether this is a vector.
|
||||
pub const fn is_vector(self) -> bool {
|
||||
matches!(self, Self::Vector(_))
|
||||
}
|
||||
|
||||
/// Returns whether this is any scalar type.
|
||||
pub const fn is_scalar(self) -> bool {
|
||||
!matches!(self, Self::Vector(_))
|
||||
}
|
||||
|
||||
/// Returns the scalar width in bits, if this is a scalar type.
|
||||
pub const fn bit_size(self) -> Option<u16> {
|
||||
match self {
|
||||
Self::Void => None,
|
||||
Self::Bool => Some(1),
|
||||
Self::Int(ty) => Some(ty.bits()),
|
||||
Self::Float(ty) => Some(ty.bits()),
|
||||
Self::Bits(ty) => Some(ty.bits()),
|
||||
Self::Ptr(ty) => Some(ty.bits()),
|
||||
Self::Vector(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the vector description, if this is a vector.
|
||||
pub const fn as_vector(self) -> Option<VectorType> {
|
||||
match self {
|
||||
Self::Vector(ty) => Some(ty),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the scalar lane type if this is a vector, otherwise `None`.
|
||||
pub const fn lane_type(self) -> Option<LaneType> {
|
||||
match self {
|
||||
Self::Vector(ty) => Some(ty.lane()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the number of lanes if this is a vector.
|
||||
pub const fn lanes(self) -> Option<u16> {
|
||||
match self {
|
||||
Self::Vector(ty) => Some(ty.lanes()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Convenience constructor for `i8`.
|
||||
pub const fn i8() -> Self {
|
||||
Self::int(8)
|
||||
}
|
||||
|
||||
/// Convenience constructor for `i16`.
|
||||
pub const fn i16() -> Self {
|
||||
Self::int(16)
|
||||
}
|
||||
|
||||
/// Convenience constructor for `i32`.
|
||||
pub const fn i32() -> Self {
|
||||
Self::int(32)
|
||||
}
|
||||
|
||||
/// Convenience constructor for `i64`.
|
||||
pub const fn i64() -> Self {
|
||||
Self::int(64)
|
||||
}
|
||||
|
||||
/// Convenience constructor for `i128`.
|
||||
pub const fn i128() -> Self {
|
||||
Self::int(128)
|
||||
}
|
||||
|
||||
/// Convenience constructor for `f32`.
|
||||
pub const fn f32() -> Self {
|
||||
Self::float(FloatType::F32)
|
||||
}
|
||||
|
||||
/// Convenience constructor for `f64`.
|
||||
pub const fn f64() -> Self {
|
||||
Self::float(FloatType::F64)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Type {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Type::Void => f.write_str("void"),
|
||||
Type::Bool => f.write_str("bool"),
|
||||
Type::Int(ty) => write!(f, "i{}", ty.bits()),
|
||||
Type::Float(FloatType::F16) => f.write_str("f16"),
|
||||
Type::Float(FloatType::F32) => f.write_str("f32"),
|
||||
Type::Float(FloatType::F64) => f.write_str("f64"),
|
||||
Type::Float(FloatType::F80) => f.write_str("f80"),
|
||||
Type::Float(FloatType::F128) => f.write_str("f128"),
|
||||
Type::Bits(ty) => write!(f, "b{}", ty.bits()),
|
||||
Type::Ptr(ty) => {
|
||||
if ty.addr_space() == 0 {
|
||||
write!(f, "ptr{}", ty.bits())
|
||||
} else {
|
||||
write!(f, "ptr{}@{}", ty.bits(), ty.addr_space())
|
||||
}
|
||||
}
|
||||
Type::Vector(ty) => {
|
||||
if ty.scalable() {
|
||||
write!(f, "vec<?x{} x {}>", ty.lanes(), ty.lane())
|
||||
} else {
|
||||
write!(f, "vec<{} x {}>", ty.lanes(), ty.lane())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for LaneType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
LaneType::Bool => f.write_str("bool"),
|
||||
LaneType::Int(ty) => write!(f, "i{}", ty.bits()),
|
||||
LaneType::Float(FloatType::F16) => f.write_str("f16"),
|
||||
LaneType::Float(FloatType::F32) => f.write_str("f32"),
|
||||
LaneType::Float(FloatType::F64) => f.write_str("f64"),
|
||||
LaneType::Float(FloatType::F80) => f.write_str("f80"),
|
||||
LaneType::Float(FloatType::F128) => f.write_str("f128"),
|
||||
LaneType::Bits(ty) => write!(f, "b{}", ty.bits()),
|
||||
LaneType::Ptr(ty) => {
|
||||
if ty.addr_space() == 0 {
|
||||
write!(f, "ptr{}", ty.bits())
|
||||
} else {
|
||||
write!(f, "ptr{}@{}", ty.bits(), ty.addr_space())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
27
src/main.rs
Normal file
27
src/main.rs
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
mod arch;
|
||||
mod ir;
|
||||
|
||||
use clap::{
|
||||
Parser,
|
||||
builder::{
|
||||
Styles,
|
||||
styling::{AnsiColor, Effects},
|
||||
},
|
||||
};
|
||||
|
||||
const STYLES: Styles = Styles::styled()
|
||||
.header(AnsiColor::Green.on_default().effects(Effects::BOLD))
|
||||
.usage(AnsiColor::Green.on_default().effects(Effects::BOLD))
|
||||
.literal(AnsiColor::Cyan.on_default().effects(Effects::BOLD))
|
||||
.placeholder(AnsiColor::Cyan.on_default());
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(name = "slonik", author)]
|
||||
#[command(about = "an experimental decompiler")]
|
||||
#[command(disable_version_flag = true, arg_required_else_help = true)]
|
||||
#[command(styles=STYLES)]
|
||||
struct Args {}
|
||||
|
||||
fn main() {
|
||||
let args = Args::parse();
|
||||
}
|
||||
1
src/x86.rs
Normal file
1
src/x86.rs
Normal file
|
|
@ -0,0 +1 @@
|
|||
mod state;
|
||||
1
src/x86/state.rs
Normal file
1
src/x86/state.rs
Normal file
|
|
@ -0,0 +1 @@
|
|||
|
||||
Loading…
Add table
Reference in a new issue