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