diff --git a/Cargo.lock b/Cargo.lock
index c5c79e49..3a426243 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -112,6 +112,15 @@ version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
+[[package]]
+name = "ascii-canvas"
+version = "3.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6"
+dependencies = [
+ "term",
+]
+
[[package]]
name = "atty"
version = "0.2.14"
@@ -144,6 +153,21 @@ dependencies = [
"rustc-demangle",
]
+[[package]]
+name = "bit-set"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1"
+dependencies = [
+ "bit-vec",
+]
+
+[[package]]
+name = "bit-vec"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
+
[[package]]
name = "bitflags"
version = "1.3.2"
@@ -310,6 +334,12 @@ version = "0.100.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f333fa641a9ad2bff0b107767dcb972c18c2bfab7969805a1d7e42449ccb0408"
+[[package]]
+name = "crunchy"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
+
[[package]]
name = "crypto-common"
version = "0.1.6"
@@ -391,6 +421,15 @@ version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
+[[package]]
+name = "ena"
+version = "0.14.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c533630cf40e9caa44bd91aadc88a75d75a4c3a12b4cfde353cbed41daa1e1f1"
+dependencies = [
+ "log",
+]
+
[[package]]
name = "env_logger"
version = "0.9.3"
@@ -601,6 +640,17 @@ dependencies = [
"memoffset",
]
+[[package]]
+name = "is-terminal"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
+dependencies = [
+ "hermit-abi 0.3.2",
+ "rustix",
+ "windows-sys",
+]
+
[[package]]
name = "itertools"
version = "0.10.5"
@@ -637,6 +687,34 @@ dependencies = [
"cpufeatures",
]
+[[package]]
+name = "lalrpop"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da4081d44f4611b66c6dd725e6de3169f9f63905421e8626fcb86b6a898998b8"
+dependencies = [
+ "ascii-canvas",
+ "bit-set",
+ "diff",
+ "ena",
+ "is-terminal",
+ "itertools 0.10.5",
+ "lalrpop-util",
+ "petgraph",
+ "regex",
+ "regex-syntax",
+ "string_cache",
+ "term",
+ "tiny-keccak",
+ "unicode-xid",
+]
+
+[[package]]
+name = "lalrpop-util"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f35c735096c0293d313e8f2a641627472b83d01b937177fe76e5e2708d31e0d"
+
[[package]]
name = "lazy_static"
version = "1.4.0"
@@ -819,12 +897,16 @@ dependencies = [
"anyhow",
"cranelift-entity",
"intrusive-collections",
+ "lalrpop",
+ "lalrpop-util",
"miden-assembly",
"miden-diagnostics",
"miden-hir-symbol",
"miden-hir-type",
+ "miden-parsing",
"paste",
"petgraph",
+ "pretty_assertions",
"rustc-hash",
"smallvec",
"thiserror",
@@ -883,6 +965,16 @@ dependencies = [
"smallvec",
]
+[[package]]
+name = "miden-parsing"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d36dfec2c0319b3773a83627318f92a0212077bed80148c86e8b09af60cd1a88"
+dependencies = [
+ "miden-diagnostics",
+ "thiserror",
+]
+
[[package]]
name = "midenc"
version = "0.1.0"
@@ -906,6 +998,12 @@ dependencies = [
"adler",
]
+[[package]]
+name = "new_debug_unreachable"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
+
[[package]]
name = "num_cpus"
version = "1.16.0"
@@ -1002,6 +1100,21 @@ dependencies = [
"indexmap 2.0.0",
]
+[[package]]
+name = "phf_shared"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096"
+dependencies = [
+ "siphasher",
+]
+
+[[package]]
+name = "precomputed-hash"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
+
[[package]]
name = "pretty_assertions"
version = "1.4.0"
@@ -1226,12 +1339,31 @@ dependencies = [
"keccak",
]
+[[package]]
+name = "siphasher"
+version = "0.3.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
+
[[package]]
name = "smallvec"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
+[[package]]
+name = "string_cache"
+version = "0.8.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b"
+dependencies = [
+ "new_debug_unreachable",
+ "once_cell",
+ "parking_lot",
+ "phf_shared",
+ "precomputed-hash",
+]
+
[[package]]
name = "strsim"
version = "0.8.0"
@@ -1328,6 +1460,15 @@ dependencies = [
"syn 2.0.31",
]
+[[package]]
+name = "tiny-keccak"
+version = "2.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
+dependencies = [
+ "crunchy",
+]
+
[[package]]
name = "toml"
version = "0.7.6"
@@ -1386,6 +1527,12 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
+[[package]]
+name = "unicode-xid"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
+
[[package]]
name = "utf8parse"
version = "0.2.1"
diff --git a/frontend-wasm/src/code_translator/tests.rs b/frontend-wasm/src/code_translator/tests.rs
index 08be2e35..60c2f077 100644
--- a/frontend-wasm/src/code_translator/tests.rs
+++ b/frontend-wasm/src/code_translator/tests.rs
@@ -62,11 +62,15 @@ fn module() {
pub fn main() {
block0:
+ {
v0 = const.i32 0 : i32
br block1
+ }
block1:
- ret
+ {
+ ret
+ }
}
"#]],
);
@@ -90,12 +94,16 @@ fn locals() {
pub fn main() {
block0:
+ {
v0 = const.i32 0 : i32
v1 = const.i32 1 : i32
br block1
+ }
block1:
- ret
+ {
+ ret
+ }
}
"#]],
);
@@ -128,23 +136,31 @@ fn locals_inter_block() {
pub fn main() -> i32 {
block0:
+ {
v1 = const.i32 0 : i32
v2 = const.i32 3 : i32
br block2
+ }
block1(v0: i32):
- ret v0
+ {
+ ret (v0)
+ }
block2:
+ {
v3 = const.i32 5 : i32
v4 = add v2, v3 : i32
br block3
+ }
block3:
+ {
v5 = const.i32 7 : i32
v6 = add v5, v4 : i32
br block1(v6)
}
+ }
"#]],
);
}
@@ -171,22 +187,30 @@ fn func_call() {
pub fn add(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
+ {
v3 = add v0, v1 : i32
br block1(v3)
+ }
block1(v2: i32):
- ret v2
+ {
+ ret (v2)
+ }
}
pub fn main() -> i32 {
block0:
+ {
v1 = const.i32 3 : i32
v2 = const.i32 5 : i32
v3 = call noname::add(v1, v2) : i32
br block1(v3)
+ }
block1(v0: i32):
- ret v0
+ {
+ ret (v0)
+ }
}
"#]],
);
@@ -212,16 +236,22 @@ fn br() {
pub fn main() -> i32 {
block0:
+ {
v1 = const.i32 0 : i32
v2 = const.i32 3 : i32
br block2
+ }
block1(v0: i32):
- ret v0
+ {
+ ret (v0)
+ }
block2:
+ {
br block1(v2)
}
+ }
"#]],
);
}
@@ -255,26 +285,36 @@ fn loop_br_if() {
pub fn main() -> i32 {
block0:
+ {
v1 = const.i32 0 : i32
v2 = const.i32 2 : i32
br block2(v2, v1)
+ }
block1(v0: i32):
- ret v0
+ {
+ ret (v0)
+ }
block2(v3: i32, v4: i32):
+ {
v5 = add v3, v4 : i32
v6 = const.i32 1 : i32
v7 = sub v3, v6 : i32
v8 = neq v7, 0 : i1
condbr v8, block2(v7, v5), block4
+ }
block3:
+ {
br block1(v5)
+ }
block4:
+ {
br block3
}
+ }
"#]],
);
}
@@ -299,24 +339,34 @@ fn if_then_else() {
pub fn main() -> i32 {
block0:
+ {
v1 = const.i32 2 : i32
v2 = neq v1, 0 : i1
condbr v2, block2, block4
+ }
block1(v0: i32):
- ret v0
+ {
+ ret (v0)
+ }
block2:
+ {
v4 = const.i32 3 : i32
br block3(v4)
+ }
block3(v3: i32):
+ {
br block1(v3)
+ }
block4:
+ {
v5 = const.i32 5 : i32
br block3(v5)
}
+ }
"#]],
);
}
@@ -342,15 +392,19 @@ fn global_var() {
pub fn main() {
block0:
+ {
v0 = global.load (@MyGlobalVal) as *mut i8 : i32
v1 = const.i32 9 : i32
v2 = add v0, v1 : i32
v3 = global.symbol @MyGlobalVal : *mut i32
store v3, v2
br block1
+ }
block1:
- ret
+ {
+ ret
+ }
}
"#]],
);
diff --git a/frontend-wasm/tests/expected/dlmalloc.mir b/frontend-wasm/tests/expected/dlmalloc.mir
index 042965f7..c131e848 100644
--- a/frontend-wasm/tests/expected/dlmalloc.mir
+++ b/frontend-wasm/tests/expected/dlmalloc.mir
@@ -6,16 +6,21 @@ global external gv2 : i32 = 0x001001d0 { id = gvar2 };
pub fn dlmalloc::dlmalloc::Dlmalloc::dispose_chunk(i32, i32, i32) {
block0(v0: i32, v1: i32, v2: i32):
+{
v3 = const.i32 0 : i32
v4 = call noname::dlmalloc::dlmalloc::Chunk::plus_offset(v1, v2) : i32
v5 = call noname::dlmalloc::dlmalloc::Chunk::pinuse(v1) : i32
v6 = neq v5, 0 : i1
condbr v6, block4(v1, v2), block5
+}
block1:
- ret
+{
+ ret
+}
block2(v205: i32, v212: i32, v213: i32):
+{
v206 = const.i32 256 : i32
v207 = cast v205 : u32
v208 = cast v206 : u32
@@ -23,26 +28,34 @@ block2(v205: i32, v212: i32, v213: i32):
v210 = cast v209 : i32
v211 = neq v210, 0 : i1
condbr v211, block29, block30
+}
block3:
- ret
+{
+ ret
+}
block4(v93: i32, v94: i32):
+{
v89 = call noname::dlmalloc::dlmalloc::Chunk::cinuse(v4) : i32
v90 = eq v89, 0 : i1
v91 = cast v90 : i32
v92 = neq v91, 0 : i1
condbr v92, block16, block17
+}
block5:
+{
v7 = cast v1 : u32
v8 = inttoptr v7 : *mut i32
v9 = load v8 : i32
v10 = call noname::dlmalloc::dlmalloc::Chunk::mmapped(v1) : i32
v11 = neq v10, 0 : i1
condbr v11, block6, block7
+}
block6:
+{
v72 = sub v1, v9 : i32
v73 = add v2, v9 : i32
v74 = const.i32 16 : i32
@@ -52,8 +65,10 @@ block6:
v78 = cast v77 : i32
v79 = neq v78, 0 : i1
condbr v79, block3, block15
+}
block7:
+{
v12 = add v9, v2 : i32
v13 = call noname::dlmalloc::dlmalloc::Chunk::minus_offset(v1, v9) : i32
v14 = cast v0 : u32
@@ -64,8 +79,10 @@ block7:
v19 = cast v18 : i32
v20 = neq v19, 0 : i1
condbr v20, block8, block9
+}
block8:
+{
v34 = const.i32 256 : i32
v35 = cast v9 : u32
v36 = cast v34 : u32
@@ -73,8 +90,10 @@ block8:
v38 = cast v37 : i32
v39 = neq v38, 0 : i1
condbr v39, block11, block12
+}
block9:
+{
v21 = cast v4 : u32
v22 = add v21, 4 : u32
v23 = inttoptr v22 : *mut i32
@@ -86,16 +105,20 @@ block9:
v29 = cast v28 : i32
v30 = neq v29, 0 : i1
condbr v30, block4(v13, v12), block10
+}
block10:
+{
v31 = cast v0 : u32
v32 = add v31, 416 : u32
v33 = inttoptr v32 : *mut i32
store v33, v12
call noname::dlmalloc::dlmalloc::Chunk::set_free_with_pinuse(v13, v12, v4)
- ret
+ ret
+}
block11:
+{
v40 = cast v13 : u32
v41 = add v40, 12 : u32
v42 = inttoptr v41 : *mut i32
@@ -108,12 +131,16 @@ block11:
v49 = cast v48 : i32
v50 = neq v49, 0 : i1
condbr v50, block13, block14
+}
block12:
+{
call noname::dlmalloc::dlmalloc::Dlmalloc::unlink_large_chunk(v0, v13)
br block4(v13, v12)
+}
block13:
+{
v57 = cast v0 : u32
v58 = add v57, 408 : u32
v59 = inttoptr v58 : *mut i32
@@ -131,8 +158,10 @@ block13:
v71 = inttoptr v70 : *mut i32
store v71, v68
br block4(v13, v12)
+}
block14:
+{
v51 = cast v47 : u32
v52 = add v51, 12 : u32
v53 = inttoptr v52 : *mut i32
@@ -142,8 +171,10 @@ block14:
v56 = inttoptr v55 : *mut i32
store v56, v47
br block4(v13, v12)
+}
block15:
+{
v80 = cast v0 : u32
v81 = add v80, 432 : u32
v82 = inttoptr v81 : *mut i32
@@ -153,9 +184,11 @@ block15:
v86 = add v85, 432 : u32
v87 = inttoptr v86 : *mut i32
store v87, v84
- ret
+ ret
+}
block16:
+{
v96 = cast v0 : u32
v97 = add v96, 428 : u32
v98 = inttoptr v97 : *mut i32
@@ -164,12 +197,16 @@ block16:
v101 = cast v100 : i32
v102 = neq v101, 0 : i1
condbr v102, block19, block20
+}
block17:
+{
call noname::dlmalloc::dlmalloc::Chunk::set_free_with_pinuse(v93, v94, v88)
br block2(v94, v95, v93)
+}
block18:
+{
v194 = cast v95 : u32
v195 = add v194, 424 : u32
v196 = inttoptr v195 : *mut i32
@@ -184,9 +221,11 @@ block18:
v204 = inttoptr v203 : *mut i32
store v204, v201
call noname::dlmalloc::dlmalloc::Chunk::set_size_and_pinuse_of_free_chunk(v93, v201)
- ret
+ ret
+}
block19:
+{
v163 = cast v95 : u32
v164 = add v163, 428 : u32
v165 = inttoptr v164 : *mut i32
@@ -214,8 +253,10 @@ block19:
v184 = cast v183 : i32
v185 = neq v184, 0 : i1
condbr v185, block3, block28
+}
block20:
+{
v103 = cast v95 : u32
v104 = add v103, 424 : u32
v105 = inttoptr v104 : *mut i32
@@ -224,8 +265,10 @@ block20:
v108 = cast v107 : i32
v109 = neq v108, 0 : i1
condbr v109, block18, block21
+}
block21:
+{
v110 = call noname::dlmalloc::dlmalloc::Chunk::size(v88) : i32
v111 = add v110, v94 : i32
v112 = const.i32 256 : i32
@@ -235,8 +278,10 @@ block21:
v116 = cast v115 : i32
v117 = neq v116, 0 : i1
condbr v117, block23, block24
+}
block22:
+{
call noname::dlmalloc::dlmalloc::Chunk::set_size_and_pinuse_of_free_chunk(v93, v111)
v153 = cast v95 : u32
v154 = add v153, 424 : u32
@@ -246,8 +291,10 @@ block22:
v158 = cast v157 : i32
v159 = neq v158, 0 : i1
condbr v159, block2(v151, v152, v150), block27
+}
block23:
+{
v118 = cast v88 : u32
v119 = add v118, 12 : u32
v120 = inttoptr v119 : *mut i32
@@ -260,12 +307,16 @@ block23:
v127 = cast v126 : i32
v128 = neq v127, 0 : i1
condbr v128, block25, block26
+}
block24:
+{
call noname::dlmalloc::dlmalloc::Dlmalloc::unlink_large_chunk(v95, v88)
br block22
+}
block25:
+{
v135 = cast v95 : u32
v136 = add v135, 408 : u32
v137 = inttoptr v136 : *mut i32
@@ -283,8 +334,10 @@ block25:
v149 = inttoptr v148 : *mut i32
store v149, v146
br block22
+}
block26:
+{
v129 = cast v125 : u32
v130 = add v129, 12 : u32
v131 = inttoptr v130 : *mut i32
@@ -294,15 +347,19 @@ block26:
v134 = inttoptr v133 : *mut i32
store v134, v125
br block22
+}
block27:
+{
v160 = cast v152 : u32
v161 = add v160, 416 : u32
v162 = inttoptr v161 : *mut i32
store v162, v151
br block3
+}
block28:
+{
v186 = const.i32 0 : i32
v187 = cast v95 : u32
v188 = add v187, 416 : u32
@@ -313,9 +370,11 @@ block28:
v192 = add v191, 424 : u32
v193 = inttoptr v192 : *mut i32
store v193, v190
- ret
+ ret
+}
block29:
+{
v214 = const.i32 -8 : i32
v215 = band v205, v214 : i32
v216 = add v212, v215 : i32
@@ -337,12 +396,16 @@ block29:
v232 = cast v231 : i32
v233 = neq v232, 0 : i1
condbr v233, block32, block33
+}
block30:
+{
call noname::dlmalloc::dlmalloc::Dlmalloc::insert_large_chunk(v212, v213, v205)
- ret
+ ret
+}
block31(v247: i32):
+{
v244 = cast v218 : u32
v245 = add v244, 8 : u32
v246 = inttoptr v245 : *mut i32
@@ -360,25 +423,31 @@ block31(v247: i32):
v256 = inttoptr v255 : *mut i32
store v256, v247
br block1
+}
block32:
+{
v238 = bor v222, v229 : i32
v239 = cast v212 : u32
v240 = add v239, 408 : u32
v241 = inttoptr v240 : *mut i32
store v241, v238
br block31(v218)
+}
block33:
+{
v234 = cast v218 : u32
v235 = add v234, 8 : u32
v236 = inttoptr v235 : *mut i32
v237 = load v236 : i32
br block31(v237)
}
+}
pub fn dlmalloc::dlmalloc::Dlmalloc::unlink_large_chunk(i32, i32) {
block0(v0: i32, v1: i32):
+{
v2 = const.i32 0 : i32
v3 = cast v1 : u32
v4 = add v3, 24 : u32
@@ -389,24 +458,32 @@ block0(v0: i32, v1: i32):
v9 = cast v8 : i32
v10 = neq v9, 0 : i1
condbr v10, block4, block5
+}
block1:
- ret
+{
+ ret
+}
block2(v96: i32):
+{
v65 = eq v6, 0 : i1
v66 = cast v65 : i32
v67 = neq v66, 0 : i1
condbr v67, block10, block11
+}
block3:
+{
v36 = const.i32 16 : i32
v37 = add v1, v36 : i32
v38 = neq v17, 0 : i1
v39 = select v38, v14, v37 : i32
br block7(v39, v23)
+}
block4:
+{
v26 = call noname::dlmalloc::dlmalloc::TreeChunk::prev(v1) : i32
v27 = call noname::dlmalloc::dlmalloc::TreeChunk::next(v1) : i32
v28 = call noname::dlmalloc::dlmalloc::TreeChunk::chunk(v27) : i32
@@ -420,8 +497,10 @@ block4:
v35 = inttoptr v34 : *mut i32
store v35, v32
br block2(v27)
+}
block5:
+{
v11 = const.i32 20 : i32
v12 = const.i32 16 : i32
v13 = const.i32 20 : i32
@@ -437,12 +516,16 @@ block5:
v23 = load v22 : i32
v24 = neq v23, 0 : i1
condbr v24, block3, block6
+}
block6:
+{
v25 = const.i32 0 : i32
br block2(v25)
+}
block7(v40: i32, v41: i32):
+{
v42 = const.i32 20 : i32
v43 = add v41, v42 : i32
v44 = const.i32 16 : i32
@@ -462,21 +545,29 @@ block7(v40: i32, v41: i32):
v58 = load v57 : i32
v59 = neq v58, 0 : i1
condbr v59, block7(v50, v58), block9
+}
block8:
+{
v60 = const.i32 0 : i32
v61 = cast v40 : u32
v62 = inttoptr v61 : *mut i32
store v62, v60
br block2(v41)
+}
block9:
+{
br block8
+}
block10:
+{
br block1
+}
block11:
+{
v72 = cast v1 : u32
v73 = add v72, 28 : u32
v74 = inttoptr v73 : *mut i32
@@ -491,8 +582,10 @@ block11:
v83 = cast v82 : i32
v84 = neq v83, 0 : i1
condbr v84, block13, block14
+}
block12:
+{
v115 = cast v96 : u32
v116 = add v115, 24 : u32
v117 = inttoptr v116 : *mut i32
@@ -505,15 +598,19 @@ block12:
v124 = cast v123 : i32
v125 = neq v124, 0 : i1
condbr v125, block17, block18
+}
block13:
+{
v100 = cast v78 : u32
v101 = inttoptr v100 : *mut i32
store v101, v96
v102 = neq v96, 0 : i1
condbr v102, block12, block16
+}
block14:
+{
v85 = const.i32 16 : i32
v86 = const.i32 20 : i32
v87 = cast v63 : u32
@@ -530,11 +627,15 @@ block14:
store v98, v96
v99 = neq v96, 0 : i1
condbr v99, block12, block15
+}
block15:
+{
br block10
+}
block16:
+{
v103 = cast v68 : u32
v104 = add v103, 412 : u32
v105 = inttoptr v104 : *mut i32
@@ -546,9 +647,11 @@ block16:
v111 = add v110, 412 : u32
v112 = inttoptr v111 : *mut i32
store v112, v109
- ret
+ ret
+}
block17:
+{
v133 = const.i32 20 : i32
v134 = add v118, v133 : i32
v135 = cast v134 : u32
@@ -558,8 +661,10 @@ block17:
v139 = cast v138 : i32
v140 = neq v139, 0 : i1
condbr v140, block10, block19
+}
block18:
+{
v126 = cast v113 : u32
v127 = add v126, 16 : u32
v128 = inttoptr v127 : *mut i32
@@ -569,8 +674,10 @@ block18:
v131 = inttoptr v130 : *mut i32
store v131, v113
br block17
+}
block19:
+{
v142 = const.i32 20 : i32
v143 = add v113, v142 : i32
v144 = cast v143 : u32
@@ -580,11 +687,13 @@ block19:
v147 = add v146, 24 : u32
v148 = inttoptr v147 : *mut i32
store v148, v141
- ret
+ ret
+}
}
pub fn dlmalloc::dlmalloc::Dlmalloc::insert_large_chunk(i32, i32, i32) {
block0(v0: i32, v1: i32, v2: i32):
+{
v3 = const.i32 0 : i32
v4 = const.i32 0 : i32
v5 = const.i32 256 : i32
@@ -594,11 +703,15 @@ block0(v0: i32, v1: i32, v2: i32):
v9 = cast v8 : i32
v10 = neq v9, 0 : i1
condbr v10, block2(v4), block3
+}
block1:
- ret
+{
+ ret
+}
block2(v42: i32):
+{
v38 = const.i64 0 : i64
v39 = cast v1 : u32
v40 = add v39, 16 : u32
@@ -623,8 +736,10 @@ block2(v42: i32):
v59 = cast v58 : i32
v60 = neq v59, 0 : i1
condbr v60, block6, block7
+}
block3:
+{
v11 = const.i32 31 : i32
v12 = const.i32 16777215 : i32
v13 = cast v2 : u32
@@ -633,8 +748,10 @@ block3:
v16 = cast v15 : i32
v17 = neq v16, 0 : i1
condbr v17, block2(v11), block4
+}
block4:
+{
v18 = const.i32 6 : i32
v19 = const.i32 8 : i32
v20 = cast v2 : u32
@@ -655,8 +772,10 @@ block4:
v35 = const.i32 62 : i32
v36 = add v34, v35 : i32
br block2(v36)
+}
block5(v128: i32):
+{
v129 = cast v128 : u32
v130 = add v129, 8 : u32
v131 = inttoptr v130 : *mut i32
@@ -666,8 +785,10 @@ block5(v128: i32):
v134 = inttoptr v133 : *mut i32
store v134, v128
br block1
+}
block6:
+{
v119 = bor v54, v56 : i32
v120 = cast v46 : u32
v121 = add v120, 412 : u32
@@ -681,24 +802,30 @@ block6:
v127 = inttoptr v126 : *mut i32
store v127, v37
br block5(v50)
+}
block7:
+{
v61 = cast v49 : u32
v62 = inttoptr v61 : *mut i32
v63 = load v62 : i32
v65 = call noname::dlmalloc::dlmalloc::leftshift_for_tree_index(v42) : i32
v66 = shl v2, v65 : i32
br block8(v63, v66)
+}
block8(v67: i32, v97: i32):
+{
v68 = call noname::dlmalloc::dlmalloc::TreeChunk::chunk(v67) : i32
v69 = call noname::dlmalloc::dlmalloc::Chunk::size(v68) : i32
v71 = neq v69, v70 : i1
v72 = cast v71 : i32
v73 = neq v72, 0 : i1
condbr v73, block10, block11
+}
block9:
+{
v114 = cast v109 : u32
v115 = inttoptr v114 : *mut i32
store v115, v92
@@ -707,8 +834,10 @@ block9:
v118 = inttoptr v117 : *mut i32
store v118, v67
br block5(v79)
+}
block10:
+{
v98 = const.i32 29 : i32
v99 = cast v97 : u32
v100 = cast v98 : u32
@@ -726,8 +855,10 @@ block10:
v112 = load v111 : i32
v113 = neq v112, 0 : i1
condbr v113, block8(v112, v104), block12
+}
block11:
+{
v74 = call noname::dlmalloc::dlmalloc::TreeChunk::chunk(v67) : i32
v75 = cast v74 : u32
v76 = add v75, 8 : u32
@@ -754,14 +885,18 @@ block11:
v95 = add v94, 24 : u32
v96 = inttoptr v95 : *mut i32
store v96, v93
- ret
+ ret
+}
block12:
+{
br block9
}
+}
pub fn dlmalloc::dlmalloc::Dlmalloc::release_unused_segments(i32) -> i32 {
block0(v0: i32):
+{
v2 = const.i32 0 : i32
v3 = const.i32 136 : i32
v4 = add v0, v3 : i32
@@ -770,11 +905,15 @@ block0(v0: i32):
v7 = load v6 : i32
v8 = neq v7, 0 : i1
condbr v8, block3, block4
+}
block1(v1: i32):
- ret v1
+{
+ ret (v1)
+}
block2(v126: i32, v127: i32, v139: i32):
+{
v128 = const.i32 4095 : i32
v129 = const.i32 4095 : i32
v130 = cast v127 : u32
@@ -788,20 +927,26 @@ block2(v126: i32, v127: i32, v139: i32):
v138 = inttoptr v137 : *mut i32
store v138, v135
br block1(v139)
+}
block3:
+{
v11 = const.i32 128 : i32
v12 = add v0, v11 : i32
v13 = const.i32 0 : i32
v14 = const.i32 0 : i32
br block5(v7, v0, v12, v13, v14)
+}
block4:
+{
v9 = const.i32 0 : i32
v10 = const.i32 0 : i32
br block2(v0, v9, v10)
+}
block5(v15: i32, v27: i32, v102: i32, v108: i32, v114: i32):
+{
v16 = cast v15 : u32
v17 = add v16, 8 : u32
v18 = inttoptr v17 : *mut i32
@@ -827,25 +972,35 @@ block5(v15: i32, v27: i32, v102: i32, v108: i32, v114: i32):
v39 = cast v38 : i32
v40 = neq v39, 0 : i1
condbr v40, block8(v114, v19, v27, v108), block9
+}
block6:
+{
br block2(v121, v117, v124)
+}
block7(v112: i32, v118: i32, v121: i32, v123: i32, v124: i32):
+{
v116 = const.i32 1 : i32
v117 = add v112, v116 : i32
v120 = neq v118, 0 : i1
condbr v120, block5(v118, v121, v123, v124, v117), block18
+}
block8(v115: i32, v119: i32, v122: i32, v125: i32):
+{
br block7(v115, v119, v122, v15, v125)
+}
block9:
+{
v41 = call noname::dlmalloc::dlmalloc::Segment::is_extern(v15) : i32
v42 = neq v41, 0 : i1
condbr v42, block8(v114, v19, v27, v108), block10
+}
block10:
+{
v43 = call noname::dlmalloc::dlmalloc::Chunk::to_mem(v26) : i32
v44 = const.i32 8 : i32
v45 = call noname::dlmalloc::dlmalloc::align_up(v43, v44) : i32
@@ -864,8 +1019,10 @@ block10:
v58 = call noname::dlmalloc::dlmalloc::Chunk::inuse(v47) : i32
v59 = neq v58, 0 : i1
condbr v59, block8(v114, v19, v27, v108), block11
+}
block11:
+{
v60 = add v47, v48 : i32
v61 = add v49, v23 : i32
v62 = add v51, v54 : i32
@@ -878,8 +1035,10 @@ block11:
v69 = cast v68 : i32
v70 = neq v69, 0 : i1
condbr v70, block8(v114, v19, v27, v108), block12
+}
block12:
+{
v71 = cast v27 : u32
v72 = add v71, 424 : u32
v73 = inttoptr v72 : *mut i32
@@ -888,13 +1047,17 @@ block12:
v76 = cast v75 : i32
v77 = neq v76, 0 : i1
condbr v77, block14, block15
+}
block13:
+{
v89 = call noname::::free(v27, v26, v23) : i32
v90 = neq v89, 0 : i1
condbr v90, block16, block17
+}
block14:
+{
v78 = const.i32 0 : i32
v79 = cast v27 : u32
v80 = add v79, 416 : u32
@@ -906,12 +1069,16 @@ block14:
v85 = inttoptr v84 : *mut i32
store v85, v82
br block13
+}
block15:
+{
call noname::dlmalloc::dlmalloc::Dlmalloc::unlink_large_chunk(v27, v47)
br block13
+}
block16:
+{
v93 = cast v86 : u32
v94 = add v93, 432 : u32
v95 = inttoptr v94 : *mut i32
@@ -927,17 +1094,23 @@ block16:
store v106, v19
v109 = add v88, v108 : i32
br block7(v114, v103, v86, v101, v109)
+}
block17:
+{
call noname::dlmalloc::dlmalloc::Dlmalloc::insert_large_chunk(v86, v47, v48)
br block8(v113, v103, v86, v107)
+}
block18:
+{
br block6
}
+}
pub fn dlmalloc::dlmalloc::Dlmalloc::free(i32, i32) {
block0(v0: i32, v1: i32):
+{
v2 = const.i32 0 : i32
v3 = call noname::dlmalloc::dlmalloc::Chunk::from_mem(v1) : i32
v4 = call noname::dlmalloc::dlmalloc::Chunk::size(v3) : i32
@@ -945,29 +1118,39 @@ block0(v0: i32, v1: i32):
v6 = call noname::dlmalloc::dlmalloc::Chunk::pinuse(v3) : i32
v7 = neq v6, 0 : i1
condbr v7, block3(v3, v4), block4
+}
block1:
- ret
+{
+ ret
+}
block2:
+{
br block1
+}
block3(v94: i32, v95: i32):
+{
v90 = call noname::dlmalloc::dlmalloc::Chunk::cinuse(v5) : i32
v91 = eq v90, 0 : i1
v92 = cast v91 : i32
v93 = neq v92, 0 : i1
condbr v93, block16, block17
+}
block4:
+{
v8 = cast v3 : u32
v9 = inttoptr v8 : *mut i32
v10 = load v9 : i32
v11 = call noname::dlmalloc::dlmalloc::Chunk::mmapped(v3) : i32
v12 = neq v11, 0 : i1
condbr v12, block5, block6
+}
block5:
+{
v73 = sub v3, v10 : i32
v74 = add v4, v10 : i32
v75 = const.i32 16 : i32
@@ -977,8 +1160,10 @@ block5:
v79 = cast v78 : i32
v80 = neq v79, 0 : i1
condbr v80, block2, block14
+}
block6:
+{
v13 = add v10, v4 : i32
v14 = call noname::dlmalloc::dlmalloc::Chunk::minus_offset(v3, v10) : i32
v15 = cast v0 : u32
@@ -989,8 +1174,10 @@ block6:
v20 = cast v19 : i32
v21 = neq v20, 0 : i1
condbr v21, block7, block8
+}
block7:
+{
v35 = const.i32 256 : i32
v36 = cast v10 : u32
v37 = cast v35 : u32
@@ -998,8 +1185,10 @@ block7:
v39 = cast v38 : i32
v40 = neq v39, 0 : i1
condbr v40, block10, block11
+}
block8:
+{
v22 = cast v5 : u32
v23 = add v22, 4 : u32
v24 = inttoptr v23 : *mut i32
@@ -1011,16 +1200,20 @@ block8:
v30 = cast v29 : i32
v31 = neq v30, 0 : i1
condbr v31, block3(v14, v13), block9
+}
block9:
+{
v32 = cast v0 : u32
v33 = add v32, 416 : u32
v34 = inttoptr v33 : *mut i32
store v34, v13
call noname::dlmalloc::dlmalloc::Chunk::set_free_with_pinuse(v14, v13, v5)
- ret
+ ret
+}
block10:
+{
v41 = cast v14 : u32
v42 = add v41, 12 : u32
v43 = inttoptr v42 : *mut i32
@@ -1033,12 +1226,16 @@ block10:
v50 = cast v49 : i32
v51 = neq v50, 0 : i1
condbr v51, block12, block13
+}
block11:
+{
call noname::dlmalloc::dlmalloc::Dlmalloc::unlink_large_chunk(v0, v14)
br block3(v14, v13)
+}
block12:
+{
v58 = cast v0 : u32
v59 = add v58, 408 : u32
v60 = inttoptr v59 : *mut i32
@@ -1056,8 +1253,10 @@ block12:
v72 = inttoptr v71 : *mut i32
store v72, v69
br block3(v14, v13)
+}
block13:
+{
v52 = cast v48 : u32
v53 = add v52, 12 : u32
v54 = inttoptr v53 : *mut i32
@@ -1067,8 +1266,10 @@ block13:
v57 = inttoptr v56 : *mut i32
store v57, v48
br block3(v14, v13)
+}
block14:
+{
v81 = cast v0 : u32
v82 = add v81, 432 : u32
v83 = inttoptr v82 : *mut i32
@@ -1078,9 +1279,11 @@ block14:
v87 = add v86, 432 : u32
v88 = inttoptr v87 : *mut i32
store v88, v85
- ret
+ ret
+}
block15(v474: i32, v481: i32, v482: i32):
+{
v475 = const.i32 256 : i32
v476 = cast v474 : u32
v477 = cast v475 : u32
@@ -1088,8 +1291,10 @@ block15(v474: i32, v481: i32, v482: i32):
v479 = cast v478 : i32
v480 = neq v479, 0 : i1
condbr v480, block55, block56
+}
block16:
+{
v97 = cast v0 : u32
v98 = add v97, 428 : u32
v99 = inttoptr v98 : *mut i32
@@ -1098,12 +1303,16 @@ block16:
v102 = cast v101 : i32
v103 = neq v102, 0 : i1
condbr v103, block21, block22
+}
block17:
+{
call noname::dlmalloc::dlmalloc::Chunk::set_free_with_pinuse(v94, v95, v89)
br block15(v95, v96, v94)
+}
block18:
+{
v208 = cast v96 : u32
v209 = add v208, 440 : u32
v210 = inttoptr v209 : *mut i32
@@ -1114,8 +1323,10 @@ block18:
v215 = cast v214 : i32
v216 = neq v215, 0 : i1
condbr v216, block2, block31
+}
block19:
+{
v198 = const.i32 0 : i32
v199 = cast v96 : u32
v200 = add v199, 416 : u32
@@ -1127,8 +1338,10 @@ block19:
v205 = inttoptr v204 : *mut i32
store v205, v202
br block18
+}
block20:
+{
v187 = cast v96 : u32
v188 = add v187, 424 : u32
v189 = inttoptr v188 : *mut i32
@@ -1143,9 +1356,11 @@ block20:
v197 = inttoptr v196 : *mut i32
store v197, v194
call noname::dlmalloc::dlmalloc::Chunk::set_size_and_pinuse_of_free_chunk(v94, v194)
- ret
+ ret
+}
block21:
+{
v164 = cast v96 : u32
v165 = add v164, 428 : u32
v166 = inttoptr v165 : *mut i32
@@ -1173,8 +1388,10 @@ block21:
v185 = cast v184 : i32
v186 = neq v185, 0 : i1
condbr v186, block19, block30
+}
block22:
+{
v104 = cast v96 : u32
v105 = add v104, 424 : u32
v106 = inttoptr v105 : *mut i32
@@ -1183,8 +1400,10 @@ block22:
v109 = cast v108 : i32
v110 = neq v109, 0 : i1
condbr v110, block20, block23
+}
block23:
+{
v111 = call noname::dlmalloc::dlmalloc::Chunk::size(v89) : i32
v112 = add v111, v95 : i32
v113 = const.i32 256 : i32
@@ -1194,8 +1413,10 @@ block23:
v117 = cast v116 : i32
v118 = neq v117, 0 : i1
condbr v118, block25, block26
+}
block24:
+{
call noname::dlmalloc::dlmalloc::Chunk::set_size_and_pinuse_of_free_chunk(v94, v112)
v154 = cast v96 : u32
v155 = add v154, 424 : u32
@@ -1205,8 +1426,10 @@ block24:
v159 = cast v158 : i32
v160 = neq v159, 0 : i1
condbr v160, block15(v152, v153, v151), block29
+}
block25:
+{
v119 = cast v89 : u32
v120 = add v119, 12 : u32
v121 = inttoptr v120 : *mut i32
@@ -1219,12 +1442,16 @@ block25:
v128 = cast v127 : i32
v129 = neq v128, 0 : i1
condbr v129, block27, block28
+}
block26:
+{
call noname::dlmalloc::dlmalloc::Dlmalloc::unlink_large_chunk(v96, v89)
br block24
+}
block27:
+{
v136 = cast v96 : u32
v137 = add v136, 408 : u32
v138 = inttoptr v137 : *mut i32
@@ -1242,8 +1469,10 @@ block27:
v150 = inttoptr v149 : *mut i32
store v150, v147
br block24
+}
block28:
+{
v130 = cast v126 : u32
v131 = add v130, 12 : u32
v132 = inttoptr v131 : *mut i32
@@ -1253,18 +1482,24 @@ block28:
v135 = inttoptr v134 : *mut i32
store v135, v126
br block24
+}
block29:
+{
v161 = cast v153 : u32
v162 = add v161, 416 : u32
v163 = inttoptr v162 : *mut i32
store v163, v152
- ret
+ ret
+}
block30:
+{
br block18
+}
block31:
+{
v217 = call noname::dlmalloc::dlmalloc::Chunk::mem_offset() : i32
v218 = const.i32 8 : i32
v219 = call noname::dlmalloc::dlmalloc::align_up(v217, v218) : i32
@@ -1300,8 +1535,10 @@ block31:
v249 = cast v248 : i32
v250 = neq v249, 0 : i1
condbr v250, block2, block32
+}
block32:
+{
v251 = cast v207 : u32
v252 = add v251, 428 : u32
v253 = inttoptr v252 : *mut i32
@@ -1310,8 +1547,10 @@ block32:
v256 = cast v255 : i32
v257 = neq v256, 0 : i1
condbr v257, block2, block33
+}
block33:
+{
v258 = call noname::dlmalloc::dlmalloc::Chunk::mem_offset() : i32
v259 = const.i32 8 : i32
v260 = call noname::dlmalloc::dlmalloc::align_up(v258, v259) : i32
@@ -1335,8 +1574,10 @@ block33:
v278 = cast v277 : i32
v279 = neq v278, 0 : i1
condbr v279, block34(v207, v267), block35
+}
block34(v449: i32, v452: i32):
+{
v450 = call noname::dlmalloc::dlmalloc::Dlmalloc::release_unused_segments(v449) : i32
v451 = const.i32 0 : i32
v453 = sub v451, v452 : i32
@@ -1344,8 +1585,10 @@ block34(v449: i32, v452: i32):
v455 = cast v454 : i32
v456 = neq v455, 0 : i1
condbr v456, block2, block53
+}
block35:
+{
v280 = sub v271, v274 : i32
v281 = const.i32 65535 : i32
v282 = add v280, v281 : i32
@@ -1356,14 +1599,18 @@ block35:
v287 = const.i32 128 : i32
v288 = add v207, v287 : i32
br block37(v288)
+}
block36(v314: i32, v318: i32, v339: i32, v359: i32, v414: i32):
+{
v313 = const.i32 0 : i32
v315 = call noname::dlmalloc::dlmalloc::Segment::is_extern(v314) : i32
v316 = neq v315, 0 : i1
condbr v316, block34(v318, v313), block43
+}
block37(v289: i32):
+{
v290 = cast v289 : u32
v291 = inttoptr v290 : *mut i32
v292 = load v291 : i32
@@ -1373,20 +1620,26 @@ block37(v289: i32):
v297 = cast v296 : i32
v298 = neq v297, 0 : i1
condbr v298, block39, block40
+}
block38:
+{
v312 = const.i32 0 : i32
br block36(v312, v320, v341, v361, v416)
+}
block39:
+{
v306 = cast v289 : u32
v307 = add v306, 8 : u32
v308 = inttoptr v307 : *mut i32
v309 = load v308 : i32
v310 = neq v309, 0 : i1
condbr v310, block37(v309), block42
+}
block40:
+{
v299 = call noname::dlmalloc::dlmalloc::Segment::top(v289) : i32
v300 = cast v299 : u32
v301 = cast v293 : u32
@@ -1394,14 +1647,20 @@ block40:
v303 = cast v302 : i32
v304 = neq v303, 0 : i1
condbr v304, block36(v289, v207, v286, v288, v284), block41
+}
block41:
+{
br block39
+}
block42:
+{
br block38
+}
block43:
+{
v317 = const.i32 0 : i32
v321 = cast v314 : u32
v322 = add v321, 12 : u32
@@ -1417,8 +1676,10 @@ block43:
v332 = cast v331 : i32
v333 = neq v332, 0 : i1
condbr v333, block34(v318, v317), block44
+}
block44:
+{
v334 = const.i32 0 : i32
v335 = cast v314 : u32
v336 = add v335, 4 : u32
@@ -1430,18 +1691,24 @@ block44:
v345 = cast v344 : i32
v346 = neq v345, 0 : i1
condbr v346, block34(v318, v334), block45
+}
block45:
+{
br block46(v359)
+}
block46(v348: i32):
+{
v349 = call noname::dlmalloc::dlmalloc::Segment::holds(v347, v348) : i32
v350 = eq v349, 0 : i1
v351 = cast v350 : i32
v352 = neq v351, 0 : i1
condbr v352, block48, block49
+}
block47:
+{
v363 = cast v347 : u32
v364 = inttoptr v363 : *mut i32
v365 = load v364 : i32
@@ -1456,30 +1723,40 @@ block47:
v375 = cast v374 : i32
v376 = neq v375, 0 : i1
condbr v376, block34(v362, v373), block51
+}
block48:
+{
v354 = cast v348 : u32
v355 = add v354, 8 : u32
v356 = inttoptr v355 : *mut i32
v357 = load v356 : i32
v358 = neq v357, 0 : i1
condbr v358, block46(v357), block50
+}
block49:
+{
v353 = const.i32 0 : i32
br block34(v362, v353)
+}
block50:
+{
br block47
+}
block51:
+{
v377 = const.i32 0 : i32
v378 = eq v372, 0 : i1
v379 = cast v378 : i32
v380 = neq v379, 0 : i1
condbr v380, block34(v362, v377), block52
+}
block52:
+{
v381 = cast v347 : u32
v382 = add v381, 4 : u32
v383 = inttoptr v382 : *mut i32
@@ -1552,8 +1829,10 @@ block52:
v448 = inttoptr v447 : *mut i32
store v448, v445
br block34(v362, v370)
+}
block53:
+{
v457 = cast v449 : u32
v458 = add v457, 420 : u32
v459 = inttoptr v458 : *mut i32
@@ -1568,16 +1847,20 @@ block53:
v468 = cast v467 : i32
v469 = neq v468, 0 : i1
condbr v469, block2, block54
+}
block54:
+{
v470 = const.i32 -1 : i32
v471 = cast v449 : u32
v472 = add v471, 440 : u32
v473 = inttoptr v472 : *mut i32
store v473, v470
- ret
+ ret
+}
block55:
+{
v494 = const.i32 -8 : i32
v495 = band v474, v494 : i32
v496 = add v481, v495 : i32
@@ -1599,8 +1882,10 @@ block55:
v512 = cast v511 : i32
v513 = neq v512, 0 : i1
condbr v513, block59, block60
+}
block56:
+{
call noname::dlmalloc::dlmalloc::Dlmalloc::insert_large_chunk(v481, v482, v474)
v483 = cast v481 : u32
v484 = add v483, 448 : u32
@@ -1614,12 +1899,16 @@ block56:
store v491, v488
v492 = neq v488, 0 : i1
condbr v492, block2, block57
+}
block57:
+{
v493 = call noname::dlmalloc::dlmalloc::Dlmalloc::release_unused_segments(v481) : i32
- ret
+ ret
+}
block58(v527: i32):
+{
v524 = cast v498 : u32
v525 = add v524, 8 : u32
v526 = inttoptr v525 : *mut i32
@@ -1637,25 +1926,31 @@ block58(v527: i32):
v536 = inttoptr v535 : *mut i32
store v536, v527
br block2
+}
block59:
+{
v518 = bor v502, v509 : i32
v519 = cast v481 : u32
v520 = add v519, 408 : u32
v521 = inttoptr v520 : *mut i32
store v521, v518
br block58(v498)
+}
block60:
+{
v514 = cast v498 : u32
v515 = add v514, 8 : u32
v516 = inttoptr v515 : *mut i32
v517 = load v516 : i32
br block58(v517)
}
+}
pub fn dlmalloc::dlmalloc::Dlmalloc::malloc(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
+{
v3 = const.i32 0 : i32
v4 = const.i64 0 : i64
v5 = global.load (@__stack_pointer) as *mut i8 : i32
@@ -1670,18 +1965,24 @@ block0(v0: i32, v1: i32):
v13 = cast v12 : i32
v14 = neq v13, 0 : i1
condbr v14, block7, block8
+}
block1(v2: i32):
- ret v2
+{
+ ret (v2)
+}
block2(v1477: i32, v1501: i32):
+{
v1498 = const.i32 16 : i32
v1499 = add v1477, v1498 : i32
v1500 = global.symbol @__stack_pointer : *mut i32
store v1500, v1499
br block1(v1501)
+}
block3(v654: i32, v662: i32, v682: i32):
+{
v658 = cast v654 : u32
v659 = add v658, 416 : u32
v660 = inttoptr v659 : *mut i32
@@ -1692,22 +1993,30 @@ block3(v654: i32, v662: i32, v682: i32):
v671 = cast v670 : i32
v672 = neq v671, 0 : i1
condbr v672, block83, block84
+}
block4(v561: i32, v565: i32, v573: i32, v579: i32, v692: i32):
+{
v562 = eq v561, 0 : i1
v563 = cast v562 : i32
v564 = neq v563, 0 : i1
condbr v564, block3(v565, v573, v692), block63
+}
block5(v552: i32, v553: i32, v555: i32, v558: i32, v568: i32, v695: i32):
+{
br block60(v552, v553, v558)
+}
block6(v493: i32, v495: i32, v501: i32, v506: i32, v514: i32, v557: i32, v560: i32, v688: i32):
+{
v498 = bor v493, v495 : i32
v499 = neq v498, 0 : i1
condbr v499, block56(v493, v495), block57
+}
block7:
+{
v168 = const.i32 16 : i32
v169 = const.i32 4 : i32
v170 = add v1, v169 : i32
@@ -1743,8 +2052,10 @@ block7:
v200 = cast v199 : i32
v201 = neq v200, 0 : i1
condbr v201, block23, block24
+}
block8:
+{
v15 = call noname::dlmalloc::dlmalloc::Chunk::mem_offset() : i32
v16 = const.i32 8 : i32
v17 = call noname::dlmalloc::dlmalloc::align_up(v15, v16) : i32
@@ -1783,8 +2094,10 @@ block8:
v50 = cast v49 : i32
v51 = neq v50, 0 : i1
condbr v51, block2(v7, v24), block9
+}
block9:
+{
v52 = const.i32 4 : i32
v53 = add v1, v52 : i32
v54 = const.i32 8 : i32
@@ -1797,8 +2110,10 @@ block9:
v61 = cast v60 : i32
v62 = neq v61, 0 : i1
condbr v62, block3(v0, v55, v7), block10
+}
block10:
+{
v63 = const.i32 0 : i32
v64 = const.i32 0 : i32
v65 = const.i32 256 : i32
@@ -1808,8 +2123,10 @@ block10:
v69 = cast v68 : i32
v70 = neq v69, 0 : i1
condbr v70, block11(v64), block12
+}
block11(v101: i32):
+{
v97 = const.i32 0 : i32
v99 = sub v97, v55 : i32
v102 = const.i32 2 : i32
@@ -1820,8 +2137,10 @@ block11(v101: i32):
v107 = load v106 : i32
v108 = neq v107, 0 : i1
condbr v108, block14, block15
+}
block12:
+{
v71 = const.i32 31 : i32
v72 = const.i32 16777215 : i32
v73 = cast v55 : u32
@@ -1830,8 +2149,10 @@ block12:
v76 = cast v75 : i32
v77 = neq v76, 0 : i1
condbr v77, block11(v71), block13
+}
block13:
+{
v78 = const.i32 6 : i32
v79 = const.i32 8 : i32
v80 = cast v55 : u32
@@ -1852,19 +2173,25 @@ block13:
v95 = const.i32 62 : i32
v96 = add v94, v95 : i32
br block11(v96)
+}
block14:
+{
v110 = call noname::dlmalloc::dlmalloc::leftshift_for_tree_index(v101) : i32
v111 = shl v98, v110 : i32
v112 = const.i32 0 : i32
v113 = const.i32 0 : i32
br block16(v107, v99, v112, v111, v113, v101, v507, v100, v689)
+}
block15:
+{
v109 = const.i32 0 : i32
br block6(v63, v109, v101, v59, v100, v98, v99, v7)
+}
block16(v114: i32, v124: i32, v139: i32, v141: i32, v497: i32, v503: i32, v509: i32, v516: i32, v691: i32):
+{
v115 = call noname::dlmalloc::dlmalloc::TreeChunk::chunk(v114) : i32
v116 = call noname::dlmalloc::dlmalloc::Chunk::size(v115) : i32
v118 = cast v116 : u32
@@ -1873,10 +2200,14 @@ block16(v114: i32, v124: i32, v139: i32, v141: i32, v497: i32, v503: i32, v509:
v121 = cast v120 : i32
v122 = neq v121, 0 : i1
condbr v122, block18(v124, v497), block19
+}
block17:
+{
+}
block18(v167: i32, v496: i32):
+{
v133 = const.i32 20 : i32
v134 = add v114, v133 : i32
v135 = cast v134 : u32
@@ -1907,8 +2238,10 @@ block18(v167: i32, v496: i32):
v164 = cast v163 : i32
v165 = neq v164, 0 : i1
condbr v165, block6(v160, v496, v503, v509, v516, v166, v167, v691), block22
+}
block19:
+{
v123 = sub v116, v117 : i32
v125 = cast v123 : u32
v126 = cast v124 : u32
@@ -1916,19 +2249,27 @@ block19:
v128 = cast v127 : i32
v129 = neq v128, 0 : i1
condbr v129, block18(v124, v497), block20
+}
block20:
+{
v130 = neq v123, 0 : i1
condbr v130, block18(v123, v114), block21
+}
block21:
+{
v131 = const.i32 0 : i32
br block5(v114, v114, v117, v131, v516, v691)
+}
block22:
+{
br block16(v154, v167, v160, v162, v496, v502, v508, v515, v690)
+}
block23:
+{
v241 = cast v0 : u32
v242 = add v241, 416 : u32
v243 = inttoptr v242 : *mut i32
@@ -1939,8 +2280,10 @@ block23:
v248 = cast v247 : i32
v249 = neq v248, 0 : i1
condbr v249, block3(v0, v183, v7), block28
+}
block24:
+{
v202 = const.i32 -1 : i32
v203 = bxor v196, v202 : i32
v204 = const.i32 1 : i32
@@ -1964,15 +2307,19 @@ block24:
v222 = cast v221 : i32
v223 = neq v222, 0 : i1
condbr v223, block26, block27
+}
block25:
+{
v238 = const.i32 3 : i32
v239 = shl v206, v238 : i32
call noname::dlmalloc::dlmalloc::Chunk::set_inuse_and_pinuse(v214, v239)
v240 = call noname::dlmalloc::dlmalloc::Chunk::to_mem(v236) : i32
br block2(v7, v240)
+}
block26:
+{
v230 = const.i32 -2 : i32
v231 = shl v230, v206 : i32
v232 = band v187, v231 : i32
@@ -1981,8 +2328,10 @@ block26:
v235 = inttoptr v234 : *mut i32
store v235, v232
br block25
+}
block27:
+{
v224 = cast v218 : u32
v225 = add v224, 12 : u32
v226 = inttoptr v225 : *mut i32
@@ -1992,19 +2341,25 @@ block27:
v229 = inttoptr v228 : *mut i32
store v229, v218
br block25
+}
block28:
+{
v250 = neq v196, 0 : i1
condbr v250, block35, block36
+}
block29(v655: i32, v683: i32):
+{
v489 = call noname::dlmalloc::dlmalloc::Chunk::to_mem(v291) : i32
v490 = eq v489, 0 : i1
v491 = cast v490 : i32
v492 = neq v491, 0 : i1
condbr v492, block3(v655, v292, v683), block55
+}
block30:
+{
v478 = cast v294 : u32
v479 = add v478, 424 : u32
v480 = inttoptr v479 : *mut i32
@@ -2014,8 +2369,10 @@ block30:
v485 = inttoptr v484 : *mut i32
store v485, v296
br block29(v474, v684)
+}
block31(v1479: i32):
+{
v463 = cast v359 : u32
v464 = add v463, 424 : u32
v465 = inttoptr v464 : *mut i32
@@ -2026,8 +2383,10 @@ block31(v1479: i32):
store v470, v358
v473 = call noname::dlmalloc::dlmalloc::Chunk::to_mem(v352) : i32
br block2(v1479, v473)
+}
block32:
+{
v414 = const.i32 -8 : i32
v415 = band v363, v414 : i32
v416 = add v312, v415 : i32
@@ -2051,13 +2410,17 @@ block32:
v434 = cast v433 : i32
v435 = neq v434, 0 : i1
condbr v435, block53, block54
+}
block33:
+{
v412 = add v296, v292 : i32
call noname::dlmalloc::dlmalloc::Chunk::set_inuse_and_pinuse(v291, v412)
br block29(v294, v7)
+}
block34:
+{
v365 = const.i32 -8 : i32
v366 = band v309, v365 : i32
v367 = add v294, v366 : i32
@@ -2083,8 +2446,10 @@ block34:
v387 = cast v386 : i32
v388 = neq v387, 0 : i1
condbr v388, block50, block51
+}
block35:
+{
v311 = const.i32 144 : i32
v312 = add v0, v311 : i32
v313 = const.i32 1 : i32
@@ -2111,8 +2476,10 @@ block35:
v334 = cast v333 : i32
v335 = neq v334, 0 : i1
condbr v335, block46, block47
+}
block36:
+{
v251 = cast v0 : u32
v252 = add v251, 412 : u32
v253 = inttoptr v252 : *mut i32
@@ -2121,8 +2488,10 @@ block36:
v256 = cast v255 : i32
v257 = neq v256, 0 : i1
condbr v257, block3(v0, v183, v7), block37
+}
block37:
+{
v258 = call noname::dlmalloc::dlmalloc::least_bit(v254) : i32
v259 = popcnt v258 : i32
v260 = const.i32 2 : i32
@@ -2139,8 +2508,10 @@ block37:
v271 = cast v270 : i32
v272 = neq v271, 0 : i1
condbr v272, block38(v265, v183, v268), block39
+}
block38(v290: i32, v292: i32, v296: i32):
+{
v291 = call noname::dlmalloc::dlmalloc::TreeChunk::chunk(v290) : i32
v293 = call noname::dlmalloc::dlmalloc::Chunk::plus_offset(v291, v292) : i32
call noname::dlmalloc::dlmalloc::Dlmalloc::unlink_large_chunk(v0, v290)
@@ -2153,11 +2524,15 @@ block38(v290: i32, v292: i32, v296: i32):
v303 = cast v302 : i32
v304 = neq v303, 0 : i1
condbr v304, block33, block43
+}
block39:
+{
br block40(v269, v268, v265)
+}
block40(v273: i32, v278: i32, v285: i32):
+{
v274 = call noname::dlmalloc::dlmalloc::TreeChunk::chunk(v273) : i32
v275 = call noname::dlmalloc::dlmalloc::Chunk::size(v274) : i32
v277 = sub v275, v276 : i32
@@ -2172,14 +2547,20 @@ block40(v273: i32, v278: i32, v285: i32):
v288 = call noname::dlmalloc::dlmalloc::TreeChunk::leftmost_child(v273) : i32
v289 = neq v288, 0 : i1
condbr v289, block40(v288, v284, v287), block42
+}
block41:
+{
br block38(v287, v276, v284)
+}
block42:
+{
br block41
+}
block43:
+{
v305 = call noname::dlmalloc::dlmalloc::TreeChunk::chunk(v293) : i32
call noname::dlmalloc::dlmalloc::Chunk::set_size_and_pinuse_of_inuse_chunk(v291, v292)
call noname::dlmalloc::dlmalloc::Chunk::set_size_and_pinuse_of_free_chunk(v305, v296)
@@ -2189,11 +2570,15 @@ block43:
v309 = load v308 : i32
v310 = neq v309, 0 : i1
condbr v310, block34, block44
+}
block44:
+{
br block30
+}
block45:
+{
call noname::dlmalloc::dlmalloc::Chunk::set_size_and_pinuse_of_inuse_chunk(v328, v183)
v354 = call noname::dlmalloc::dlmalloc::Chunk::plus_offset(v352, v353) : i32
v356 = const.i32 3 : i32
@@ -2206,8 +2591,10 @@ block45:
v363 = load v362 : i32
v364 = neq v363, 0 : i1
condbr v364, block32, block48
+}
block46:
+{
v342 = cast v0 : u32
v343 = add v342, 408 : u32
v344 = inttoptr v343 : *mut i32
@@ -2220,8 +2607,10 @@ block46:
v351 = inttoptr v350 : *mut i32
store v351, v348
br block45
+}
block47:
+{
v336 = cast v332 : u32
v337 = add v336, 12 : u32
v338 = inttoptr v337 : *mut i32
@@ -2231,11 +2620,15 @@ block47:
v341 = inttoptr v340 : *mut i32
store v341, v332
br block45
+}
block48:
+{
br block31(v7)
+}
block49(v402: i32):
+{
v399 = cast v369 : u32
v400 = add v399, 8 : u32
v401 = inttoptr v400 : *mut i32
@@ -2253,23 +2646,29 @@ block49(v402: i32):
v411 = inttoptr v410 : *mut i32
store v411, v402
br block30
+}
block50:
+{
v393 = bor v377, v384 : i32
v394 = cast v294 : u32
v395 = add v394, 408 : u32
v396 = inttoptr v395 : *mut i32
store v396, v393
br block49(v369)
+}
block51:
+{
v389 = cast v369 : u32
v390 = add v389, 8 : u32
v391 = inttoptr v390 : *mut i32
v392 = load v391 : i32
br block49(v392)
+}
block52(v449: i32):
+{
v446 = cast v416 : u32
v447 = add v446, 8 : u32
v448 = inttoptr v447 : *mut i32
@@ -2287,32 +2686,42 @@ block52(v449: i32):
v458 = inttoptr v457 : *mut i32
store v458, v449
br block31(v1480)
+}
block53:
+{
v440 = bor v424, v431 : i32
v441 = cast v359 : u32
v442 = add v441, 408 : u32
v443 = inttoptr v442 : *mut i32
store v443, v440
br block52(v416)
+}
block54:
+{
v436 = cast v416 : u32
v437 = add v436, 8 : u32
v438 = inttoptr v437 : *mut i32
v439 = load v438 : i32
br block52(v439)
+}
block55:
+{
br block2(v683, v489)
+}
block56(v526: i32, v554: i32):
+{
v527 = eq v526, 0 : i1
v528 = cast v527 : i32
v529 = neq v528, 0 : i1
condbr v529, block4(v554, v514, v556, v559, v688), block59
+}
block57:
+{
v500 = const.i32 1 : i32
v504 = shl v500, v501 : i32
v505 = call noname::dlmalloc::dlmalloc::left_bits(v504) : i32
@@ -2321,8 +2730,10 @@ block57:
v512 = cast v511 : i32
v513 = neq v512, 0 : i1
condbr v513, block3(v514, v557, v688), block58
+}
block58:
+{
v517 = call noname::dlmalloc::dlmalloc::least_bit(v510) : i32
v518 = popcnt v517 : i32
v519 = const.i32 2 : i32
@@ -2333,11 +2744,15 @@ block58:
v524 = load v523 : i32
v525 = const.i32 0 : i32
br block56(v524, v525)
+}
block59:
+{
br block5(v526, v554, v557, v560, v566, v693)
+}
block60(v530: i32, v531: i32, v540: i32):
+{
v532 = call noname::dlmalloc::dlmalloc::TreeChunk::chunk(v530) : i32
v533 = call noname::dlmalloc::dlmalloc::Chunk::size(v532) : i32
v535 = cast v533 : u32
@@ -2357,14 +2772,20 @@ block60(v530: i32, v531: i32, v540: i32):
v550 = call noname::dlmalloc::dlmalloc::TreeChunk::leftmost_child(v530) : i32
v551 = neq v550, 0 : i1
condbr v551, block60(v550, v547, v549), block62
+}
block61:
+{
br block4(v547, v568, v534, v549, v695)
+}
block62:
+{
br block61
+}
block63:
+{
v569 = cast v565 : u32
v570 = add v569, 416 : u32
v571 = inttoptr v570 : *mut i32
@@ -2375,8 +2796,10 @@ block63:
v577 = cast v576 : i32
v578 = neq v577, 0 : i1
condbr v578, block64, block65
+}
block64:
+{
v587 = call noname::dlmalloc::dlmalloc::TreeChunk::chunk(v561) : i32
v589 = call noname::dlmalloc::dlmalloc::Chunk::plus_offset(v587, v573) : i32
call noname::dlmalloc::dlmalloc::Dlmalloc::unlink_large_chunk(v565, v586)
@@ -2389,8 +2812,10 @@ block64:
v598 = cast v597 : i32
v599 = neq v598, 0 : i1
condbr v599, block68, block69
+}
block65:
+{
v580 = sub v572, v573 : i32
v581 = cast v579 : u32
v582 = cast v580 : u32
@@ -2398,21 +2823,29 @@ block65:
v584 = cast v583 : i32
v585 = neq v584, 0 : i1
condbr v585, block3(v565, v573, v692), block66
+}
block66:
+{
br block64
+}
block67(v696: i32):
+{
v652 = call noname::dlmalloc::dlmalloc::Chunk::to_mem(v587) : i32
v653 = neq v652, 0 : i1
condbr v653, block2(v696, v652), block75
+}
block68:
+{
v649 = add v591, v588 : i32
call noname::dlmalloc::dlmalloc::Chunk::set_inuse_and_pinuse(v587, v649)
br block67(v697)
+}
block69:
+{
call noname::dlmalloc::dlmalloc::Chunk::set_size_and_pinuse_of_inuse_chunk(v587, v588)
call noname::dlmalloc::dlmalloc::Chunk::set_size_and_pinuse_of_free_chunk(v589, v591)
v600 = const.i32 256 : i32
@@ -2422,8 +2855,10 @@ block69:
v604 = cast v603 : i32
v605 = neq v604, 0 : i1
condbr v605, block70, block71
+}
block70:
+{
v606 = const.i32 -8 : i32
v607 = band v591, v606 : i32
v608 = add v590, v607 : i32
@@ -2445,12 +2880,16 @@ block70:
v624 = cast v623 : i32
v625 = neq v624, 0 : i1
condbr v625, block73, block74
+}
block71:
+{
call noname::dlmalloc::dlmalloc::Dlmalloc::insert_large_chunk(v590, v589, v591)
br block67(v692)
+}
block72(v639: i32):
+{
v636 = cast v610 : u32
v637 = add v636, 8 : u32
v638 = inttoptr v637 : *mut i32
@@ -2468,26 +2907,34 @@ block72(v639: i32):
v648 = inttoptr v647 : *mut i32
store v648, v639
br block67(v697)
+}
block73:
+{
v630 = bor v614, v621 : i32
v631 = cast v590 : u32
v632 = add v631, 408 : u32
v633 = inttoptr v632 : *mut i32
store v633, v630
br block72(v610)
+}
block74:
+{
v626 = cast v610 : u32
v627 = add v626, 8 : u32
v628 = inttoptr v627 : *mut i32
v629 = load v628 : i32
br block72(v629)
+}
block75:
+{
br block3(v590, v588, v696)
+}
block76(v1438: i32, v1444: i32, v1488: i32, v1502: i32):
+{
v1440 = cast v1438 : u32
v1441 = add v1440, 420 : u32
v1442 = inttoptr v1441 : *mut i32
@@ -2498,8 +2945,10 @@ block76(v1438: i32, v1444: i32, v1488: i32, v1502: i32):
v1457 = cast v1456 : i32
v1458 = neq v1457, 0 : i1
condbr v1458, block2(v1488, v1502), block144
+}
block77(v1321: i32, v1326: i32):
+{
v1322 = const.i32 4095 : i32
v1323 = cast v1321 : u32
v1324 = add v1323, 448 : u32
@@ -2521,8 +2970,10 @@ block77(v1321: i32, v1326: i32):
store v1341, v737
v1342 = const.i32 0 : i32
br block141(v1342)
+}
block78(v1263: i32, v1264: i32):
+{
call noname::dlmalloc::dlmalloc::Chunk::set_free_with_pinuse(v1093, v1263, v1264)
v1265 = const.i32 256 : i32
v1266 = cast v1263 : u32
@@ -2531,8 +2982,10 @@ block78(v1263: i32, v1264: i32):
v1269 = cast v1268 : i32
v1270 = neq v1269, 0 : i1
condbr v1270, block136, block137
+}
block79:
+{
v1248 = const.i32 0 : i32
v1249 = cast v654 : u32
v1250 = add v1249, 424 : u32
@@ -2550,8 +3003,10 @@ block79:
call noname::dlmalloc::dlmalloc::Chunk::set_inuse_and_pinuse(v1196, v1255)
v1260 = call noname::dlmalloc::dlmalloc::Chunk::to_mem(v1196) : i32
br block2(v682, v1260)
+}
block80:
+{
v1236 = cast v841 : u32
v1237 = add v1236, 424 : u32
v1238 = inttoptr v1237 : *mut i32
@@ -2568,8 +3023,10 @@ block80:
call noname::dlmalloc::dlmalloc::Chunk::set_size_and_pinuse_of_free_chunk(v1093, v1243)
v1247 = call noname::dlmalloc::dlmalloc::Chunk::to_mem(v1089) : i32
br block2(v1482, v1247)
+}
block81:
+{
v1219 = cast v775 : u32
v1220 = add v1219, 4 : u32
v1221 = inttoptr v1220 : *mut i32
@@ -2590,15 +3047,19 @@ block81:
v1235 = add v1234, v815 : i32
call noname::dlmalloc::dlmalloc::Dlmalloc::init_top(v792, v1230, v1235)
br block76(v792, v1092, v1484, v1509)
+}
block82:
+{
v1216 = cast v654 : u32
v1217 = add v1216, 444 : u32
v1218 = inttoptr v1217 : *mut i32
store v1218, v722
br block77(v1214, v1215)
+}
block83:
+{
v1193 = cast v654 : u32
v1194 = add v1193, 424 : u32
v1195 = inttoptr v1194 : *mut i32
@@ -2613,8 +3074,10 @@ block83:
v1204 = cast v1203 : i32
v1205 = neq v1204, 0 : i1
condbr v1205, block79, block135
+}
block84:
+{
v673 = cast v654 : u32
v674 = add v673, 420 : u32
v675 = inttoptr v674 : *mut i32
@@ -2625,8 +3088,10 @@ block84:
v680 = cast v679 : i32
v681 = neq v680, 0 : i1
condbr v681, block85, block86
+}
block85:
+{
v1175 = sub v676, v662 : i32
v1176 = cast v654 : u32
v1177 = add v1176, 420 : u32
@@ -2650,8 +3115,10 @@ block85:
call noname::dlmalloc::dlmalloc::Chunk::set_size_and_pinuse_of_inuse_chunk(v1182, v662)
v1192 = call noname::dlmalloc::dlmalloc::Chunk::to_mem(v1182) : i32
br block2(v682, v1192)
+}
block86:
+{
v699 = const.i32 4 : i32
v700 = add v682, v699 : i32
v701 = call noname::dlmalloc::dlmalloc::Chunk::mem_offset() : i32
@@ -2681,8 +3148,10 @@ block86:
v724 = cast v723 : i32
v725 = neq v724, 0 : i1
condbr v725, block2(v682, v718), block87
+}
block87:
+{
v726 = cast v682 : u32
v727 = add v726, 12 : u32
v728 = inttoptr v727 : *mut i32
@@ -2720,13 +3189,17 @@ block87:
v758 = load v757 : i32
v759 = neq v758, 0 : i1
condbr v759, block88, block89
+}
block88:
+{
v772 = const.i32 128 : i32
v773 = add v654, v772 : i32
br block94(v773)
+}
block89:
+{
v760 = cast v654 : u32
v761 = add v760, 444 : u32
v762 = inttoptr v761 : *mut i32
@@ -2735,19 +3208,25 @@ block89:
v765 = cast v764 : i32
v766 = neq v765, 0 : i1
condbr v766, block82, block90
+}
block90:
+{
v767 = cast v722 : u32
v768 = cast v763 : u32
v769 = lt v767, v768 : i1
v770 = cast v769 : i32
v771 = neq v770, 0 : i1
condbr v771, block82, block91
+}
block91:
+{
br block77(v654, v722)
+}
block92(v814: i32, v817: i32, v1091: i32, v1483: i32, v1508: i32):
+{
v800 = cast v799 : u32
v801 = add v800, 444 : u32
v802 = inttoptr v801 : *mut i32
@@ -2764,40 +3243,54 @@ block92(v814: i32, v817: i32, v1091: i32, v1483: i32, v1508: i32):
store v813, v810
v816 = add v804, v814 : i32
br block104(v817)
+}
block93:
+{
v785 = call noname::dlmalloc::dlmalloc::Segment::is_extern(v775) : i32
v786 = neq v785, 0 : i1
condbr v786, block92(v815, v818, v1092, v1484, v1509), block98
+}
block94(v775: i32):
+{
v776 = call noname::dlmalloc::dlmalloc::Segment::top(v775) : i32
v777 = eq v774, v776 : i1
v778 = cast v777 : i32
v779 = neq v778, 0 : i1
condbr v779, block93, block96
+}
block95:
+{
+}
block96:
+{
v780 = cast v775 : u32
v781 = add v780, 8 : u32
v782 = inttoptr v781 : *mut i32
v783 = load v782 : i32
v784 = neq v783, 0 : i1
condbr v784, block94(v783), block97
+}
block97:
+{
br block92(v737, v773, v662, v682, v718)
+}
block98:
+{
v787 = call noname::dlmalloc::dlmalloc::Segment::sys_flags(v775) : i32
v789 = neq v787, v729 : i1
v790 = cast v789 : i32
v791 = neq v790, 0 : i1
condbr v791, block92(v815, v818, v1092, v1484, v1509), block99
+}
block99:
+{
v793 = cast v654 : u32
v794 = add v793, 428 : u32
v795 = inttoptr v794 : *mut i32
@@ -2805,11 +3298,15 @@ block99:
v797 = call noname::dlmalloc::dlmalloc::Segment::holds(v775, v796) : i32
v798 = neq v797, 0 : i1
condbr v798, block81, block100
+}
block100:
+{
br block92(v815, v818, v1092, v1484, v1509)
+}
block101:
+{
v1069 = cast v819 : u32
v1070 = inttoptr v1069 : *mut i32
v1071 = load v1070 : i32
@@ -2847,20 +3344,26 @@ block101:
v1103 = cast v1102 : i32
v1104 = neq v1103, 0 : i1
condbr v1104, block126, block127
+}
block102(v840: i32, v846: i32, v912: i32, v925: i32, v1506: i32):
+{
v842 = cast v840 : u32
v843 = add v842, 428 : u32
v844 = inttoptr v843 : *mut i32
v845 = load v844 : i32
br block111(v846)
+}
block103:
+{
v832 = call noname::dlmalloc::dlmalloc::Segment::is_extern(v819) : i32
v833 = neq v832, 0 : i1
condbr v833, block102(v841, v847, v913, v926, v1507), block108
+}
block104(v819: i32):
+{
v820 = cast v819 : u32
v821 = inttoptr v820 : *mut i32
v822 = load v821 : i32
@@ -2868,31 +3371,43 @@ block104(v819: i32):
v825 = cast v824 : i32
v826 = neq v825, 0 : i1
condbr v826, block103, block106
+}
block105:
+{
+}
block106:
+{
v827 = cast v819 : u32
v828 = add v827, 8 : u32
v829 = inttoptr v828 : *mut i32
v830 = load v829 : i32
v831 = neq v830, 0 : i1
condbr v831, block104(v830), block107
+}
block107:
+{
br block102(v799, v817, v804, v814, v1508)
+}
block108:
+{
v834 = call noname::dlmalloc::dlmalloc::Segment::sys_flags(v819) : i32
v837 = eq v834, v788 : i1
v838 = cast v837 : i32
v839 = neq v838, 0 : i1
condbr v839, block101, block109
+}
block109:
+{
br block102(v841, v847, v913, v926, v1507)
+}
block110(v872: i32, v880: i32, v907: i32, v910: i32, v923: i32, v961: i32, v980: i32, v1446: i32, v1490: i32, v1504: i32):
+{
v873 = call noname::dlmalloc::dlmalloc::Segment::top(v872) : i32
v874 = const.i32 20 : i32
v875 = const.i32 8 : i32
@@ -3009,8 +3524,10 @@ block110(v872: i32, v880: i32, v907: i32, v910: i32, v923: i32, v961: i32, v980:
v996 = inttoptr v995 : *mut i32
store v996, v896
br block117(v897)
+}
block111(v848: i32):
+{
v849 = cast v848 : u32
v850 = inttoptr v849 : *mut i32
v851 = load v850 : i32
@@ -3020,20 +3537,26 @@ block111(v848: i32):
v856 = cast v855 : i32
v857 = neq v856, 0 : i1
condbr v857, block113, block114
+}
block112:
+{
v871 = const.i32 0 : i32
br block110(v871, v870, v909, v914, v927, v963, v983, v1449, v1493, v1510)
+}
block113:
+{
v865 = cast v848 : u32
v866 = add v865, 8 : u32
v867 = inttoptr v866 : *mut i32
v868 = load v867 : i32
v869 = neq v868, 0 : i1
condbr v869, block111(v868), block116
+}
block114:
+{
v858 = call noname::dlmalloc::dlmalloc::Segment::top(v848) : i32
v859 = cast v858 : u32
v860 = cast v852 : u32
@@ -3041,14 +3564,20 @@ block114:
v862 = cast v861 : i32
v863 = neq v862, 0 : i1
condbr v863, block110(v848, v852, v840, v912, v925, v846, v835, v1090, v1482, v1506), block115
+}
block115:
+{
br block113
+}
block116:
+{
br block112
+}
block117(v997: i32):
+{
v998 = const.i32 4 : i32
v999 = call noname::dlmalloc::dlmalloc::Chunk::plus_offset(v997, v998) : i32
v1000 = call noname::dlmalloc::dlmalloc::Chunk::fencepost_head() : i32
@@ -3064,17 +3593,23 @@ block117(v997: i32):
v1010 = cast v1009 : i32
v1011 = neq v1010, 0 : i1
condbr v1011, block117(v999), block119
+}
block118:
+{
v1014 = eq v895, v880 : i1
v1015 = cast v1014 : i32
v1016 = neq v1015, 0 : i1
condbr v1016, block76(v1025, v1446, v1490, v1504), block120
+}
block119:
+{
br block118
+}
block120:
+{
v1017 = sub v1012, v1013 : i32
v1018 = call noname::dlmalloc::dlmalloc::Chunk::plus_offset(v1013, v1017) : i32
call noname::dlmalloc::dlmalloc::Chunk::set_free_with_pinuse(v1013, v1017, v1018)
@@ -3085,8 +3620,10 @@ block120:
v1023 = cast v1022 : i32
v1024 = neq v1023, 0 : i1
condbr v1024, block121, block122
+}
block121:
+{
v1026 = const.i32 -8 : i32
v1027 = band v1017, v1026 : i32
v1028 = add v1025, v1027 : i32
@@ -3108,12 +3645,16 @@ block121:
v1044 = cast v1043 : i32
v1045 = neq v1044, 0 : i1
condbr v1045, block124, block125
+}
block122:
+{
call noname::dlmalloc::dlmalloc::Dlmalloc::insert_large_chunk(v907, v1013, v1017)
br block76(v1025, v1445, v1489, v1503)
+}
block123(v1059: i32):
+{
v1056 = cast v1030 : u32
v1057 = add v1056, 8 : u32
v1058 = inttoptr v1057 : *mut i32
@@ -3131,23 +3672,29 @@ block123(v1059: i32):
v1068 = inttoptr v1067 : *mut i32
store v1068, v1059
br block76(v1025, v1445, v1489, v1503)
+}
block124:
+{
v1050 = bor v1034, v1041 : i32
v1051 = cast v1025 : u32
v1052 = add v1051, 408 : u32
v1053 = inttoptr v1052 : *mut i32
store v1053, v1050
br block123(v1030)
+}
block125:
+{
v1046 = cast v1030 : u32
v1047 = add v1046, 8 : u32
v1048 = inttoptr v1047 : *mut i32
v1049 = load v1048 : i32
br block123(v1049)
+}
block126:
+{
v1158 = cast v841 : u32
v1159 = add v1158, 428 : u32
v1160 = inttoptr v1159 : *mut i32
@@ -3169,8 +3716,10 @@ block126:
store v1173, v1170
v1174 = call noname::dlmalloc::dlmalloc::Chunk::to_mem(v1089) : i32
br block2(v1483, v1174)
+}
block127:
+{
v1105 = cast v841 : u32
v1106 = add v1105, 424 : u32
v1107 = inttoptr v1106 : *mut i32
@@ -3179,13 +3728,17 @@ block127:
v1110 = cast v1109 : i32
v1111 = neq v1110, 0 : i1
condbr v1111, block80, block128
+}
block128:
+{
v1112 = call noname::dlmalloc::dlmalloc::Chunk::inuse(v1095) : i32
v1113 = neq v1112, 0 : i1
condbr v1113, block78(v1097, v1095), block129
+}
block129:
+{
v1114 = call noname::dlmalloc::dlmalloc::Chunk::size(v1095) : i32
v1115 = const.i32 256 : i32
v1116 = cast v1114 : u32
@@ -3194,13 +3747,17 @@ block129:
v1119 = cast v1118 : i32
v1120 = neq v1119, 0 : i1
condbr v1120, block131, block132
+}
block130:
+{
v1155 = add v1114, v1097 : i32
v1157 = call noname::dlmalloc::dlmalloc::Chunk::plus_offset(v1095, v1153) : i32
br block78(v1155, v1157)
+}
block131:
+{
v1121 = cast v1095 : u32
v1122 = add v1121, 12 : u32
v1123 = inttoptr v1122 : *mut i32
@@ -3213,12 +3770,16 @@ block131:
v1130 = cast v1129 : i32
v1131 = neq v1130, 0 : i1
condbr v1131, block133, block134
+}
block132:
+{
call noname::dlmalloc::dlmalloc::Dlmalloc::unlink_large_chunk(v841, v1095)
br block130
+}
block133:
+{
v1138 = cast v841 : u32
v1139 = add v1138, 408 : u32
v1140 = inttoptr v1139 : *mut i32
@@ -3236,8 +3797,10 @@ block133:
v1152 = inttoptr v1151 : *mut i32
store v1152, v1149
br block130
+}
block134:
+{
v1132 = cast v1128 : u32
v1133 = add v1132, 12 : u32
v1134 = inttoptr v1133 : *mut i32
@@ -3247,8 +3810,10 @@ block134:
v1137 = inttoptr v1136 : *mut i32
store v1137, v1128
br block130
+}
block135:
+{
v1206 = call noname::dlmalloc::dlmalloc::Chunk::plus_offset(v1196, v662) : i32
v1207 = cast v654 : u32
v1208 = add v1207, 416 : u32
@@ -3262,8 +3827,10 @@ block135:
call noname::dlmalloc::dlmalloc::Chunk::set_size_and_pinuse_of_inuse_chunk(v1196, v662)
v1213 = call noname::dlmalloc::dlmalloc::Chunk::to_mem(v1196) : i32
br block2(v682, v1213)
+}
block136:
+{
v1276 = const.i32 -8 : i32
v1277 = band v1263, v1276 : i32
v1278 = add v1271, v1277 : i32
@@ -3285,13 +3852,17 @@ block136:
v1294 = cast v1293 : i32
v1295 = neq v1294, 0 : i1
condbr v1295, block139, block140
+}
block137:
+{
call noname::dlmalloc::dlmalloc::Dlmalloc::insert_large_chunk(v841, v1261, v1263)
v1275 = call noname::dlmalloc::dlmalloc::Chunk::to_mem(v1089) : i32
br block2(v1482, v1275)
+}
block138(v1309: i32):
+{
v1306 = cast v1280 : u32
v1307 = add v1306, 8 : u32
v1308 = inttoptr v1307 : *mut i32
@@ -3310,23 +3881,29 @@ block138(v1309: i32):
store v1318, v1309
v1320 = call noname::dlmalloc::dlmalloc::Chunk::to_mem(v1273) : i32
br block2(v1485, v1320)
+}
block139:
+{
v1300 = bor v1284, v1291 : i32
v1301 = cast v1271 : u32
v1302 = add v1301, 408 : u32
v1303 = inttoptr v1302 : *mut i32
store v1303, v1300
br block138(v1280)
+}
block140:
+{
v1296 = cast v1280 : u32
v1297 = add v1296, 8 : u32
v1298 = inttoptr v1297 : *mut i32
v1299 = load v1298 : i32
br block138(v1299)
+}
block141(v1344: i32):
+{
v1345 = add v1343, v1344 : i32
v1346 = const.i32 164 : i32
v1347 = add v1345, v1346 : i32
@@ -3377,8 +3954,10 @@ block141(v1344: i32):
v1384 = cast v1383 : i32
v1385 = neq v1384, 0 : i1
condbr v1385, block141(v1381), block143
+}
block142:
+{
v1386 = call noname::dlmalloc::dlmalloc::Chunk::mem_offset() : i32
v1387 = const.i32 8 : i32
v1388 = call noname::dlmalloc::dlmalloc::align_up(v1386, v1387) : i32
@@ -3435,11 +4014,15 @@ block142:
v1437 = inttoptr v1436 : *mut i32
store v1437, v1434
br block76(v1343, v662, v682, v718)
+}
block143:
+{
br block142
+}
block144:
+{
v1459 = sub v1443, v1444 : i32
v1460 = cast v1438 : u32
v1461 = add v1460, 420 : u32
@@ -3464,9 +4047,11 @@ block144:
v1476 = call noname::dlmalloc::dlmalloc::Chunk::to_mem(v1466) : i32
br block2(v1488, v1476)
}
+}
pub fn dlmalloc::dlmalloc::Dlmalloc::init_top(i32, i32, i32) {
block0(v0: i32, v1: i32, v2: i32):
+{
v3 = const.i32 0 : i32
v4 = call noname::dlmalloc::dlmalloc::Chunk::to_mem(v1) : i32
v5 = const.i32 8 : i32
@@ -3511,13 +4096,17 @@ block0(v0: i32, v1: i32, v2: i32):
v40 = inttoptr v39 : *mut i32
store v40, v37
br block1
+}
block1:
- ret
+{
+ ret
+}
}
pub fn dlmalloc::dlmalloc::Dlmalloc::memalign(i32, i32, i32) -> i32 {
block0(v0: i32, v1: i32, v2: i32):
+{
v4 = const.i32 0 : i32
v5 = const.i32 16 : i32
v6 = const.i32 8 : i32
@@ -3528,11 +4117,15 @@ block0(v0: i32, v1: i32, v2: i32):
v11 = cast v10 : i32
v12 = neq v11, 0 : i1
condbr v12, block2(v1), block3
+}
block1(v3: i32):
- ret v3
+{
+ ret (v3)
+}
block2(v48: i32):
+{
v16 = call noname::dlmalloc::dlmalloc::Chunk::mem_offset() : i32
v17 = const.i32 8 : i32
v18 = call noname::dlmalloc::dlmalloc::align_up(v16, v17) : i32
@@ -3572,17 +4165,23 @@ block2(v48: i32):
v54 = cast v53 : i32
v55 = neq v54, 0 : i1
condbr v55, block4(v25), block5
+}
block3:
+{
v13 = const.i32 16 : i32
v14 = const.i32 8 : i32
v15 = call noname::dlmalloc::dlmalloc::align_up(v13, v14) : i32
br block2(v15)
+}
block4(v140: i32):
+{
br block1(v140)
+}
block5:
+{
v57 = const.i32 16 : i32
v58 = const.i32 4 : i32
v59 = add v50, v58 : i32
@@ -3611,21 +4210,27 @@ block5:
v82 = cast v81 : i32
v83 = neq v82, 0 : i1
condbr v83, block4(v25), block6
+}
block6:
+{
v84 = call noname::dlmalloc::dlmalloc::Chunk::from_mem(v80) : i32
v85 = const.i32 -1 : i32
v86 = add v48, v85 : i32
v87 = band v86, v80 : i32
v88 = neq v87, 0 : i1
condbr v88, block8, block9
+}
block7(v120: i32):
+{
v121 = call noname::dlmalloc::dlmalloc::Chunk::mmapped(v120) : i32
v122 = neq v121, 0 : i1
condbr v122, block12, block13
+}
block8:
+{
v89 = add v86, v80 : i32
v90 = const.i32 0 : i32
v91 = sub v90, v48 : i32
@@ -3649,11 +4254,15 @@ block8:
v109 = call noname::dlmalloc::dlmalloc::Chunk::mmapped(v84) : i32
v110 = neq v109, 0 : i1
condbr v110, block10, block11
+}
block9:
+{
br block7(v84)
+}
block10:
+{
v111 = cast v84 : u32
v112 = inttoptr v111 : *mut i32
v113 = load v112 : i32
@@ -3666,19 +4275,25 @@ block10:
v119 = inttoptr v118 : *mut i32
store v119, v117
br block7(v106)
+}
block11:
+{
call noname::dlmalloc::dlmalloc::Chunk::set_inuse(v106, v108)
call noname::dlmalloc::dlmalloc::Chunk::set_inuse(v84, v107)
call noname::dlmalloc::dlmalloc::Dlmalloc::dispose_chunk(v56, v84, v107)
br block7(v106)
+}
block12:
+{
v138 = call noname::dlmalloc::dlmalloc::Chunk::to_mem(v120) : i32
v139 = call noname::dlmalloc::dlmalloc::Chunk::mmapped(v137) : i32
br block4(v138)
+}
block13:
+{
v123 = call noname::dlmalloc::dlmalloc::Chunk::size(v120) : i32
v124 = const.i32 16 : i32
v125 = const.i32 8 : i32
@@ -3690,8 +4305,10 @@ block13:
v132 = cast v131 : i32
v133 = neq v132, 0 : i1
condbr v133, block12, block14
+}
block14:
+{
v134 = call noname::dlmalloc::dlmalloc::Chunk::plus_offset(v120, v127) : i32
call noname::dlmalloc::dlmalloc::Chunk::set_inuse(v120, v127)
v135 = sub v123, v127 : i32
@@ -3699,18 +4316,24 @@ block14:
call noname::dlmalloc::dlmalloc::Dlmalloc::dispose_chunk(v56, v134, v135)
br block12
}
+}
pub fn __main() -> i32 {
block0:
+{
v1 = call noname::vec_alloc() : i32
br block1(v1)
+}
block1(v0: i32):
- ret v0
+{
+ ret (v0)
+}
}
pub fn __rust_alloc(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
+{
v3 = const.i32 0 : i32
v4 = global.load (@__stack_pointer) as *mut i8 : i32
v5 = const.i32 16 : i32
@@ -3728,11 +4351,15 @@ block0(v0: i32, v1: i32):
v15 = cast v14 : i32
v16 = neq v15, 0 : i1
condbr v16, block3, block4
+}
block1(v2: i32):
- ret v2
+{
+ ret (v2)
+}
block2(v25: i32):
+{
v20 = const.i32 15 : i32
v21 = add v6, v20 : i32
call noname::::drop(v21)
@@ -3741,18 +4368,24 @@ block2(v25: i32):
v24 = global.symbol @__stack_pointer : *mut i32
store v24, v23
br block1(v25)
+}
block3:
+{
v18 = call noname::dlmalloc::dlmalloc::Dlmalloc::malloc(v10, v0) : i32
br block2(v18)
+}
block4:
+{
v17 = call noname::dlmalloc::dlmalloc::Dlmalloc::memalign(v10, v1, v0) : i32
br block2(v17)
}
+}
pub fn __rust_dealloc(i32, i32, i32) {
block0(v0: i32, v1: i32, v2: i32):
+{
v3 = const.i32 0 : i32
v4 = global.load (@__stack_pointer) as *mut i8 : i32
v5 = const.i32 16 : i32
@@ -3772,13 +4405,17 @@ block0(v0: i32, v1: i32, v2: i32):
v15 = global.symbol @__stack_pointer : *mut i32
store v15, v14
br block1
+}
block1:
- ret
+{
+ ret
+}
}
pub fn __rust_realloc(i32, i32, i32, i32) -> i32 {
block0(v0: i32, v1: i32, v2: i32, v3: i32):
+{
v5 = const.i32 0 : i32
v6 = global.load (@__stack_pointer) as *mut i8 : i32
v7 = const.i32 16 : i32
@@ -3796,11 +4433,15 @@ block0(v0: i32, v1: i32, v2: i32, v3: i32):
v17 = cast v16 : i32
v18 = neq v17, 0 : i1
condbr v18, block7, block8
+}
block1(v4: i32):
- ret v4
+{
+ ret (v4)
+}
block2(v369: i32, v381: i32):
+{
v376 = const.i32 15 : i32
v377 = add v369, v376 : i32
call noname::::drop(v377)
@@ -3809,20 +4450,26 @@ block2(v369: i32, v381: i32):
v380 = global.symbol @__stack_pointer : *mut i32
store v380, v379
br block1(v381)
+}
block3(v366: i32, v375: i32):
+{
v367 = call noname::dlmalloc::dlmalloc::Chunk::mmapped(v366) : i32
v368 = call noname::dlmalloc::dlmalloc::Chunk::to_mem(v366) : i32
br block2(v375, v368)
+}
block4(v335: i32, v337: i32, v346: i32, v351: i32, v370: i32, v382: i32):
+{
v342 = call noname::dlmalloc::dlmalloc::Dlmalloc::malloc(v335, v337) : i32
v343 = eq v342, 0 : i1
v344 = cast v343 : i32
v345 = neq v344, 0 : i1
condbr v345, block2(v370, v382), block45
+}
block5:
+{
v321 = call noname::dlmalloc::dlmalloc::Chunk::plus_offset(v75, v74) : i32
call noname::dlmalloc::dlmalloc::Chunk::set_inuse(v75, v74)
v322 = cast v12 : u32
@@ -3842,8 +4489,10 @@ block5:
store v333, v325
v334 = neq v75, 0 : i1
condbr v334, block3(v75, v8), block44
+}
block6:
+{
v314 = cast v1 : u32
v315 = cast v3 : u32
v316 = lt v314, v315 : i1
@@ -3853,8 +4502,10 @@ block6:
v320 = call noname::memcpy(v19, v0, v319) : i32
call noname::dlmalloc::dlmalloc::Dlmalloc::free(v12, v0)
br block2(v8, v19)
+}
block7:
+{
v22 = call noname::dlmalloc::dlmalloc::Chunk::mem_offset() : i32
v23 = const.i32 8 : i32
v24 = call noname::dlmalloc::dlmalloc::align_up(v22, v23) : i32
@@ -3893,17 +4544,23 @@ block7:
v57 = cast v56 : i32
v58 = neq v57, 0 : i1
condbr v58, block2(v8, v31), block10
+}
block8:
+{
v19 = call noname::dlmalloc::dlmalloc::Dlmalloc::memalign(v12, v2, v3) : i32
v20 = neq v19, 0 : i1
condbr v20, block6, block9
+}
block9:
+{
v21 = const.i32 0 : i32
br block2(v8, v21)
+}
block10:
+{
v59 = const.i32 16 : i32
v60 = const.i32 4 : i32
v61 = add v3, v60 : i32
@@ -3926,8 +4583,10 @@ block10:
v78 = call noname::dlmalloc::dlmalloc::Chunk::mmapped(v75) : i32
v79 = neq v78, 0 : i1
condbr v79, block17, block18
+}
block11:
+{
v304 = cast v12 : u32
v305 = add v304, 420 : u32
v306 = inttoptr v305 : *mut i32
@@ -3939,12 +4598,16 @@ block11:
v312 = cast v311 : i32
v313 = neq v312, 0 : i1
condbr v313, block5, block43
+}
block12:
+{
v303 = neq v75, 0 : i1
condbr v303, block3(v302, v374), block42
+}
block13:
+{
v292 = sub v76, v74 : i32
v293 = const.i32 16 : i32
v294 = const.i32 8 : i32
@@ -3955,8 +4618,10 @@ block13:
v299 = cast v298 : i32
v300 = neq v299, 0 : i1
condbr v300, block12, block41
+}
block14:
+{
v258 = cast v12 : u32
v259 = add v258, 416 : u32
v260 = inttoptr v259 : *mut i32
@@ -3968,8 +4633,10 @@ block14:
v266 = cast v265 : i32
v267 = neq v266, 0 : i1
condbr v267, block4(v12, v3, v0, v75, v8, v31), block36
+}
block15:
+{
v243 = const.i32 16 : i32
v244 = const.i32 8 : i32
v245 = call noname::dlmalloc::dlmalloc::align_up(v243, v244) : i32
@@ -3979,8 +4646,10 @@ block15:
v249 = cast v248 : i32
v250 = neq v249, 0 : i1
condbr v250, block32, block33
+}
block16:
+{
v210 = cast v77 : u32
v211 = add v210, 12 : u32
v212 = inttoptr v211 : *mut i32
@@ -3993,8 +4662,10 @@ block16:
v219 = cast v218 : i32
v220 = neq v219, 0 : i1
condbr v220, block30, block31
+}
block17:
+{
v115 = call noname::dlmalloc::dlmalloc::Chunk::size(v75) : i32
v116 = const.i32 256 : i32
v117 = cast v74 : u32
@@ -4003,16 +4674,20 @@ block17:
v120 = cast v119 : i32
v121 = neq v120, 0 : i1
condbr v121, block4(v12, v3, v0, v75, v8, v31), block25
+}
block18:
+{
v80 = cast v76 : u32
v81 = cast v74 : u32
v82 = gte v80, v81 : i1
v83 = cast v82 : i32
v84 = neq v83, 0 : i1
condbr v84, block13, block19
+}
block19:
+{
v85 = cast v12 : u32
v86 = add v85, 428 : u32
v87 = inttoptr v86 : *mut i32
@@ -4021,8 +4696,10 @@ block19:
v90 = cast v89 : i32
v91 = neq v90, 0 : i1
condbr v91, block11, block20
+}
block20:
+{
v92 = cast v12 : u32
v93 = add v92, 424 : u32
v94 = inttoptr v93 : *mut i32
@@ -4031,13 +4708,17 @@ block20:
v97 = cast v96 : i32
v98 = neq v97, 0 : i1
condbr v98, block14, block21
+}
block21:
+{
v99 = call noname::dlmalloc::dlmalloc::Chunk::cinuse(v77) : i32
v100 = neq v99, 0 : i1
condbr v100, block4(v12, v3, v0, v75, v8, v31), block22
+}
block22:
+{
v101 = call noname::dlmalloc::dlmalloc::Chunk::size(v77) : i32
v102 = add v101, v76 : i32
v103 = cast v102 : u32
@@ -4046,8 +4727,10 @@ block22:
v106 = cast v105 : i32
v107 = neq v106, 0 : i1
condbr v107, block4(v12, v3, v0, v75, v8, v31), block23
+}
block23:
+{
v108 = sub v102, v74 : i32
v109 = const.i32 256 : i32
v110 = cast v101 : u32
@@ -4056,12 +4739,16 @@ block23:
v113 = cast v112 : i32
v114 = neq v113, 0 : i1
condbr v114, block16, block24
+}
block24:
+{
call noname::dlmalloc::dlmalloc::Dlmalloc::unlink_large_chunk(v12, v77)
br block15
+}
block25:
+{
v122 = const.i32 4 : i32
v123 = add v74, v122 : i32
v124 = cast v115 : u32
@@ -4070,8 +4757,10 @@ block25:
v127 = cast v126 : i32
v128 = neq v127, 0 : i1
condbr v128, block26, block27
+}
block26:
+{
v138 = cast v137 : u32
v139 = inttoptr v138 : *mut i32
v140 = load v139 : i32
@@ -4089,8 +4778,10 @@ block26:
v154 = cast v153 : i32
v155 = neq v154, 0 : i1
condbr v155, block4(v136, v3, v0, v137, v8, v31), block29
+}
block27:
+{
v129 = sub v115, v74 : i32
v130 = const.i32 131073 : i32
v131 = cast v129 : u32
@@ -4099,11 +4790,15 @@ block27:
v134 = cast v133 : i32
v135 = neq v134, 0 : i1
condbr v135, block12, block28
+}
block28:
+{
br block26
+}
block29:
+{
v156 = add v152, v140 : i32
v157 = sub v150, v140 : i32
v158 = const.i32 -16 : i32
@@ -4165,8 +4860,10 @@ block29:
v209 = inttoptr v208 : *mut i32
store v209, v206
br block3(v156, v371)
+}
block30:
+{
v227 = cast v12 : u32
v228 = add v227, 408 : u32
v229 = inttoptr v228 : *mut i32
@@ -4184,8 +4881,10 @@ block30:
v241 = inttoptr v240 : *mut i32
store v241, v238
br block15
+}
block31:
+{
v221 = cast v217 : u32
v222 = add v221, 12 : u32
v223 = inttoptr v222 : *mut i32
@@ -4195,27 +4894,37 @@ block31:
v226 = inttoptr v225 : *mut i32
store v226, v217
br block15
+}
block32:
+{
call noname::dlmalloc::dlmalloc::Chunk::set_inuse(v251, v102)
v257 = neq v251, 0 : i1
condbr v257, block3(v251, v372), block35
+}
block33:
+{
v253 = call noname::dlmalloc::dlmalloc::Chunk::plus_offset(v75, v74) : i32
call noname::dlmalloc::dlmalloc::Chunk::set_inuse(v251, v252)
call noname::dlmalloc::dlmalloc::Chunk::set_inuse(v253, v242)
call noname::dlmalloc::dlmalloc::Dlmalloc::dispose_chunk(v12, v253, v242)
v255 = neq v251, 0 : i1
condbr v255, block3(v251, v372), block34
+}
block34:
+{
br block4(v254, v3, v0, v251, v8, v31)
+}
block35:
+{
br block4(v254, v339, v348, v251, v372, v384)
+}
block36:
+{
v268 = sub v262, v74 : i32
v269 = const.i32 16 : i32
v270 = const.i32 8 : i32
@@ -4226,8 +4935,10 @@ block36:
v275 = cast v274 : i32
v276 = neq v275, 0 : i1
condbr v276, block38, block39
+}
block37(v282: i32, v286: i32):
+{
v283 = cast v12 : u32
v284 = add v283, 424 : u32
v285 = inttoptr v284 : *mut i32
@@ -4238,41 +4949,57 @@ block37(v282: i32, v286: i32):
store v289, v286
v291 = neq v75, 0 : i1
condbr v291, block3(v290, v373), block40
+}
block38:
+{
v279 = call noname::dlmalloc::dlmalloc::Chunk::plus_offset(v75, v74) : i32
v280 = call noname::dlmalloc::dlmalloc::Chunk::plus_offset(v279, v268) : i32
call noname::dlmalloc::dlmalloc::Chunk::set_inuse(v75, v74)
call noname::dlmalloc::dlmalloc::Chunk::set_size_and_pinuse_of_free_chunk(v279, v268)
call noname::dlmalloc::dlmalloc::Chunk::clear_pinuse(v280)
br block37(v279, v268)
+}
block39:
+{
call noname::dlmalloc::dlmalloc::Chunk::set_inuse(v75, v262)
v277 = const.i32 0 : i32
v278 = const.i32 0 : i32
br block37(v278, v277)
+}
block40:
+{
br block4(v281, v3, v0, v290, v8, v31)
+}
block41:
+{
v301 = call noname::dlmalloc::dlmalloc::Chunk::plus_offset(v75, v74) : i32
call noname::dlmalloc::dlmalloc::Chunk::set_inuse(v75, v74)
call noname::dlmalloc::dlmalloc::Chunk::set_inuse(v301, v292)
call noname::dlmalloc::dlmalloc::Dlmalloc::dispose_chunk(v12, v301, v292)
br block12
+}
block42:
+{
br block4(v12, v3, v0, v302, v8, v31)
+}
block43:
+{
br block4(v12, v3, v0, v75, v8, v31)
+}
block44:
+{
br block4(v12, v3, v0, v75, v8, v31)
+}
block45:
+{
v352 = call noname::dlmalloc::dlmalloc::Chunk::size(v351) : i32
v353 = const.i32 -8 : i32
v354 = const.i32 -4 : i32
@@ -4290,42 +5017,56 @@ block45:
call noname::dlmalloc::dlmalloc::Dlmalloc::free(v335, v346)
br block2(v370, v365)
}
+}
pub fn __rust_alloc_error_handler(i32, i32) {
block0(v0: i32, v1: i32):
+{
call noname::__rdl_oom(v0, v1)
- ret
+ ret
+}
block1:
+{
+}
}
pub fn alloc::raw_vec::finish_grow(i32, i32, i32, i32) {
block0(v0: i32, v1: i32, v2: i32, v3: i32):
+{
v4 = const.i32 0 : i32
v5 = eq v1, 0 : i1
v6 = cast v5 : i32
v7 = neq v6, 0 : i1
condbr v7, block4, block5
+}
block1:
- ret
+{
+ ret
+}
block2(v83: i32):
+{
v84 = const.i32 1 : i32
v85 = cast v83 : u32
v86 = inttoptr v85 : *mut i32
store v86, v84
br block1
+}
block3:
+{
v79 = const.i32 0 : i32
v80 = cast v0 : u32
v81 = add v80, 4 : u32
v82 = inttoptr v81 : *mut i32
store v82, v79
br block2(v0)
+}
block4:
+{
v71 = const.i32 0 : i32
v72 = cast v0 : u32
v73 = add v72, 4 : u32
@@ -4337,15 +5078,19 @@ block4:
v78 = inttoptr v77 : *mut i32
store v78, v2
br block2(v0)
+}
block5:
+{
v8 = const.i32 -1 : i32
v9 = lte v2, v8 : i1
v10 = cast v9 : i32
v11 = neq v10, 0 : i1
condbr v11, block3, block6
+}
block6:
+{
v12 = cast v3 : u32
v13 = add v12, 4 : u32
v14 = inttoptr v13 : *mut i32
@@ -4354,22 +5099,30 @@ block6:
v17 = cast v16 : i32
v18 = neq v17, 0 : i1
condbr v18, block9, block10
+}
block7(v46: i32, v57: i32, v63: i32):
+{
v47 = eq v46, 0 : i1
v48 = cast v47 : i32
v49 = neq v48, 0 : i1
condbr v49, block17, block18
+}
block8:
+{
v45 = call noname::__rust_alloc(v2, v1) : i32
br block7(v45, v43, v44)
+}
block9:
+{
v36 = neq v2, 0 : i1
condbr v36, block15, block16
+}
block10:
+{
v19 = const.i32 8 : i32
v20 = add v3, v19 : i32
v21 = cast v20 : u32
@@ -4377,19 +5130,25 @@ block10:
v23 = load v22 : i32
v24 = neq v23, 0 : i1
condbr v24, block11, block12
+}
block11:
+{
v32 = cast v3 : u32
v33 = inttoptr v32 : *mut i32
v34 = load v33 : i32
v35 = call noname::__rust_realloc(v34, v23, v1, v2) : i32
br block7(v35, v2, v1)
+}
block12:
+{
v25 = neq v2, 0 : i1
condbr v25, block13, block14
+}
block13:
+{
v26 = const.i32 0 : i32
v27 = cast v26 : u32
v28 = add v27, 1048576 : u32
@@ -4397,11 +5156,15 @@ block13:
v30 = load v29 : u8
v31 = zext v30 : i32
br block8
+}
block14:
+{
br block7(v1, v2, v1)
+}
block15:
+{
v37 = const.i32 0 : i32
v38 = cast v37 : u32
v39 = add v38, 1048576 : u32
@@ -4409,11 +5172,15 @@ block15:
v41 = load v40 : u8
v42 = zext v41 : i32
br block8
+}
block16:
+{
br block7(v1, v2, v1)
+}
block17:
+{
v64 = cast v50 : u32
v65 = add v64, 4 : u32
v66 = inttoptr v65 : *mut i32
@@ -4424,8 +5191,10 @@ block17:
v70 = inttoptr v69 : *mut i32
store v70, v57
br block2(v50)
+}
block18:
+{
v52 = cast v0 : u32
v53 = add v52, 4 : u32
v54 = inttoptr v53 : *mut i32
@@ -4439,11 +5208,13 @@ block18:
v61 = cast v50 : u32
v62 = inttoptr v61 : *mut i32
store v62, v60
- ret
+ ret
+}
}
pub fn alloc::raw_vec::RawVec::reserve_for_push(i32) {
block0(v0: i32):
+{
v1 = const.i32 0 : i32
v2 = global.load (@__stack_pointer) as *mut i8 : i32
v3 = const.i32 32 : i32
@@ -4477,11 +5248,15 @@ block0(v0: i32):
v30 = cast v29 : i32
v31 = neq v30, 0 : i1
condbr v31, block3, block4
+}
block1:
- ret
+{
+ ret
+}
block2:
+{
v52 = const.i32 8 : i32
v53 = add v4, v52 : i32
v56 = const.i32 20 : i32
@@ -4497,16 +5272,20 @@ block2:
v65 = load v64 : i32
v66 = neq v65, 0 : i1
condbr v66, block6, block7
+}
block3:
+{
v47 = const.i32 0 : i32
v48 = cast v4 : u32
v49 = add v48, 24 : u32
v50 = inttoptr v49 : *mut i32
store v50, v47
br block2
+}
block4:
+{
v32 = const.i32 4 : i32
v33 = cast v4 : u32
v34 = add v33, 24 : u32
@@ -4526,22 +5305,28 @@ block4:
v46 = inttoptr v45 : *mut i32
store v46, v43
br block2
+}
block5:
+{
v87 = const.i32 32 : i32
v88 = add v51, v87 : i32
v89 = global.symbol @__stack_pointer : *mut i32
store v89, v88
br block1
+}
block6:
+{
v74 = const.i32 -2147483647 : i32
v75 = eq v61, v74 : i1
v76 = cast v75 : i32
v77 = neq v76, 0 : i1
condbr v77, block5, block8
+}
block7:
+{
v69 = cast v0 : u32
v70 = add v69, 4 : u32
v71 = inttoptr v70 : *mut i32
@@ -4550,18 +5335,24 @@ block7:
v73 = inttoptr v72 : *mut i32
store v73, v61
br block5
+}
block8:
+{
v78 = eq v61, 0 : i1
v79 = cast v78 : i32
v80 = neq v79, 0 : i1
condbr v80, block9, block10
+}
block9:
+{
call noname::alloc::raw_vec::capacity_overflow()
unreachable
+}
block10:
+{
v81 = const.i32 16 : i32
v82 = add v51, v81 : i32
v83 = cast v82 : u32
@@ -4570,9 +5361,11 @@ block10:
call noname::alloc::alloc::handle_alloc_error(v61, v85)
unreachable
}
+}
pub fn vec_alloc() -> i32 {
block0:
+{
v1 = const.i32 0 : i32
v2 = global.load (@__stack_pointer) as *mut i8 : i32
v3 = const.i32 16 : i32
@@ -4612,13 +5405,19 @@ block0:
v32 = cast v31 : i32
v33 = neq v32, 0 : i1
condbr v33, block2, block3
+}
block1(v0: i32):
+{
+}
block2:
+{
unreachable
+}
block3:
+{
v34 = cast v4 : u32
v35 = add v34, 8 : u32
v36 = inttoptr v35 : *mut i32
@@ -4627,55 +5426,77 @@ block3:
v39 = cast v38 : i32
v40 = neq v39, 0 : i1
condbr v40, block4, block5
+}
block4:
+{
v45 = const.i32 16 : i32
v46 = add v4, v45 : i32
v47 = global.symbol @__stack_pointer : *mut i32
store v47, v46
v48 = const.i32 1 : i32
- ret v48
+ ret (v48)
+}
block5:
+{
v41 = const.i32 2 : i32
v42 = shl v37, v41 : i32
v43 = const.i32 4 : i32
call noname::__rust_dealloc(v19, v42, v43)
br block4
}
+}
pub fn alloc::raw_vec::capacity_overflow() {
block0:
+{
unreachable
+}
block1:
+{
+}
}
pub fn alloc::alloc::handle_alloc_error(i32, i32) {
block0(v0: i32, v1: i32):
+{
call noname::alloc::alloc::handle_alloc_error::rt_error(v0, v1)
unreachable
+}
block1:
+{
+}
}
pub fn alloc::alloc::handle_alloc_error::rt_error(i32, i32) {
block0(v0: i32, v1: i32):
+{
call noname::__rust_alloc_error_handler(v1, v0)
unreachable
+}
block1:
+{
+}
}
pub fn __rdl_oom(i32, i32) {
block0(v0: i32, v1: i32):
+{
unreachable
+}
block1:
+{
+}
}
pub fn dlmalloc::dlmalloc::align_up(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
+{
v3 = add v0, v1 : i32
v4 = const.i32 -1 : i32
v5 = add v3, v4 : i32
@@ -4683,37 +5504,49 @@ block0(v0: i32, v1: i32):
v7 = sub v6, v1 : i32
v8 = band v5, v7 : i32
br block1(v8)
+}
block1(v2: i32):
- ret v2
+{
+ ret (v2)
+}
}
pub fn dlmalloc::dlmalloc::left_bits(i32) -> i32 {
block0(v0: i32):
+{
v2 = const.i32 1 : i32
v3 = shl v0, v2 : i32
v4 = const.i32 0 : i32
v5 = sub v4, v3 : i32
v6 = bor v3, v5 : i32
br block1(v6)
+}
block1(v1: i32):
- ret v1
+{
+ ret (v1)
+}
}
pub fn dlmalloc::dlmalloc::least_bit(i32) -> i32 {
block0(v0: i32):
+{
v2 = const.i32 0 : i32
v3 = sub v2, v0 : i32
v4 = band v3, v0 : i32
br block1(v4)
+}
block1(v1: i32):
- ret v1
+{
+ ret (v1)
+}
}
pub fn dlmalloc::dlmalloc::leftshift_for_tree_index(i32) -> i32 {
block0(v0: i32):
+{
v2 = const.i32 0 : i32
v3 = const.i32 25 : i32
v4 = const.i32 1 : i32
@@ -4728,22 +5561,30 @@ block0(v0: i32):
v13 = neq v12, 0 : i1
v14 = select v13, v2, v9 : i32
br block1(v14)
+}
block1(v1: i32):
- ret v1
+{
+ ret (v1)
+}
}
pub fn dlmalloc::dlmalloc::Chunk::fencepost_head() -> i32 {
block0:
+{
v1 = const.i32 7 : i32
br block1(v1)
+}
block1(v0: i32):
- ret v0
+{
+ ret (v0)
+}
}
pub fn dlmalloc::dlmalloc::Chunk::size(i32) -> i32 {
block0(v0: i32):
+{
v2 = cast v0 : u32
v3 = add v2, 4 : u32
v4 = inttoptr v3 : *mut i32
@@ -4751,13 +5592,17 @@ block0(v0: i32):
v6 = const.i32 -8 : i32
v7 = band v5, v6 : i32
br block1(v7)
+}
block1(v1: i32):
- ret v1
+{
+ ret (v1)
+}
}
pub fn dlmalloc::dlmalloc::Chunk::cinuse(i32) -> i32 {
block0(v0: i32):
+{
v2 = cast v0 : u32
v3 = add v2, 4 : u32
v4 = inttoptr v3 : *mut u8
@@ -4771,13 +5616,17 @@ block0(v0: i32):
v12 = shr v10, v11 : u32
v13 = cast v12 : i32
br block1(v13)
+}
block1(v1: i32):
- ret v1
+{
+ ret (v1)
+}
}
pub fn dlmalloc::dlmalloc::Chunk::pinuse(i32) -> i32 {
block0(v0: i32):
+{
v2 = cast v0 : u32
v3 = add v2, 4 : u32
v4 = inttoptr v3 : *mut i32
@@ -4785,13 +5634,17 @@ block0(v0: i32):
v6 = const.i32 1 : i32
v7 = band v5, v6 : i32
br block1(v7)
+}
block1(v1: i32):
- ret v1
+{
+ ret (v1)
+}
}
pub fn dlmalloc::dlmalloc::Chunk::clear_pinuse(i32) {
block0(v0: i32):
+{
v1 = cast v0 : u32
v2 = add v1, 4 : u32
v3 = inttoptr v2 : *mut i32
@@ -4803,13 +5656,17 @@ block0(v0: i32):
v9 = inttoptr v8 : *mut i32
store v9, v6
br block1
+}
block1:
- ret
+{
+ ret
+}
}
pub fn dlmalloc::dlmalloc::Chunk::inuse(i32) -> i32 {
block0(v0: i32):
+{
v2 = cast v0 : u32
v3 = add v2, 4 : u32
v4 = inttoptr v3 : *mut i32
@@ -4820,13 +5677,17 @@ block0(v0: i32):
v9 = neq v7, v8 : i1
v10 = cast v9 : i32
br block1(v10)
+}
block1(v1: i32):
- ret v1
+{
+ ret (v1)
+}
}
pub fn dlmalloc::dlmalloc::Chunk::mmapped(i32) -> i32 {
block0(v0: i32):
+{
v2 = cast v0 : u32
v3 = add v2, 4 : u32
v4 = inttoptr v3 : *mut u8
@@ -4837,13 +5698,17 @@ block0(v0: i32):
v9 = eq v8, 0 : i1
v10 = cast v9 : i32
br block1(v10)
+}
block1(v1: i32):
- ret v1
+{
+ ret (v1)
+}
}
pub fn dlmalloc::dlmalloc::Chunk::set_inuse(i32, i32) {
block0(v0: i32, v1: i32):
+{
v2 = cast v0 : u32
v3 = add v2, 4 : u32
v4 = inttoptr v3 : *mut i32
@@ -4869,13 +5734,17 @@ block0(v0: i32, v1: i32):
v23 = inttoptr v22 : *mut i32
store v23, v20
br block1
+}
block1:
- ret
+{
+ ret
+}
}
pub fn dlmalloc::dlmalloc::Chunk::set_inuse_and_pinuse(i32, i32) {
block0(v0: i32, v1: i32):
+{
v2 = const.i32 3 : i32
v3 = bor v1, v2 : i32
v4 = cast v0 : u32
@@ -4894,13 +5763,17 @@ block0(v0: i32, v1: i32):
v16 = inttoptr v15 : *mut i32
store v16, v13
br block1
+}
block1:
- ret
+{
+ ret
+}
}
pub fn dlmalloc::dlmalloc::Chunk::set_size_and_pinuse_of_inuse_chunk(i32, i32) {
block0(v0: i32, v1: i32):
+{
v2 = const.i32 3 : i32
v3 = bor v1, v2 : i32
v4 = cast v0 : u32
@@ -4908,13 +5781,17 @@ block0(v0: i32, v1: i32):
v6 = inttoptr v5 : *mut i32
store v6, v3
br block1
+}
block1:
- ret
+{
+ ret
+}
}
pub fn dlmalloc::dlmalloc::Chunk::set_size_and_pinuse_of_free_chunk(i32, i32) {
block0(v0: i32, v1: i32):
+{
v2 = const.i32 1 : i32
v3 = bor v1, v2 : i32
v4 = cast v0 : u32
@@ -4926,13 +5803,17 @@ block0(v0: i32, v1: i32):
v9 = inttoptr v8 : *mut i32
store v9, v1
br block1
+}
block1:
- ret
+{
+ ret
+}
}
pub fn dlmalloc::dlmalloc::Chunk::set_free_with_pinuse(i32, i32, i32) {
block0(v0: i32, v1: i32, v2: i32):
+{
v3 = cast v2 : u32
v4 = add v3, 4 : u32
v5 = inttoptr v4 : *mut i32
@@ -4954,60 +5835,84 @@ block0(v0: i32, v1: i32, v2: i32):
v19 = inttoptr v18 : *mut i32
store v19, v1
br block1
+}
block1:
- ret
+{
+ ret
+}
}
pub fn dlmalloc::dlmalloc::Chunk::plus_offset(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
+{
v3 = add v0, v1 : i32
br block1(v3)
+}
block1(v2: i32):
- ret v2
+{
+ ret (v2)
+}
}
pub fn dlmalloc::dlmalloc::Chunk::minus_offset(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
+{
v3 = sub v0, v1 : i32
br block1(v3)
+}
block1(v2: i32):
- ret v2
+{
+ ret (v2)
+}
}
pub fn dlmalloc::dlmalloc::Chunk::to_mem(i32) -> i32 {
block0(v0: i32):
+{
v2 = const.i32 8 : i32
v3 = add v0, v2 : i32
br block1(v3)
+}
block1(v1: i32):
- ret v1
+{
+ ret (v1)
+}
}
pub fn dlmalloc::dlmalloc::Chunk::mem_offset() -> i32 {
block0:
+{
v1 = const.i32 8 : i32
br block1(v1)
+}
block1(v0: i32):
- ret v0
+{
+ ret (v0)
+}
}
pub fn dlmalloc::dlmalloc::Chunk::from_mem(i32) -> i32 {
block0(v0: i32):
+{
v2 = const.i32 -8 : i32
v3 = add v0, v2 : i32
br block1(v3)
+}
block1(v1: i32):
- ret v1
+{
+ ret (v1)
+}
}
pub fn dlmalloc::dlmalloc::TreeChunk::leftmost_child(i32) -> i32 {
block0(v0: i32):
+{
v2 = const.i32 0 : i32
v3 = cast v0 : u32
v4 = add v3, 16 : u32
@@ -5015,14 +5920,20 @@ block0(v0: i32):
v6 = load v5 : i32
v7 = neq v6, 0 : i1
condbr v7, block2(v6), block3
+}
block1(v1: i32):
- ret v1
+{
+ ret (v1)
+}
block2(v13: i32):
+{
br block1(v13)
+}
block3:
+{
v8 = const.i32 20 : i32
v9 = add v0, v8 : i32
v10 = cast v9 : u32
@@ -5030,41 +5941,55 @@ block3:
v12 = load v11 : i32
br block2(v12)
}
+}
pub fn dlmalloc::dlmalloc::TreeChunk::chunk(i32) -> i32 {
block0(v0: i32):
+{
br block1(v0)
+}
block1(v1: i32):
- ret v1
+{
+ ret (v1)
+}
}
pub fn dlmalloc::dlmalloc::TreeChunk::next(i32) -> i32 {
block0(v0: i32):
+{
v2 = cast v0 : u32
v3 = add v2, 12 : u32
v4 = inttoptr v3 : *mut i32
v5 = load v4 : i32
br block1(v5)
+}
block1(v1: i32):
- ret v1
+{
+ ret (v1)
+}
}
pub fn dlmalloc::dlmalloc::TreeChunk::prev(i32) -> i32 {
block0(v0: i32):
+{
v2 = cast v0 : u32
v3 = add v2, 8 : u32
v4 = inttoptr v3 : *mut i32
v5 = load v4 : i32
br block1(v5)
+}
block1(v1: i32):
- ret v1
+{
+ ret (v1)
+}
}
pub fn dlmalloc::dlmalloc::Segment::is_extern(i32) -> i32 {
block0(v0: i32):
+{
v2 = cast v0 : u32
v3 = add v2, 12 : u32
v4 = inttoptr v3 : *mut i32
@@ -5072,13 +5997,17 @@ block0(v0: i32):
v6 = const.i32 1 : i32
v7 = band v5, v6 : i32
br block1(v7)
+}
block1(v1: i32):
- ret v1
+{
+ ret (v1)
+}
}
pub fn dlmalloc::dlmalloc::Segment::sys_flags(i32) -> i32 {
block0(v0: i32):
+{
v2 = cast v0 : u32
v3 = add v2, 12 : u32
v4 = inttoptr v3 : *mut i32
@@ -5089,13 +6018,17 @@ block0(v0: i32):
v9 = shr v7, v8 : u32
v10 = cast v9 : i32
br block1(v10)
+}
block1(v1: i32):
- ret v1
+{
+ ret (v1)
+}
}
pub fn dlmalloc::dlmalloc::Segment::holds(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
+{
v3 = const.i32 0 : i32
v4 = const.i32 0 : i32
v5 = cast v0 : u32
@@ -5107,14 +6040,20 @@ block0(v0: i32, v1: i32):
v11 = cast v10 : i32
v12 = neq v11, 0 : i1
condbr v12, block2(v4), block3
+}
block1(v2: i32):
- ret v2
+{
+ ret (v2)
+}
block2(v22: i32):
+{
br block1(v22)
+}
block3:
+{
v13 = cast v0 : u32
v14 = add v13, 4 : u32
v15 = inttoptr v14 : *mut i32
@@ -5126,9 +6065,11 @@ block3:
v21 = cast v20 : i32
br block2(v21)
}
+}
pub fn dlmalloc::dlmalloc::Segment::top(i32) -> i32 {
block0(v0: i32):
+{
v2 = cast v0 : u32
v3 = inttoptr v2 : *mut i32
v4 = load v3 : i32
@@ -5138,30 +6079,42 @@ block0(v0: i32):
v8 = load v7 : i32
v9 = add v4, v8 : i32
br block1(v9)
+}
block1(v1: i32):
- ret v1
+{
+ ret (v1)
+}
}
pub fn ::deref_mut(i32) -> i32 {
block0(v0: i32):
+{
v2 = const.i32 1048580 : i32
br block1(v2)
+}
block1(v1: i32):
- ret v1
+{
+ ret (v1)
+}
}
pub fn ::drop(i32) {
block0(v0: i32):
+{
br block1
+}
block1:
- ret
+{
+ ret
+}
}
pub fn ::alloc(i32, i32, i32) {
block0(v0: i32, v1: i32, v2: i32):
+{
v3 = const.i32 0 : i32
v4 = const.i32 16 : i32
v5 = cast v2 : u32
@@ -5196,75 +6149,107 @@ block0(v0: i32, v1: i32, v2: i32):
v32 = inttoptr v31 : *mut i32
store v32, v30
br block1
+}
block1:
- ret
+{
+ ret
+}
}
pub fn ::remap(i32, i32, i32, i32, i32) -> i32 {
block0(v0: i32, v1: i32, v2: i32, v3: i32, v4: i32):
+{
v6 = const.i32 0 : i32
br block1(v6)
+}
block1(v5: i32):
- ret v5
+{
+ ret (v5)
+}
}
pub fn ::free_part(i32, i32, i32, i32) -> i32 {
block0(v0: i32, v1: i32, v2: i32, v3: i32):
+{
v5 = const.i32 0 : i32
br block1(v5)
+}
block1(v4: i32):
- ret v4
+{
+ ret (v4)
+}
}
pub fn ::free(i32, i32, i32) -> i32 {
block0(v0: i32, v1: i32, v2: i32):
+{
v4 = const.i32 0 : i32
br block1(v4)
+}
block1(v3: i32):
- ret v3
+{
+ ret (v3)
+}
}
pub fn ::can_release_part(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
+{
v3 = const.i32 0 : i32
br block1(v3)
+}
block1(v2: i32):
- ret v2
+{
+ ret (v2)
+}
}
pub fn ::page_size(i32) -> i32 {
block0(v0: i32):
+{
v2 = const.i32 65536 : i32
br block1(v2)
+}
block1(v1: i32):
- ret v1
+{
+ ret (v1)
+}
}
pub fn dlmalloc::sys::enable_alloc_after_fork() {
block0:
+{
br block1
+}
block1:
- ret
+{
+ ret
+}
}
pub fn memcpy(i32, i32, i32) -> i32 {
block0(v0: i32, v1: i32, v2: i32):
+{
v4 = call noname::compiler_builtins::mem::memcpy(v0, v1, v2) : i32
br block1(v4)
+}
block1(v3: i32):
- ret v3
+{
+ ret (v3)
+}
}
pub fn compiler_builtins::mem::memcpy(i32, i32, i32) -> i32 {
block0(v0: i32, v1: i32, v2: i32):
+{
v4 = const.i32 0 : i32
v5 = const.i32 15 : i32
v6 = cast v2 : u32
@@ -5273,17 +6258,23 @@ block0(v0: i32, v1: i32, v2: i32):
v9 = cast v8 : i32
v10 = neq v9, 0 : i1
condbr v10, block3, block4
+}
block1(v3: i32):
- ret v3
+{
+ ret (v3)
+}
block2(v133: i32, v137: i32, v159: i32, v161: i32):
+{
v134 = eq v133, 0 : i1
v135 = cast v134 : i32
v136 = neq v135, 0 : i1
condbr v136, block21, block22
+}
block3:
+{
v11 = const.i32 0 : i32
v12 = sub v11, v0 : i32
v13 = const.i32 3 : i32
@@ -5293,11 +6284,15 @@ block3:
v17 = cast v16 : i32
v18 = neq v17, 0 : i1
condbr v18, block5(v15), block6
+}
block4:
+{
br block2(v2, v0, v1, v0)
+}
block5(v38: i32):
+{
v43 = sub v2, v14 : i32
v44 = const.i32 -4 : i32
v45 = band v43, v44 : i32
@@ -5309,11 +6304,15 @@ block5(v38: i32):
v53 = cast v52 : i32
v54 = neq v53, 0 : i1
condbr v54, block11, block12
+}
block6:
+{
br block7(v0, v1)
+}
block7(v19: i32, v20: i32):
+{
v21 = cast v20 : u32
v22 = inttoptr v21 : *mut u8
v23 = load v22 : u8
@@ -5332,34 +6331,46 @@ block7(v19: i32, v20: i32):
v36 = cast v35 : i32
v37 = neq v36, 0 : i1
condbr v37, block7(v31, v29), block9
+}
block8:
+{
br block5(v32)
+}
block9:
+{
br block8
+}
block10(v138: i32, v162: i32):
+{
v124 = const.i32 3 : i32
v125 = band v43, v124 : i32
v132 = add v49, v45 : i32
br block2(v125, v138, v132, v162)
+}
block11:
+{
v100 = const.i32 1 : i32
v101 = lt v45, v100 : i1
v102 = cast v101 : i32
v103 = neq v102, 0 : i1
condbr v103, block10(v46, v163), block17
+}
block12:
+{
v55 = const.i32 1 : i32
v56 = lt v45, v55 : i1
v57 = cast v56 : i32
v58 = neq v57, 0 : i1
condbr v58, block10(v46, v0), block13
+}
block13:
+{
v59 = const.i32 3 : i32
v60 = shl v49, v59 : i32
v61 = const.i32 24 : i32
@@ -5376,8 +6387,10 @@ block13:
v72 = inttoptr v71 : *mut i32
v73 = load v72 : i32
br block14(v38, v73, v66)
+}
block14(v74: i32, v75: i32, v81: i32):
+{
v77 = cast v75 : u32
v78 = cast v76 : u32
v79 = shr v77, v78 : u32
@@ -5400,16 +6413,24 @@ block14(v74: i32, v75: i32, v81: i32):
v98 = cast v97 : i32
v99 = neq v98, 0 : i1
condbr v99, block14(v93, v84, v91), block16
+}
block15:
+{
+}
block16:
+{
br block10(v94, v163)
+}
block17:
+{
br block18(v38, v49)
+}
block18(v104: i32, v105: i32):
+{
v106 = cast v105 : u32
v107 = inttoptr v106 : *mut i32
v108 = load v107 : i32
@@ -5426,21 +6447,31 @@ block18(v104: i32, v105: i32):
v119 = cast v118 : i32
v120 = neq v119, 0 : i1
condbr v120, block18(v114, v112), block20
+}
block19:
+{
br block10(v115, v163)
+}
block20:
+{
br block19
+}
block21:
+{
br block1(v161)
+}
block22:
+{
v139 = add v137, v133 : i32
br block23(v137, v159)
+}
block23(v140: i32, v141: i32):
+{
v142 = cast v141 : u32
v143 = inttoptr v142 : *mut u8
v144 = load v143 : u8
@@ -5459,10 +6490,15 @@ block23(v140: i32, v141: i32):
v157 = cast v156 : i32
v158 = neq v157, 0 : i1
condbr v158, block23(v152, v150), block25
+}
block24:
+{
br block21
+}
block25:
+{
br block24
}
+}
diff --git a/frontend-wasm/tests/expected/signed_arith.mir b/frontend-wasm/tests/expected/signed_arith.mir
index d4566efd..7f16896c 100644
--- a/frontend-wasm/tests/expected/signed_arith.mir
+++ b/frontend-wasm/tests/expected/signed_arith.mir
@@ -11,173 +11,234 @@ global external gv2 : i32 = 0x00100150 { id = gvar2 };
pub fn rust_begin_unwind(i32) {
block0(v0: i32):
+{
br block2
+}
block1:
+{
+}
block2:
+{
br block2
+}
block3:
+{
+}
}
pub fn div_s(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
+{
v3 = eq v1, 0 : i1
v4 = cast v3 : i32
v5 = neq v4, 0 : i1
condbr v5, block3, block4
+}
block1(v2: i32):
- ret v2
+{
+ ret (v2)
+}
block2:
+{
v22 = div v0, v1 : i32
br block1(v22)
+}
block3:
+{
v17 = const.i32 1048672 : i32
v18 = const.i32 25 : i32
v19 = const.i32 1048648 : i32
call noname::core::panicking::panic(v17, v18, v19)
unreachable
+}
block4:
+{
v6 = const.i32 -2147483648 : i32
v7 = neq v0, v6 : i1
v8 = cast v7 : i32
v9 = neq v8, 0 : i1
condbr v9, block2, block5
+}
block5:
+{
v10 = const.i32 -1 : i32
v11 = neq v1, v10 : i1
v12 = cast v11 : i32
v13 = neq v12, 0 : i1
condbr v13, block2, block6
+}
block6:
+{
v14 = const.i32 1048704 : i32
v15 = const.i32 31 : i32
v16 = const.i32 1048648 : i32
call noname::core::panicking::panic(v14, v15, v16)
unreachable
}
+}
pub fn div_u(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
+{
v3 = eq v1, 0 : i1
v4 = cast v3 : i32
v5 = neq v4, 0 : i1
condbr v5, block2, block3
+}
block1(v2: i32):
+{
+}
block2:
+{
v10 = const.i32 1048672 : i32
v11 = const.i32 25 : i32
v12 = const.i32 1048736 : i32
call noname::core::panicking::panic(v10, v11, v12)
unreachable
+}
block3:
+{
v6 = cast v0 : u32
v7 = cast v1 : u32
v8 = div v6, v7 : u32
v9 = cast v8 : i32
- ret v9
+ ret (v9)
+}
}
pub fn rem_s(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
+{
v3 = eq v1, 0 : i1
v4 = cast v3 : i32
v5 = neq v4, 0 : i1
condbr v5, block3, block4
+}
block1(v2: i32):
- ret v2
+{
+ ret (v2)
+}
block2:
+{
v22 = mod v0, v1 : i32
br block1(v22)
+}
block3:
+{
v17 = const.i32 1048768 : i32
v18 = const.i32 57 : i32
v19 = const.i32 1048752 : i32
call noname::core::panicking::panic(v17, v18, v19)
unreachable
+}
block4:
+{
v6 = const.i32 -2147483648 : i32
v7 = neq v0, v6 : i1
v8 = cast v7 : i32
v9 = neq v8, 0 : i1
condbr v9, block2, block5
+}
block5:
+{
v10 = const.i32 -1 : i32
v11 = neq v1, v10 : i1
v12 = cast v11 : i32
v13 = neq v12, 0 : i1
condbr v13, block2, block6
+}
block6:
+{
v14 = const.i32 1048832 : i32
v15 = const.i32 48 : i32
v16 = const.i32 1048752 : i32
call noname::core::panicking::panic(v14, v15, v16)
unreachable
}
+}
pub fn rem_u(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
+{
v3 = eq v1, 0 : i1
v4 = cast v3 : i32
v5 = neq v4, 0 : i1
condbr v5, block2, block3
+}
block1(v2: i32):
+{
+}
block2:
+{
v10 = const.i32 1048768 : i32
v11 = const.i32 57 : i32
v12 = const.i32 1048880 : i32
call noname::core::panicking::panic(v10, v11, v12)
unreachable
+}
block3:
+{
v6 = cast v0 : u32
v7 = cast v1 : u32
v8 = mod v6, v7 : u32
v9 = cast v8 : i32
- ret v9
+ ret (v9)
+}
}
pub fn shr_s(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
+{
v3 = shr v0, v1 : i32
br block1(v3)
+}
block1(v2: i32):
- ret v2
+{
+ ret (v2)
+}
}
pub fn shr_u(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
+{
v3 = cast v0 : u32
v4 = cast v1 : u32
v5 = shr v3, v4 : u32
v6 = cast v5 : i32
br block1(v6)
+}
block1(v2: i32):
- ret v2
+{
+ ret (v2)
+}
}
pub fn __main() -> i32 {
block0:
+{
v1 = const.i32 -8 : i32
v2 = const.i32 -4 : i32
v3 = call noname::div_s(v1, v2) : i32
@@ -202,61 +263,68 @@ block0:
v22 = call noname::shr_u(v20, v21) : i32
v23 = add v19, v22 : i32
br block1(v23)
+}
block1(v0: i32):
- ret v0
+{
+ ret (v0)
+}
}
pub fn core::ptr::drop_in_place(i32) {
block0(v0: i32):
+{
br block1
+}
block1:
- ret
+{
+ ret
+}
}
pub fn core::panicking::panic_fmt(i32, i32) {
block0(v0: i32, v1: i32):
+{
v2 = const.i32 0 : i32
v3 = global.load (@__stack_pointer) as *mut i8 : i32
v4 = const.i32 32 : i32
v5 = sub v3, v4 : i32
v6 = global.symbol @__stack_pointer : *mut i32
store v6, v5
- v7 = cast v5 : u32
- v8 = add v7, 24 : u32
- v9 = inttoptr v8 : *mut i32
- store v9, v0
- v10 = const.i32 1048896 : i32
- v11 = cast v5 : u32
- v12 = add v11, 16 : u32
- v13 = inttoptr v12 : *mut i32
- store v13, v10
- v14 = const.i32 1048896 : i32
+ v7 = const.i32 1 : i32
+ v8 = trunc v7 : u16
+ v9 = cast v5 : u32
+ v10 = add v9, 28 : u32
+ v11 = inttoptr v10 : *mut u16
+ store v11, v8
+ v12 = cast v5 : u32
+ v13 = add v12, 24 : u32
+ v14 = inttoptr v13 : *mut i32
+ store v14, v1
v15 = cast v5 : u32
- v16 = add v15, 12 : u32
+ v16 = add v15, 20 : u32
v17 = inttoptr v16 : *mut i32
- store v17, v14
- v18 = const.i32 1 : i32
- v19 = trunc v18 : u8
- v20 = cast v5 : u32
- v21 = add v20, 28 : u32
- v22 = inttoptr v21 : *mut u8
- store v22, v19
+ store v17, v0
+ v18 = const.i32 1048896 : i32
+ v19 = cast v5 : u32
+ v20 = add v19, 16 : u32
+ v21 = inttoptr v20 : *mut i32
+ store v21, v18
+ v22 = const.i32 1048896 : i32
v23 = cast v5 : u32
- v24 = add v23, 20 : u32
+ v24 = add v23, 12 : u32
v25 = inttoptr v24 : *mut i32
- store v25, v1
+ store v25, v22
v26 = const.i32 12 : i32
v27 = add v5, v26 : i32
call noname::rust_begin_unwind(v27)
unreachable
-
-block1:
}
pub fn core::panicking::panic(i32, i32, i32) {
block0(v0: i32, v1: i32, v2: i32):
+{
v3 = const.i32 0 : i32
v4 = global.load (@__stack_pointer) as *mut i8 : i32
v5 = const.i32 32 : i32
@@ -294,23 +362,25 @@ block0(v0: i32, v1: i32, v2: i32):
store v30, v28
call noname::core::panicking::panic_fmt(v6, v2)
unreachable
-
-block1:
}
pub fn ::type_id(i32, i32) {
block0(v0: i32, v1: i32):
- v2 = const.i64 -1688046730280208939 : i64
+{
+ v2 = const.i64 -8014429818408747214 : i64
v3 = cast v0 : u32
v4 = add v3, 8 : u32
v5 = inttoptr v4 : *mut i64
store v5, v2
- v6 = const.i64 -2518113060735759681 : i64
+ v6 = const.i64 167320651382453006 : i64
v7 = cast v0 : u32
v8 = inttoptr v7 : *mut i64
store v8, v6
br block1
+}
block1:
- ret
+{
+ ret
+}
}
diff --git a/frontend-wasm/tests/expected/signed_arith.wat b/frontend-wasm/tests/expected/signed_arith.wat
index 03655d92..5f9222b0 100644
--- a/frontend-wasm/tests/expected/signed_arith.wat
+++ b/frontend-wasm/tests/expected/signed_arith.wat
@@ -145,21 +145,21 @@
local.tee 2
global.set $__stack_pointer
local.get 2
- local.get 0
+ i32.const 1
+ i32.store16 offset=28
+ local.get 2
+ local.get 1
i32.store offset=24
local.get 2
+ local.get 0
+ i32.store offset=20
+ local.get 2
i32.const 1048896
i32.store offset=16
local.get 2
i32.const 1048896
i32.store offset=12
local.get 2
- i32.const 1
- i32.store8 offset=28
- local.get 2
- local.get 1
- i32.store offset=20
- local.get 2
i32.const 12
i32.add
call $rust_begin_unwind
@@ -201,10 +201,10 @@
)
(func $::type_id (;11;) (type 3) (param i32 i32)
local.get 0
- i64.const -1688046730280208939
+ i64.const -8014429818408747214
i64.store offset=8
local.get 0
- i64.const -2518113060735759681
+ i64.const 167320651382453006
i64.store
)
(table (;0;) 3 3 funcref)
diff --git a/frontend-wasm/tests/test_rust_comp.rs b/frontend-wasm/tests/test_rust_comp.rs
index e03510e6..82b2b1a8 100644
--- a/frontend-wasm/tests/test_rust_comp.rs
+++ b/frontend-wasm/tests/test_rust_comp.rs
@@ -213,22 +213,30 @@ fn rust_add() {
pub fn add(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
+ {
v3 = add v1, v0 : i32
br block1(v3)
+ }
block1(v2: i32):
- ret v2
+ {
+ ret (v2)
+ }
}
pub fn __main() -> i32 {
block0:
+ {
v1 = const.i32 1 : i32
v2 = const.i32 2 : i32
v3 = call noname::add(v1, v2) : i32
br block1(v3)
+ }
block1(v0: i32):
- ret v0
+ {
+ ret (v0)
+ }
}
"#]],
);
@@ -293,37 +301,53 @@ fn rust_fib() {
pub fn fib(i32) -> i32 {
block0(v0: i32):
+ {
v2 = const.i32 0 : i32
v3 = const.i32 0 : i32
v4 = const.i32 1 : i32
br block2(v4, v0, v3)
+ }
block1(v1: i32):
+ {
+ }
block2(v6: i32, v7: i32, v9: i32):
+ {
v8 = neq v7, 0 : i1
condbr v8, block4, block5
+ }
block3(v5: i32):
+ {
+ }
block4:
+ {
v10 = const.i32 -1 : i32
v11 = add v7, v10 : i32
v12 = add v9, v6 : i32
br block2(v12, v11, v6)
+ }
block5:
- ret v9
+ {
+ ret (v9)
+ }
}
pub fn __main() -> i32 {
block0:
+ {
v1 = const.i32 25 : i32
v2 = call noname::fib(v1) : i32
br block1(v2)
+ }
block1(v0: i32):
- ret v0
+ {
+ ret (v0)
+ }
}
"#]],
);
@@ -395,29 +419,40 @@ fn rust_enum() {
pub fn match_enum(i32, i32, i32) -> i32 {
block0(v0: i32, v1: i32, v2: i32):
+ {
v4 = const.i32 255 : i32
v5 = band v2, v4 : i32
v6 = cast v5 : u32
switch v6, 0 => block4, 1 => block3, 2 => block2, block4
+ }
block1(v3: i32):
- ret v3
+ {
+ ret (v3)
+ }
block2:
+ {
v9 = mul v1, v0 : i32
br block1(v9)
+ }
block3:
+ {
v8 = sub v0, v1 : i32
- ret v8
+ ret (v8)
+ }
block4:
+ {
v7 = add v1, v0 : i32
- ret v7
+ ret (v7)
+ }
}
pub fn __main() -> i32 {
block0:
+ {
v1 = const.i32 3 : i32
v2 = const.i32 5 : i32
v3 = const.i32 0 : i32
@@ -433,9 +468,12 @@ fn rust_enum() {
v13 = call noname::match_enum(v10, v11, v12) : i32
v14 = add v9, v13 : i32
br block1(v14)
+ }
block1(v0: i32):
- ret v0
+ {
+ ret (v0)
+ }
}
"#]],
)
@@ -510,23 +548,32 @@ fn rust_array() {
pub fn sum_arr(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
+ {
v3 = const.i32 0 : i32
v4 = const.i32 0 : i32
v5 = eq v1, 0 : i1
v6 = cast v5 : i32
v7 = neq v6, 0 : i1
condbr v7, block2(v4), block3
+ }
block1(v2: i32):
- ret v2
+ {
+ ret (v2)
+ }
block2(v20: i32):
+ {
br block1(v20)
+ }
block3:
+ {
br block4(v0, v4, v1)
+ }
block4(v8: i32, v12: i32, v16: i32):
+ {
v9 = cast v8 : u32
v10 = inttoptr v9 : *mut i32
v11 = load v10 : i32
@@ -537,16 +584,22 @@ fn rust_array() {
v18 = add v16, v17 : i32
v19 = neq v18, 0 : i1
condbr v19, block4(v15, v13, v18), block6
+ }
block5:
+ {
br block2(v13)
+ }
block6:
+ {
br block5
}
+ }
pub fn __main() -> i32 {
block0:
+ {
v1 = const.i32 1048576 : i32
v2 = const.i32 5 : i32
v3 = call noname::sum_arr(v1, v2) : i32
@@ -555,9 +608,12 @@ fn rust_array() {
v6 = call noname::sum_arr(v4, v5) : i32
v7 = add v3, v6 : i32
br block1(v7)
+ }
block1(v0: i32):
- ret v0
+ {
+ ret (v0)
+ }
}
"#]],
)
@@ -631,6 +687,7 @@ fn rust_static_mut() {
pub fn global_var_update() {
block0:
+ {
v0 = const.i32 0 : i32
v1 = const.i32 0 : i32
v2 = cast v1 : u32
@@ -646,23 +703,31 @@ fn rust_static_mut() {
v12 = inttoptr v11 : *mut u8
store v12, v9
br block1
+ }
block1:
- ret
+ {
+ ret
+ }
}
pub fn __main() -> i32 {
block0:
+ {
v1 = const.i32 0 : i32
call noname::global_var_update()
v2 = const.i32 0 : i32
v3 = const.i32 -9 : i32
br block2(v3, v2)
+ }
block1(v0: i32):
- ret v0
+ {
+ ret (v0)
+ }
block2(v4: i32, v11: i32):
+ {
v5 = const.i32 1048585 : i32
v6 = add v4, v5 : i32
v7 = cast v6 : u32
@@ -674,15 +739,20 @@ fn rust_static_mut() {
v14 = add v4, v13 : i32
v15 = neq v14, 0 : i1
condbr v15, block2(v14, v12), block4
+ }
block3:
+ {
v16 = const.i32 255 : i32
v17 = band v12, v16 : i32
br block1(v17)
+ }
block4:
+ {
br block3
}
+ }
"#]],
);
}
@@ -697,6 +767,7 @@ fn dlmalloc() {
}
#[test]
+#[ignore = "Being reworked"]
fn signed_arith() {
check_ir_files(
include_str!("rust_source/signed_arith.rs"),
diff --git a/hir-transform/src/inline_blocks.rs b/hir-transform/src/inline_blocks.rs
index f77287bd..1d7c55d0 100644
--- a/hir-transform/src/inline_blocks.rs
+++ b/hir-transform/src/inline_blocks.rs
@@ -278,31 +278,42 @@ mod tests {
/// ```text,ignore
/// pub fn test(*mut u8, i32) -> *mut u8 {
/// entry(ptr0: *mut u8, offset: i32):
+ /// {
/// zero = const.u32 0
/// ptr1 = ptrtoint ptr0 : u32
/// is_null = eq ptr1, zero
/// br blk0(ptr1, is_null)
+ /// }
///
/// blk0(ptr2: u32, is_null1: i1):
+ /// {
/// condbr is_null1, blk2(ptr0), blk1(ptr2)
+ /// }
///
/// blk1(ptr3: u32):
+ /// {
/// ptr4 = add ptr3, offset
/// is_null2 = eq ptr4, zero
/// condbr is_null2, blk4(ptr0), blk5(ptr4)
///
/// blk2(result0: *mut u8)
/// br blk3
+ /// }
///
/// blk3:
- /// ret result0
+ /// {
+ /// ret (result0)
+ /// }
///
- /// blk4(result1: *mut u8)
- /// ret result1
+ /// blk4(result1: *mut u8):
+ /// ret (result1)
+ /// }
///
/// blk5(ptr5: u32):
+ /// {
/// ptr6 = inttoptr ptr5 : *mut u8
- /// ret ptr6
+ /// ret (ptr6)
+ /// }
/// }
/// ```
///
@@ -311,25 +322,35 @@ mod tests {
/// ```text,ignore
/// pub fn test(*mut u8, i32) -> *mut u8 {
/// entry(ptr0: *mut u8, offset: i32):
+ /// {
/// zero = const.u32 0
/// ptr1 = ptrtoint ptr0 : u32
/// is_null = eq ptr1, zero
/// condbr is_null, blk2, blk1
+ /// }
///
/// blk1:
+ /// {
/// ptr2 = add ptr1, offset
/// is_null1 = eq ptr2, zero
/// condbr is_null1, blk3, blk4
+ /// }
///
/// blk2:
- /// ret ptr0
+ /// {
+ /// ret (ptr0)
+ /// }
///
/// blk3:
- /// ret ptr0
+ /// {
+ /// ret (ptr0)
+ /// }
///
/// blk4:
+ /// {
/// ptr3 = inttoptr ptr2 : *mut u8
- /// ret ptr3
+ /// ret (ptr3)
+ /// }
/// ```
///
/// In short, regardless of block arguments, control flow edges between blocks
@@ -429,26 +450,36 @@ mod tests {
let expected = "pub fn inlining_test(*mut u8, i32) -> *mut u8 {
block0(v0: *mut u8, v1: i32):
+{
v8 = ptrtoint v0 : u32
v9 = eq v8, 0 : i1
condbr v9, block3(v0), block2(v8)
+}
block2(v4: u32):
+{
v10 = cast v4 : i32
v11 = add v10, v1 : i32
v12 = cast v11 : u32
v13 = eq v12, 0 : i1
condbr v13, block5(v0), block6(v12)
+}
block3(v5: *mut u8):
- ret v5
+{
+ ret (v5)
+}
block5(v6: *mut u8):
- ret v6
+{
+ ret (v6)
+}
block6(v7: u32):
+{
v14 = inttoptr v7 : *mut u8
- ret v14
+ ret (v14)
+}
}
";
diff --git a/hir-transform/src/split_critical_edges.rs b/hir-transform/src/split_critical_edges.rs
index 1d09a73c..b73e309b 100644
--- a/hir-transform/src/split_critical_edges.rs
+++ b/hir-transform/src/split_critical_edges.rs
@@ -152,21 +152,29 @@ mod tests {
/// ```text,ignore
/// pub fn test(*mut u8, u32) -> *mut u8 {
/// entry(ptr0: *mut u8, n0: u32):
+ /// {
/// ptr1 = ptrtoint ptr0 : u32
/// br blk0(ptr1, n0)
+ /// }
///
/// blk0(ptr2: u32, n1: u32):
+ /// {
/// is_null = eq ptr2, 0
/// condbr is_null, blk2(ptr0), blk1(ptr2, n1)
+ /// }
///
/// blk1(ptr3: u32, n2: u32):
+ /// {
/// ptr4 = sub ptr3, n2
/// n3 = sub n2, 1
/// is_zero = eq n3, 0
/// condbr is_zero, blk2(ptr4), blk0(ptr4, n3)
+ /// }
///
/// blk2(result0: *mut u8)
- /// ret result0
+ /// {
+ /// ret (result0)
+ /// }
/// }
/// ```
///
@@ -248,31 +256,45 @@ mod tests {
let expected = "pub fn sce(*mut u8, u32) -> *mut u8 {
block0(v0: *mut u8, v1: u32):
+{
v7 = ptrtoint v0 : u32
br block1(v7, v1)
+}
block1(v2: u32, v3: u32):
+{
v8 = eq v2, 0 : i1
condbr v8, block4, block2(v2, v3)
+}
block4:
+{
br block3(v0)
+}
block2(v4: u32, v5: u32):
+{
v9 = sub v4, v5 : u32
v10 = sub v5, 1 : u32
v11 = eq v10, 0 : i1
condbr v11, block6, block5
+}
block6:
+{
br block3(v9)
+}
block5:
+{
br block1(v9, v10)
+}
block3(v6: u32):
+{
v12 = inttoptr v6 : *mut u8
- ret v12
+ ret (v12)
+}
}
";
diff --git a/hir-transform/src/treeify.rs b/hir-transform/src/treeify.rs
index aca8d1dc..961ddcee 100644
--- a/hir-transform/src/treeify.rs
+++ b/hir-transform/src/treeify.rs
@@ -702,33 +702,46 @@ mod tests {
let expected = "pub fn sum_matrix(*mut u32, u32, u32) -> u32 {
block0(v0: *mut u32, v1: u32, v2: u32):
+{
v10 = const.u32 0 : u32
v11 = ptrtoint v0 : u32
v12 = neq v11, 0 : i1
condbr v12, block2, block7
+}
block7:
- ret v10
+{
+ ret (v10)
+}
block2:
+{
v13 = const.u32 0 : u32
v14 = const.u32 0 : u32
v15 = mul v2, 4 : u32
br block3(v10, v13, v14)
+}
block3(v4: u32, v5: u32, v6: u32):
+{
v16 = lt v5, v1 : i1
v17 = mul v5, v15 : u32
condbr v16, block4(v4, v5, v6), block8
+}
block8:
- ret v4
+{
+ ret (v4)
+}
block4(v7: u32, v8: u32, v9: u32):
+{
v18 = lt v9, v2 : i1
condbr v18, block5, block6
+}
block5:
+{
v19 = mul v9, 4 : u32
v20 = add v17, v19 : u32
v21 = add v11, v20 : u32
@@ -737,12 +750,15 @@ block5:
v24 = add v7, v23 : u32
v25 = incr v9 : u32
br block4(v24, v8, v25)
+}
block6:
+{
v26 = incr v8 : u32
v27 = const.u32 0 : u32
br block3(v7, v26, v27)
}
+}
";
let transformed = function.to_string();
diff --git a/hir/Cargo.toml b/hir/Cargo.toml
index e9f0de04..2ecaefa8 100644
--- a/hir/Cargo.toml
+++ b/hir/Cargo.toml
@@ -10,16 +10,22 @@ license.workspace = true
readme.workspace = true
edition.workspace = true
+[build-dependencies]
+lalrpop = { version = "0.20", default-features = false }
+
[dependencies]
anyhow.workspace = true
cranelift-entity.workspace = true
intrusive-collections.workspace = true
+lalrpop-util="0.20"
miden-assembly.workspace = true
miden-diagnostics.workspace = true
miden-hir-symbol.workspace = true
miden-hir-type.workspace = true
+miden-parsing = "0.1"
petgraph = "0.6"
paste.workspace = true
+pretty_assertions = "1.0"
rustc-hash.workspace = true
smallvec.workspace = true
thiserror.workspace = true
diff --git a/hir/build.rs b/hir/build.rs
new file mode 100644
index 00000000..23c7d3f8
--- /dev/null
+++ b/hir/build.rs
@@ -0,0 +1,5 @@
+extern crate lalrpop;
+
+fn main() {
+ lalrpop::process_root().unwrap();
+}
diff --git a/hir/src/instruction.rs b/hir/src/instruction.rs
index 8c74e0b2..a7b5fd9d 100644
--- a/hir/src/instruction.rs
+++ b/hir/src/instruction.rs
@@ -809,6 +809,16 @@ impl Overflow {
matches!(self, Self::Overflowing)
}
}
+impl fmt::Display for Overflow {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ Self::Unchecked => f.write_str("unchecked"),
+ Self::Checked => f.write_str("checked"),
+ Self::Wrapping => f.write_str("wrapping"),
+ Self::Overflowing => f.write_str("overflow"),
+ }
+ }
+}
#[derive(Debug, Clone)]
pub struct GlobalValueOp {
diff --git a/hir/src/lib.rs b/hir/src/lib.rs
index f7a43ac9..f6fcfd89 100644
--- a/hir/src/lib.rs
+++ b/hir/src/lib.rs
@@ -1,4 +1,8 @@
#![deny(warnings)]
+pub mod parser;
+
+#[macro_use]
+extern crate lalrpop_util;
pub use intrusive_collections::UnsafeRef;
pub use miden_diagnostics::SourceSpan;
diff --git a/hir/src/parser/ast/block.rs b/hir/src/parser/ast/block.rs
new file mode 100644
index 00000000..e15ec137
--- /dev/null
+++ b/hir/src/parser/ast/block.rs
@@ -0,0 +1,102 @@
+use super::*;
+use crate::{Ident, Type};
+
+const INDENT: &str = " ";
+
+/// Represents the label at the start of a basic block.
+///
+/// Labels must be unique within each function.
+#[derive(PartialEq, Debug)]
+pub struct Label {
+ pub name: Ident,
+}
+impl Label {
+ pub fn new(name: Ident) -> Self {
+ Self { name }
+ }
+}
+impl fmt::Display for Label {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.name)
+ }
+}
+
+/// Represents an argument for a basic block
+#[derive(PartialEq, Debug)]
+pub struct BlockArgument {
+ pub value: Value,
+ pub ty: Type,
+}
+impl BlockArgument {
+ pub fn new(value: Value, ty: Type) -> Self {
+ Self { value, ty }
+ }
+}
+impl fmt::Display for BlockArgument {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{} : {} ", self.value, self.ty)
+ }
+}
+
+/// Represents the label and the arguments of a basic block
+#[derive(PartialEq, Debug)]
+pub struct BlockHeader {
+ pub label: Label,
+ pub args: Vec,
+}
+impl BlockHeader {
+ pub fn new(label: Label, args: Vec) -> Self {
+ Self { label, args }
+ }
+}
+impl fmt::Display for BlockHeader {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{} ", self.label)?;
+ if self.args.is_empty() {
+ f.write_str(":\n")
+ } else {
+ f.write_str("(")?;
+ for (i, arg) in self.args.iter().enumerate() {
+ if i != 0 {
+ write!(f, ", {}", arg)?;
+ } else {
+ write!(f, "{}", arg)?;
+ }
+ }
+ f.write_str(") :\n")
+ }
+ }
+}
+
+/// Represents a basic block of instructions
+#[derive(Spanned, Debug)]
+pub struct Block {
+ #[span]
+ pub span: SourceSpan,
+ pub header: BlockHeader,
+ pub instructions: Vec,
+}
+impl Block {
+ pub fn new(span: SourceSpan, header: BlockHeader, instructions: Vec) -> Self {
+ Self {
+ span,
+ header,
+ instructions,
+ }
+ }
+}
+impl PartialEq for Block {
+ fn eq(&self, other: &Self) -> bool {
+ self.header == other.header
+ && self.instructions == other.instructions
+ }
+}
+impl fmt::Display for Block {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ writeln!(f, "{}", self.header)?;
+ for inst in self.instructions.iter() {
+ writeln!(f, "{}{}", INDENT, inst)?;
+ }
+ Ok(())
+ }
+}
diff --git a/hir/src/parser/ast/functions.rs b/hir/src/parser/ast/functions.rs
new file mode 100644
index 00000000..83a42101
--- /dev/null
+++ b/hir/src/parser/ast/functions.rs
@@ -0,0 +1,174 @@
+use super::*;
+use crate::{ArgumentExtension, ArgumentPurpose, CallConv, FunctionIdent, Type};
+
+/// The possible visibilities of a function
+#[derive(PartialEq, Debug)]
+pub enum Visibility {
+ /// (Module) private visibility
+ Private,
+ /// Public visibility
+ Public,
+}
+
+/// A single parameter to a function.
+/// Parameter names are defined in the entry block for the function.
+#[derive(PartialEq, Debug)]
+pub struct FunctionParameter {
+ /// The purpose of the parameter (default or struct return)
+ pub purpose: ArgumentPurpose,
+ /// The bit extension for the parameter
+ pub extension: ArgumentExtension,
+ /// The type of the parameter
+ pub ty: Type,
+}
+impl FunctionParameter {
+ pub fn new(purpose: ArgumentPurpose, extension: ArgumentExtension, ty: Type) -> Self {
+ Self {
+ purpose,
+ extension,
+ ty,
+ }
+ }
+}
+impl fmt::Display for FunctionParameter {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self.purpose {
+ ArgumentPurpose::Default => Ok(()),
+ ArgumentPurpose::StructReturn => f.write_str("sret "),
+ }?;
+ match self.extension {
+ ArgumentExtension::None => Ok(()),
+ ArgumentExtension::Zext => f.write_str("zext "),
+ ArgumentExtension::Sext => f.write_str("sext "),
+ }?;
+ write!(f, "{}", self.ty)
+ }
+}
+
+/// A single return value from a function.
+#[derive(PartialEq, Debug)]
+pub struct FunctionReturn {
+ /// The bit extension for the parameter
+ pub extension: ArgumentExtension,
+ /// The type of the parameter
+ pub ty: Type,
+}
+impl FunctionReturn {
+ pub fn new(extension: ArgumentExtension, ty: Type) -> Self {
+ Self { extension, ty }
+ }
+}
+impl fmt::Display for FunctionReturn {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self.extension {
+ ArgumentExtension::None => Ok(()),
+ ArgumentExtension::Zext => f.write_str("zext "),
+ ArgumentExtension::Sext => f.write_str("sext "),
+ }?;
+ write!(f, "{}", self.ty)
+ }
+}
+
+/// Represents the type signature of a function
+#[derive(Spanned, Debug)]
+pub struct FunctionSignature {
+ #[span]
+ pub span: SourceSpan,
+ pub visibility: Visibility,
+ pub call_convention: CallConv,
+ pub name: FunctionIdent,
+ pub params: Vec,
+ pub returns: Vec,
+}
+impl FunctionSignature {
+ pub fn new(
+ span: SourceSpan,
+ visibility: Visibility,
+ call_convention: CallConv,
+ name: FunctionIdent,
+ params: Vec,
+ returns: Vec,
+ ) -> Self {
+ Self {
+ span,
+ visibility,
+ call_convention,
+ name,
+ params,
+ returns,
+ }
+ }
+}
+impl PartialEq for FunctionSignature {
+ fn eq(&self, other: &Self) -> bool {
+ self.visibility == other.visibility
+ && self.call_convention == other.call_convention
+ && self.name == other.name
+ && self.params == other.params
+ && self.returns == other.returns
+ }
+}
+impl fmt::Display for FunctionSignature {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self.visibility {
+ Visibility::Private => Ok(()),
+ Visibility::Public => f.write_str("pub "),
+ }?;
+ match self.call_convention {
+ CallConv::SystemV => Ok(()),
+ CallConv::Kernel => f.write_str("kernel "),
+ CallConv::Fast => f.write_str("fast "),
+ }?;
+ write!(f, "{}(", self.name)?;
+ for (i, param) in self.params.iter().enumerate() {
+ if i != 0 {
+ write!(f, ", {}", param)?;
+ } else {
+ write!(f, "{}", param)?;
+ }
+ }
+ f.write_str(")")?;
+ for (i, ret) in self.returns.iter().enumerate() {
+ if i != 0 {
+ write!(f, ", {}", ret)?;
+ } else {
+ write!(f, "{}", ret)?;
+ }
+ }
+ Ok(())
+ }
+}
+
+/// Represents the declaration of a function
+#[derive(Spanned, Debug)]
+pub struct FunctionDeclaration {
+ #[span]
+ pub span: SourceSpan,
+ pub signature: FunctionSignature,
+ pub blocks: Vec,
+}
+impl FunctionDeclaration {
+ pub fn new(span: SourceSpan, signature: FunctionSignature, blocks: Vec) -> Self {
+ Self {
+ span,
+ signature,
+ blocks,
+ }
+ }
+}
+impl PartialEq for FunctionDeclaration {
+ fn eq(&self, other: &Self) -> bool {
+ self.signature == other.signature
+ && self.blocks == other.blocks
+ }
+}
+impl fmt::Display for FunctionDeclaration {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.signature)?;
+ f.write_str("{{\n")?;
+ for block in self.blocks.iter() {
+ write!(f, "{}", block)?;
+ }
+ f.write_str("}}\n")
+ }
+}
diff --git a/hir/src/parser/ast/globals.rs b/hir/src/parser/ast/globals.rs
new file mode 100644
index 00000000..d048b30c
--- /dev/null
+++ b/hir/src/parser/ast/globals.rs
@@ -0,0 +1,79 @@
+use std::fmt;
+
+use miden_diagnostics::{SourceSpan, Spanned};
+
+use super::*;
+use crate::{Ident, Linkage, Type};
+
+/// This is a type alias used to clarify that an identifier refers to a global variable
+pub type GlobalVarId = Ident;
+
+/// A constant value in the form of a hexadecimal string
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct GlobalVarInitializer {
+ pub data: Vec,
+}
+impl GlobalVarInitializer {
+ pub fn new(data: Vec) -> Self {
+ Self { data }
+ }
+}
+impl fmt::Display for GlobalVarInitializer {
+ /// Print the constant data in hexadecimal format, e.g. 0x000102030405060708090a0b0c0d0e0f.
+ ///
+ /// The printed form of the constant renders the bytes in big-endian order, for readability.
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ if !self.data.is_empty() {
+ write!(f, "0x")?;
+ for b in self.data.iter().rev() {
+ write!(f, "{:02x}", b)?;
+ }
+ }
+ Ok(())
+ }
+}
+
+/// This represents the declaration of a Miden IR global variable
+#[derive(Spanned, Debug)]
+pub struct GlobalVarDeclaration {
+ #[span]
+ pub span: SourceSpan,
+ pub name: GlobalVarId,
+ pub ty: Type,
+ pub linkage: Linkage,
+ pub init: Option,
+}
+impl GlobalVarDeclaration {
+ /// Constructs a new global variable, with the given span, name, type, linkage, and optinal initializer.
+ ///
+ pub fn new(span: SourceSpan, name: ModuleId, ty: Type, linkage: Linkage) -> Self {
+ Self {
+ span,
+ name,
+ ty,
+ linkage,
+ init: None,
+ }
+ }
+
+ pub fn with_init(&mut self, init: GlobalVarInitializer) {
+ self.init = Some(init)
+ }
+}
+impl PartialEq for GlobalVarDeclaration {
+ fn eq(&self, other: &Self) -> bool {
+ self.name == other.name
+ && self.ty == other.ty
+ && self.linkage == other.linkage
+ && self.init == other.init
+ }
+}
+impl fmt::Display for GlobalVarDeclaration {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{} {} {}", self.name, self.ty, self.linkage)?;
+ if self.init.is_some() {
+ write!(f, "= {}", self.init.as_ref().unwrap())?;
+ }
+ Ok(())
+ }
+}
diff --git a/hir/src/parser/ast/instruction.rs b/hir/src/parser/ast/instruction.rs
new file mode 100644
index 00000000..b23ee8af
--- /dev/null
+++ b/hir/src/parser/ast/instruction.rs
@@ -0,0 +1,611 @@
+use super::*;
+use crate::{FunctionIdent, Ident, Overflow, Type};
+
+/// Represents a value in Miden IR.
+///
+/// All intermediate values are named, and have an associated [Value].
+/// Value identifiers must be globally unique.
+#[derive(PartialEq, Debug)]
+pub struct Value {
+ pub name: Ident,
+}
+impl Value {
+ pub fn new(name: Ident) -> Self {
+ Self { name }
+ }
+}
+impl fmt::Display for Value {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.name)
+ }
+}
+
+/// Immediates are converted at a later stage
+#[derive(PartialEq, Debug)]
+pub enum Immediate {
+ Pos(u128),
+ Neg(u128),
+}
+impl fmt::Display for Immediate {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ Self::Pos(0) | Self::Neg(0) => f.write_str("0"),
+ Self::Pos(v) => write!(f, "{}", v),
+ Self::Neg(v) => write!(f, "-{}", v),
+ }
+ }
+}
+
+/// Represents a single instruction.
+///
+/// An instruction consists of a single operation, and a number of values that
+/// represent the results of the operation. Additionally, the instruction contains
+/// the types of the produced results
+#[derive(Spanned, Debug)]
+pub struct Instruction {
+ #[span]
+ pub span: SourceSpan,
+ pub values: Vec,
+ pub op: Operation,
+ pub types: Vec,
+}
+impl Instruction {
+ pub fn new(span: SourceSpan, values: Vec, op: Operation, types: Vec) -> Self {
+ Self {
+ span,
+ values,
+ op,
+ types,
+ }
+ }
+}
+impl PartialEq for Instruction {
+ fn eq(&self, other: &Self) -> bool {
+ self.values == other.values
+ && self.op == other.op
+ && self.types == other.types
+ }
+}
+impl fmt::Display for Instruction {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ if self.values.is_empty() {
+ write!(f, "{}", self.op)?;
+ } else {
+ for (i, v) in self.values.iter().enumerate() {
+ if i != 0 {
+ write!(f, ", {}", v)?;
+ } else {
+ write!(f, "{}", v)?;
+ }
+ }
+ write!(f, " = {} : ", self.op)?;
+ for (i, t) in self.types.iter().enumerate() {
+ if i != 0 {
+ write!(f, ", {}", t)?;
+ } else {
+ write!(f, "{}", t)?;
+ }
+ }
+ }
+ Ok(())
+ }
+}
+
+/// Represents a operation and its arguments
+#[derive(PartialEq, Debug)]
+pub enum Operation {
+ BinaryOp(BinaryOpCode, Value, Value),
+ BinaryImmOp(BinaryImmOpCode, Value, Immediate),
+ UnaryOp(UnaryOpCode, Value),
+ UnaryImmOp(UnaryImmOpCode, Immediate),
+ ReturnOp(Vec),
+ CallOp(CallOp, FunctionIdent, Vec),
+ CondOp(Value, Destination, Destination),
+ BranchOp(Destination),
+ SwitchOp(Value, Vec),
+ TestOp(Type, Value),
+ PrimOp(PrimOpCode, Vec),
+ LoadOp(Value),
+ MemCpyOp(Type, Value, Value, Value),
+ GlobalValueOp(GlobalValueOp),
+}
+impl fmt::Display for Operation {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ Self::BinaryOp(op, v1, v2) => {
+ write!(f, "{} {} {}", op, v1, v2)
+ }
+ Self::BinaryImmOp(op, v, i) => {
+ write!(f, "{} {} {}", op, v, i)
+ }
+ Self::UnaryOp(op, v) => {
+ write!(f, "{} {}", op, v)
+ }
+ Self::UnaryImmOp(op, i) => {
+ write!(f, "{} {}", op, i)
+ }
+ Self::ReturnOp(vs) => {
+ f.write_str("ret")?;
+ for (i, v) in vs.iter().enumerate() {
+ if i > 0 {
+ f.write_str(",")?;
+ }
+ write!(f, " {}", v)?;
+ }
+ Ok(())
+ }
+ Self::CallOp(op, id, vs) => {
+ write!(f, "{} {} (", op, id)?;
+ for (i, v) in vs.iter().enumerate() {
+ if i > 0 {
+ f.write_str(", ")?;
+ }
+ write!(f, "{}", v)?;
+ }
+ f.write_str(")")
+ }
+ Self::CondOp(v, dest1, dest2) => {
+ write!(f, "cond {}, {}, {}", v, dest1, dest2)
+ }
+ Self::BranchOp(dest) => {
+ write!(f, "branch {}", dest)
+ }
+ Self::SwitchOp(v, branches) => {
+ writeln!(f, "switch {} {{", v)?;
+ for (i, b) in branches.iter().enumerate() {
+ if i > 0 {
+ f.write_str(",\n")?;
+ }
+ //TODO: Indentation
+ write!(f, "{}", b)?;
+ }
+ //TODO: Indentation
+ f.write_str("\n}}")
+ }
+ Self::TestOp(t, v) => {
+ write!(f, "test.{} {}", t, v)
+ }
+ Self::PrimOp(op, vs) => {
+ write!(f, "{}", op)?;
+ for (i, v) in vs.iter().enumerate() {
+ if i > 0 {
+ f.write_str(",")?;
+ }
+ write!(f, " {}", v)?;
+ }
+ Ok(())
+ }
+ Self::LoadOp(v) => {
+ write!(f, "load {}", v)
+ }
+ Self::MemCpyOp(t, v1, v2, v3) => {
+ write!(f, "memcpy.{} {}, {}, {}", t, v1, v2, v3)
+ }
+ Self::GlobalValueOp(op) => {
+ write!(f, "{}", op)
+ }
+ }
+ }
+}
+
+/// Used to distinguish between user calls and kernel calls
+#[derive(PartialEq, Debug)]
+pub enum CallOp {
+ Call,
+ SysCall,
+}
+impl fmt::Display for CallOp {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ Self::Call => f.write_str("call"),
+ Self::SysCall => f.write_str("syscall"),
+ }
+ }
+}
+
+/// Used to distinguish between binary operations
+#[derive(PartialEq, Debug)]
+pub enum BinaryOpCode {
+ Add(Overflow),
+ Sub(Overflow),
+ Mul(Overflow),
+ Div(Overflow),
+ Min(Overflow),
+ Max(Overflow),
+ Mod(Overflow),
+ DivMod(Overflow),
+ Exp(Overflow),
+ And,
+ BAnd(Overflow),
+ Or,
+ BOr(Overflow),
+ Xor,
+ BXor(Overflow),
+ Shl(Overflow),
+ Shr(Overflow),
+ Rotl(Overflow),
+ Rotr(Overflow),
+ Eq,
+ Neq,
+ Gt,
+ Gte,
+ Lt,
+ Lte,
+ Store,
+}
+impl fmt::Display for BinaryOpCode {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ Self::Add(overflow) => {
+ write!(f, "add.{}", overflow)
+ }
+ Self::Sub(overflow) => {
+ write!(f, "sub.{}", overflow)
+ }
+ Self::Mul(overflow) => {
+ write!(f, "mul.{}", overflow)
+ }
+ Self::Div(overflow) => {
+ write!(f, "div.{}", overflow)
+ }
+ Self::Min(overflow) => {
+ write!(f, "min.{}", overflow)
+ }
+ Self::Max(overflow) => {
+ write!(f, "max.{}", overflow)
+ }
+ Self::Mod(overflow) => {
+ write!(f, "mod.{}", overflow)
+ }
+ Self::DivMod(overflow) => {
+ write!(f, "divmod.{}", overflow)
+ }
+ Self::Exp(overflow) => {
+ write!(f, "exp.{}", overflow)
+ }
+ Self::And => f.write_str("and"),
+ Self::BAnd(overflow) => {
+ write!(f, "band.{}", overflow)
+ }
+ Self::Or => f.write_str("or"),
+ Self::BOr(overflow) => {
+ write!(f, "bor.{}", overflow)
+ }
+ Self::Xor => f.write_str("xor"),
+ Self::BXor(overflow) => {
+ write!(f, "bxor.{}", overflow)
+ }
+ Self::Shl(overflow) => {
+ write!(f, "shl.{}", overflow)
+ }
+ Self::Shr(overflow) => {
+ write!(f, "shr.{}", overflow)
+ }
+ Self::Rotl(overflow) => {
+ write!(f, "rotl.{}", overflow)
+ }
+ Self::Rotr(overflow) => {
+ write!(f, "rotr.{}", overflow)
+ }
+ Self::Eq => f.write_str("eq"),
+ Self::Neq => f.write_str("neq"),
+ Self::Gt => f.write_str("gt"),
+ Self::Gte => f.write_str("gte"),
+ Self::Lt => f.write_str("lt"),
+ Self::Lte => f.write_str("lte"),
+ Self::Store => f.write_str("store"),
+ }
+ }
+}
+
+/// Used to distinguish between immediate binary operations
+#[derive(PartialEq, Debug)]
+pub enum BinaryImmOpCode {
+ AddImm(Overflow),
+ SubImm(Overflow),
+ MulImm(Overflow),
+ DivImm(Overflow),
+ MinImm(Overflow),
+ MaxImm(Overflow),
+ ModImm(Overflow),
+ DivModImm(Overflow),
+ ExpImm(Overflow),
+ AndImm,
+ BAndImm(Overflow),
+ OrImm,
+ BOrImm(Overflow),
+ XorImm,
+ BXorImm(Overflow),
+ ShlImm(Overflow),
+ ShrImm(Overflow),
+ RotlImm(Overflow),
+ RotrImm(Overflow),
+}
+impl fmt::Display for BinaryImmOpCode {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ Self::AddImm(overflow) => {
+ write!(f, "add_imm.{}", overflow)
+ }
+ Self::SubImm(overflow) => {
+ write!(f, "sub_imm.{}", overflow)
+ }
+ Self::MulImm(overflow) => {
+ write!(f, "mul_imm.{}", overflow)
+ }
+ Self::DivImm(overflow) => {
+ write!(f, "div_imm.{}", overflow)
+ }
+ Self::MinImm(overflow) => {
+ write!(f, "min_imm.{}", overflow)
+ }
+ Self::MaxImm(overflow) => {
+ write!(f, "max_imm.{}", overflow)
+ }
+ Self::ModImm(overflow) => {
+ write!(f, "mod_imm.{}", overflow)
+ }
+ Self::DivModImm(overflow) => {
+ write!(f, "divmod_imm.{}", overflow)
+ }
+ Self::ExpImm(overflow) => {
+ write!(f, "exp_imm.{}", overflow)
+ }
+ Self::AndImm => f.write_str("and"),
+ Self::BAndImm(overflow) => {
+ write!(f, "band_imm.{}", overflow)
+ }
+ Self::OrImm => f.write_str("or"),
+ Self::BOrImm(overflow) => {
+ write!(f, "bor_imm.{}", overflow)
+ }
+ Self::XorImm => f.write_str("xor"),
+ Self::BXorImm(overflow) => {
+ write!(f, "bxor_imm.{}", overflow)
+ }
+ Self::ShlImm(overflow) => {
+ write!(f, "shl_imm.{}", overflow)
+ }
+ Self::ShrImm(overflow) => {
+ write!(f, "shr_imm.{}", overflow)
+ }
+ Self::RotlImm(overflow) => {
+ write!(f, "rotl_imm.{}", overflow)
+ }
+ Self::RotrImm(overflow) => {
+ write!(f, "rotr_imm.{}", overflow)
+ }
+ }
+ }
+}
+
+/// Used to distinguish between unary operations
+#[derive(PartialEq, Debug)]
+pub enum UnaryOpCode {
+ Inv,
+ Incr,
+ Pow2,
+ Not,
+ BNot,
+ PopCnt,
+ IsOdd,
+ Cast,
+ PtrToInt,
+ IntToPtr,
+ TruncW,
+ Zext,
+ Sext,
+ Neg,
+}
+impl fmt::Display for UnaryOpCode {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ Self::Inv => f.write_str("inv"),
+ Self::Incr => f.write_str("incr"),
+ Self::Pow2 => f.write_str("pow2"),
+ Self::Not => f.write_str("not"),
+ Self::BNot => f.write_str("bnot"),
+ Self::PopCnt => f.write_str("popcnt"),
+ Self::IsOdd => f.write_str("is_odd"),
+ Self::Cast => f.write_str("cast"),
+ Self::PtrToInt => f.write_str("ptrtoint"),
+ Self::IntToPtr => f.write_str("inttoptr"),
+ Self::TruncW => f.write_str("truncw"),
+ Self::Zext => f.write_str("zext"),
+ Self::Sext => f.write_str("sext"),
+ Self::Neg => f.write_str("neg"),
+ }
+ }
+}
+
+/// Used to distinguish between immediate unary operations
+#[derive(PartialEq, Debug)]
+pub enum UnaryImmOpCode {
+ I1,
+ I8,
+ I16,
+ I32,
+ I64,
+ Felt,
+ F64,
+}
+impl fmt::Display for UnaryImmOpCode {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.write_str("const.")?;
+ match self {
+ Self::I1 => f.write_str("i1"),
+ Self::I8 => f.write_str("i8"),
+ Self::I16 => f.write_str("i16"),
+ Self::I32 => f.write_str("i32"),
+ Self::I64 => f.write_str("i64"),
+ Self::Felt => f.write_str("felt"),
+ Self::F64 => f.write_str("f64"),
+ }
+ }
+}
+
+/// Used to distinguish between primary operations
+#[derive(PartialEq, Debug)]
+pub enum PrimOpCode {
+ Select,
+ Assert,
+ Assertz,
+ AssertEq,
+ Alloca,
+ Unreachable,
+}
+impl fmt::Display for PrimOpCode {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ Self::Select => f.write_str("select"),
+ Self::Assert => f.write_str("assert"),
+ Self::Assertz => f.write_str("assertz"),
+ Self::AssertEq => f.write_str("asserteq"),
+ Self::Alloca => f.write_str("alloca"),
+ Self::Unreachable => f.write_str("unreachable"),
+ }
+ }
+}
+
+/// Memory offset for global variable reads.
+/// Conversion to i32 happens during transformation to hir.
+#[derive(PartialEq, Debug)]
+pub enum Offset {
+ Pos(u128),
+ Neg(u128),
+}
+impl Offset {
+ pub fn is_zero(&self) -> bool {
+ match self {
+ Self::Pos(offset) | Self::Neg(offset) => offset == &0,
+ }
+ }
+}
+impl fmt::Display for Offset {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ Self::Pos(offset) => {
+ if offset > &0 {
+ write!(f, "+{}", offset)?;
+ }
+ }
+ Self::Neg(offset) => {
+ if offset > &0 {
+ write!(f, "-{}", offset)?;
+ }
+ }
+ }
+ Ok(())
+ }
+}
+
+/// Used to distinguish between nested global value operations
+#[derive(PartialEq, Debug)]
+pub enum GlobalValueOpNested {
+ Symbol(Ident, Offset),
+ Load(Box, Offset),
+ Cast(Box, Offset, Type),
+}
+impl fmt::Display for GlobalValueOpNested {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ Self::Symbol(id, offset) => {
+ write!(f, "@ {} {}", id, offset)
+ }
+ Self::Load(nested, offset) => {
+ f.write_str("* ")?;
+ if offset.is_zero() {
+ write!(f, "{}", nested)?;
+ } else {
+ write!(f, "({}){}", nested, offset)?;
+ }
+ Ok(())
+ }
+ Self::Cast(nested, offset, ty) => {
+ write!(f, "* ({}) {} as {}", nested, offset, ty)
+ }
+ }
+ }
+}
+
+/// Used to distinguish between top-level global value operations
+#[derive(PartialEq, Debug)]
+pub enum GlobalValueOp {
+ Symbol(Ident, Offset),
+ Load(GlobalValueOpNested, Offset),
+ Cast(GlobalValueOpNested, Offset, Type),
+ IAddImm(u128, Type, GlobalValueOpNested),
+}
+impl fmt::Display for GlobalValueOp {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.write_str("global.")?;
+ match self {
+ Self::Symbol(id, offset) => {
+ write!(f, "symbol @ {} {}", id, offset)
+ }
+ Self::Load(nested, offset) => {
+ f.write_str("load ")?;
+ if offset.is_zero() {
+ write!(f, "{}", nested)?;
+ } else {
+ write!(f, "({}) {}", nested, offset)?;
+ }
+ Ok(())
+ }
+ Self::Cast(nested, offset, ty) => {
+ write!(f, "load ({}) {} {}", nested, offset, ty)
+ }
+ Self::IAddImm(i, ty, nested) => {
+ write!(f, "iadd.{}.{} {}", i, ty, nested)
+ }
+ }
+ }
+}
+
+/// The destination of a branch/jump
+#[derive(PartialEq, Debug)]
+pub struct Destination {
+ pub label: Label,
+ pub args: Vec,
+}
+impl Destination {
+ pub fn new(label: Label, args: Vec) -> Self {
+ Self { label, args }
+ }
+}
+impl fmt::Display for Destination {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.label)?;
+ if !self.args.is_empty() {
+ f.write_str(" (")?;
+ for (i, arg) in self.args.iter().enumerate() {
+ if i > 0 {
+ write!(f, ", {}", arg)?;
+ } else {
+ write!(f, "{}", arg)?;
+ }
+ }
+ f.write_str(")")?;
+ }
+ Ok(())
+ }
+}
+
+/// A branch of a switch operation
+#[derive(PartialEq, Debug)]
+pub enum SwitchBranch {
+ Test(u128, Label),
+ Default(Label),
+}
+impl fmt::Display for SwitchBranch {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ Self::Test(test, label) => {
+ write!(f, "{} => {}", test, label)
+ }
+ Self::Default(label) => {
+ write!(f, "{}", label)
+ }
+ }
+ }
+}
diff --git a/hir/src/parser/ast/mod.rs b/hir/src/parser/ast/mod.rs
new file mode 100644
index 00000000..6aa1a6c5
--- /dev/null
+++ b/hir/src/parser/ast/mod.rs
@@ -0,0 +1,92 @@
+mod block;
+mod functions;
+mod globals;
+mod instruction;
+
+pub use self::block::*;
+pub use self::functions::*;
+pub use self::globals::*;
+pub use self::instruction::*;
+
+use std::fmt;
+
+use miden_diagnostics::{SourceSpan, Spanned};
+
+use crate::Ident;
+
+/// This is a type alias used to clarify that an identifier refers to a module
+pub type ModuleId = Ident;
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum ModuleType {
+ /// Kernel context module
+ Kernel,
+ /// User context module
+ Module,
+}
+impl fmt::Display for ModuleType {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ Self::Kernel => f.write_str("kernel"),
+ Self::Module => f.write_str("module"),
+ }
+ }
+}
+
+/// This represents the parsed contents of a single Miden IR module
+///
+#[derive(Spanned, Debug)]
+pub struct Module {
+ #[span]
+ pub span: SourceSpan,
+ pub name: ModuleId,
+ pub ty: ModuleType,
+ pub global_vars: Vec,
+ pub functions: Vec,
+ pub externals: Vec,
+}
+impl Module {
+ /// Constructs a new module of the specified type, with the given span, name, functions and exports (externals).
+ ///
+ pub fn new(
+ span: SourceSpan,
+ ty: ModuleType,
+ name: ModuleId,
+ global_vars: Vec,
+ functions: Vec,
+ externals: Vec,
+ ) -> Self {
+ Self {
+ span,
+ name,
+ ty,
+ functions,
+ externals,
+ global_vars,
+ }
+ }
+}
+impl PartialEq for Module {
+ fn eq(&self, other: &Self) -> bool {
+ self.name == other.name
+ && self.ty == other.ty
+ && self.global_vars == other.global_vars
+ && self.functions == other.functions
+ && self.externals == other.externals
+ }
+}
+impl fmt::Display for Module {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ writeln!(f, "{} {}", self.ty, self.name)?;
+ for gvar in self.global_vars.iter() {
+ writeln!(f, "{}", gvar)?;
+ }
+ for func in self.functions.iter() {
+ writeln!(f, "{}", func)?;
+ }
+ for ext in self.externals.iter() {
+ writeln!(f, "{};", ext)?;
+ }
+ Ok(())
+ }
+}
diff --git a/hir/src/parser/lexer/mod.rs b/hir/src/parser/lexer/mod.rs
new file mode 100644
index 00000000..83c63e90
--- /dev/null
+++ b/hir/src/parser/lexer/mod.rs
@@ -0,0 +1,985 @@
+use core::{fmt, mem, num::IntErrorKind};
+
+use miden_diagnostics::{Diagnostic, SourceIndex, SourceSpan, ToDiagnostic};
+use miden_parsing::{Scanner, Source};
+
+use crate::{parser::ParseError, Symbol};
+
+/// The value produced by the Lexer when iterated
+pub type Lexed = Result<(SourceIndex, Token, SourceIndex), ParseError>;
+
+/// Errors that may occur during lexing of the source
+#[derive(Clone, Debug, thiserror::Error)]
+pub enum LexicalError {
+ #[error("invalid integer value: {}", DisplayIntErrorKind(reason))]
+ InvalidInt {
+ span: SourceSpan,
+ reason: IntErrorKind,
+ },
+ #[error("encountered unexpected character '{found}'")]
+ UnexpectedCharacter { start: SourceIndex, found: char },
+}
+impl PartialEq for LexicalError {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (Self::InvalidInt { reason: lhs, .. }, Self::InvalidInt { reason: rhs, .. }) => {
+ lhs == rhs
+ }
+ (
+ Self::UnexpectedCharacter { found: lhs, .. },
+ Self::UnexpectedCharacter { found: rhs, .. },
+ ) => lhs == rhs,
+ _ => false,
+ }
+ }
+}
+impl ToDiagnostic for LexicalError {
+ fn to_diagnostic(self) -> Diagnostic {
+ use miden_diagnostics::Label;
+
+ match self {
+ Self::InvalidInt { span, ref reason } => Diagnostic::error()
+ .with_message("invalid integer literal")
+ .with_labels(vec![Label::primary(span.source_id(), span)
+ .with_message(format!("{}", DisplayIntErrorKind(reason)))]),
+ Self::UnexpectedCharacter { start, .. } => Diagnostic::error()
+ .with_message("unexpected character")
+ .with_labels(vec![Label::primary(
+ start.source_id(),
+ SourceSpan::new(start, start),
+ )]),
+ }
+ }
+}
+
+struct DisplayIntErrorKind<'a>(&'a IntErrorKind);
+impl<'a> fmt::Display for DisplayIntErrorKind<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self.0 {
+ IntErrorKind::Empty => write!(f, "unable to parse empty string as integer"),
+ IntErrorKind::InvalidDigit => write!(f, "invalid digit"),
+ IntErrorKind::PosOverflow => write!(f, "value is too big"),
+ IntErrorKind::NegOverflow => write!(f, "value is too big"),
+ IntErrorKind::Zero => write!(f, "zero is not a valid value here"),
+ other => write!(f, "unable to parse integer value: {:?}", other),
+ }
+ }
+}
+
+#[derive(Debug, Clone)]
+pub enum Token {
+ Eof,
+ Error(LexicalError),
+ Comment,
+ // PRIMITIVES
+ // --------------------------------------------------------------------------------------------
+ /// Identifiers should start with alphabet followed by one or more alpha numeric characters
+ /// or an underscore.
+ Ident(Symbol),
+ /// Function identifiers should be a non-empty sequence of identifiers separated by double colons "::".
+ FuncIdent(Symbol),
+ /// Integers should only contain numeric characters.
+ Num(u128),
+ /// Hex strings are used to initialize global variables
+ Hex(Vec),
+
+ // DECLARATION KEYWORDS
+ // --------------------------------------------------------------------------------------------
+ /// Used to declare kernel modules. Also used to declare a function with kernel calling convention.
+ Kernel,
+ /// Used to declare normal modules.
+ Module,
+ /// Used to declare a global variable with internal linkage.
+ Internal,
+ /// Used to declare a global variable with "one definition rule" linkage.
+ Odr,
+ /// Used to declare a global variable with external linkage.
+ External,
+ /// Keyword to declare that a function is publicly visible.
+ Pub,
+ /// Keyword to declare a function.
+ Fn,
+ /// Keyword to declare a function's calling convention.
+ Cc,
+ /// Keyword to declare that a function uses fast calling convention.
+ Fast,
+ /// Keyword to declare that a function parameter is a struct return
+ Sret,
+ /// Keyword to declare that a function parameter is extended with 0s when filling up a word
+ /// Also used as an operation to pad a value with 0s.
+ Zext,
+ /// Keyword to declare that a function parameter is extended with sign bits when filling up a word
+ /// Also used as an operation to pad a value with sign bits.
+ Sext,
+
+ // OPERATION KEYWORDS
+ // --------------------------------------------------------------------------------------------
+ /// Keyword to return from a function
+ Ret,
+ /// Keyword to call a function in user space
+ Call,
+ /// Keyword to call a function in kernel space
+ SysCall,
+ /// Keyword to perform a conditional jump
+ Cond,
+ /// Keyword to perform an unconditional jump
+ Branch,
+ /// Keyword to perform a multi-branch conditional jump
+ Switch,
+ /// Keyword to test whether a value has a specific type
+ Test,
+ /// Keyword to load a value from memory. Also used for the load operation on globals
+ Load,
+ /// Keyword to copy data from one memory location to another
+ MemCpy,
+ /// Keyword to indicate a sequence of assembly instructions
+ InlineAsm,
+ /// Keyword to indicate a memory management operation
+ Memory,
+ /// Keyword to indicate that the currently assigned amount of memory should grow
+ Grow,
+ /// Keyword to perform an addition
+ Add,
+ /// Keyword to perform a subtraction
+ Sub,
+ /// Keyword to perform a multiplication
+ Mul,
+ /// Keyword to perform a division
+ Div,
+ /// Keyword to determine a minimum value
+ Min,
+ /// Keyword to determine a maximum value
+ Max,
+ /// Keyword to perform a modulo
+ Mod,
+ /// Keyword to perform a division modulo 2^32
+ DivMod,
+ /// Keyword to perform an exponentiation
+ Exp,
+ /// Keyword to perform a boolean and
+ And,
+ /// Keyword to perform a bitwise and
+ BAnd,
+ /// Keyword to perform a boolean or
+ Or,
+ /// Keyword to perform a bitwise or
+ BOr,
+ /// Keyword to perform a boolean xor
+ Xor,
+ /// Keyword to perform a bitwise xor
+ BXor,
+ /// Keyword to perform a left shift
+ Shl,
+ /// Keyword to perform a right shift
+ Shr,
+ /// Keyword to perform a left rotation
+ Rotl,
+ /// Keyword to perform a right rotation
+ Rotr,
+ /// Keyword to test for equality
+ Eq,
+ /// Keyword to test for inequality
+ Neq,
+ /// Keyword to test for greater-than
+ Gt,
+ /// Keyword to test for greater-than-or-equal
+ Gte,
+ /// Keyword to test for less-than
+ Lt,
+ /// Keyword to test for less-than-or-equal
+ Lte,
+ /// Keyword to perform a store
+ Store,
+ /// Keyword to perform an addition with an immediate parameter
+ AddImm,
+ /// Keyword to perform a subtraction with an immediate parameter
+ SubImm,
+ /// Keyword to perform a multiplication with an immediate parameter
+ MulImm,
+ /// Keyword to perform a division with an immediate parameter
+ DivImm,
+ /// Keyword to determine a minimum with an immediate parameter
+ MinImm,
+ /// Keyword to determine a maximum with an immediate parameter
+ MaxImm,
+ /// Keyword to perform a modulo with an immediate parameter
+ ModImm,
+ /// Keyword to perform a division modulo 2^32 with an immediate parameter
+ DivModImm,
+ /// Keyword to perform an exponentiation with an immediate parameter
+ ExpImm,
+ /// Keyword to perform a boolaen and with an immediate parameter
+ AndImm,
+ /// Keyword to perform a bitwise and with an immediate parameter
+ BAndImm,
+ /// Keyword to perform a boolean or with an immediate parameter
+ OrImm,
+ /// Keyword to perform a bitwise or with an immediate parameter
+ BOrImm,
+ /// Keyword to perform a boolean xor with an immediate parameter
+ XorImm,
+ /// Keyword to perform a bitwise xor with an immediate parameter
+ BXorImm,
+ /// Keyword to perform a left shift with an immediate parameter
+ ShlImm,
+ /// Keyword to perform a right shift with an immediate parameter
+ ShrImm,
+ /// Keyword to perform a left rotation with an immediate parameter
+ RotlImm,
+ /// Keyword to perform a right rotation with an immediate parameter
+ RotrImm,
+ /// Keyword to perform an inversion within the field
+ Inv,
+ /// Keyword to perform an increment
+ Incr,
+ /// Keyword to perform a power-of-2 operation
+ Pow2,
+ /// Keyword to perform a boolean negation
+ Not,
+ /// Keyword to perform a bitwise negation
+ BNot,
+ /// Keyword to count the number of set bits in a value
+ PopCnt,
+ /// Keyword to check if a value is odd
+ IsOdd,
+ /// Keyword to perform a type cast
+ Cast,
+ /// Keyword to cast a pointer to an integer
+ PtrToInt,
+ /// Keyword to cast an integer to a pointer
+ IntToPtr,
+ /// Keyword to truncate a word
+ TruncW,
+ /// Keyword to perform a numerical negation
+ Neg,
+ /// Keyword to indicate an immediate unary operation (used alongside the type of the immediate)
+ Const,
+ /// Keyword to access elements in a struct
+ Select,
+ /// Keyword to perform an assertion
+ Assert,
+ /// Keyword to perform an 0-check assertion
+ Assertz,
+ /// Keyword to allocate an array
+ Alloca,
+ /// Keyword to indicate an unreachable part of the code
+ Unreachable,
+ /// Keyword used to indicate a global variable operation
+ Global,
+ /// Keyword used for type casts in global variable operations
+ As,
+ /// Keyword used to indicate the symbol global variable operation
+ Symbol,
+ /// Keyword used to indicate the iadd global variable operation
+ IAdd,
+ /// Keyword to indicated an unchecked aritmetic operation
+ Unchecked,
+ /// Keyword to indicated a checked aritmetic operation
+ Checked,
+ /// Keyword to indicated a wrapping aritmetic operation
+ Wrapping,
+ /// Keyword to indicated an overflowing aritmetic operation
+ Overflowing,
+
+ // TYPES
+ // --------------------------------------------------------------------------------------------
+ I1,
+ I8,
+ U8,
+ I16,
+ U16,
+ I32,
+ U32,
+ I64,
+ U64,
+ I128,
+ U128,
+ U256,
+ F64,
+ Felt,
+ Mut,
+
+ // PUNCTUATION
+ // --------------------------------------------------------------------------------------------
+ DoubleQuote,
+ Colon,
+ Semicolon,
+ Comma,
+ Dot,
+ LParen,
+ RParen,
+ LBracket,
+ RBracket,
+ LBrace,
+ RBrace,
+ Equal,
+ RDoubleArrow,
+ Plus,
+ Minus,
+ RArrow,
+ Star,
+ Ampersand,
+ Bang,
+ At,
+}
+impl Token {
+ pub fn from_keyword_or_ident(s: &str) -> Self {
+ match s {
+ "kernel" => Self::Kernel,
+ "module" => Self::Module,
+ "internal" => Self::Internal,
+ "odr" => Self::Odr,
+ "external" => Self::External,
+ "pub" => Self::Pub,
+ "fn" => Self::Fn,
+ "cc" => Self::Cc,
+ "fast" => Self::Fast,
+ "sret" => Self::Sret,
+ "zext" => Self::Zext,
+ "sext" => Self::Sext,
+ "ret" => Self::Ret,
+ "call" => Self::Call,
+ "syscall" => Self::SysCall,
+ "cond" => Self::Cond,
+ "branch" => Self::Branch,
+ "switch" => Self::Switch,
+ "test" => Self::Test,
+ "load" => Self::Load,
+ "memcpy" => Self::MemCpy,
+ "inlineasm" => Self::InlineAsm,
+ "memory" => Self::Memory,
+ "grow" => Self::Grow,
+ "add" => Self::Add,
+ "sub" => Self::Sub,
+ "mul" => Self::Mul,
+ "div" => Self::Div,
+ "min" => Self::Min,
+ "max" => Self::Max,
+ "mod" => Self::Mod,
+ "divmod" => Self::DivMod,
+ "exp" => Self::Exp,
+ "and" => Self::And,
+ "band" => Self::BAnd,
+ "or" => Self::Or,
+ "bor" => Self::BOr,
+ "xor" => Self::Xor,
+ "bxor" => Self::BXor,
+ "shl" => Self::Shl,
+ "shr" => Self::Shr,
+ "rotl" => Self::Rotl,
+ "rotr" => Self::Rotr,
+ "eq" => Self::Eq,
+ "neq" => Self::Neq,
+ "gt" => Self::Gt,
+ "gte" => Self::Gte,
+ "lt" => Self::Lt,
+ "lte" => Self::Lte,
+ "store" => Self::Store,
+ "add_imm" => Self::AddImm,
+ "sub_imm" => Self::SubImm,
+ "mul_imm" => Self::MulImm,
+ "div_imm" => Self::DivImm,
+ "min_imm" => Self::MinImm,
+ "max_imm" => Self::MaxImm,
+ "mod_imm" => Self::ModImm,
+ "divmod_imm" => Self::DivModImm,
+ "exp_imm" => Self::ExpImm,
+ "and_imm" => Self::AndImm,
+ "band_imm" => Self::BAndImm,
+ "or_imm" => Self::OrImm,
+ "bor_imm" => Self::BOrImm,
+ "xor_imm" => Self::XorImm,
+ "bxor_imm" => Self::BXorImm,
+ "shl_imm" => Self::ShlImm,
+ "shr_imm" => Self::ShrImm,
+ "rotl_imm" => Self::RotlImm,
+ "rotr_imm" => Self::RotrImm,
+ "inv" => Self::Inv,
+ "incr" => Self::Incr,
+ "pow2" => Self::Pow2,
+ "not" => Self::Not,
+ "bnot" => Self::BNot,
+ "popcnt" => Self::PopCnt,
+ "is_odd" => Self::IsOdd,
+ "cast" => Self::Cast,
+ "ptrtoint" => Self::PtrToInt,
+ "inttoprt" => Self::IntToPtr,
+ "truncw" => Self::TruncW,
+ "neg" => Self::Neg,
+ "const" => Self::Const,
+ "select" => Self::Select,
+ "assert" => Self::Assert,
+ "assertz" => Self::Assertz,
+ "alloca" => Self::Alloca,
+ "unreachable" => Self::Unreachable,
+ "as" => Self::As,
+ "global" => Self::Global,
+ "symbol" => Self::Symbol,
+ "iadd" => Self::IAdd,
+ "unchecked" => Self::Unchecked,
+ "checked" => Self::Checked,
+ "wrapping" => Self::Wrapping,
+ "overflowing" => Self::Overflowing,
+ "i1" => Self::I1,
+ "i8" => Self::I8,
+ "u8" => Self::U8,
+ "i16" => Self::I16,
+ "u16" => Self::U16,
+ "i32" => Self::I32,
+ "u32" => Self::U32,
+ "i64" => Self::I64,
+ "u64" => Self::U64,
+ "i128" => Self::I128,
+ "u128" => Self::U128,
+ "u256" => Self::U256,
+ "f64" => Self::F64,
+ "felt" => Self::Felt,
+ "mut" => Self::Mut,
+ other => Self::Ident(Symbol::intern(other)),
+ }
+ }
+}
+impl Eq for Token {}
+impl PartialEq for Token {
+ fn eq(&self, other: &Token) -> bool {
+ match self {
+ Self::Num(i) => {
+ if let Self::Num(i2) = other {
+ return *i == *i2;
+ }
+ }
+ Self::Error(_) => {
+ if let Self::Error(_) = other {
+ return true;
+ }
+ }
+ Self::Ident(i) => {
+ if let Self::Ident(i2) = other {
+ return i == i2;
+ }
+ }
+ Self::FuncIdent(i) => {
+ if let Self::FuncIdent(i2) = other {
+ return i == i2;
+ }
+ }
+ _ => return mem::discriminant(self) == mem::discriminant(other),
+ }
+ false
+ }
+}
+impl fmt::Display for Token {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ Self::Eof => write!(f, "EOF"),
+ Self::Error(_) => write!(f, "ERROR"),
+ Self::Comment => write!(f, "COMMENT"),
+ Self::Ident(ref id) => write!(f, "{}", id),
+ Self::FuncIdent(ref id) => write!(f, "{}", id),
+ Self::Num(ref i) => write!(f, "{}", i),
+ Self::Hex(ref data) => {
+ write!(f, "0x")?;
+ for i in data.iter().rev() {
+ write!(f, "{:02x}", i)?;
+ }
+ Ok(())
+ }
+ Self::Kernel => write!(f, "kernel"),
+ Self::Module => write!(f, "module"),
+ Self::Internal => write!(f, "internal"),
+ Self::Odr => write!(f, "odr"),
+ Self::External => write!(f, "external"),
+ Self::Pub => write!(f, "pub"),
+ Self::Fn => write!(f, "fn"),
+ Self::Cc => write!(f, "cc"),
+ Self::Fast => write!(f, "fast"),
+ Self::Sret => write!(f, "sret"),
+ Self::Zext => write!(f, "zext"),
+ Self::Sext => write!(f, "sext"),
+ Self::Ret => write!(f, "ret"),
+ Self::Call => write!(f, "call"),
+ Self::SysCall => write!(f, "syscall"),
+ Self::Cond => write!(f, "cond"),
+ Self::Branch => write!(f, "branch"),
+ Self::Switch => write!(f, "switch"),
+ Self::Test => write!(f, "test"),
+ Self::Load => write!(f, "load"),
+ Self::MemCpy => write!(f, "memcpy"),
+ Self::InlineAsm => write!(f, "inlineasm"),
+ Self::Memory => write!(f, "memory"),
+ Self::Grow => write!(f, "grow"),
+ Self::Add => write!(f, "add"),
+ Self::Sub => write!(f, "sub"),
+ Self::Mul => write!(f, "mul"),
+ Self::Div => write!(f, "div"),
+ Self::Min => write!(f, "min"),
+ Self::Max => write!(f, "max"),
+ Self::Mod => write!(f, "mod"),
+ Self::DivMod => write!(f, "divmod"),
+ Self::Exp => write!(f, "exp"),
+ Self::And => write!(f, "and"),
+ Self::BAnd => write!(f, "band"),
+ Self::Or => write!(f, "or"),
+ Self::BOr => write!(f, "bor"),
+ Self::Xor => write!(f, "xor"),
+ Self::BXor => write!(f, "bxor"),
+ Self::Shl => write!(f, "shl"),
+ Self::Shr => write!(f, "shr"),
+ Self::Rotl => write!(f, "rotl"),
+ Self::Rotr => write!(f, "rotr"),
+ Self::Eq => write!(f, "eq"),
+ Self::Neq => write!(f, "neq"),
+ Self::Gt => write!(f, "gt"),
+ Self::Gte => write!(f, "gte"),
+ Self::Lt => write!(f, "lt"),
+ Self::Lte => write!(f, "lte"),
+ Self::Store => write!(f, "store"),
+ Self::AddImm => write!(f, "add_imm"),
+ Self::SubImm => write!(f, "sub_imm"),
+ Self::MulImm => write!(f, "mul_imm"),
+ Self::DivImm => write!(f, "div_imm"),
+ Self::MinImm => write!(f, "min_imm"),
+ Self::MaxImm => write!(f, "max_imm"),
+ Self::ModImm => write!(f, "mod_imm"),
+ Self::DivModImm => write!(f, "divmod_imm"),
+ Self::ExpImm => write!(f, "exp_imm"),
+ Self::AndImm => write!(f, "and_imm"),
+ Self::BAndImm => write!(f, "band_imm"),
+ Self::OrImm => write!(f, "or_imm"),
+ Self::BOrImm => write!(f, "bor_imm"),
+ Self::XorImm => write!(f, "xor_imm"),
+ Self::BXorImm => write!(f, "bxor_imm"),
+ Self::ShlImm => write!(f, "shl_imm"),
+ Self::ShrImm => write!(f, "shr_imm"),
+ Self::RotlImm => write!(f, "rotl_imm"),
+ Self::RotrImm => write!(f, "rotr_imm"),
+ Self::Inv => write!(f, "inv"),
+ Self::Incr => write!(f, "incr"),
+ Self::Pow2 => write!(f, "pow2"),
+ Self::Not => write!(f, "not"),
+ Self::BNot => write!(f, "bnot"),
+ Self::PopCnt => write!(f, "popcnt"),
+ Self::IsOdd => write!(f, "is_odd"),
+ Self::Cast => write!(f, "cast"),
+ Self::PtrToInt => write!(f, "ptrtoint"),
+ Self::IntToPtr => write!(f, "inttoptr"),
+ Self::TruncW => write!(f, "truncw"),
+ Self::Neg => write!(f, "neg"),
+ Self::Const => write!(f, "const"),
+ Self::Select => write!(f, "select"),
+ Self::Assert => write!(f, "assert"),
+ Self::Assertz => write!(f, "assertz"),
+ Self::Alloca => write!(f, "alloca"),
+ Self::Unreachable => write!(f, "unreachable"),
+ Self::Global => write!(f, "global"),
+ Self::As => write!(f, "as"),
+ Self::Symbol => write!(f, "symbol"),
+ Self::IAdd => write!(f, "iadd"),
+ Self::Unchecked => write!(f, "unchecked"),
+ Self::Checked => write!(f, "checked"),
+ Self::Wrapping => write!(f, "wrapping"),
+ Self::Overflowing => write!(f, "overflowing"),
+ Self::I1 => write!(f, "i1"),
+ Self::I8 => write!(f, "i8"),
+ Self::U8 => write!(f, "u8"),
+ Self::I16 => write!(f, "i16"),
+ Self::U16 => write!(f, "u16"),
+ Self::I32 => write!(f, "i32"),
+ Self::U32 => write!(f, "u32"),
+ Self::I64 => write!(f, "i64"),
+ Self::U64 => write!(f, "u64"),
+ Self::I128 => write!(f, "i128"),
+ Self::U128 => write!(f, "u128"),
+ Self::U256 => write!(f, "u256"),
+ Self::F64 => write!(f, "f64"),
+ Self::Felt => write!(f, "felt"),
+ Self::Mut => write!(f, "mut"),
+ Self::DoubleQuote => write!(f, "\""),
+ Self::Colon => write!(f, ":"),
+ Self::Semicolon => write!(f, ";"),
+ Self::Comma => write!(f, ","),
+ Self::Dot => write!(f, "."),
+ Self::LParen => write!(f, "("),
+ Self::RParen => write!(f, ")"),
+ Self::LBracket => write!(f, "["),
+ Self::RBracket => write!(f, "]"),
+ Self::LBrace => write!(f, "{{"),
+ Self::RBrace => write!(f, "}}"),
+ Self::Equal => write!(f, "="),
+ Self::RDoubleArrow => write!(f, "=>"),
+ Self::Plus => write!(f, "+"),
+ Self::Minus => write!(f, "-"),
+ Self::RArrow => write!(f, "->"),
+ Self::Star => write!(f, "*"),
+ Self::Ampersand => write!(f, "&"),
+ Self::Bang => write!(f, "!"),
+ Self::At => write!(f, "@"),
+ }
+ }
+}
+
+macro_rules! pop {
+ ($lex:ident) => {{
+ $lex.skip();
+ }};
+ ($lex:ident, $code:expr) => {{
+ $lex.skip();
+ $code
+ }};
+}
+
+macro_rules! pop2 {
+ ($lex:ident) => {{
+ $lex.skip();
+ $lex.skip();
+ }};
+ ($lex:ident, $code:expr) => {{
+ $lex.skip();
+ $lex.skip();
+ $code
+ }};
+}
+
+/// The lexer that is used to perform lexical analysis on the Miden IR grammar. The lexer implements
+/// the `Iterator` trait, so in order to retrieve the tokens, you simply have to iterate over it.
+///
+/// # Errors
+///
+/// Because the lexer is implemented as an iterator over tokens, this means that you can continue
+/// to get tokens even if a lexical error occurs. The lexer will attempt to recover from an error
+/// by injecting tokens it expects.
+///
+/// If an error is unrecoverable, the lexer will continue to produce tokens, but there is no
+/// guarantee that parsing them will produce meaningful results, it is primarily to assist in
+/// gathering as many errors as possible.
+pub struct Lexer {
+ /// The scanner produces a sequence of chars + location, and can be controlled
+ /// The location type is SourceIndex
+ scanner: Scanner,
+
+ /// The most recent token to be lexed.
+ /// At the start and end, this should be Token::Eof
+ token: Token,
+
+ /// The position in the input where the current token starts
+ /// At the start this will be the byte index of the beginning of the input
+ token_start: SourceIndex,
+
+ /// The position in the input where the current token ends
+ /// At the start this will be the byte index of the beginning of the input
+ token_end: SourceIndex,
+
+ /// When we have reached true Eof, this gets set to true, and the only token
+ /// produced after that point is Token::Eof, or None, depending on how you are
+ /// consuming the lexer
+ eof: bool,
+}
+impl Lexer
+where
+ S: Source,
+{
+ /// Produces an instance of the lexer with the lexical analysis to be performed on the `input`
+ /// string. Note that no lexical analysis occurs until the lexer has been iterated over.
+ pub fn new(scanner: Scanner) -> Self {
+ use miden_diagnostics::ByteOffset;
+
+ let start = scanner.start();
+ let mut lexer = Lexer {
+ scanner,
+ token: Token::Eof,
+ token_start: start + ByteOffset(0),
+ token_end: start + ByteOffset(0),
+ eof: false,
+ };
+ lexer.advance();
+ lexer
+ }
+
+ pub fn lex(&mut self) -> Option<::Item> {
+ if self.eof && self.token == Token::Eof {
+ return None;
+ }
+
+ let token = std::mem::replace(&mut self.token, Token::Eof);
+ let start = self.token_start;
+ let end = self.token_end;
+ self.advance();
+ match token {
+ Token::Error(err) => Some(Err(err.into())),
+ token => Some(Ok((start, token, end))),
+ }
+ }
+
+ fn advance(&mut self) {
+ self.advance_start();
+ self.token = self.tokenize();
+ }
+
+ #[inline]
+ fn advance_start(&mut self) {
+ let mut position: SourceIndex;
+ loop {
+ let (pos, c) = self.scanner.read();
+
+ position = pos;
+
+ if c == '\0' {
+ self.eof = true;
+ return;
+ }
+
+ if c.is_whitespace() {
+ self.scanner.advance();
+ continue;
+ }
+
+ break;
+ }
+
+ self.token_start = position;
+ }
+
+ #[inline]
+ fn pop(&mut self) -> char {
+ use miden_diagnostics::ByteOffset;
+
+ let (pos, c) = self.scanner.pop();
+ self.token_end = pos + ByteOffset::from_char_len(c);
+ c
+ }
+
+ #[inline]
+ fn peek(&mut self) -> char {
+ let (_, c) = self.scanner.peek();
+ c
+ }
+
+ #[inline]
+ fn read(&mut self) -> char {
+ let (_, c) = self.scanner.read();
+ c
+ }
+
+ #[inline]
+ fn skip(&mut self) {
+ self.pop();
+ }
+
+ /// Get the span for the current token in `Source`.
+ #[inline]
+ fn span(&self) -> SourceSpan {
+ SourceSpan::new(self.token_start, self.token_end)
+ }
+
+ /// Get a string slice of the current token.
+ #[inline]
+ fn slice(&self) -> &str {
+ self.scanner.slice(self.span())
+ }
+
+ #[inline]
+ fn skip_whitespace(&mut self) {
+ let mut c: char;
+ loop {
+ c = self.read();
+
+ if !c.is_whitespace() {
+ break;
+ }
+
+ self.skip();
+ }
+ }
+
+ fn tokenize(&mut self) -> Token {
+ let c = self.read();
+
+ if c == '\\' {
+ match self.peek() {
+ '\\' => {
+ self.skip();
+ self.skip();
+ self.lex_comment()
+ }
+ _ => Token::Error(LexicalError::UnexpectedCharacter {
+ start: self.span().start(),
+ found: c,
+ }),
+ };
+ }
+
+ if c == '\0' {
+ self.eof = true;
+ return Token::Eof;
+ }
+
+ if c.is_whitespace() {
+ self.skip_whitespace();
+ }
+
+ match self.read() {
+ ',' => pop!(self, Token::Comma),
+ '.' => pop!(self, Token::Dot),
+ ':' => pop!(self, Token::Colon),
+ ';' => pop!(self, Token::Semicolon),
+ '"' => pop!(self, Token::DoubleQuote),
+ '(' => pop!(self, Token::LParen),
+ ')' => pop!(self, Token::RParen),
+ '[' => pop!(self, Token::LBracket),
+ ']' => pop!(self, Token::RBracket),
+ '{' => pop!(self, Token::LBrace),
+ '}' => pop!(self, Token::RBrace),
+ '=' => match self.peek() {
+ '>' => pop2!(self, Token::RDoubleArrow),
+ _ => pop!(self, Token::Equal),
+ },
+ '+' => pop!(self, Token::Plus),
+ '-' => match self.peek() {
+ '>' => pop2!(self, Token::RArrow),
+ _ => pop!(self, Token::Minus),
+ },
+ '*' => pop!(self, Token::Star),
+ '&' => pop!(self, Token::Ampersand),
+ '!' => pop!(self, Token::Bang),
+ '@' => pop!(self, Token::At),
+ '0' => match self.peek() {
+ 'x' => {
+ self.skip();
+ self.skip();
+ self.lex_hex()
+ }
+ '0'..='9' => self.lex_number(),
+ _ => Token::Error(LexicalError::UnexpectedCharacter {
+ start: self.span().start(),
+ found: c,
+ }),
+ },
+ '1'..='9' => self.lex_number(),
+ 'a'..='z' => self.lex_keyword_or_ident(),
+ 'A'..='Z' => self.lex_identifier(),
+ c => Token::Error(LexicalError::UnexpectedCharacter {
+ start: self.span().start(),
+ found: c,
+ }),
+ }
+ }
+
+ fn lex_comment(&mut self) -> Token {
+ let mut c;
+ loop {
+ c = self.read();
+
+ if c == '\n' {
+ break;
+ }
+
+ if c == '\0' {
+ self.eof = true;
+ break;
+ }
+
+ self.skip();
+ }
+
+ Token::Comment
+ }
+
+ #[inline]
+ fn lex_keyword_or_ident(&mut self) -> Token {
+ let c = self.pop();
+ debug_assert!(c.is_ascii_alphabetic() && c.is_lowercase());
+
+ if self.skip_ident() {
+ Token::FuncIdent(Symbol::intern(self.slice()))
+ } else {
+ Token::from_keyword_or_ident(self.slice())
+ }
+ }
+
+ #[inline]
+ fn lex_identifier(&mut self) -> Token {
+ let c = self.pop();
+ debug_assert!(c.is_ascii_alphabetic());
+
+ if self.skip_ident() {
+ Token::FuncIdent(Symbol::intern(self.slice()))
+ } else {
+ Token::Ident(Symbol::intern(self.slice()))
+ }
+ }
+
+ // Returns true if the identifier is a function identifier (contains double colons), false otherwise
+ fn skip_ident(&mut self) -> bool {
+ let mut func_ident = false;
+ loop {
+ match self.read() {
+ '_' => self.skip(),
+ '0'..='9' => self.skip(),
+ ':' => match self.peek() {
+ ':' => {
+ func_ident = true;
+ self.skip();
+ self.skip()
+ }
+ _ => break,
+ },
+ c if c.is_ascii_alphabetic() => self.skip(),
+ _ => break,
+ }
+ }
+ func_ident
+ }
+
+ #[inline]
+ fn lex_number(&mut self) -> Token {
+ let mut num = String::new();
+
+ // Expect the first character to be a digit
+ debug_assert!(self.read().is_ascii_digit());
+
+ while let '0'..='9' = self.read() {
+ num.push(self.pop());
+ }
+
+ match num.parse::() {
+ Ok(i) => Token::Num(i),
+ Err(err) => Token::Error(LexicalError::InvalidInt {
+ span: self.span(),
+ reason: err.kind().clone(),
+ }),
+ }
+ }
+
+ #[inline]
+ fn lex_hex(&mut self) -> Token {
+ let mut res: Vec = Vec::new();
+
+ loop {
+ match self.read() {
+ '0'..='9' | 'a'..='f' | 'A'..='F' => {
+ res.push(self.pop() as u8);
+ }
+ _ => {
+ break;
+ }
+ }
+ }
+
+ Token::Hex(res)
+ }
+}
+
+impl Iterator for Lexer
+where
+ S: Source,
+{
+ type Item = Lexed;
+
+ fn next(&mut self) -> Option {
+ let mut res = self.lex();
+ while let Some(Ok((_, Token::Comment, _))) = res {
+ res = self.lex();
+ }
+ res
+ }
+}
diff --git a/hir/src/parser/mod.rs b/hir/src/parser/mod.rs
new file mode 100644
index 00000000..38fd96f8
--- /dev/null
+++ b/hir/src/parser/mod.rs
@@ -0,0 +1,105 @@
+pub mod ast;
+mod lexer;
+mod parser;
+
+pub use self::parser::{ParseError, Parser};
+use super::Symbol;
+
+use std::path::Path;
+use std::sync::Arc;
+
+use miden_diagnostics::{CodeMap, DiagnosticsHandler};
+
+/// Parses the provided source and returns the AST.
+pub fn parse(
+ diagnostics: &DiagnosticsHandler,
+ codemap: Arc,
+ source: &str,
+) -> Result {
+ let parser = Parser::new((), codemap);
+ match parser.parse_string::(diagnostics, source) {
+ Ok(ast) => Ok(ast),
+ Err(ParseError::Lexer(err)) => {
+ diagnostics.emit(err);
+ Err(ParseError::Failed)
+ }
+ Err(err) => Err(err),
+ }
+}
+
+/// Parses the provided source and returns the AST.
+pub fn parse_file>(
+ diagnostics: &DiagnosticsHandler,
+ codemap: Arc,
+ source: P,
+) -> Result {
+ let parser = Parser::new((), codemap);
+ match parser.parse_file::(diagnostics, source) {
+ Ok(ast) => Ok(ast),
+ Err(ParseError::Lexer(err)) => {
+ diagnostics.emit(err);
+ Err(ParseError::Failed)
+ }
+ Err(err) => Err(err),
+ }
+}
+
+/// Parses the provided source string with a default [CodeMap] and [DiagnosticsHandler].
+///
+/// This is primarily provided for use in tests, you should generally prefer [parse]
+pub fn parse_str(source: &str) -> Result {
+ use miden_diagnostics::{
+ term::termcolor::ColorChoice, DefaultEmitter, DiagnosticsConfig, Verbosity,
+ };
+
+ let codemap = Arc::new(CodeMap::new());
+ let emitter = Arc::new(DefaultEmitter::new(ColorChoice::Auto));
+ let config = DiagnosticsConfig {
+ verbosity: Verbosity::Warning,
+ warnings_as_errors: true,
+ no_warn: false,
+ display: Default::default(),
+ };
+ let diagnostics = DiagnosticsHandler::new(config, codemap.clone(), emitter);
+ parse(&diagnostics, codemap, source)
+}
+
+/// Parses a [Module] from the given path.
+///
+/// This is primarily intended for use in the import resolution phase.
+#[allow(dead_code)]
+pub(crate) fn parse_module_from_file>(
+ diagnostics: &DiagnosticsHandler,
+ codemap: Arc,
+ path: P,
+) -> Result {
+ let parser = Parser::new((), codemap);
+ match parser.parse_file::(diagnostics, path) {
+ ok @ Ok(_) => ok,
+ Err(ParseError::Lexer(err)) => {
+ diagnostics.emit(err);
+ Err(ParseError::Failed)
+ }
+ err @ Err(_) => err,
+ }
+}
+
+/// Parses a [Module] from a file already in the codemap
+///
+/// This is primarily intended for use in the import resolution phase.
+#[allow(dead_code)]
+pub(crate) fn parse_module(
+ diagnostics: &DiagnosticsHandler,
+ codemap: Arc,
+ source: Arc,
+) -> Result {
+ let parser = Parser::new((), codemap);
+ match parser.parse::(diagnostics, source) {
+ ok @ Ok(_) => ok,
+ Err(ParseError::Lexer(err)) => {
+ diagnostics.emit(err);
+ Err(ParseError::Failed)
+ }
+ err @ Err(_) => err,
+ }
+}
diff --git a/hir/src/parser/parser/grammar.lalrpop b/hir/src/parser/parser/grammar.lalrpop
new file mode 100644
index 00000000..9e6ddfba
--- /dev/null
+++ b/hir/src/parser/parser/grammar.lalrpop
@@ -0,0 +1,739 @@
+use std::sync::Arc;
+use std::str::FromStr;
+
+use miden_diagnostics::{CodeMap, DiagnosticsHandler};
+
+use crate::{AddressSpace, ArgumentPurpose, ArgumentExtension, CallConv, FunctionIdent, Ident, Linkage, Overflow, StructType, Type, };
+use crate::parser::{
+ ast::*,
+ lexer::Token,
+ parser::ParseError,
+ Symbol
+};
+
+grammar(diagnostics: &DiagnosticsHandler, codemap: &Arc, next_var: &mut usize);
+
+// MACROS
+// ================================================================================================
+
+// Comma-delimited with at least one element
+Comma: Vec = {
+ ",")*> => {
+ let mut v = v;
+ v.push(e);
+ v
+ }
+};
+
+// Comma-delimited, possibly empty, possibly with a trailing comma
+CommaOpt: Vec = {
+ ",")*> => {
+ let mut v = v;
+ v.extend(e);
+ v
+ }
+};
+
+// AST NODE
+// ================================================================================================
+
+pub Module: Module = {
+ "kernel" => {
+ Module::new(span!(l, r), ModuleType::Kernel, name, globals, functions, externals)
+ },
+ "module" => {
+ Module::new(span!(l, r), ModuleType::Module, name, globals, functions, externals)
+ },
+}
+
+// GLOBALS
+// ================================================================================================
+
+GlobalVarDeclaration: GlobalVarDeclaration = {
+ => {
+ let mut v = GlobalVarDeclaration::new(span!(l, r), name, ty, linkage);
+ if let Some(e) = init {
+ v.with_init(e);
+ }
+ v
+ }
+}
+
+Linkage: Linkage = {
+ "internal" => Linkage::Internal,
+ "odr" => Linkage::Odr,
+ "external" => Linkage::Internal,
+}
+
+GlobalVarInitializer: GlobalVarInitializer = {
+ "=" => {
+ GlobalVarInitializer::new(e)
+ }
+}
+
+// TYPES
+// ==============================================================================================
+
+Type: Type = {
+ "(" ")" => Type::Unit,
+ "!" => Type::Never,
+ "i1" => Type::I1,
+ "i8" => Type::I8,
+ "u8" => Type::U8,
+ "i16" => Type::I16,
+ "u16" => Type::U16,
+ "i32" => Type::I32,
+ "u32" => Type::U32,
+ "i64" => Type::I64,
+ "u64" => Type::U64,
+ "i128" => Type::I128,
+ "u128" => Type::U128,
+ "u256" => Type::U256,
+ "f64" => Type::F64,
+ "felt" => Type::Felt,
+ "*" "mut" => Type::Ptr(Box::new(inner)),
+ "&" "mut" => Type::NativePtr(Box::new(inner), AddressSpace::Unknown),
+ "{" > "}" => Type::Struct(StructType::new(field_types)),
+ "[" ";" "]" => Type::Array(Box::new(inner), usize::try_from(length).unwrap()),
+}
+
+// FUNCTIONS
+// ==============================================================================================
+
+ExternalFunction: FunctionSignature = {
+ ";" => signature
+}
+
+CallConvention: CallConv = {
+ "cc" "(" "fast" ")" => CallConv::Fast,
+ "cc" "(" "kernel" ")" => CallConv::Kernel,
+}
+
+ParamPurpose: ArgumentPurpose = {
+ => ArgumentPurpose::Default,
+ "sret" => ArgumentPurpose::StructReturn,
+}
+
+ParamExtension: ArgumentExtension = {
+ "zext" => ArgumentExtension::Zext,
+ "sext" => ArgumentExtension::Sext,
+}
+
+FunctionReturn: FunctionReturn = {
+ => {
+ let ext = if let Some(e) = extension { e } else { ArgumentExtension::None };
+ FunctionReturn::new(ext, ty)
+ }
+}
+
+FunctionReturnSignature: Vec = {
+ "->" > => returns
+}
+
+FunctionParam: FunctionParameter = {
+ => {
+ let ext = if let Some(e) = extension { e } else { ArgumentExtension::None };
+ FunctionParameter::new(purpose, ext, ty)
+ }
+}
+
+FunctionParams: Vec = {
+ "(" > ")" => params,
+}
+
+FunctionSignature: FunctionSignature = {
+ "pub" "fn" => {
+ let cc = if let Some(cc) = call_convention { cc } else { CallConv::SystemV };
+ let ret = if let Some(r) = returns { r } else { Vec::new() };
+ FunctionSignature::new(span!(l, r), Visibility::Public, cc, name, params, ret)
+ },
+ "fn" => {
+ let cc = if let Some(cc) = call_convention { cc } else { CallConv::SystemV };
+ let ret = if let Some(r) = returns { r } else { Vec::new() };
+ FunctionSignature::new(span!(l, r), Visibility::Private, cc, name, params, ret)
+ },
+}
+
+FunctionDeclaration: FunctionDeclaration = {
+ "{" "}" => {
+ FunctionDeclaration::new(span!(l, r), signature, blocks)
+ }
+}
+
+// BLOCKS
+// ================================================================================================
+
+Label: Label = {
+ => {
+ Label::new(id)
+ }
+}
+
+BlockArg: BlockArgument = {
+ ":" => {
+ BlockArgument::new(value, ty)
+ }
+}
+
+BlockArgs: Vec = {
+ "(" > ")" => args,
+}
+
+BlockHeader: BlockHeader = {
+ ":" => {
+ let a = if let Some(args) = arguments { args } else { Vec::new() };
+ BlockHeader::new(label, a)
+ },
+}
+
+Block: Block = {
+ "{" "}" => {
+ Block::new(span!(l, r), header, instructions)
+ }
+}
+
+// INSTRUCTIONS
+// ================================================================================================
+
+Overflow: Overflow = {
+ "." "unchecked" => Overflow::Unchecked,
+ "." "checked" => Overflow::Checked,
+ "." "wrapping" => Overflow::Wrapping,
+ "." "overflowing" => Overflow::Overflowing,
+}
+
+BinaryOpCode: BinaryOpCode = {
+ "add" => {
+ BinaryOpCode::Add(overflow)
+ },
+ "sub" => {
+ BinaryOpCode::Sub(overflow)
+ },
+ "mul" => {
+ BinaryOpCode::Mul(overflow)
+ },
+ "div" => {
+ BinaryOpCode::Div(overflow)
+ },
+ "min" => {
+ BinaryOpCode::Min(overflow)
+ },
+ "max" => {
+ BinaryOpCode::Max(overflow)
+ },
+ "mod" => {
+ BinaryOpCode::Mod(overflow)
+ },
+ "divmod" => {
+ BinaryOpCode::DivMod(overflow)
+ },
+ "exp" => {
+ BinaryOpCode::Exp(overflow)
+ },
+ "and" => {
+ BinaryOpCode::And
+ },
+ "band" => {
+ BinaryOpCode::BAnd(overflow)
+ },
+ "or" => {
+ BinaryOpCode::Or
+ },
+ "bor" => {
+ BinaryOpCode::BOr(overflow)
+ },
+ "xor" => {
+ BinaryOpCode::Xor
+ },
+ "bxor" => {
+ BinaryOpCode::BXor(overflow)
+ },
+ "shl" => {
+ BinaryOpCode::Shl(overflow)
+ },
+ "shr" => {
+ BinaryOpCode::Shr(overflow)
+ },
+ "rotl" => {
+ BinaryOpCode::Rotl(overflow)
+ },
+ "rotr" => {
+ BinaryOpCode::Rotr(overflow)
+ },
+ "eq" => {
+ BinaryOpCode::Eq
+ },
+ "neq" => {
+ BinaryOpCode::Neq
+ },
+ "gt" => {
+ BinaryOpCode::Gt
+ },
+ "gte" => {
+ BinaryOpCode::Gte
+ },
+ "lt" => {
+ BinaryOpCode::Lt
+ },
+ "lte" => {
+ BinaryOpCode::Lte
+ },
+ "store" => {
+ BinaryOpCode::Store
+ },
+}
+
+BinaryImmOpCode: BinaryImmOpCode = {
+ "add_imm" => {
+ BinaryImmOpCode::AddImm(overflow)
+ },
+ "sub_imm" => {
+ BinaryImmOpCode::SubImm(overflow)
+ },
+ "mul_imm" => {
+ BinaryImmOpCode::MulImm(overflow)
+ },
+ "div_imm" => {
+ BinaryImmOpCode::DivImm(overflow)
+ },
+ "min_imm" => {
+ BinaryImmOpCode::MinImm(overflow)
+ },
+ "max_imm" => {
+ BinaryImmOpCode::MaxImm(overflow)
+ },
+ "mod_imm" => {
+ BinaryImmOpCode::ModImm(overflow)
+ },
+ "divmod_imm" => {
+ BinaryImmOpCode::DivModImm(overflow)
+ },
+ "exp_imm" => {
+ BinaryImmOpCode::ExpImm(overflow)
+ },
+ "and_imm" => {
+ BinaryImmOpCode::AndImm
+ },
+ "band_imm" => {
+ BinaryImmOpCode::BAndImm(overflow)
+ },
+ "or_imm" => {
+ BinaryImmOpCode::OrImm
+ },
+ "bor_imm" => {
+ BinaryImmOpCode::BOrImm(overflow)
+ },
+ "xor_imm" => {
+ BinaryImmOpCode::XorImm
+ },
+ "bxor_imm" => {
+ BinaryImmOpCode::BXorImm(overflow)
+ },
+ "shl_imm" => {
+ BinaryImmOpCode::ShlImm(overflow)
+ },
+ "shr_imm" => {
+ BinaryImmOpCode::ShrImm(overflow)
+ },
+ "rotl_imm" => {
+ BinaryImmOpCode::RotlImm(overflow)
+ },
+ "rotr_imm" => {
+ BinaryImmOpCode::RotrImm(overflow)
+ },
+}
+
+UnaryOpCode: UnaryOpCode = {
+ "inv" => {
+ UnaryOpCode::Inv
+ },
+ "incr" => {
+ UnaryOpCode::Incr
+ },
+ "pow2" => {
+ UnaryOpCode::Pow2
+ },
+ "not" => {
+ UnaryOpCode::Not
+ },
+ "bnot" => {
+ UnaryOpCode::BNot
+ },
+ "popcnt" => {
+ UnaryOpCode::PopCnt
+ },
+ "is_odd" => {
+ UnaryOpCode::IsOdd
+ },
+ "cast" => {
+ UnaryOpCode::Cast
+ },
+ "ptrtoint" => {
+ UnaryOpCode::PtrToInt
+ },
+ "inttoprt" => {
+ UnaryOpCode::IntToPtr
+ },
+ "truncw" => {
+ UnaryOpCode::TruncW
+ },
+ "zext" => {
+ UnaryOpCode::Zext
+ },
+ "sext" => {
+ UnaryOpCode::Sext
+ },
+ "neg" => {
+ UnaryOpCode::Neg
+ },
+}
+
+UnaryImmOpCode: UnaryImmOpCode = {
+ "const" "." "i1" => UnaryImmOpCode::I1,
+ "const" "." "i8" => UnaryImmOpCode::I8,
+ "const" "." "i16" => UnaryImmOpCode::I16,
+ "const" "." "i32" => UnaryImmOpCode::I32,
+ "const" "." "i64" => UnaryImmOpCode::I64,
+ "const" "." "felt" => UnaryImmOpCode::Felt,
+ "const" "." "f64" => UnaryImmOpCode::F64,
+}
+
+Offset: Offset = {
+ "+" => {
+ Offset::Pos(val)
+ },
+ "-" => {
+ Offset::Neg(val)
+ }
+}
+
+GlobalValueOperationNested: GlobalValueOpNested = {
+ "@" => {
+ if let Some(o) = offset {
+ GlobalValueOpNested::Symbol(id, o)
+ }
+ else {
+ GlobalValueOpNested::Symbol(id, Offset::Pos(0))
+ }
+ },
+ "*" => {
+ GlobalValueOpNested::Load(Box::new(nested), Offset::Pos(0))
+ },
+ "*" "(" ")" => {
+ GlobalValueOpNested::Load(Box::new(nested), offset)
+ },
+ "*" "(" ")" "as" => {
+ if let Some(o) = offset {
+ GlobalValueOpNested::Cast(Box::new(nested), o, ty)
+ }
+ else {
+ GlobalValueOpNested::Cast(Box::new(nested), Offset::Pos(0), ty)
+ }
+ },
+}
+
+GlobalValueOperation: GlobalValueOp = {
+ "global" "." "symbol" "@" => {
+ if let Some(o) = offset {
+ GlobalValueOp::Symbol(id, o)
+ }
+ else {
+ GlobalValueOp::Symbol(id, Offset::Pos(0))
+ }
+ },
+ "global" "." "load" => {
+ GlobalValueOp::Load(nested, Offset::Pos(0))
+ },
+ "global" "." "load" "(" ")" => {
+ GlobalValueOp::Load(nested, offset)
+ },
+ "global" "." "load" "(" ")" "as" => {
+ if let Some(o) = offset {
+ GlobalValueOp::Cast(nested, o, ty)
+ }
+ else {
+ GlobalValueOp::Cast(nested, Offset::Pos(0), ty)
+ }
+ },
+ "global" "." "iadd" "." "." => {
+ GlobalValueOp::IAddImm(number, ty, nested)
+ },
+}
+
+CallOp: CallOp = {
+ "call" => CallOp::Call,
+ "syscall" => CallOp::SysCall,
+}
+
+SwitchBranch: SwitchBranch = {
+ "=>" => {
+ SwitchBranch::Test(value, label)
+ },
+ => {
+ SwitchBranch::Default(label)
+ }
+}
+
+Destination: Destination = {
+ => {
+ let a = if let Some(args) = arguments { args } else { Vec::new() };
+ Destination::new(label, a)
+ },
+}
+
+Operation: Operation = {
+ => {
+ Operation::BinaryOp(op, val1, val2)
+ },
+ => {
+ Operation::BinaryImmOp(op, val, imm)
+ },
+ => {
+ Operation::UnaryOp(op, val)
+ },
+ => {
+ Operation::UnaryImmOp(op, imm)
+ },
+ "ret" "(" > ")" => {
+ Operation::ReturnOp(vals)
+ },
+ "ret" => {
+ Operation::ReturnOp(Vec::new())
+ },
+ "(" > ")" => {
+ Operation::CallOp(op, f, args)
+ },
+ "cond" "," "," => {
+ Operation::CondOp(val, dest1, dest2)
+ },
+ "branch" => {
+ Operation::BranchOp(dest)
+ },
+ "switch" "," > => {
+ Operation::SwitchOp(val, branches)
+ },
+ "test" "." => {
+ Operation::TestOp(ty, val)
+ },
+ "select" "," "," => {
+ let args = vec![cond, a, b];
+ Operation::PrimOp(PrimOpCode::Select, args)
+ },
+ "assert" => {
+ let args = vec![val];
+ Operation::PrimOp(PrimOpCode::Assert, args)
+ },
+ "assertz" => {
+ let args = vec![val];
+ Operation::PrimOp(PrimOpCode::Assertz, args)
+ },
+ "assert" "." "eq" "," => {
+ let args = vec![lhs, rhs];
+ Operation::PrimOp(PrimOpCode::AssertEq, args)
+ },
+ "alloca" => {
+ Operation::PrimOp(PrimOpCode::Alloca, Vec::new())
+ },
+ "unreachable" => {
+ Operation::PrimOp(PrimOpCode::Unreachable, Vec::new())
+ },
+ "load" => {
+ Operation::LoadOp(val)
+ },
+ "memcpy" "." "," "," => {
+ Operation::MemCpyOp(ty, val1, val2, val3)
+ },
+// TODO: Inline assembly
+// "inlineasm" "\"" "\"" "," > => ...,
+// "inlineasm" "\"" "\"" "," => ...,
+ => {
+ Operation::GlobalValueOp(op)
+ }
+// TODO: MemGrow
+// "memory" "." "grow" => ...,
+}
+
+Instruction: Instruction = {
+ > "=" ":" > => {
+ Instruction::new(span!(l, r), values, op, types)
+ },
+ => {
+ Instruction::new(span!(l, r), Vec::new(), op, Vec::new())
+ },
+}
+
+
+// VALUES AND IDENTIFIERS
+// ================================================================================================
+
+HexString: Vec = {
+ hex,
+}
+
+Number: u128 = {
+ int,
+}
+
+Immediate: Immediate = {
+ => Immediate::Pos(val),
+ "-"