Prepare for Spring 2025.

This commit is contained in:
Janggun Lee
2025-02-24 17:31:17 +09:00
parent a8e0aa5e69
commit fad9d02fea
53 changed files with 3442 additions and 1679 deletions

120
Cargo.lock generated
View File

@@ -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",
]

View File

@@ -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"

View File

@@ -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
View 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
View 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
View 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
}

View File

@@ -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:

View File

@@ -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
View 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
View 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
}

View File

@@ -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
View 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
}

View File

@@ -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

View File

@@ -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)
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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
View 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
}

View File

@@ -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
View 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
}

View File

@@ -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

View File

@@ -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
View 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
}

View File

@@ -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:

View File

@@ -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
View 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
View 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
}

View File

@@ -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
View 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
}

View File

@@ -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
View 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
}

View File

@@ -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:

View File

@@ -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
View 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
}

View File

@@ -1,3 +1,3 @@
[toolchain]
channel = "1.83.0"
channel = "1.85.0"
components = ["rustfmt", "clippy", "rust-analyzer"]

View File

@@ -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 {}

View File

@@ -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))`

View File

@@ -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;

View File

@@ -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,

View File

@@ -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));
}
}

View File

@@ -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)
}))
{

View File

@@ -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}")))
)
}
}

View File

@@ -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!()

View File

@@ -2,8 +2,8 @@
use std::collections::HashMap;
use crate::ir::*;
use crate::Translate;
use crate::ir::*;
#[derive(Default, Debug)]
pub struct Visualizer {

View File

@@ -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()

View File

@@ -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
}

View File

@@ -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;

View File

@@ -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)
}
}

View File

@@ -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

View File

@@ -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 {

View File

@@ -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)
}