mirror of
https://github.com/kmc7468/cs420.git
synced 2025-12-15 15:08:52 +00:00
Prepare for Spring 2025.
This commit is contained in:
120
Cargo.lock
generated
120
Cargo.lock
generated
@@ -59,9 +59,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.6.0"
|
version = "2.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
@@ -77,9 +77,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.5.23"
|
version = "4.5.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84"
|
checksum = "92b7b18d71fad5313a1e320fa9897994228ce274b60faa4d694fe0ea89cd9e6d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap_builder",
|
"clap_builder",
|
||||||
"clap_derive",
|
"clap_derive",
|
||||||
@@ -87,9 +87,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_builder"
|
name = "clap_builder"
|
||||||
version = "4.5.23"
|
version = "4.5.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838"
|
checksum = "a35db2071778a7344791a4fb4f95308b5673d219dee3ae348b86642574ecc90c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstream",
|
"anstream",
|
||||||
"anstyle",
|
"anstyle",
|
||||||
@@ -99,9 +99,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_derive"
|
name = "clap_derive"
|
||||||
version = "4.5.18"
|
version = "4.5.28"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
|
checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@@ -145,13 +145,14 @@ checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.2.15"
|
version = "0.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"wasi",
|
"wasi",
|
||||||
|
"windows-targets",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -211,9 +212,9 @@ checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linux-raw-sys"
|
name = "linux-raw-sys"
|
||||||
version = "0.4.14"
|
version = "0.4.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
|
checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
@@ -226,15 +227,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.20.2"
|
version = "1.20.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
|
checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ordered-float"
|
name = "ordered-float"
|
||||||
version = "4.6.0"
|
version = "5.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951"
|
checksum = "e2c1f9f56e534ac6a9b8a4600bdf0f530fb393b5f393e7b4d03489c3cf0c3f01"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
@@ -272,14 +273,14 @@ version = "0.2.20"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
|
checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"zerocopy",
|
"zerocopy 0.7.35",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.92"
|
version = "1.0.93"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
|
checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
@@ -295,20 +296,20 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
version = "0.8.5"
|
version = "0.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
|
||||||
"rand_chacha",
|
"rand_chacha",
|
||||||
"rand_core",
|
"rand_core",
|
||||||
|
"zerocopy 0.8.18",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand_chacha"
|
name = "rand_chacha"
|
||||||
version = "0.3.1"
|
version = "0.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ppv-lite86",
|
"ppv-lite86",
|
||||||
"rand_core",
|
"rand_core",
|
||||||
@@ -316,18 +317,19 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand_core"
|
name = "rand_core"
|
||||||
version = "0.6.4"
|
version = "0.9.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
checksum = "a88e0da7a2c97baa202165137c158d0a2e824ac465d13d81046727b34cb247d3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom",
|
"getrandom",
|
||||||
|
"zerocopy 0.8.18",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "0.38.42"
|
version = "0.38.44"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85"
|
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"errno",
|
"errno",
|
||||||
@@ -344,9 +346,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.95"
|
version = "2.0.98"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "46f71c0377baf4ef1cc3e3402ded576dccc315800fbc62dfc7fe04b009773b4a"
|
checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -355,9 +357,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tempfile"
|
name = "tempfile"
|
||||||
version = "3.15.0"
|
version = "3.17.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704"
|
checksum = "22e5a0acb1f3f55f65cc4a866c361b2fb2a0ff6366785ae6fbb5f85df07ba230"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"fastrand",
|
"fastrand",
|
||||||
@@ -369,18 +371,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "2.0.9"
|
version = "2.0.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f072643fd0190df67a8bab670c20ef5d8737177d6ac6b2e9a236cb096206b2cc"
|
checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl",
|
"thiserror-impl",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror-impl"
|
name = "thiserror-impl"
|
||||||
version = "2.0.9"
|
version = "2.0.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7b50fa271071aae2e6ee85f842e2e28ba8cd2c5fb67f11fcb1fd70b276f9e7d4"
|
checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -389,9 +391,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.14"
|
version = "1.0.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
|
checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf8parse"
|
name = "utf8parse"
|
||||||
@@ -401,18 +403,21 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wait-timeout"
|
name = "wait-timeout"
|
||||||
version = "0.2.0"
|
version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
|
checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.11.0+wasi-snapshot-preview1"
|
version = "0.13.3+wasi-0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2"
|
||||||
|
dependencies = [
|
||||||
|
"wit-bindgen-rt",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
@@ -487,6 +492,15 @@ version = "0.52.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wit-bindgen-rt"
|
||||||
|
version = "0.33.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy"
|
name = "zerocopy"
|
||||||
version = "0.7.35"
|
version = "0.7.35"
|
||||||
@@ -494,7 +508,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
|
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"zerocopy-derive",
|
"zerocopy-derive 0.7.35",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy"
|
||||||
|
version = "0.8.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "79386d31a42a4996e3336b0919ddb90f81112af416270cff95b5f5af22b839c2"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy-derive 0.8.18",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -507,3 +530,14 @@ dependencies = [
|
|||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zerocopy-derive"
|
||||||
|
version = "0.8.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "76331675d372f91bf8d17e13afbd5fe639200b73d01f0fc748bb059f9cca2db7"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|||||||
14
Cargo.toml
14
Cargo.toml
@@ -5,7 +5,7 @@ authors = [
|
|||||||
"Chunmyong Park <chunmyong.park@kaist.ac.kr>",
|
"Chunmyong Park <chunmyong.park@kaist.ac.kr>",
|
||||||
"Jeehoon Kang <jeehoon.kang@kaist.ac.kr>",
|
"Jeehoon Kang <jeehoon.kang@kaist.ac.kr>",
|
||||||
]
|
]
|
||||||
edition = "2021"
|
edition = "2024"
|
||||||
default-run = "kecc"
|
default-run = "kecc"
|
||||||
|
|
||||||
description = "KAIST Educational C Compiler"
|
description = "KAIST Educational C Compiler"
|
||||||
@@ -32,13 +32,13 @@ required-features = ["build-bin"]
|
|||||||
build-bin = ["clap"]
|
build-bin = ["clap"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "4.5.23", features = ["derive"], optional = true }
|
clap = { version = "4.5.30", features = ["derive"], optional = true }
|
||||||
thiserror = "2.0.9"
|
thiserror = "2.0.11"
|
||||||
lang-c = "0.15.1"
|
lang-c = "0.15.1"
|
||||||
itertools = "0.14.0"
|
itertools = "0.14.0"
|
||||||
tempfile = "3.14.0"
|
tempfile = "3.17.1"
|
||||||
ordered-float = "4.6.0"
|
ordered-float = "5.0.0"
|
||||||
hexf-parse = "0.2.1"
|
hexf-parse = "0.2.1"
|
||||||
wait-timeout = "0.2.0"
|
wait-timeout = "0.2.1"
|
||||||
peg = "0.8.4"
|
peg = "0.8.4"
|
||||||
rand = "0.8.5"
|
rand = "0.9.0"
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ use std::process::{Command, Stdio};
|
|||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use kecc::{
|
use kecc::{
|
||||||
ir, ok_or_exit, write, Asmgen, Deadcode, Gvn, IrParse, IrVisualizer, Irgen, Mem2reg, Optimize,
|
Asmgen, Deadcode, Gvn, IrParse, IrVisualizer, Irgen, Mem2reg, O1, Optimize, Parse, SimplifyCfg,
|
||||||
Parse, SimplifyCfg, Translate, O1,
|
Translate, ir, ok_or_exit, write,
|
||||||
};
|
};
|
||||||
use lang_c::ast::TranslationUnit;
|
use lang_c::ast::TranslationUnit;
|
||||||
use tempfile::tempdir;
|
use tempfile::tempdir;
|
||||||
|
|||||||
9
examples/c/lost_copy.c
Normal file
9
examples/c/lost_copy.c
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
int main() {
|
||||||
|
int i = 0;
|
||||||
|
int result = 0;
|
||||||
|
do {
|
||||||
|
result = i;
|
||||||
|
i++;
|
||||||
|
} while (i < 4);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
10
examples/c/swap.c
Normal file
10
examples/c/swap.c
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
int main() {
|
||||||
|
int a = 1;
|
||||||
|
int b = 2;
|
||||||
|
do {
|
||||||
|
int t = a;
|
||||||
|
a = b;
|
||||||
|
b = t;
|
||||||
|
} while (b == 1);
|
||||||
|
return a * 10 + b;
|
||||||
|
}
|
||||||
33
examples/ir0/lost_copy.ir
Normal file
33
examples/ir0/lost_copy.ir
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
|
||||||
|
fun i32 @main () {
|
||||||
|
init:
|
||||||
|
bid: b0
|
||||||
|
allocations:
|
||||||
|
%l0:i32:i
|
||||||
|
%l1:i32:result
|
||||||
|
|
||||||
|
block b0:
|
||||||
|
%b0:i0:unit = store 0:i32 %l0:i32*
|
||||||
|
%b0:i1:unit = store 0:i32 %l1:i32*
|
||||||
|
j b1()
|
||||||
|
|
||||||
|
block b1:
|
||||||
|
%b1:i0:i32 = load %l0:i32*
|
||||||
|
%b1:i1:unit = store %b1:i0:i32 %l1:i32*
|
||||||
|
%b1:i2:i32 = load %l0:i32*
|
||||||
|
%b1:i3:i32 = add %b1:i2:i32 1:i32
|
||||||
|
%b1:i4:unit = store %b1:i3:i32 %l0:i32*
|
||||||
|
j b2()
|
||||||
|
|
||||||
|
block b2:
|
||||||
|
%b2:i0:i32 = load %l0:i32*
|
||||||
|
%b2:i1:u1 = cmp lt %b2:i0:i32 4:i32
|
||||||
|
br %b2:i1:u1, b1(), b3()
|
||||||
|
|
||||||
|
block b3:
|
||||||
|
%b3:i0:i32 = load %l1:i32*
|
||||||
|
ret %b3:i0:i32
|
||||||
|
|
||||||
|
block b4:
|
||||||
|
ret 0:i32
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
struct %t1 : { a:i8, %anon:struct %t0, c:f64 }
|
|
||||||
struct %t0 : { b:[4 x [5 x i32]] }
|
struct %t0 : { b:[4 x [5 x i32]] }
|
||||||
|
struct %t1 : { a:i8, %anon:struct %t0, c:f64 }
|
||||||
|
|
||||||
fun unit @init (i32, i32, [5 x i32]*) {
|
fun unit @init (i32, i32, [5 x i32]*) {
|
||||||
init:
|
init:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
struct %t1 : { a:i8, %anon:struct %t0, c:i64 }
|
|
||||||
struct %t0 : { b:[4 x i32] }
|
struct %t0 : { b:[4 x i32] }
|
||||||
|
struct %t1 : { a:i8, %anon:struct %t0, c:i64 }
|
||||||
|
|
||||||
fun i32 @main () {
|
fun i32 @main () {
|
||||||
init:
|
init:
|
||||||
|
|||||||
38
examples/ir0/swap.ir
Normal file
38
examples/ir0/swap.ir
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
|
||||||
|
fun i32 @main () {
|
||||||
|
init:
|
||||||
|
bid: b0
|
||||||
|
allocations:
|
||||||
|
%l0:i32:a
|
||||||
|
%l1:i32:b
|
||||||
|
%l2:i32:t
|
||||||
|
|
||||||
|
block b0:
|
||||||
|
%b0:i0:unit = store 1:i32 %l0:i32*
|
||||||
|
%b0:i1:unit = store 2:i32 %l1:i32*
|
||||||
|
j b1()
|
||||||
|
|
||||||
|
block b1:
|
||||||
|
%b1:i0:i32 = load %l0:i32*
|
||||||
|
%b1:i1:unit = store %b1:i0:i32 %l2:i32*
|
||||||
|
%b1:i2:i32 = load %l1:i32*
|
||||||
|
%b1:i3:unit = store %b1:i2:i32 %l0:i32*
|
||||||
|
%b1:i4:i32 = load %l2:i32*
|
||||||
|
%b1:i5:unit = store %b1:i4:i32 %l1:i32*
|
||||||
|
j b2()
|
||||||
|
|
||||||
|
block b2:
|
||||||
|
%b2:i0:i32 = load %l1:i32*
|
||||||
|
%b2:i1:u1 = cmp eq %b2:i0:i32 1:i32
|
||||||
|
br %b2:i1:u1, b1(), b3()
|
||||||
|
|
||||||
|
block b3:
|
||||||
|
%b3:i0:i32 = load %l0:i32*
|
||||||
|
%b3:i1:i32 = mul %b3:i0:i32 10:i32
|
||||||
|
%b3:i2:i32 = load %l1:i32*
|
||||||
|
%b3:i3:i32 = add %b3:i1:i32 %b3:i2:i32
|
||||||
|
ret %b3:i3:i32
|
||||||
|
|
||||||
|
block b4:
|
||||||
|
ret 0:i32
|
||||||
|
}
|
||||||
27
examples/ir1/lost_copy.ir
Normal file
27
examples/ir1/lost_copy.ir
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
fun i32 @main () {
|
||||||
|
init:
|
||||||
|
bid: b0
|
||||||
|
allocations:
|
||||||
|
%l0:i32:i
|
||||||
|
%l1:i32:result
|
||||||
|
|
||||||
|
block b0:
|
||||||
|
%b0:i0:unit = store 0:i32 %l0:i32*
|
||||||
|
%b0:i1:unit = store 0:i32 %l1:i32*
|
||||||
|
j b1()
|
||||||
|
|
||||||
|
block b1:
|
||||||
|
%b1:i0:i32 = load %l0:i32*
|
||||||
|
%b1:i1:unit = store %b1:i0:i32 %l1:i32*
|
||||||
|
%b1:i2:i32 = load %l0:i32*
|
||||||
|
%b1:i3:i32 = add %b1:i2:i32 1:i32
|
||||||
|
%b1:i4:unit = store %b1:i3:i32 %l0:i32*
|
||||||
|
%b1:i5:i32 = load %l0:i32*
|
||||||
|
%b1:i6:u1 = cmp lt %b1:i5:i32 4:i32
|
||||||
|
br %b1:i6:u1, b1(), b3()
|
||||||
|
|
||||||
|
block b3:
|
||||||
|
%b3:i0:i32 = load %l1:i32*
|
||||||
|
ret %b3:i0:i32
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
struct Sub : { m1:i64, m2:i64, m3:i64, m4:i64 }
|
|
||||||
struct Big : { m1:struct Sub, m2:struct Sub, m3:struct Sub }
|
struct Big : { m1:struct Sub, m2:struct Sub, m3:struct Sub }
|
||||||
|
struct Sub : { m1:i64, m2:i64, m3:i64, m4:i64 }
|
||||||
|
|
||||||
fun struct Big @foo (struct Big) {
|
fun struct Big @foo (struct Big) {
|
||||||
init:
|
init:
|
||||||
|
|||||||
32
examples/ir1/swap.ir
Normal file
32
examples/ir1/swap.ir
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
|
||||||
|
fun i32 @main () {
|
||||||
|
init:
|
||||||
|
bid: b0
|
||||||
|
allocations:
|
||||||
|
%l0:i32:a
|
||||||
|
%l1:i32:b
|
||||||
|
%l2:i32:t
|
||||||
|
|
||||||
|
block b0:
|
||||||
|
%b0:i0:unit = store 1:i32 %l0:i32*
|
||||||
|
%b0:i1:unit = store 2:i32 %l1:i32*
|
||||||
|
j b1()
|
||||||
|
|
||||||
|
block b1:
|
||||||
|
%b1:i0:i32 = load %l0:i32*
|
||||||
|
%b1:i1:unit = store %b1:i0:i32 %l2:i32*
|
||||||
|
%b1:i2:i32 = load %l1:i32*
|
||||||
|
%b1:i3:unit = store %b1:i2:i32 %l0:i32*
|
||||||
|
%b1:i4:i32 = load %l2:i32*
|
||||||
|
%b1:i5:unit = store %b1:i4:i32 %l1:i32*
|
||||||
|
%b1:i6:i32 = load %l1:i32*
|
||||||
|
%b1:i7:u1 = cmp eq %b1:i6:i32 1:i32
|
||||||
|
br %b1:i7:u1, b1(), b3()
|
||||||
|
|
||||||
|
block b3:
|
||||||
|
%b3:i0:i32 = load %l0:i32*
|
||||||
|
%b3:i1:i32 = mul %b3:i0:i32 10:i32
|
||||||
|
%b3:i2:i32 = load %l1:i32*
|
||||||
|
%b3:i3:i32 = add %b3:i1:i32 %b3:i2:i32
|
||||||
|
ret %b3:i3:i32
|
||||||
|
}
|
||||||
@@ -17,10 +17,11 @@ block b0:
|
|||||||
%b0:i1:unit = nop
|
%b0:i1:unit = nop
|
||||||
%b0:i2:unit = nop
|
%b0:i2:unit = nop
|
||||||
%b0:i3:unit = nop
|
%b0:i3:unit = nop
|
||||||
j b2(0:i32)
|
j b2(0:i32, undef:i32)
|
||||||
|
|
||||||
block b2:
|
block b2:
|
||||||
%b2:p0:i32:i
|
%b2:p0:i32:i
|
||||||
|
%b2:p1:i32:j
|
||||||
%b2:i0:unit = nop
|
%b2:i0:unit = nop
|
||||||
%b2:i1:unit = nop
|
%b2:i1:unit = nop
|
||||||
%b2:i2:u1 = cmp lt %b2:p0:i32 %b0:p0:i32
|
%b2:i2:u1 = cmp lt %b2:p0:i32 %b0:p0:i32
|
||||||
@@ -64,7 +65,7 @@ block b10:
|
|||||||
%b10:i0:unit = nop
|
%b10:i0:unit = nop
|
||||||
%b10:i1:i32 = add %b2:p0:i32 1:i32
|
%b10:i1:i32 = add %b2:p0:i32 1:i32
|
||||||
%b10:i2:unit = nop
|
%b10:i2:unit = nop
|
||||||
j b2(%b10:i1:i32)
|
j b2(%b10:i1:i32, %b7:p0:i32)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun i32 @main () {
|
fun i32 @main () {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -30,18 +30,19 @@ block b2:
|
|||||||
%b2:i1:unit = nop
|
%b2:i1:unit = nop
|
||||||
%b2:i2:i32 = add 2:i32 5:i32
|
%b2:i2:i32 = add 2:i32 5:i32
|
||||||
%b2:i3:unit = nop
|
%b2:i3:unit = nop
|
||||||
j b3(2:i32, %b2:i2:i32)
|
j b3(2:i32, undef:i32, %b2:i2:i32)
|
||||||
|
|
||||||
block b3:
|
block b3:
|
||||||
%b3:p0:i32:p
|
%b3:p0:i32:p
|
||||||
%b3:p1:i32:t1
|
%b3:p1:i32:t0
|
||||||
|
%b3:p2:i32:t1
|
||||||
%b3:i0:unit = nop
|
%b3:i0:unit = nop
|
||||||
%b3:i1:unit = nop
|
%b3:i1:unit = nop
|
||||||
%b3:i2:i32 = load @nonce:i32*
|
%b3:i2:i32 = load @nonce:i32*
|
||||||
%b3:i3:i32 = mod %b3:i2:i32 100:i32
|
%b3:i3:i32 = mod %b3:i2:i32 100:i32
|
||||||
%b3:i4:unit = nop
|
%b3:i4:unit = nop
|
||||||
%b3:i5:unit = nop
|
%b3:i5:unit = nop
|
||||||
j b8(0:i32, %b3:p0:i32)
|
j b8(0:i32, %b3:p0:i32, undef:i32)
|
||||||
|
|
||||||
block b4:
|
block b4:
|
||||||
%b4:i0:unit = nop
|
%b4:i0:unit = nop
|
||||||
@@ -62,11 +63,12 @@ block b6:
|
|||||||
%b6:p1:i32:t0
|
%b6:p1:i32:t0
|
||||||
%b6:i0:unit = nop
|
%b6:i0:unit = nop
|
||||||
%b6:i1:unit = nop
|
%b6:i1:unit = nop
|
||||||
j b3(%b6:p0:i32, %b6:p1:i32)
|
j b3(%b6:p0:i32, %b6:p1:i32, %b6:p1:i32)
|
||||||
|
|
||||||
block b8:
|
block b8:
|
||||||
%b8:p0:i32:i
|
%b8:p0:i32:i
|
||||||
%b8:p1:i32:p
|
%b8:p1:i32:p
|
||||||
|
%b8:p2:i32:t2
|
||||||
%b8:i0:unit = nop
|
%b8:i0:unit = nop
|
||||||
%b8:i1:unit = nop
|
%b8:i1:unit = nop
|
||||||
%b8:i2:u1 = cmp lt %b8:p0:i32 %b3:i3:i32
|
%b8:i2:u1 = cmp lt %b8:p0:i32 %b3:i3:i32
|
||||||
@@ -92,7 +94,7 @@ block b12:
|
|||||||
block b13:
|
block b13:
|
||||||
%b13:i0:unit = nop
|
%b13:i0:unit = nop
|
||||||
%b13:i1:unit = nop
|
%b13:i1:unit = nop
|
||||||
%b13:i2:i32 = add %b8:p1:i32 %b3:p1:i32
|
%b13:i2:i32 = add %b8:p1:i32 %b3:p2:i32
|
||||||
%b13:i3:unit = nop
|
%b13:i3:unit = nop
|
||||||
j b14(%b13:i2:i32)
|
j b14(%b13:i2:i32)
|
||||||
|
|
||||||
@@ -121,5 +123,5 @@ block b17:
|
|||||||
%b17:p0:i32:i
|
%b17:p0:i32:i
|
||||||
%b17:p1:i32:t2
|
%b17:p1:i32:t2
|
||||||
%b17:i0:unit = nop
|
%b17:i0:unit = nop
|
||||||
j b8(%b17:p0:i32, %b14:p0:i32)
|
j b8(%b17:p0:i32, %b14:p0:i32, %b17:p1:i32)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,12 +26,13 @@ block b1:
|
|||||||
|
|
||||||
block b2:
|
block b2:
|
||||||
%b2:i0:unit = nop
|
%b2:i0:unit = nop
|
||||||
j b6(1:i32, 0:i32, 1:i32)
|
j b6(1:i32, 0:i32, 1:i32, 0:i32)
|
||||||
|
|
||||||
block b6:
|
block b6:
|
||||||
%b6:p0:i32:i
|
%b6:p0:i32:i
|
||||||
%b6:p1:i32:t1
|
%b6:p1:i32:t1
|
||||||
%b6:p2:i32:t2
|
%b6:p2:i32:t2
|
||||||
|
%b6:p3:i32:next_term
|
||||||
%b6:i0:unit = nop
|
%b6:i0:unit = nop
|
||||||
%b6:i1:unit = nop
|
%b6:i1:unit = nop
|
||||||
%b6:i2:u1 = cmp lt %b6:p0:i32 %b0:p0:i32
|
%b6:i2:u1 = cmp lt %b6:p0:i32 %b0:p0:i32
|
||||||
@@ -49,7 +50,7 @@ block b7:
|
|||||||
%b7:i8:unit = nop
|
%b7:i8:unit = nop
|
||||||
%b7:i9:i32 = add %b6:p0:i32 1:i32
|
%b7:i9:i32 = add %b6:p0:i32 1:i32
|
||||||
%b7:i10:unit = nop
|
%b7:i10:unit = nop
|
||||||
j b6(%b7:i9:i32, %b6:p2:i32, %b7:i2:i32)
|
j b6(%b7:i9:i32, %b6:p2:i32, %b7:i2:i32, %b7:i2:i32)
|
||||||
|
|
||||||
block b9:
|
block b9:
|
||||||
%b9:i0:unit = nop
|
%b9:i0:unit = nop
|
||||||
|
|||||||
@@ -26,12 +26,13 @@ block b1:
|
|||||||
|
|
||||||
block b2:
|
block b2:
|
||||||
%b2:i0:unit = nop
|
%b2:i0:unit = nop
|
||||||
j b5(1:i32, 0:i32, 1:i32)
|
j b5(1:i32, 0:i32, 1:i32, 0:i32)
|
||||||
|
|
||||||
block b5:
|
block b5:
|
||||||
%b5:p0:i32:i
|
%b5:p0:i32:i
|
||||||
%b5:p1:i32:t1
|
%b5:p1:i32:t1
|
||||||
%b5:p2:i32:t2
|
%b5:p2:i32:t2
|
||||||
|
%b5:p3:i32:next_term
|
||||||
%b5:i0:unit = nop
|
%b5:i0:unit = nop
|
||||||
%b5:i1:unit = nop
|
%b5:i1:unit = nop
|
||||||
%b5:i2:u1 = cmp lt %b5:p0:i32 %b0:p0:i32
|
%b5:i2:u1 = cmp lt %b5:p0:i32 %b0:p0:i32
|
||||||
@@ -49,7 +50,7 @@ block b6:
|
|||||||
%b6:i8:unit = nop
|
%b6:i8:unit = nop
|
||||||
%b6:i9:i32 = add %b5:p0:i32 1:i32
|
%b6:i9:i32 = add %b5:p0:i32 1:i32
|
||||||
%b6:i10:unit = nop
|
%b6:i10:unit = nop
|
||||||
j b5(%b6:i9:i32, %b5:p2:i32, %b6:i2:i32)
|
j b5(%b6:i9:i32, %b5:p2:i32, %b6:i2:i32, %b6:i2:i32)
|
||||||
|
|
||||||
block b7:
|
block b7:
|
||||||
%b7:i0:unit = nop
|
%b7:i0:unit = nop
|
||||||
|
|||||||
@@ -26,12 +26,13 @@ block b1:
|
|||||||
|
|
||||||
block b2:
|
block b2:
|
||||||
%b2:i0:unit = nop
|
%b2:i0:unit = nop
|
||||||
j b5(1:i32, 0:i32, 1:i32)
|
j b5(1:i32, 0:i32, 1:i32, 0:i32)
|
||||||
|
|
||||||
block b5:
|
block b5:
|
||||||
%b5:p0:i32:i
|
%b5:p0:i32:i
|
||||||
%b5:p1:i32:t1
|
%b5:p1:i32:t1
|
||||||
%b5:p2:i32:t2
|
%b5:p2:i32:t2
|
||||||
|
%b5:p3:i32:next_term
|
||||||
%b5:i0:unit = nop
|
%b5:i0:unit = nop
|
||||||
%b5:i1:unit = nop
|
%b5:i1:unit = nop
|
||||||
%b5:i2:i32 = add %b5:p1:i32 %b5:p2:i32
|
%b5:i2:i32 = add %b5:p1:i32 %b5:p2:i32
|
||||||
@@ -46,7 +47,7 @@ block b5:
|
|||||||
%b5:i11:unit = nop
|
%b5:i11:unit = nop
|
||||||
%b5:i12:unit = nop
|
%b5:i12:unit = nop
|
||||||
%b5:i13:u1 = cmp lt %b5:i9:i32 %b0:p0:i32
|
%b5:i13:u1 = cmp lt %b5:i9:i32 %b0:p0:i32
|
||||||
br %b5:i13:u1, b5(%b5:i9:i32, %b5:p2:i32, %b5:i2:i32), b7()
|
br %b5:i13:u1, b5(%b5:i9:i32, %b5:p2:i32, %b5:i2:i32, %b5:i2:i32), b7()
|
||||||
|
|
||||||
block b7:
|
block b7:
|
||||||
%b7:i0:unit = nop
|
%b7:i0:unit = nop
|
||||||
|
|||||||
@@ -11,10 +11,12 @@ init:
|
|||||||
block b0:
|
block b0:
|
||||||
%b0:i0:unit = nop
|
%b0:i0:unit = nop
|
||||||
%b0:i1:unit = nop
|
%b0:i1:unit = nop
|
||||||
j b2(0:i32)
|
j b2(0:i32, undef:i32, undef:i32)
|
||||||
|
|
||||||
block b2:
|
block b2:
|
||||||
%b2:p0:i32:i
|
%b2:p0:i32:i
|
||||||
|
%b2:p1:i32:i
|
||||||
|
%b2:p2:i32:k
|
||||||
%b2:i0:unit = nop
|
%b2:i0:unit = nop
|
||||||
%b2:i1:u1 = cmp lt %b2:p0:i32 10:i32
|
%b2:i1:u1 = cmp lt %b2:p0:i32 10:i32
|
||||||
br %b2:i1:u1, b3(), b5()
|
br %b2:i1:u1, b3(), b5()
|
||||||
@@ -25,7 +27,7 @@ block b3:
|
|||||||
%b3:i2:unit = nop
|
%b3:i2:unit = nop
|
||||||
%b3:i3:i32 = add %b2:p0:i32 1:i32
|
%b3:i3:i32 = add %b2:p0:i32 1:i32
|
||||||
%b3:i4:unit = nop
|
%b3:i4:unit = nop
|
||||||
j b2(%b3:i3:i32)
|
j b2(%b3:i3:i32, 0:i32, 0:i32)
|
||||||
|
|
||||||
block b5:
|
block b5:
|
||||||
ret 1:i32
|
ret 1:i32
|
||||||
|
|||||||
29
examples/ir2/lost_copy.ir
Normal file
29
examples/ir2/lost_copy.ir
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
fun i32 @main () {
|
||||||
|
init:
|
||||||
|
bid: b0
|
||||||
|
allocations:
|
||||||
|
%l0:i32:i
|
||||||
|
%l1:i32:result
|
||||||
|
|
||||||
|
block b0:
|
||||||
|
%b0:i0:unit = nop
|
||||||
|
%b0:i1:unit = nop
|
||||||
|
j b1(0:i32, 0:i32)
|
||||||
|
|
||||||
|
block b1:
|
||||||
|
%b1:p0:i32:i
|
||||||
|
%b1:p1:i32:result
|
||||||
|
%b1:i0:unit = nop
|
||||||
|
%b1:i1:unit = nop
|
||||||
|
%b1:i2:unit = nop
|
||||||
|
%b1:i3:i32 = add %b1:p0:i32 1:i32
|
||||||
|
%b1:i4:unit = nop
|
||||||
|
%b1:i5:unit = nop
|
||||||
|
%b1:i6:u1 = cmp lt %b1:i3:i32 4:i32
|
||||||
|
br %b1:i6:u1, b1(%b1:i3:i32, %b1:p0:i32), b3()
|
||||||
|
|
||||||
|
block b3:
|
||||||
|
%b3:i0:unit = nop
|
||||||
|
ret %b1:p0:i32
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
struct %t1 : { a:i8, %anon:struct %t0, c:f64 }
|
|
||||||
struct %t0 : { b:[4 x [5 x i32]] }
|
struct %t0 : { b:[4 x [5 x i32]] }
|
||||||
|
struct %t1 : { a:i8, %anon:struct %t0, c:f64 }
|
||||||
|
|
||||||
fun unit @init (i32, i32, [5 x i32]*) {
|
fun unit @init (i32, i32, [5 x i32]*) {
|
||||||
init:
|
init:
|
||||||
@@ -19,10 +19,11 @@ block b0:
|
|||||||
%b0:i1:unit = nop
|
%b0:i1:unit = nop
|
||||||
%b0:i2:unit = nop
|
%b0:i2:unit = nop
|
||||||
%b0:i3:unit = nop
|
%b0:i3:unit = nop
|
||||||
j b2(0:i32)
|
j b2(0:i32, undef:i32)
|
||||||
|
|
||||||
block b2:
|
block b2:
|
||||||
%b2:p0:i32:i
|
%b2:p0:i32:i
|
||||||
|
%b2:p1:i32:j
|
||||||
%b2:i0:unit = nop
|
%b2:i0:unit = nop
|
||||||
%b2:i1:unit = nop
|
%b2:i1:unit = nop
|
||||||
%b2:i2:u1 = cmp lt %b2:p0:i32 %b0:p0:i32
|
%b2:i2:u1 = cmp lt %b2:p0:i32 %b0:p0:i32
|
||||||
@@ -66,7 +67,7 @@ block b10:
|
|||||||
%b10:i0:unit = nop
|
%b10:i0:unit = nop
|
||||||
%b10:i1:i32 = add %b2:p0:i32 1:i32
|
%b10:i1:i32 = add %b2:p0:i32 1:i32
|
||||||
%b10:i2:unit = nop
|
%b10:i2:unit = nop
|
||||||
j b2(%b10:i1:i32)
|
j b2(%b10:i1:i32, %b7:p0:i32)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun i32 @main () {
|
fun i32 @main () {
|
||||||
|
|||||||
35
examples/ir2/swap.ir
Normal file
35
examples/ir2/swap.ir
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
|
||||||
|
fun i32 @main () {
|
||||||
|
init:
|
||||||
|
bid: b0
|
||||||
|
allocations:
|
||||||
|
%l0:i32:a
|
||||||
|
%l1:i32:b
|
||||||
|
%l2:i32:t
|
||||||
|
|
||||||
|
block b0:
|
||||||
|
%b0:i0:unit = nop
|
||||||
|
%b0:i1:unit = nop
|
||||||
|
j b1(1:i32, 2:i32, undef:i32)
|
||||||
|
|
||||||
|
block b1:
|
||||||
|
%b1:p0:i32:a
|
||||||
|
%b1:p1:i32:b
|
||||||
|
%b1:p2:i32:t
|
||||||
|
%b1:i0:unit = nop
|
||||||
|
%b1:i1:unit = nop
|
||||||
|
%b1:i2:unit = nop
|
||||||
|
%b1:i3:unit = nop
|
||||||
|
%b1:i4:unit = nop
|
||||||
|
%b1:i5:unit = nop
|
||||||
|
%b1:i6:unit = nop
|
||||||
|
%b1:i7:u1 = cmp eq %b1:p0:i32 1:i32
|
||||||
|
br %b1:i7:u1, b1(%b1:p1:i32, %b1:p0:i32, %b1:p0:i32), b3()
|
||||||
|
|
||||||
|
block b3:
|
||||||
|
%b3:i0:unit = nop
|
||||||
|
%b3:i1:i32 = mul %b1:p1:i32 10:i32
|
||||||
|
%b3:i2:unit = nop
|
||||||
|
%b3:i3:i32 = add %b3:i1:i32 %b1:p0:i32
|
||||||
|
ret %b3:i3:i32
|
||||||
|
}
|
||||||
@@ -45,14 +45,15 @@ block b0:
|
|||||||
%b0:i30:unit = nop
|
%b0:i30:unit = nop
|
||||||
%b0:i31:unit = nop
|
%b0:i31:unit = nop
|
||||||
%b0:i32:unit = nop
|
%b0:i32:unit = nop
|
||||||
j b2(%b0:i29:i32, 0:i32)
|
j b2(%b0:i29:i32, 0:i32, undef:u1)
|
||||||
|
|
||||||
block b2:
|
block b2:
|
||||||
%b2:p0:i32:temp
|
%b2:p0:i32:temp
|
||||||
%b2:p1:i32:i
|
%b2:p1:i32:i
|
||||||
|
%b2:p2:u1:t0
|
||||||
%b2:i0:unit = nop
|
%b2:i0:unit = nop
|
||||||
%b2:i1:u1 = cmp lt %b2:p1:i32 10:i32
|
%b2:i1:u1 = cmp lt %b2:p1:i32 10:i32
|
||||||
br %b2:i1:u1, b3(), b5()
|
br %b2:i1:u1, b3(), b5(%b2:p2:u1)
|
||||||
|
|
||||||
block b3:
|
block b3:
|
||||||
%b3:i0:unit = nop
|
%b3:i0:unit = nop
|
||||||
@@ -60,6 +61,7 @@ block b3:
|
|||||||
br %b3:i1:u1, b9(), b10()
|
br %b3:i1:u1, b9(), b10()
|
||||||
|
|
||||||
block b5:
|
block b5:
|
||||||
|
%b5:p0:u1:t0
|
||||||
%b5:i0:unit = nop
|
%b5:i0:unit = nop
|
||||||
switch %b2:p0:i32 default b13(%b2:p0:i32) [
|
switch %b2:p0:i32 default b13(%b2:p0:i32) [
|
||||||
1:i32 b14()
|
1:i32 b14()
|
||||||
@@ -73,7 +75,7 @@ block b7:
|
|||||||
%b7:i4:unit = nop
|
%b7:i4:unit = nop
|
||||||
%b7:i5:i32 = add %b2:p1:i32 1:i32
|
%b7:i5:i32 = add %b2:p1:i32 1:i32
|
||||||
%b7:i6:unit = nop
|
%b7:i6:unit = nop
|
||||||
j b2(%b7:i2:i32, %b7:i5:i32)
|
j b2(%b7:i2:i32, %b7:i5:i32, %b11:p0:u1)
|
||||||
|
|
||||||
block b9:
|
block b9:
|
||||||
%b9:i0:unit = nop
|
%b9:i0:unit = nop
|
||||||
@@ -88,7 +90,7 @@ block b10:
|
|||||||
block b11:
|
block b11:
|
||||||
%b11:p0:u1:t0
|
%b11:p0:u1:t0
|
||||||
%b11:i0:unit = nop
|
%b11:i0:unit = nop
|
||||||
br %b11:p0:u1, b5(), b7()
|
br %b11:p0:u1, b5(%b11:p0:u1), b7()
|
||||||
|
|
||||||
block b13:
|
block b13:
|
||||||
%b13:p0:i32:temp
|
%b13:p0:i32:temp
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ block b1:
|
|||||||
%b1:p1:i32:i
|
%b1:p1:i32:i
|
||||||
%b1:i0:unit = nop
|
%b1:i0:unit = nop
|
||||||
%b1:i1:u1 = cmp lt %b1:p1:i32 100:i32
|
%b1:i1:u1 = cmp lt %b1:p1:i32 100:i32
|
||||||
br %b1:i1:u1, b2(), b3(%b1:p0:i32)
|
br %b1:i1:u1, b2(), b3(%b1:p0:i32, %b1:p1:i32)
|
||||||
|
|
||||||
block b2:
|
block b2:
|
||||||
%b2:i0:unit = nop
|
%b2:i0:unit = nop
|
||||||
@@ -31,6 +31,7 @@ block b2:
|
|||||||
|
|
||||||
block b3:
|
block b3:
|
||||||
%b3:p0:i32:sum
|
%b3:p0:i32:sum
|
||||||
|
%b3:p1:i32:i
|
||||||
%b3:i0:unit = nop
|
%b3:i0:unit = nop
|
||||||
ret %b3:p0:i32
|
ret %b3:p0:i32
|
||||||
|
|
||||||
@@ -52,7 +53,7 @@ block b5:
|
|||||||
%b5:i8:unit = nop
|
%b5:i8:unit = nop
|
||||||
%b5:i9:i32 = add %b0:i3:i32 2:i32
|
%b5:i9:i32 = add %b0:i3:i32 2:i32
|
||||||
%b5:i10:u1 = cmp eq %b5:i5:i32 %b5:i9:i32
|
%b5:i10:u1 = cmp eq %b5:i5:i32 %b5:i9:i32
|
||||||
br %b5:i10:u1, b3(%b5:i2:i32), b1(%b5:i2:i32, %b5:i5:i32)
|
br %b5:i10:u1, b3(%b5:i2:i32, %b5:i5:i32), b1(%b5:i2:i32, %b5:i5:i32)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun i32 @main () {
|
fun i32 @main () {
|
||||||
|
|||||||
19
examples/ir3/lost_copy.ir
Normal file
19
examples/ir3/lost_copy.ir
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
fun i32 @main () {
|
||||||
|
init:
|
||||||
|
bid: b0
|
||||||
|
allocations:
|
||||||
|
|
||||||
|
|
||||||
|
block b0:
|
||||||
|
j b1(0:i32)
|
||||||
|
|
||||||
|
block b1:
|
||||||
|
%b1:p0:i32:i
|
||||||
|
%b1:i0:i32 = add %b1:p0:i32 1:i32
|
||||||
|
%b1:i1:u1 = cmp lt %b1:i0:i32 4:i32
|
||||||
|
br %b1:i1:u1, b1(%b1:i0:i32), b3()
|
||||||
|
|
||||||
|
block b3:
|
||||||
|
ret %b1:p0:i32
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
struct %t1 : { a:i8, %anon:struct %t0, c:f64 }
|
|
||||||
struct %t0 : { b:[4 x [5 x i32]] }
|
struct %t0 : { b:[4 x [5 x i32]] }
|
||||||
|
struct %t1 : { a:i8, %anon:struct %t0, c:f64 }
|
||||||
|
|
||||||
fun unit @init (i32, i32, [5 x i32]*) {
|
fun unit @init (i32, i32, [5 x i32]*) {
|
||||||
init:
|
init:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
struct Sub : { m1:i64, m2:i64, m3:i64, m4:i64 }
|
|
||||||
struct Big : { m1:struct Sub, m2:struct Sub, m3:struct Sub }
|
struct Big : { m1:struct Sub, m2:struct Sub, m3:struct Sub }
|
||||||
|
struct Sub : { m1:i64, m2:i64, m3:i64, m4:i64 }
|
||||||
|
|
||||||
fun struct Big @foo (struct Big) {
|
fun struct Big @foo (struct Big) {
|
||||||
init:
|
init:
|
||||||
|
|||||||
21
examples/ir3/swap.ir
Normal file
21
examples/ir3/swap.ir
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
fun i32 @main () {
|
||||||
|
init:
|
||||||
|
bid: b0
|
||||||
|
allocations:
|
||||||
|
|
||||||
|
|
||||||
|
block b0:
|
||||||
|
j b1(1:i32, 2:i32)
|
||||||
|
|
||||||
|
block b1:
|
||||||
|
%b1:p0:i32:a
|
||||||
|
%b1:p1:i32:b
|
||||||
|
%b1:i0:u1 = cmp eq %b1:p0:i32 1:i32
|
||||||
|
br %b1:i0:u1, b1(%b1:p1:i32, %b1:p0:i32), b3()
|
||||||
|
|
||||||
|
block b3:
|
||||||
|
%b3:i0:i32 = mul %b1:p1:i32 10:i32
|
||||||
|
%b3:i1:i32 = add %b3:i0:i32 %b1:p0:i32
|
||||||
|
ret %b3:i1:i32
|
||||||
|
}
|
||||||
19
examples/ir4/lost_copy.ir
Normal file
19
examples/ir4/lost_copy.ir
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
fun i32 @main () {
|
||||||
|
init:
|
||||||
|
bid: b0
|
||||||
|
allocations:
|
||||||
|
|
||||||
|
|
||||||
|
block b0:
|
||||||
|
j b1(0:i32)
|
||||||
|
|
||||||
|
block b1:
|
||||||
|
%b1:p0:i32:i
|
||||||
|
%b1:i0:i32 = add %b1:p0:i32 1:i32
|
||||||
|
%b1:i1:u1 = cmp lt %b1:i0:i32 4:i32
|
||||||
|
br %b1:i1:u1, b1(%b1:i0:i32), b3()
|
||||||
|
|
||||||
|
block b3:
|
||||||
|
ret %b1:p0:i32
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
struct %t1 : { a:i8, %anon:struct %t0, c:i64 }
|
|
||||||
struct %t0 : { b:[4 x i32] }
|
struct %t0 : { b:[4 x i32] }
|
||||||
|
struct %t1 : { a:i8, %anon:struct %t0, c:i64 }
|
||||||
|
|
||||||
fun i32 @main () {
|
fun i32 @main () {
|
||||||
init:
|
init:
|
||||||
|
|||||||
21
examples/ir4/swap.ir
Normal file
21
examples/ir4/swap.ir
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
fun i32 @main () {
|
||||||
|
init:
|
||||||
|
bid: b0
|
||||||
|
allocations:
|
||||||
|
|
||||||
|
|
||||||
|
block b0:
|
||||||
|
j b1(1:i32, 2:i32)
|
||||||
|
|
||||||
|
block b1:
|
||||||
|
%b1:p0:i32:a
|
||||||
|
%b1:p1:i32:b
|
||||||
|
%b1:i0:u1 = cmp eq %b1:p0:i32 1:i32
|
||||||
|
br %b1:i0:u1, b1(%b1:p1:i32, %b1:p0:i32), b3()
|
||||||
|
|
||||||
|
block b3:
|
||||||
|
%b3:i0:i32 = mul %b1:p1:i32 10:i32
|
||||||
|
%b3:i1:i32 = add %b3:i0:i32 %b1:p0:i32
|
||||||
|
ret %b3:i1:i32
|
||||||
|
}
|
||||||
@@ -85,7 +85,7 @@ block b0:
|
|||||||
%b0:i2:unit = nop
|
%b0:i2:unit = nop
|
||||||
switch undef:i32 default b1() [
|
switch undef:i32 default b1() [
|
||||||
2:i32 b2(0:i32)
|
2:i32 b2(0:i32)
|
||||||
3:i32 b3()
|
3:i32 b3(0:i32)
|
||||||
]
|
]
|
||||||
|
|
||||||
block b1:
|
block b1:
|
||||||
@@ -99,9 +99,10 @@ block b2:
|
|||||||
%b2:i0:unit = nop
|
%b2:i0:unit = nop
|
||||||
%b2:i1:unit = call @sink:[ret:unit params:(i32)]*(%b2:p0:i32)
|
%b2:i1:unit = call @sink:[ret:unit params:(i32)]*(%b2:p0:i32)
|
||||||
%b2:i2:unit = nop
|
%b2:i2:unit = nop
|
||||||
j b3()
|
j b3(200:i32)
|
||||||
|
|
||||||
block b3:
|
block b3:
|
||||||
|
%b3:p0:i32:x
|
||||||
%b3:i0:unit = nop
|
%b3:i0:unit = nop
|
||||||
j b0(300:i32)
|
j b0(300:i32)
|
||||||
}
|
}
|
||||||
@@ -139,8 +140,8 @@ block b0:
|
|||||||
%b0:i8:unit = nop
|
%b0:i8:unit = nop
|
||||||
|
|
||||||
switch undef:i32 default b1() [
|
switch undef:i32 default b1() [
|
||||||
2:i32 b2(0:i32)
|
2:i32 b2(0:i32, 2:i64)
|
||||||
3:i32 b3()
|
3:i32 b3(0:i32, 1:i16, 2:i64)
|
||||||
]
|
]
|
||||||
|
|
||||||
block b1:
|
block b1:
|
||||||
@@ -152,10 +153,11 @@ block b1:
|
|||||||
%b1:i4:unit = call @sink:[ret:unit params:(i32)]*(2:i64)
|
%b1:i4:unit = call @sink:[ret:unit params:(i32)]*(2:i64)
|
||||||
%b1:i5:unit = nop
|
%b1:i5:unit = nop
|
||||||
|
|
||||||
j b2(100:i32)
|
j b2(100:i32, 102:i64)
|
||||||
|
|
||||||
block b2:
|
block b2:
|
||||||
%b2:p0:i32:x
|
%b2:p0:i32:x
|
||||||
|
%b2:p1:i64:z
|
||||||
|
|
||||||
%b2:i0:unit = nop
|
%b2:i0:unit = nop
|
||||||
%b2:i1:unit = call @sink:[ret:unit params:(i32)]*(%b2:p0:i32)
|
%b2:i1:unit = call @sink:[ret:unit params:(i32)]*(%b2:p0:i32)
|
||||||
@@ -164,9 +166,12 @@ block b2:
|
|||||||
%b2:i4:unit = call @sink:[ret:unit params:(i32)]*(1:i16)
|
%b2:i4:unit = call @sink:[ret:unit params:(i32)]*(1:i16)
|
||||||
%b2:i5:unit = nop
|
%b2:i5:unit = nop
|
||||||
|
|
||||||
j b3()
|
j b3(200:i32, 201:i16, %b2:p1:i64)
|
||||||
|
|
||||||
block b3:
|
block b3:
|
||||||
|
%b3:p0:i32:x
|
||||||
|
%b3:p1:i16:y
|
||||||
|
%b3:p2:i64:z
|
||||||
%b3:i0:unit = nop
|
%b3:i0:unit = nop
|
||||||
%b3:i1:unit = nop
|
%b3:i1:unit = nop
|
||||||
%b3:i2:unit = nop
|
%b3:i2:unit = nop
|
||||||
|
|||||||
19
examples/opt/lost_copy.ir
Normal file
19
examples/opt/lost_copy.ir
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
fun i32 @main () {
|
||||||
|
init:
|
||||||
|
bid: b0
|
||||||
|
allocations:
|
||||||
|
|
||||||
|
|
||||||
|
block b0:
|
||||||
|
j b1(0:i32)
|
||||||
|
|
||||||
|
block b1:
|
||||||
|
%b1:p0:i32:i
|
||||||
|
%b1:i0:i32 = add %b1:p0:i32 1:i32
|
||||||
|
%b1:i1:u1 = cmp lt %b1:i0:i32 4:i32
|
||||||
|
br %b1:i1:u1, b1(%b1:i0:i32), b3()
|
||||||
|
|
||||||
|
block b3:
|
||||||
|
ret %b1:p0:i32
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
struct %t1 : { a:i8, %anon:struct %t0, c:f64 }
|
|
||||||
struct %t0 : { b:[4 x [5 x i32]] }
|
struct %t0 : { b:[4 x [5 x i32]] }
|
||||||
|
struct %t1 : { a:i8, %anon:struct %t0, c:f64 }
|
||||||
|
|
||||||
fun unit @init (i32, i32, [5 x i32]*) {
|
fun unit @init (i32, i32, [5 x i32]*) {
|
||||||
init:
|
init:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
struct %t1 : { a:i8, %anon:struct %t0, c:i64 }
|
|
||||||
struct %t0 : { b:[4 x i32] }
|
struct %t0 : { b:[4 x i32] }
|
||||||
|
struct %t1 : { a:i8, %anon:struct %t0, c:i64 }
|
||||||
|
|
||||||
fun i32 @main () {
|
fun i32 @main () {
|
||||||
init:
|
init:
|
||||||
|
|||||||
21
examples/opt/swap.ir
Normal file
21
examples/opt/swap.ir
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
fun i32 @main () {
|
||||||
|
init:
|
||||||
|
bid: b0
|
||||||
|
allocations:
|
||||||
|
|
||||||
|
|
||||||
|
block b0:
|
||||||
|
j b1(1:i32, 2:i32)
|
||||||
|
|
||||||
|
block b1:
|
||||||
|
%b1:p0:i32:a
|
||||||
|
%b1:p1:i32:b
|
||||||
|
%b1:i0:u1 = cmp eq %b1:p0:i32 1:i32
|
||||||
|
br %b1:i0:u1, b1(%b1:p1:i32, %b1:p0:i32), b3()
|
||||||
|
|
||||||
|
block b3:
|
||||||
|
%b3:i0:i32 = mul %b1:p1:i32 10:i32
|
||||||
|
%b3:i1:i32 = add %b3:i0:i32 %b1:p0:i32
|
||||||
|
ret %b3:i1:i32
|
||||||
|
}
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
[toolchain]
|
[toolchain]
|
||||||
channel = "1.83.0"
|
channel = "1.85.0"
|
||||||
components = ["rustfmt", "clippy", "rust-analyzer"]
|
components = ["rustfmt", "clippy", "rust-analyzer"]
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
use std::collections::{HashMap, HashSet, VecDeque};
|
use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
|
||||||
|
|
||||||
use lang_c::ast;
|
use lang_c::ast;
|
||||||
|
|
||||||
use crate::ir::HasDtype;
|
use crate::ir::HasDtype;
|
||||||
use crate::{asm, ir, Translate};
|
use crate::opt::opt_utils;
|
||||||
|
use crate::{Translate, asm, ir};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Asmgen {}
|
pub struct Asmgen {}
|
||||||
|
|||||||
@@ -523,7 +523,7 @@ impl IsEquiv for AlignOf {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn assert_ast_equiv(lhs: &TranslationUnit, rhs: &TranslationUnit) {
|
pub(crate) fn assert_ast_equiv(lhs: &TranslationUnit, rhs: &TranslationUnit) {
|
||||||
if !lhs.is_equiv(rhs) {
|
if !lhs.is_equiv(rhs) {
|
||||||
panic!(
|
panic!(
|
||||||
r#"assertion failed: `(left.is_equiv(right))`
|
r#"assertion failed: `(left.is_equiv(right))`
|
||||||
|
|||||||
@@ -2,5 +2,5 @@ mod ast_equiv;
|
|||||||
mod parse;
|
mod parse;
|
||||||
mod write_c;
|
mod write_c;
|
||||||
|
|
||||||
pub use ast_equiv::assert_ast_equiv;
|
pub(crate) use ast_equiv::assert_ast_equiv;
|
||||||
pub use parse::Parse;
|
pub use parse::Parse;
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ use core::ops::Deref;
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use lang_c::ast::*;
|
use lang_c::ast::*;
|
||||||
use lang_c::driver::{parse, Config, Error as ParseError};
|
use lang_c::driver::{Config, Error as ParseError, parse};
|
||||||
use lang_c::span::Node;
|
use lang_c::span::Node;
|
||||||
|
|
||||||
use crate::utils::AssertSupported;
|
|
||||||
use crate::Translate;
|
use crate::Translate;
|
||||||
|
use crate::utils::AssertSupported;
|
||||||
|
|
||||||
/// Parse Error
|
/// Parse Error
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -616,7 +616,7 @@ impl AssertSupported for AlignOf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_valid_global_variable_declaration(decl: &Declaration) -> bool {
|
fn is_valid_global_variable_declaration(decl: &Declaration) -> bool {
|
||||||
let declarators = &decl.declarators;
|
let declarators = &decl.declarators;
|
||||||
|
|
||||||
declarators.iter().all(|init_decl| {
|
declarators.iter().all(|init_decl| {
|
||||||
@@ -629,7 +629,7 @@ pub fn is_valid_global_variable_declaration(decl: &Declaration) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_valid_global_variable_initializer(initializer: &Initializer) -> bool {
|
fn is_valid_global_variable_initializer(initializer: &Initializer) -> bool {
|
||||||
match initializer {
|
match initializer {
|
||||||
Initializer::Expression(expr) => match &expr.node {
|
Initializer::Expression(expr) => match &expr.node {
|
||||||
Expression::Constant(_) => true,
|
Expression::Constant(_) => true,
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
use core::convert::TryFrom;
|
use core::convert::TryFrom;
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use core::ops::Deref;
|
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
|
||||||
use itertools::izip;
|
|
||||||
use lang_c::ast;
|
use lang_c::ast;
|
||||||
use lang_c::span::Node;
|
use lang_c::span::Node;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::ir::*;
|
use crate::ir::*;
|
||||||
use crate::some_or;
|
|
||||||
|
|
||||||
/// TODO(document)
|
/// TODO(document)
|
||||||
#[derive(Debug, PartialEq, Eq, Error)]
|
#[derive(Debug, PartialEq, Eq, Error)]
|
||||||
@@ -227,13 +224,13 @@ impl BaseDtype {
|
|||||||
tq => {
|
tq => {
|
||||||
return Err(DtypeError::Misc {
|
return Err(DtypeError::Misc {
|
||||||
message: format!("unsupported typq qualifier: {tq:#?}"),
|
message: format!("unsupported typq qualifier: {tq:#?}"),
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_specifier_qualifier(
|
pub(crate) fn apply_specifier_qualifier(
|
||||||
&mut self,
|
&mut self,
|
||||||
typename_specifier: &ast::SpecifierQualifier,
|
typename_specifier: &ast::SpecifierQualifier,
|
||||||
) -> Result<(), DtypeError> {
|
) -> Result<(), DtypeError> {
|
||||||
@@ -247,14 +244,14 @@ impl BaseDtype {
|
|||||||
sq => {
|
sq => {
|
||||||
return Err(DtypeError::Misc {
|
return Err(DtypeError::Misc {
|
||||||
message: format!("unsupported specifier qualifier: {sq:#?}"),
|
message: format!("unsupported specifier qualifier: {sq:#?}"),
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_declaration_specifier(
|
pub(crate) fn apply_declaration_specifier(
|
||||||
&mut self,
|
&mut self,
|
||||||
declaration_specifier: &ast::DeclarationSpecifier,
|
declaration_specifier: &ast::DeclarationSpecifier,
|
||||||
) -> Result<(), DtypeError> {
|
) -> Result<(), DtypeError> {
|
||||||
@@ -271,7 +268,7 @@ impl BaseDtype {
|
|||||||
ds => {
|
ds => {
|
||||||
return Err(DtypeError::Misc {
|
return Err(DtypeError::Misc {
|
||||||
message: format!("unsupported declaration qualifier: {ds:#?}"),
|
message: format!("unsupported declaration qualifier: {ds:#?}"),
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,7 +286,7 @@ impl BaseDtype {
|
|||||||
///
|
///
|
||||||
/// * `self` - Part that has been converted to 'BaseDtype' on the pointer declarator.
|
/// * `self` - Part that has been converted to 'BaseDtype' on the pointer declarator.
|
||||||
/// * `pointer_qualifier` - Pointer qualifiers required to apply to 'BaseDtype' immediately.
|
/// * `pointer_qualifier` - Pointer qualifiers required to apply to 'BaseDtype' immediately.
|
||||||
pub fn apply_pointer_qualifier(
|
pub(crate) fn apply_pointer_qualifier(
|
||||||
&mut self,
|
&mut self,
|
||||||
pointer_qualifier: &ast::PointerQualifier,
|
pointer_qualifier: &ast::PointerQualifier,
|
||||||
) -> Result<(), DtypeError> {
|
) -> Result<(), DtypeError> {
|
||||||
@@ -300,14 +297,14 @@ impl BaseDtype {
|
|||||||
pq => {
|
pq => {
|
||||||
return Err(DtypeError::Misc {
|
return Err(DtypeError::Misc {
|
||||||
message: format!("unsupported pointer qualifier: {pq:#?}"),
|
message: format!("unsupported pointer qualifier: {pq:#?}"),
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_specifier_qualifiers(
|
pub(crate) fn apply_specifier_qualifiers(
|
||||||
&mut self,
|
&mut self,
|
||||||
typename_specifiers: &[Node<ast::SpecifierQualifier>],
|
typename_specifiers: &[Node<ast::SpecifierQualifier>],
|
||||||
) -> Result<(), DtypeError> {
|
) -> Result<(), DtypeError> {
|
||||||
@@ -318,7 +315,7 @@ impl BaseDtype {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_declaration_specifiers(
|
pub(crate) fn apply_declaration_specifiers(
|
||||||
&mut self,
|
&mut self,
|
||||||
declaration_specifiers: &[Node<ast::DeclarationSpecifier>],
|
declaration_specifiers: &[Node<ast::DeclarationSpecifier>],
|
||||||
) -> Result<(), DtypeError> {
|
) -> Result<(), DtypeError> {
|
||||||
@@ -445,7 +442,7 @@ impl TryFrom<BaseDtype> for Dtype {
|
|||||||
_ => {
|
_ => {
|
||||||
return Err(DtypeError::Misc {
|
return Err(DtypeError::Misc {
|
||||||
message: "two or more size modifiers in declaration specifiers".to_string(),
|
message: "two or more size modifiers in declaration specifiers".to_string(),
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -985,17 +982,18 @@ impl Dtype {
|
|||||||
.expect("`offsets` must be `Some`");
|
.expect("`offsets` must be `Some`");
|
||||||
|
|
||||||
assert_eq!(fields.len(), offsets.len());
|
assert_eq!(fields.len(), offsets.len());
|
||||||
for (field, &offset) in izip!(fields, offsets) {
|
for (field, &offset) in fields.iter().zip(offsets) {
|
||||||
if let Some(name) = field.name() {
|
if let Some(name) = field.name() {
|
||||||
if name == field_name {
|
if name == field_name {
|
||||||
return Some((offset, field.deref().clone()));
|
return Some((offset, field.deref().clone()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let field_dtype = field.deref();
|
let field_dtype = field.deref();
|
||||||
let (offset_inner, dtype) = some_or!(
|
let Some((offset_inner, dtype)) =
|
||||||
field_dtype.get_offset_struct_field(field_name, structs),
|
field_dtype.get_offset_struct_field(field_name, structs)
|
||||||
continue
|
else {
|
||||||
);
|
continue;
|
||||||
|
};
|
||||||
return Some((offset + offset_inner, dtype));
|
return Some((offset + offset_inner, dtype));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
use core::{fmt, iter, mem};
|
use core::{fmt, iter, mem};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use itertools::izip;
|
|
||||||
use ordered_float::OrderedFloat;
|
use ordered_float::OrderedFloat;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
@@ -184,8 +183,7 @@ impl Value {
|
|||||||
Dtype::Float { width, .. } => Self::float(f64::default(), *width),
|
Dtype::Float { width, .. } => Self::float(f64::default(), *width),
|
||||||
Dtype::Pointer { inner, .. } => Self::nullptr(inner.deref().clone()),
|
Dtype::Pointer { inner, .. } => Self::nullptr(inner.deref().clone()),
|
||||||
Dtype::Array { inner, size } => {
|
Dtype::Array { inner, size } => {
|
||||||
let values = iter::repeat(Self::default_from_dtype(inner, structs))
|
let values = iter::repeat_n(Self::default_from_dtype(inner, structs), *size)
|
||||||
.take(*size)
|
|
||||||
.collect::<Result<Vec<_>, _>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
Self::array(inner.deref().clone(), values)
|
Self::array(inner.deref().clone(), values)
|
||||||
}
|
}
|
||||||
@@ -605,7 +603,7 @@ mod calculator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: change to template function in the future
|
// TODO: change to template function in the future
|
||||||
pub fn calculate_binary_operator_expression(
|
pub(crate) fn calculate_binary_operator_expression(
|
||||||
op: &ast::BinaryOperator,
|
op: &ast::BinaryOperator,
|
||||||
lhs: Value,
|
lhs: Value,
|
||||||
rhs: Value,
|
rhs: Value,
|
||||||
@@ -675,7 +673,7 @@ mod calculator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn calculate_unary_operator_expression(
|
pub(crate) fn calculate_unary_operator_expression(
|
||||||
op: &ast::UnaryOperator,
|
op: &ast::UnaryOperator,
|
||||||
operand: Value,
|
operand: Value,
|
||||||
) -> Result<Value, ()> {
|
) -> Result<Value, ()> {
|
||||||
@@ -727,7 +725,7 @@ mod calculator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn calculate_typecast(value: Value, dtype: Dtype) -> Result<Value, ()> {
|
pub(crate) fn calculate_typecast(value: Value, dtype: Dtype) -> Result<Value, ()> {
|
||||||
if value.dtype() == dtype {
|
if value.dtype() == dtype {
|
||||||
return Ok(value);
|
return Ok(value);
|
||||||
}
|
}
|
||||||
@@ -851,7 +849,7 @@ impl Byte {
|
|||||||
|
|
||||||
fn block_from_dtype(dtype: &Dtype, structs: &HashMap<String, Option<Dtype>>) -> Vec<Self> {
|
fn block_from_dtype(dtype: &Dtype, structs: &HashMap<String, Option<Dtype>>) -> Vec<Self> {
|
||||||
let size = dtype.size_align_of(structs).unwrap().0;
|
let size = dtype.size_align_of(structs).unwrap().0;
|
||||||
iter::repeat(Self::Undef).take(size).collect()
|
iter::repeat_n(Self::Undef, size).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn u128_to_bytes(mut value: u128, size: usize) -> Vec<u8> {
|
fn u128_to_bytes(mut value: u128, size: usize) -> Vec<u8> {
|
||||||
@@ -889,27 +887,25 @@ impl Byte {
|
|||||||
width, is_signed, ..
|
width, is_signed, ..
|
||||||
} => {
|
} => {
|
||||||
let size = dtype.size_align_of(structs).unwrap().0;
|
let size = dtype.size_align_of(structs).unwrap().0;
|
||||||
let bytes = bytes.by_ref().take(size).collect::<Vec<_>>();
|
let Some(value) = bytes
|
||||||
let value = some_or!(
|
.take(size)
|
||||||
bytes
|
.map(Byte::get_concrete)
|
||||||
.iter()
|
.collect::<Option<Vec<_>>>()
|
||||||
.map(|b| b.get_concrete())
|
else {
|
||||||
.collect::<Option<Vec<_>>>(),
|
return Ok(Value::undef(dtype.clone()));
|
||||||
return Ok(Value::undef(dtype.clone()))
|
};
|
||||||
);
|
|
||||||
let value = Self::bytes_to_u128(&value, *is_signed);
|
let value = Self::bytes_to_u128(&value, *is_signed);
|
||||||
Ok(Value::int(value, *width, *is_signed))
|
Ok(Value::int(value, *width, *is_signed))
|
||||||
}
|
}
|
||||||
Dtype::Float { width, .. } => {
|
Dtype::Float { width, .. } => {
|
||||||
let size = dtype.size_align_of(structs).unwrap().0;
|
let size = dtype.size_align_of(structs).unwrap().0;
|
||||||
let bytes = bytes.by_ref().take(size).collect::<Vec<_>>();
|
let Some(value) = bytes
|
||||||
let value = some_or!(
|
.take(size)
|
||||||
bytes
|
.map(Byte::get_concrete)
|
||||||
.iter()
|
.collect::<Option<Vec<_>>>()
|
||||||
.map(|b| b.get_concrete())
|
else {
|
||||||
.collect::<Option<Vec<_>>>(),
|
return Ok(Value::undef(dtype.clone()));
|
||||||
return Ok(Value::undef(dtype.clone()))
|
};
|
||||||
);
|
|
||||||
let value = Self::bytes_to_u128(&value, false);
|
let value = Self::bytes_to_u128(&value, false);
|
||||||
let value = if size == Dtype::SIZE_OF_FLOAT {
|
let value = if size == Dtype::SIZE_OF_FLOAT {
|
||||||
f32::from_bits(value as u32) as f64
|
f32::from_bits(value as u32) as f64
|
||||||
@@ -920,17 +916,13 @@ impl Byte {
|
|||||||
Ok(Value::float(value, *width))
|
Ok(Value::float(value, *width))
|
||||||
}
|
}
|
||||||
Dtype::Pointer { inner, .. } => {
|
Dtype::Pointer { inner, .. } => {
|
||||||
let bytes = bytes
|
let Some(value) = bytes
|
||||||
.by_ref()
|
|
||||||
.take(Dtype::SIZE_OF_POINTER)
|
.take(Dtype::SIZE_OF_POINTER)
|
||||||
.collect::<Vec<_>>();
|
.map(Byte::get_pointer)
|
||||||
let value = some_or!(
|
.collect::<Option<Vec<_>>>()
|
||||||
bytes
|
else {
|
||||||
.iter()
|
return Ok(Value::undef(dtype.clone()));
|
||||||
.map(|b| b.get_pointer())
|
};
|
||||||
.collect::<Option<Vec<_>>>(),
|
|
||||||
return Ok(Value::undef(dtype.clone()))
|
|
||||||
);
|
|
||||||
|
|
||||||
let (bid, offset, _) = value.first().expect("not empty");
|
let (bid, offset, _) = value.first().expect("not empty");
|
||||||
|
|
||||||
@@ -983,13 +975,15 @@ impl Byte {
|
|||||||
let bytes = bytes.by_ref().take(*size).cloned().collect::<Vec<_>>();
|
let bytes = bytes.by_ref().take(*size).cloned().collect::<Vec<_>>();
|
||||||
|
|
||||||
assert_eq!(fields.len(), offsets.len());
|
assert_eq!(fields.len(), offsets.len());
|
||||||
let fields = izip!(fields, offsets)
|
let fields = fields
|
||||||
|
.iter()
|
||||||
|
.zip(offsets)
|
||||||
.map(|(f, o)| {
|
.map(|(f, o)| {
|
||||||
let mut sub_bytes = bytes[*o..].iter();
|
let mut sub_bytes = bytes[*o..].iter();
|
||||||
let value = Self::bytes_to_value(&mut sub_bytes, f.deref(), structs)?;
|
let value = Self::bytes_to_value(&mut sub_bytes, f.deref(), structs)?;
|
||||||
Ok(Named::new(f.name().cloned(), value))
|
Ok(Named::new(f.name().cloned(), value))
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, InterpreterError>>()?;
|
.collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
Ok(Value::Struct {
|
Ok(Value::Struct {
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
@@ -1010,9 +1004,9 @@ impl Byte {
|
|||||||
} => {
|
} => {
|
||||||
let size = value.dtype().size_align_of(structs).unwrap().0;
|
let size = value.dtype().size_align_of(structs).unwrap().0;
|
||||||
Self::u128_to_bytes(*int_value, size)
|
Self::u128_to_bytes(*int_value, size)
|
||||||
.iter()
|
.into_iter()
|
||||||
.map(|b| Self::concrete(*b))
|
.map(Self::concrete)
|
||||||
.collect::<Vec<_>>()
|
.collect()
|
||||||
}
|
}
|
||||||
Value::Float {
|
Value::Float {
|
||||||
value: float_value, ..
|
value: float_value, ..
|
||||||
@@ -1025,9 +1019,9 @@ impl Byte {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Self::u128_to_bytes(value_bits, size)
|
Self::u128_to_bytes(value_bits, size)
|
||||||
.iter()
|
.into_iter()
|
||||||
.map(|b| Self::concrete(*b))
|
.map(Self::concrete)
|
||||||
.collect::<Vec<_>>()
|
.collect()
|
||||||
}
|
}
|
||||||
Value::Pointer { bid, offset, .. } => (0..Dtype::SIZE_OF_POINTER)
|
Value::Pointer { bid, offset, .. } => (0..Dtype::SIZE_OF_POINTER)
|
||||||
.map(|i| Self::pointer(*bid, *offset, i))
|
.map(|i| Self::pointer(*bid, *offset, i))
|
||||||
@@ -1042,7 +1036,7 @@ impl Byte {
|
|||||||
.iter()
|
.iter()
|
||||||
.flat_map(|v| {
|
.flat_map(|v| {
|
||||||
let mut result = Self::value_to_bytes(v, structs);
|
let mut result = Self::value_to_bytes(v, structs);
|
||||||
result.extend(iter::repeat(Byte::Undef).take(padding));
|
result.extend(iter::repeat_n(Byte::Undef, padding));
|
||||||
result
|
result
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
@@ -1058,10 +1052,10 @@ impl Byte {
|
|||||||
.expect("`struct_type` must be struct type")
|
.expect("`struct_type` must be struct type")
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.expect("`offsets` must be `Some`");
|
.expect("`offsets` must be `Some`");
|
||||||
let mut values = iter::repeat(Byte::Undef).take(*size_of).collect::<Vec<_>>();
|
let mut values = iter::repeat_n(Byte::Undef, *size_of).collect::<Vec<_>>();
|
||||||
|
|
||||||
assert_eq!(fields.len(), offsets.len());
|
assert_eq!(fields.len(), offsets.len());
|
||||||
izip!(fields, offsets).for_each(|(f, o)| {
|
fields.iter().zip(offsets).for_each(|(f, o)| {
|
||||||
let result = Self::value_to_bytes(f.deref(), structs);
|
let result = Self::value_to_bytes(f.deref(), structs);
|
||||||
let size_of_data = f.deref().dtype().size_align_of(structs).unwrap().0;
|
let size_of_data = f.deref().dtype().size_align_of(structs).unwrap().0;
|
||||||
let _unused = values.splice(*o..(*o + size_of_data), result);
|
let _unused = values.splice(*o..(*o + size_of_data), result);
|
||||||
@@ -1270,7 +1264,9 @@ impl<'i> State<'i> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Execute a block exit.
|
// Execute a block exit.
|
||||||
let return_value = some_or!(self.interp_block_exit(&block.exit)?, return Ok(None));
|
let Some(return_value) = self.interp_block_exit(&block.exit)? else {
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
|
||||||
// If it's returning from a function, pop the stack frame.
|
// If it's returning from a function, pop the stack frame.
|
||||||
|
|
||||||
@@ -1288,7 +1284,9 @@ impl<'i> State<'i> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// restore previous state
|
// restore previous state
|
||||||
let prev_stack_frame = some_or!(self.stack.pop(), return Ok(Some(return_value)));
|
let Some(prev_stack_frame) = self.stack.pop() else {
|
||||||
|
return Ok(Some(return_value));
|
||||||
|
};
|
||||||
self.stack_frame = prev_stack_frame;
|
self.stack_frame = prev_stack_frame;
|
||||||
|
|
||||||
// create temporary register to write return value
|
// create temporary register to write return value
|
||||||
@@ -1313,7 +1311,9 @@ impl<'i> State<'i> {
|
|||||||
) -> Result<Vec<Value>, InterpreterError> {
|
) -> Result<Vec<Value>, InterpreterError> {
|
||||||
// Check that the dtype of each args matches the expected
|
// Check that the dtype of each args matches the expected
|
||||||
if !(args.len() == signature.params.len()
|
if !(args.len() == signature.params.len()
|
||||||
&& izip!(args, &signature.params)
|
&& args
|
||||||
|
.iter()
|
||||||
|
.zip(&signature.params)
|
||||||
.all(|(a, d)| a.dtype().set_const(false) == d.clone().set_const(false)))
|
.all(|(a, d)| a.dtype().set_const(false) == d.clone().set_const(false)))
|
||||||
{
|
{
|
||||||
panic!("dtype of args and params must be compatible")
|
panic!("dtype of args and params must be compatible")
|
||||||
@@ -1333,7 +1333,7 @@ impl<'i> State<'i> {
|
|||||||
.expect("block matched with `arg.bid` must be exist");
|
.expect("block matched with `arg.bid` must be exist");
|
||||||
|
|
||||||
assert_eq!(arg.args.len(), block.phinodes.len());
|
assert_eq!(arg.args.len(), block.phinodes.len());
|
||||||
for (a, d) in izip!(&arg.args, &block.phinodes) {
|
for (a, d) in arg.args.iter().zip(&block.phinodes) {
|
||||||
assert!(a.dtype().set_const(false) == d.deref().clone().set_const(false));
|
assert!(a.dtype().set_const(false) == d.deref().clone().set_const(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1394,6 +1394,7 @@ impl<'i> State<'i> {
|
|||||||
fn interp_instruction(&mut self, instruction: &Instruction) -> Result<(), InterpreterError> {
|
fn interp_instruction(&mut self, instruction: &Instruction) -> Result<(), InterpreterError> {
|
||||||
let result = match instruction {
|
let result = match instruction {
|
||||||
Instruction::Nop => Value::unit(),
|
Instruction::Nop => Value::unit(),
|
||||||
|
Instruction::Value { value, .. } => self.interp_operand(value)?,
|
||||||
Instruction::BinOp { op, lhs, rhs, .. } => {
|
Instruction::BinOp { op, lhs, rhs, .. } => {
|
||||||
let lhs = self.interp_operand(lhs)?;
|
let lhs = self.interp_operand(lhs)?;
|
||||||
let rhs = self.interp_operand(rhs)?;
|
let rhs = self.interp_operand(rhs)?;
|
||||||
@@ -1469,7 +1470,7 @@ impl<'i> State<'i> {
|
|||||||
.expect("init block must exists");
|
.expect("init block must exists");
|
||||||
|
|
||||||
if !(args.len() == block_init.phinodes.len()
|
if !(args.len() == block_init.phinodes.len()
|
||||||
&& izip!(args, &block_init.phinodes).all(|(a, d)| {
|
&& args.iter().zip(&block_init.phinodes).all(|(a, d)| {
|
||||||
a.dtype().set_const(false) == d.deref().clone().set_const(false)
|
a.dtype().set_const(false) == d.deref().clone().set_const(false)
|
||||||
}))
|
}))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ use std::hash::{Hash, Hasher};
|
|||||||
|
|
||||||
pub use dtype::{Dtype, DtypeError, HasDtype};
|
pub use dtype::{Dtype, DtypeError, HasDtype};
|
||||||
use hexf_parse::{parse_hexf32, parse_hexf64};
|
use hexf_parse::{parse_hexf32, parse_hexf64};
|
||||||
pub use interp::{interp, Value};
|
pub use interp::{Value, interp};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use lang_c::ast;
|
use lang_c::ast;
|
||||||
use ordered_float::OrderedFloat;
|
use ordered_float::OrderedFloat;
|
||||||
@@ -192,6 +192,9 @@ pub struct Block {
|
|||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum Instruction {
|
pub enum Instruction {
|
||||||
Nop,
|
Nop,
|
||||||
|
Value {
|
||||||
|
value: Operand,
|
||||||
|
},
|
||||||
BinOp {
|
BinOp {
|
||||||
op: ast::BinaryOperator,
|
op: ast::BinaryOperator,
|
||||||
lhs: Operand,
|
lhs: Operand,
|
||||||
@@ -233,6 +236,7 @@ impl HasDtype for Instruction {
|
|||||||
fn dtype(&self) -> Dtype {
|
fn dtype(&self) -> Dtype {
|
||||||
match self {
|
match self {
|
||||||
Self::Nop | Self::Store { .. } => Dtype::unit(),
|
Self::Nop | Self::Store { .. } => Dtype::unit(),
|
||||||
|
Self::Value { value } => value.dtype(),
|
||||||
Self::BinOp { dtype, .. }
|
Self::BinOp { dtype, .. }
|
||||||
| Self::UnaryOp { dtype, .. }
|
| Self::UnaryOp { dtype, .. }
|
||||||
| Self::Call {
|
| Self::Call {
|
||||||
@@ -316,6 +320,7 @@ impl fmt::Display for Instruction {
|
|||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Instruction::Nop => write!(f, "nop"),
|
Instruction::Nop => write!(f, "nop"),
|
||||||
|
Instruction::Value { value } => write!(f, "{value}"),
|
||||||
Instruction::BinOp { op, lhs, rhs, .. } => {
|
Instruction::BinOp { op, lhs, rhs, .. } => {
|
||||||
write!(f, "{} {} {}", op.write_operation(), lhs, rhs)
|
write!(f, "{} {} {}", op.write_operation(), lhs, rhs)
|
||||||
}
|
}
|
||||||
@@ -440,7 +445,7 @@ impl fmt::Display for JumpArg {
|
|||||||
self.bid,
|
self.bid,
|
||||||
self.args
|
self.args
|
||||||
.iter()
|
.iter()
|
||||||
.format_with(", ", |a, f| f(&format_args!("{}", a)))
|
.format_with(", ", |a, f| f(&format_args!("{a}")))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,28 +17,25 @@ peg::parser! {
|
|||||||
|
|
||||||
pub rule translation_unit() -> TranslationUnit
|
pub rule translation_unit() -> TranslationUnit
|
||||||
= _ named_structs:(named_struct() ** __) _ ds:(named_decl() ** __) _ {
|
= _ named_structs:(named_struct() ** __) _ ds:(named_decl() ** __) _ {
|
||||||
let mut structs = HashMap::new();
|
let mut structs = named_structs.iter().map(|named_struct| {
|
||||||
for named_struct in &named_structs {
|
|
||||||
let name = named_struct.name.as_ref().unwrap();
|
let name = named_struct.name.as_ref().unwrap();
|
||||||
let struct_type = &named_struct.inner;
|
let struct_type = &named_struct.inner;
|
||||||
let result = structs.insert(name.clone(), struct_type.clone());
|
(name.clone(), struct_type.clone())
|
||||||
assert!(result.is_none());
|
}).collect::<HashMap<_,_>>();
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve struct type in structs
|
// Resolve struct type in structs
|
||||||
|
// TODO: This is needed?
|
||||||
for named_struct in named_structs {
|
for named_struct in named_structs {
|
||||||
let name = named_struct.name.unwrap();
|
let name = named_struct.name.unwrap();
|
||||||
let dtype = some_or!(structs.get(&name).unwrap(), continue);
|
let Some(dtype) = structs.get(&name).unwrap() else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
if dtype.get_struct_size_align_offsets().unwrap().is_none() {
|
if dtype.get_struct_size_align_offsets().unwrap().is_none() {
|
||||||
resolve_structs(dtype.clone(), &mut structs);
|
resolve_structs(dtype.clone(), &mut structs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut decls = BTreeMap::new();
|
let mut decls = ds.into_iter().map(|decl| (decl.name.unwrap(), decl.inner)).collect::<BTreeMap<_,_>>();
|
||||||
for decl in ds {
|
|
||||||
let result = decls.insert(decl.name.unwrap(), decl.inner);
|
|
||||||
assert!(result.is_none());
|
|
||||||
}
|
|
||||||
|
|
||||||
TranslationUnit { decls, structs }
|
TranslationUnit { decls, structs }
|
||||||
}
|
}
|
||||||
@@ -211,11 +208,10 @@ peg::parser! {
|
|||||||
|
|
||||||
rule instruction() -> (BlockId, usize, Named<Instruction>)
|
rule instruction() -> (BlockId, usize, Named<Instruction>)
|
||||||
= "%" bid:bid() ":i" number:number() ":" dtype:dtype() name:(":" name:id() { name })? _ "=" _ instruction:instruction_inner() {
|
= "%" bid:bid() ":i" number:number() ":" dtype:dtype() name:(":" name:id() { name })? _ "=" _ instruction:instruction_inner() {
|
||||||
// TODO: The dtype of `GetElementPtr` instruction depends on the situation.
|
// TODO: The dtype of `GetElementPtr` instruction depends on the situation. Say `ptr`
|
||||||
// Let's `ptr` has `*[5 x i32]` type, after applying `GetElementPtr` instruction,
|
// has type `*[5 x i32]`, after applying `GetElementPtr`, result' dtype can currently
|
||||||
// the dtype of the result can be `*i32` or `*[5 x i32]` in the current KECC.
|
// be `*i32` or `*[5 x i32]`. Thus, we need to check the dtype of the result to confirm
|
||||||
// For this reason, we need to check the dtype of the result to confirm the dtype
|
// the dtype of `GetElementPtr` instruction when parsing IR.
|
||||||
// of `GetElementPtr` instruction when parsing IR.
|
|
||||||
let instruction = if let Instruction::GetElementPtr { ptr, offset, .. } = instruction {
|
let instruction = if let Instruction::GetElementPtr { ptr, offset, .. } = instruction {
|
||||||
Instruction::GetElementPtr { ptr, offset, dtype }
|
Instruction::GetElementPtr { ptr, offset, dtype }
|
||||||
} else {
|
} else {
|
||||||
@@ -319,6 +315,10 @@ peg::parser! {
|
|||||||
dtype: Dtype::unit(), // TODO
|
dtype: Dtype::unit(), // TODO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/
|
||||||
|
value:operand() {
|
||||||
|
Instruction::Value { value }
|
||||||
|
}
|
||||||
/
|
/
|
||||||
"<instruction>" {
|
"<instruction>" {
|
||||||
todo!()
|
todo!()
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::ir::*;
|
|
||||||
use crate::Translate;
|
use crate::Translate;
|
||||||
|
use crate::ir::*;
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
pub struct Visualizer {
|
pub struct Visualizer {
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ use crate::write_base::*;
|
|||||||
impl WriteLine for TranslationUnit {
|
impl WriteLine for TranslationUnit {
|
||||||
fn write_line(&self, indent: usize, write: &mut dyn Write) -> Result<()> {
|
fn write_line(&self, indent: usize, write: &mut dyn Write) -> Result<()> {
|
||||||
// TODO: consider KECC IR parser in the future.
|
// TODO: consider KECC IR parser in the future.
|
||||||
for (name, struct_type) in &self.structs {
|
let mut structs = self.structs.iter().collect::<Vec<_>>();
|
||||||
|
structs.sort_unstable_by_key(|&(name, _)| name);
|
||||||
|
for (name, struct_type) in structs {
|
||||||
let definition = if let Some(struct_type) = struct_type {
|
let definition = if let Some(struct_type) = struct_type {
|
||||||
let fields = struct_type
|
let fields = struct_type
|
||||||
.get_struct_fields()
|
.get_struct_fields()
|
||||||
|
|||||||
@@ -426,10 +426,9 @@ impl Irgen {
|
|||||||
///
|
///
|
||||||
/// Returns error if the previous declearation is incompatible with `decl`.
|
/// Returns error if the previous declearation is incompatible with `decl`.
|
||||||
fn add_decl(&mut self, name: &str, decl: ir::Declaration) -> Result<(), IrgenError> {
|
fn add_decl(&mut self, name: &str, decl: ir::Declaration) -> Result<(), IrgenError> {
|
||||||
let old_decl = some_or!(
|
let Some(old_decl) = self.decls.insert(name.to_string(), decl.clone()) else {
|
||||||
self.decls.insert(name.to_string(), decl.clone()),
|
return Ok(());
|
||||||
return Ok(())
|
};
|
||||||
);
|
|
||||||
|
|
||||||
// Check if type is conflicting for pre-declared one
|
// Check if type is conflicting for pre-declared one
|
||||||
if !old_decl.is_compatible(&decl) {
|
if !old_decl.is_compatible(&decl) {
|
||||||
@@ -781,9 +780,7 @@ fn is_invalid_structure(dtype: &ir::Dtype, structs: &HashMap<String, Option<ir::
|
|||||||
if let ir::Dtype::Struct { name, fields, .. } = dtype {
|
if let ir::Dtype::Struct { name, fields, .. } = dtype {
|
||||||
assert!(name.is_some() && fields.is_none());
|
assert!(name.is_some() && fields.is_none());
|
||||||
let name = name.as_ref().unwrap();
|
let name = name.as_ref().unwrap();
|
||||||
let struct_type = some_or!(structs.get(name), return true);
|
structs.get(name).is_none_or(Option::is_none)
|
||||||
|
|
||||||
struct_type.is_none()
|
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|||||||
23
src/lib.rs
23
src/lib.rs
@@ -7,8 +7,6 @@
|
|||||||
// <https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html>
|
// <https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html>
|
||||||
#![deny(
|
#![deny(
|
||||||
absolute_paths_not_starting_with_crate,
|
absolute_paths_not_starting_with_crate,
|
||||||
// Old, historical lint
|
|
||||||
// box_pointers,
|
|
||||||
elided_lifetimes_in_paths,
|
elided_lifetimes_in_paths,
|
||||||
explicit_outlives_requirements,
|
explicit_outlives_requirements,
|
||||||
keyword_idents,
|
keyword_idents,
|
||||||
@@ -16,25 +14,22 @@
|
|||||||
macro_use_extern_crate,
|
macro_use_extern_crate,
|
||||||
meta_variable_misuse,
|
meta_variable_misuse,
|
||||||
missing_abi,
|
missing_abi,
|
||||||
// Most stuff are reasonably not copy.
|
// These are stupid.
|
||||||
// missing_copy_implementations,
|
// missing_copy_implementations,
|
||||||
missing_debug_implementations,
|
// missing_debug_implementations,
|
||||||
// TODO
|
// TODO
|
||||||
// missing_docs
|
// missing_docs,
|
||||||
non_ascii_idents,
|
non_ascii_idents,
|
||||||
noop_method_call,
|
noop_method_call,
|
||||||
rust_2021_incompatible_closure_captures,
|
rust_2021_incompatible_closure_captures,
|
||||||
rust_2021_incompatible_or_patterns,
|
rust_2021_incompatible_or_patterns,
|
||||||
rust_2021_prefixes_incompatible_syntax,
|
rust_2021_prefixes_incompatible_syntax,
|
||||||
rust_2021_prelude_collisions,
|
rust_2021_prelude_collisions,
|
||||||
// Necessary for skeleton code.
|
single_use_lifetimes,
|
||||||
// single_use_lifetimes,
|
|
||||||
trivial_casts,
|
trivial_casts,
|
||||||
trivial_numeric_casts,
|
trivial_numeric_casts,
|
||||||
// Necessary for skeleton code.
|
unreachable_pub,
|
||||||
// unreachable_pub,
|
|
||||||
unsafe_code,
|
unsafe_code,
|
||||||
unsafe_op_in_unsafe_fn,
|
|
||||||
unstable_features,
|
unstable_features,
|
||||||
// Necessary for `build-bin` trick.
|
// Necessary for `build-bin` trick.
|
||||||
// unused_crate_dependencies,
|
// unused_crate_dependencies,
|
||||||
@@ -44,7 +39,7 @@
|
|||||||
unused_macro_rules,
|
unused_macro_rules,
|
||||||
unused_qualifications,
|
unused_qualifications,
|
||||||
unused_results,
|
unused_results,
|
||||||
// Allowed for more flexible variants.
|
// This is stupid. Allowed for more flexible variants.
|
||||||
// variant_size_differences,
|
// variant_size_differences,
|
||||||
)]
|
)]
|
||||||
// For skeleton code.
|
// For skeleton code.
|
||||||
@@ -67,9 +62,9 @@ pub use c::Parse;
|
|||||||
pub use ir::{Parse as IrParse, Visualizer as IrVisualizer};
|
pub use ir::{Parse as IrParse, Visualizer as IrVisualizer};
|
||||||
pub use irgen::Irgen;
|
pub use irgen::Irgen;
|
||||||
pub use opt::{
|
pub use opt::{
|
||||||
Deadcode, FunctionPass, Gvn, Mem2reg, Optimize, Repeat, SimplifyCfg, SimplifyCfgConstProp,
|
Deadcode, FunctionPass, Gvn, Mem2reg, O0, O1, Optimize, Repeat, SimplifyCfg,
|
||||||
SimplifyCfgEmpty, SimplifyCfgMerge, SimplifyCfgReach, O0, O1,
|
SimplifyCfgConstProp, SimplifyCfgEmpty, SimplifyCfgMerge, SimplifyCfgReach,
|
||||||
};
|
};
|
||||||
pub use tests::*;
|
pub use tests::*;
|
||||||
pub use utils::*;
|
pub use utils::*;
|
||||||
pub use write_base::write;
|
pub(crate) use write_base::write;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use crate::*;
|
|||||||
mod deadcode;
|
mod deadcode;
|
||||||
mod gvn;
|
mod gvn;
|
||||||
mod mem2reg;
|
mod mem2reg;
|
||||||
pub mod opt_utils;
|
pub(crate) mod opt_utils;
|
||||||
mod simplify_cfg;
|
mod simplify_cfg;
|
||||||
|
|
||||||
pub use deadcode::Deadcode;
|
pub use deadcode::Deadcode;
|
||||||
@@ -43,9 +43,7 @@ impl Optimize<ir::TranslationUnit> for Null {
|
|||||||
|
|
||||||
impl<T, O1: Optimize<T>, O2: Optimize<T>> Optimize<T> for (O1, O2) {
|
impl<T, O1: Optimize<T>, O2: Optimize<T>> Optimize<T> for (O1, O2) {
|
||||||
fn optimize(&mut self, code: &mut T) -> bool {
|
fn optimize(&mut self, code: &mut T) -> bool {
|
||||||
let changed1 = self.0.optimize(code);
|
self.0.optimize(code) | self.1.optimize(code)
|
||||||
let changed2 = self.1.optimize(code);
|
|
||||||
changed1 || changed2
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,8 +65,7 @@ where
|
|||||||
fn optimize(&mut self, code: &mut ir::TranslationUnit) -> bool {
|
fn optimize(&mut self, code: &mut ir::TranslationUnit) -> bool {
|
||||||
code.decls
|
code.decls
|
||||||
.values_mut()
|
.values_mut()
|
||||||
.map(|decl| self.optimize(decl))
|
.fold(false, |b, decl| b | self.optimize(decl))
|
||||||
.fold(false, |l, r| l | r)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,8 +74,9 @@ where
|
|||||||
T: Optimize<ir::FunctionDefinition>,
|
T: Optimize<ir::FunctionDefinition>,
|
||||||
{
|
{
|
||||||
fn optimize(&mut self, code: &mut ir::Declaration) -> bool {
|
fn optimize(&mut self, code: &mut ir::Declaration) -> bool {
|
||||||
let (_, fdef) = some_or!(code.get_function_mut(), return false);
|
let Some((_, Some(fdef))) = code.get_function_mut() else {
|
||||||
let fdef = some_or!(fdef, return false);
|
return false;
|
||||||
|
};
|
||||||
self.inner.optimize(fdef)
|
self.inner.optimize(fdef)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
87
src/tests.rs
87
src/tests.rs
@@ -1,7 +1,8 @@
|
|||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io::{stderr, Read, Write};
|
use std::io::{Read, Write, stderr};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::process::{Command, Stdio};
|
use std::process::{Command, Stdio};
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
use lang_c::*;
|
use lang_c::*;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
@@ -107,7 +108,7 @@ pub fn test_irgen(path: &Path) {
|
|||||||
.translate(&unit)
|
.translate(&unit)
|
||||||
.unwrap_or_else(|irgen_error| panic!("{}", irgen_error));
|
.unwrap_or_else(|irgen_error| panic!("{}", irgen_error));
|
||||||
|
|
||||||
let rand_num = rand::thread_rng().gen_range(1..100);
|
let rand_num = rand::rng().random_range(1..100);
|
||||||
let new_c = modify_c(path, rand_num);
|
let new_c = modify_c(path, rand_num);
|
||||||
modify_ir(&mut ir, rand_num);
|
modify_ir(&mut ir, rand_num);
|
||||||
|
|
||||||
@@ -148,17 +149,15 @@ pub fn test_irgen(path: &Path) {
|
|||||||
.spawn()
|
.spawn()
|
||||||
.expect("failed to execute the compiled executable");
|
.expect("failed to execute the compiled executable");
|
||||||
|
|
||||||
let status = some_or!(
|
let Some(status) = child
|
||||||
child
|
.wait_timeout(Duration::from_millis(1000))
|
||||||
.wait_timeout_ms(1000)
|
.expect("failed to obtain exit status from child process")
|
||||||
.expect("failed to obtain exit status from child process"),
|
else {
|
||||||
{
|
println!("timeout occurs");
|
||||||
println!("timeout occurs");
|
child.kill().unwrap();
|
||||||
child.kill().unwrap();
|
let _ = child.wait().unwrap();
|
||||||
let _ = child.wait().unwrap();
|
::std::process::exit(SKIP_TEST);
|
||||||
::std::process::exit(SKIP_TEST);
|
};
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if child
|
if child
|
||||||
.stderr
|
.stderr
|
||||||
@@ -302,7 +301,7 @@ pub fn test_asmgen(path: &Path) {
|
|||||||
.translate(&ir)
|
.translate(&ir)
|
||||||
.expect("fail to create riscv assembly code");
|
.expect("fail to create riscv assembly code");
|
||||||
|
|
||||||
let rand_num = rand::thread_rng().gen_range(1..100);
|
let rand_num = rand::rng().random_range(1..100);
|
||||||
modify_ir(&mut ir, rand_num);
|
modify_ir(&mut ir, rand_num);
|
||||||
modify_asm(&mut asm, rand_num);
|
modify_asm(&mut asm, rand_num);
|
||||||
|
|
||||||
@@ -345,17 +344,15 @@ pub fn test_asmgen(path: &Path) {
|
|||||||
.spawn()
|
.spawn()
|
||||||
.expect("failed to execute the compiled executable");
|
.expect("failed to execute the compiled executable");
|
||||||
|
|
||||||
let status = some_or!(
|
let Some(status) = child
|
||||||
child
|
.wait_timeout(Duration::from_millis(1000))
|
||||||
.wait_timeout_ms(1000)
|
.expect("failed to obtain exit status from child process")
|
||||||
.expect("failed to obtain exit status from child process"),
|
else {
|
||||||
{
|
println!("timeout occurs");
|
||||||
println!("timeout occurs");
|
child.kill().unwrap();
|
||||||
child.kill().unwrap();
|
let _ = child.wait().unwrap();
|
||||||
let _ = child.wait().unwrap();
|
::std::process::exit(SKIP_TEST);
|
||||||
::std::process::exit(SKIP_TEST);
|
};
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if child
|
if child
|
||||||
.stderr
|
.stderr
|
||||||
@@ -425,17 +422,15 @@ pub fn test_end_to_end(path: &Path) {
|
|||||||
.status()
|
.status()
|
||||||
.expect("failed to remove compiled executable");
|
.expect("failed to remove compiled executable");
|
||||||
|
|
||||||
let status = some_or!(
|
let Some(status) = child
|
||||||
child
|
.wait_timeout(Duration::from_millis(1000))
|
||||||
.wait_timeout_ms(1000)
|
.expect("failed to obtain exit status from child process")
|
||||||
.expect("failed to obtain exit status from child process"),
|
else {
|
||||||
{
|
println!("timeout occurs");
|
||||||
println!("timeout occurs");
|
child.kill().unwrap();
|
||||||
child.kill().unwrap();
|
let _ = child.wait().unwrap();
|
||||||
let _ = child.wait().unwrap();
|
::std::process::exit(SKIP_TEST);
|
||||||
::std::process::exit(SKIP_TEST);
|
};
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if child
|
if child
|
||||||
.stderr
|
.stderr
|
||||||
@@ -508,17 +503,15 @@ pub fn test_end_to_end(path: &Path) {
|
|||||||
.spawn()
|
.spawn()
|
||||||
.expect("failed to execute the compiled executable");
|
.expect("failed to execute the compiled executable");
|
||||||
|
|
||||||
let status = some_or!(
|
let Some(status) = child
|
||||||
child
|
.wait_timeout(Duration::from_millis(1000))
|
||||||
.wait_timeout_ms(1000)
|
.expect("failed to obtain exit status from child process")
|
||||||
.expect("failed to obtain exit status from child process"),
|
else {
|
||||||
{
|
println!("timeout occurs");
|
||||||
println!("timeout occurs");
|
child.kill().unwrap();
|
||||||
child.kill().unwrap();
|
let _ = child.wait().unwrap();
|
||||||
let _ = child.wait().unwrap();
|
::std::process::exit(SKIP_TEST);
|
||||||
::std::process::exit(SKIP_TEST);
|
};
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if child
|
if child
|
||||||
.stderr
|
.stderr
|
||||||
|
|||||||
13
src/utils.rs
13
src/utils.rs
@@ -1,14 +1,3 @@
|
|||||||
#[macro_export]
|
|
||||||
/// Some or executing the given expression.
|
|
||||||
macro_rules! some_or {
|
|
||||||
($e:expr_2021, $err:expr_2021) => {{
|
|
||||||
match $e {
|
|
||||||
Some(r) => r,
|
|
||||||
None => $err,
|
|
||||||
}
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
/// Ok or exiting the process.
|
/// Ok or exiting the process.
|
||||||
macro_rules! ok_or_exit {
|
macro_rules! ok_or_exit {
|
||||||
@@ -24,7 +13,7 @@ macro_rules! ok_or_exit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
/// Ok or exiting the process.
|
/// Some or exiting the process.
|
||||||
macro_rules! some_or_exit {
|
macro_rules! some_or_exit {
|
||||||
($e:expr_2021, $code:expr_2021) => {{
|
($e:expr_2021, $code:expr_2021) => {{
|
||||||
match $e {
|
match $e {
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
use std::io::{Result, Write};
|
use std::io::{Result, Write};
|
||||||
|
|
||||||
/// Write `indent` number of double spaces to `write`.
|
/// Write `indent` number of double spaces to `write`.
|
||||||
pub fn write_indent(indent: usize, write: &mut dyn Write) -> Result<()> {
|
pub(crate) fn write_indent(indent: usize, write: &mut dyn Write) -> Result<()> {
|
||||||
write!(write, "{}", " ".repeat(indent))
|
write!(write, "{}", " ".repeat(indent))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A trait for writing a type to a `Write` stream with a new line.
|
/// A trait for writing a type to a `Write` stream with a new line.
|
||||||
pub trait WriteLine {
|
pub(crate) trait WriteLine {
|
||||||
/// Write `self` to `write`, starting at `indent` number of double spaces, with a newline at the
|
/// Write `self` to `write`, starting at `indent` number of double spaces, with a newline at the
|
||||||
/// end.
|
/// end.
|
||||||
fn write_line(&self, indent: usize, write: &mut dyn Write) -> Result<()>;
|
fn write_line(&self, indent: usize, write: &mut dyn Write) -> Result<()>;
|
||||||
@@ -15,7 +15,7 @@ pub trait WriteLine {
|
|||||||
/// Essentially the same as [`ToString`].
|
/// Essentially the same as [`ToString`].
|
||||||
///
|
///
|
||||||
/// Exists to make some foreign types into a string.
|
/// Exists to make some foreign types into a string.
|
||||||
pub trait WriteString {
|
pub(crate) trait WriteString {
|
||||||
/// See [`ToString::to_string`].
|
/// See [`ToString::to_string`].
|
||||||
fn write_string(&self) -> String;
|
fn write_string(&self) -> String;
|
||||||
}
|
}
|
||||||
@@ -44,6 +44,6 @@ impl<T: WriteString> WriteString for Option<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Write `t` to `write`.
|
/// Write `t` to `write`.
|
||||||
pub fn write<T: WriteLine>(t: &T, write: &mut dyn Write) -> Result<()> {
|
pub(crate) fn write<T: WriteLine>(t: &T, write: &mut dyn Write) -> Result<()> {
|
||||||
t.write_line(0, write)
|
t.write_line(0, write)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user