implementing pointers example
This commit is contained in:
parent
602249a48a
commit
c0d4464097
109
Cargo.lock
generated
109
Cargo.lock
generated
|
@ -2,18 +2,6 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ahash"
|
|
||||||
version = "0.8.11"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"once_cell",
|
|
||||||
"version_check",
|
|
||||||
"zerocopy",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aho-corasick"
|
name = "aho-corasick"
|
||||||
version = "1.1.3"
|
version = "1.1.3"
|
||||||
|
@ -23,6 +11,12 @@ dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "allocator-api2"
|
||||||
|
version = "0.2.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstream"
|
name = "anstream"
|
||||||
version = "0.6.15"
|
version = "0.6.15"
|
||||||
|
@ -73,10 +67,13 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "bumpalo"
|
||||||
version = "1.0.0"
|
version = "3.16.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
|
||||||
|
dependencies = [
|
||||||
|
"allocator-api2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "colorchoice"
|
name = "colorchoice"
|
||||||
|
@ -112,9 +109,6 @@ name = "hashbrown"
|
||||||
version = "0.14.5"
|
version = "0.14.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||||
dependencies = [
|
|
||||||
"ahash",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hbbytecode"
|
name = "hbbytecode"
|
||||||
|
@ -188,40 +182,16 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "once_cell"
|
|
||||||
version = "1.19.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "proc-macro2"
|
|
||||||
version = "1.0.86"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
|
|
||||||
dependencies = [
|
|
||||||
"unicode-ident",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "quote"
|
|
||||||
version = "1.0.37"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regalloc2"
|
name = "regalloc2"
|
||||||
version = "0.10.2"
|
version = "0.10.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/jakubDoka/regalloc2?branch=reuse-allocations#4100af4e24bc2921c0931c901651a969c898f852"
|
||||||
checksum = "12908dbeb234370af84d0579b9f68258a0f67e201412dd9a2814e6f45b2fc0f0"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"allocator-api2",
|
||||||
|
"bumpalo",
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
"log",
|
"log",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
"slice-group-by",
|
|
||||||
"smallvec",
|
"smallvec",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -260,47 +230,18 @@ version = "2.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152"
|
checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "slice-group-by"
|
|
||||||
version = "0.3.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.13.2"
|
version = "1.13.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "syn"
|
|
||||||
version = "2.0.77"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"unicode-ident",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unicode-ident"
|
|
||||||
version = "1.0.13"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf8parse"
|
name = "utf8parse"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "version_check"
|
|
||||||
version = "0.9.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
version = "0.52.0"
|
version = "0.52.0"
|
||||||
|
@ -377,23 +318,3 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "xtask"
|
name = "xtask"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "zerocopy"
|
|
||||||
version = "0.7.35"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
|
|
||||||
dependencies = [
|
|
||||||
"zerocopy-derive",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "zerocopy-derive"
|
|
||||||
version = "0.7.35"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
|
@ -10,8 +10,7 @@ path = "src/main.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
hbbytecode = { version = "0.1.0", path = "../hbbytecode" }
|
hbbytecode = { version = "0.1.0", path = "../hbbytecode" }
|
||||||
hbvm = { path = "../hbvm", features = ["nightly"] }
|
hbvm = { path = "../hbvm", features = ["nightly"] }
|
||||||
regalloc2 = "0.10.2"
|
regalloc2 = { git = "https://github.com/jakubDoka/regalloc2", branch = "reuse-allocations", features = [] }
|
||||||
#regalloc2 = { path = "../../regalloc2/" }#git = "https://github.com/jakubDoka/regalloc2", branch = "reuse-allocations", features = [] }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
env_logger = "0.11.5"
|
env_logger = "0.11.5"
|
||||||
|
|
221
hblang/README.md
221
hblang/README.md
|
@ -133,7 +133,6 @@ main := fn(): int {
|
||||||
b := &a
|
b := &a
|
||||||
modify(b)
|
modify(b)
|
||||||
drop(a)
|
drop(a)
|
||||||
stack_reclamation_edge_case := 0
|
|
||||||
return *b - 2
|
return *b - 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -508,226 +507,6 @@ main := fn(): int {
|
||||||
if y == width break
|
if y == width break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
width += 1
|
|
||||||
|
|
||||||
loop {
|
|
||||||
if x < height {
|
|
||||||
//t += set_pixel(x, y, height)
|
|
||||||
x += 1
|
|
||||||
i += 1
|
|
||||||
} else {
|
|
||||||
x = 0
|
|
||||||
y += 1
|
|
||||||
if set_pixel(x, y, height) != i return 0
|
|
||||||
if y == width break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
width += 1
|
|
||||||
|
|
||||||
loop {
|
|
||||||
if x < height {
|
|
||||||
//t += set_pixel(x, y, height)
|
|
||||||
x += 1
|
|
||||||
i += 1
|
|
||||||
} else {
|
|
||||||
x = 0
|
|
||||||
y += 1
|
|
||||||
if set_pixel(x, y, height) != i return 0
|
|
||||||
if y == width break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
width += 1
|
|
||||||
|
|
||||||
loop {
|
|
||||||
if x < height {
|
|
||||||
//t += set_pixel(x, y, height)
|
|
||||||
x += 1
|
|
||||||
i += 1
|
|
||||||
} else {
|
|
||||||
x = 0
|
|
||||||
y += 1
|
|
||||||
if set_pixel(x, y, height) != i return 0
|
|
||||||
if y == width break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
loop {
|
|
||||||
if x < height {
|
|
||||||
//t += set_pixel(x, y, height)
|
|
||||||
x += 1
|
|
||||||
i += 1
|
|
||||||
} else {
|
|
||||||
x = 0
|
|
||||||
y += 1
|
|
||||||
if set_pixel(x, y, height) != i return 0
|
|
||||||
if y == width break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
width += 1
|
|
||||||
|
|
||||||
loop {
|
|
||||||
if x < height {
|
|
||||||
//t += set_pixel(x, y, height)
|
|
||||||
x += 1
|
|
||||||
i += 1
|
|
||||||
} else {
|
|
||||||
x = 0
|
|
||||||
y += 1
|
|
||||||
if set_pixel(x, y, height) != i return 0
|
|
||||||
if y == width break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
width += 1
|
|
||||||
|
|
||||||
loop {
|
|
||||||
if x < height {
|
|
||||||
//t += set_pixel(x, y, height)
|
|
||||||
x += 1
|
|
||||||
i += 1
|
|
||||||
} else {
|
|
||||||
x = 0
|
|
||||||
y += 1
|
|
||||||
if set_pixel(x, y, height) != i return 0
|
|
||||||
if y == width break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
width += 1
|
|
||||||
|
|
||||||
loop {
|
|
||||||
if x < height {
|
|
||||||
//t += set_pixel(x, y, height)
|
|
||||||
x += 1
|
|
||||||
i += 1
|
|
||||||
} else {
|
|
||||||
x = 0
|
|
||||||
y += 1
|
|
||||||
if set_pixel(x, y, height) != i return 0
|
|
||||||
if y == width break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
loop {
|
|
||||||
if x < height {
|
|
||||||
//t += set_pixel(x, y, height)
|
|
||||||
x += 1
|
|
||||||
i += 1
|
|
||||||
} else {
|
|
||||||
x = 0
|
|
||||||
y += 1
|
|
||||||
if set_pixel(x, y, height) != i return 0
|
|
||||||
if y == width break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
width += 1
|
|
||||||
|
|
||||||
loop {
|
|
||||||
if x < height {
|
|
||||||
//t += set_pixel(x, y, height)
|
|
||||||
x += 1
|
|
||||||
i += 1
|
|
||||||
} else {
|
|
||||||
x = 0
|
|
||||||
y += 1
|
|
||||||
if set_pixel(x, y, height) != i return 0
|
|
||||||
if y == width break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
width += 1
|
|
||||||
|
|
||||||
loop {
|
|
||||||
if x < height {
|
|
||||||
//t += set_pixel(x, y, height)
|
|
||||||
x += 1
|
|
||||||
i += 1
|
|
||||||
} else {
|
|
||||||
x = 0
|
|
||||||
y += 1
|
|
||||||
if set_pixel(x, y, height) != i return 0
|
|
||||||
if y == width break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
width += 1
|
|
||||||
|
|
||||||
loop {
|
|
||||||
if x < height {
|
|
||||||
//t += set_pixel(x, y, height)
|
|
||||||
x += 1
|
|
||||||
i += 1
|
|
||||||
} else {
|
|
||||||
x = 0
|
|
||||||
y += 1
|
|
||||||
if set_pixel(x, y, height) != i return 0
|
|
||||||
if y == width break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
loop {
|
|
||||||
if x < height {
|
|
||||||
//t += set_pixel(x, y, height)
|
|
||||||
x += 1
|
|
||||||
i += 1
|
|
||||||
} else {
|
|
||||||
x = 0
|
|
||||||
y += 1
|
|
||||||
if set_pixel(x, y, height) != i return 0
|
|
||||||
if y == width break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
width += 1
|
|
||||||
|
|
||||||
loop {
|
|
||||||
if x < height {
|
|
||||||
//t += set_pixel(x, y, height)
|
|
||||||
x += 1
|
|
||||||
i += 1
|
|
||||||
} else {
|
|
||||||
x = 0
|
|
||||||
y += 1
|
|
||||||
if set_pixel(x, y, height) != i return 0
|
|
||||||
if y == width break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
width += 1
|
|
||||||
|
|
||||||
loop {
|
|
||||||
if x < height {
|
|
||||||
//t += set_pixel(x, y, height)
|
|
||||||
x += 1
|
|
||||||
i += 1
|
|
||||||
} else {
|
|
||||||
x = 0
|
|
||||||
y += 1
|
|
||||||
if set_pixel(x, y, height) != i return 0
|
|
||||||
if y == width break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
width += 1
|
|
||||||
|
|
||||||
loop {
|
|
||||||
if x < height {
|
|
||||||
//t += set_pixel(x, y, height)
|
|
||||||
x += 1
|
|
||||||
i += 1
|
|
||||||
} else {
|
|
||||||
x = 0
|
|
||||||
y += 1
|
|
||||||
if set_pixel(x, y, height) != i return 0
|
|
||||||
if y == width break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
@ -817,7 +817,7 @@ impl Types {
|
||||||
match ty.expand() {
|
match ty.expand() {
|
||||||
ty::Kind::Ptr(_) => 8,
|
ty::Kind::Ptr(_) => 8,
|
||||||
ty::Kind::Builtin(ty::VOID) => 0,
|
ty::Kind::Builtin(ty::VOID) => 0,
|
||||||
ty::Kind::Builtin(ty::NEVER) => unreachable!(),
|
ty::Kind::Builtin(ty::NEVER) => 0,
|
||||||
ty::Kind::Builtin(ty::INT | ty::UINT) => 8,
|
ty::Kind::Builtin(ty::INT | ty::UINT) => 8,
|
||||||
ty::Kind::Builtin(ty::I32 | ty::U32 | ty::TYPE) => 4,
|
ty::Kind::Builtin(ty::I32 | ty::U32 | ty::TYPE) => 4,
|
||||||
ty::Kind::Builtin(ty::I16 | ty::U16) => 2,
|
ty::Kind::Builtin(ty::I16 | ty::U16) => 2,
|
||||||
|
|
|
@ -12,7 +12,7 @@ use {
|
||||||
},
|
},
|
||||||
task,
|
task,
|
||||||
ty::{self},
|
ty::{self},
|
||||||
Field, Func, Offset, Reloc, Sig, Size, Struct, SymKey, TypedReloc, Types,
|
Field, Func, HashMap, Offset, Reloc, Sig, Size, Struct, SymKey, TypedReloc, Types,
|
||||||
},
|
},
|
||||||
core::fmt,
|
core::fmt,
|
||||||
regalloc2::VReg,
|
regalloc2::VReg,
|
||||||
|
@ -20,6 +20,7 @@ use {
|
||||||
assert_matches::debug_assert_matches,
|
assert_matches::debug_assert_matches,
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
collections::hash_map,
|
collections::hash_map,
|
||||||
|
convert::identity,
|
||||||
fmt::{Debug, Display, Write},
|
fmt::{Debug, Display, Write},
|
||||||
hash::{Hash as _, Hasher},
|
hash::{Hash as _, Hasher},
|
||||||
mem::{self, MaybeUninit},
|
mem::{self, MaybeUninit},
|
||||||
|
@ -32,6 +33,8 @@ const VC_SIZE: usize = 16;
|
||||||
const INLINE_ELEMS: usize = VC_SIZE / 2 - 1;
|
const INLINE_ELEMS: usize = VC_SIZE / 2 - 1;
|
||||||
const VOID: Nid = 0;
|
const VOID: Nid = 0;
|
||||||
const NEVER: Nid = 1;
|
const NEVER: Nid = 1;
|
||||||
|
const ENTRY: Nid = 2;
|
||||||
|
const MEM: Nid = 3;
|
||||||
|
|
||||||
union Vc {
|
union Vc {
|
||||||
inline: InlineVc,
|
inline: InlineVc,
|
||||||
|
@ -702,12 +705,12 @@ impl Nodes {
|
||||||
Kind::Call { func } => {
|
Kind::Call { func } => {
|
||||||
write!(out, "call: {func} {} ", self[node].depth)
|
write!(out, "call: {func} {} ", self[node].depth)
|
||||||
}
|
}
|
||||||
Kind::Ctrl { index: u32::MAX } => write!(out, "ctrl: {:<5}", "entry"),
|
Kind::Entry => write!(out, "ctrl: {:<5}", "entry"),
|
||||||
Kind::Ctrl { index: 0 } => write!(out, "ctrl: {:<5}", "then"),
|
Kind::Then => write!(out, "ctrl: {:<5}", "then"),
|
||||||
Kind::Ctrl { index: 1 } => write!(out, "ctrl: {:<5}", "else"),
|
Kind::Else => write!(out, "ctrl: {:<5}", "else"),
|
||||||
Kind::Stck { size } => write!(out, "stck: {size:<5}"),
|
Kind::Stck => write!(out, "stck: "),
|
||||||
Kind::Load { offset } => write!(out, "load: {offset:<5}"),
|
Kind::Load => write!(out, "load"),
|
||||||
Kind::Stre { offset } => write!(out, "stre: {offset:<5}"),
|
Kind::Stre => write!(out, "stre"),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
|
@ -776,7 +779,7 @@ impl Nodes {
|
||||||
Kind::Return => {
|
Kind::Return => {
|
||||||
node = self[node].outputs[0];
|
node = self[node].outputs[0];
|
||||||
}
|
}
|
||||||
Kind::Ctrl { .. } => {
|
Kind::Then | Kind::Else | Kind::Entry => {
|
||||||
writeln!(
|
writeln!(
|
||||||
out,
|
out,
|
||||||
"b{node}: {} {} {:?}",
|
"b{node}: {} {} {:?}",
|
||||||
|
@ -806,16 +809,7 @@ impl Nodes {
|
||||||
}
|
}
|
||||||
node = cfg_index;
|
node = cfg_index;
|
||||||
}
|
}
|
||||||
Kind::Arg { .. }
|
_ => unreachable!(),
|
||||||
| Kind::Stck { .. }
|
|
||||||
| Kind::Load { .. }
|
|
||||||
| Kind::Stre { .. }
|
|
||||||
| Kind::CInt { .. }
|
|
||||||
| Kind::Phi
|
|
||||||
| Kind::BinOp { .. }
|
|
||||||
| Kind::UnOp { .. } => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1024,9 +1018,10 @@ pub enum Kind {
|
||||||
index: u32,
|
index: u32,
|
||||||
},
|
},
|
||||||
// [ctrl]
|
// [ctrl]
|
||||||
Ctrl {
|
Entry,
|
||||||
index: u32,
|
Mem,
|
||||||
},
|
Then,
|
||||||
|
Else,
|
||||||
// [ctrl, oper]
|
// [ctrl, oper]
|
||||||
UnOp {
|
UnOp {
|
||||||
op: lexer::TokenKind,
|
op: lexer::TokenKind,
|
||||||
|
@ -1040,22 +1035,21 @@ pub enum Kind {
|
||||||
func: ty::Func,
|
func: ty::Func,
|
||||||
},
|
},
|
||||||
// [ctrl]
|
// [ctrl]
|
||||||
Stck {
|
Stck,
|
||||||
size: Size,
|
|
||||||
},
|
|
||||||
// [ctrl, memory]
|
// [ctrl, memory]
|
||||||
Load {
|
Offset {
|
||||||
offset: Offset,
|
offset: Offset,
|
||||||
},
|
},
|
||||||
// [ctrl, memory]
|
// [ctrl, memory]
|
||||||
Stre {
|
Load,
|
||||||
offset: Offset,
|
// [ctrl, memory]
|
||||||
},
|
Stre,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Kind {
|
impl Kind {
|
||||||
fn is_pinned(&self) -> bool {
|
fn is_pinned(&self) -> bool {
|
||||||
self.is_cfg() || matches!(self, Self::Phi)
|
self.is_cfg() || matches!(self, Self::Phi | Self::Mem)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_cfg(&self) -> bool {
|
fn is_cfg(&self) -> bool {
|
||||||
|
@ -1064,7 +1058,9 @@ impl Kind {
|
||||||
Self::Start
|
Self::Start
|
||||||
| Self::End
|
| Self::End
|
||||||
| Self::Return
|
| Self::Return
|
||||||
| Self::Ctrl { .. }
|
| Self::Entry
|
||||||
|
| Self::Then
|
||||||
|
| Self::Else
|
||||||
| Self::Arg { .. }
|
| Self::Arg { .. }
|
||||||
| Self::Call { .. }
|
| Self::Call { .. }
|
||||||
| Self::If
|
| Self::If
|
||||||
|
@ -1078,7 +1074,16 @@ impl Kind {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn starts_basic_block(&self) -> bool {
|
fn starts_basic_block(&self) -> bool {
|
||||||
matches!(self, Self::Start | Self::End | Self::Ctrl { .. } | Self::Region | Self::Loop)
|
matches!(
|
||||||
|
self,
|
||||||
|
Self::Start
|
||||||
|
| Self::End
|
||||||
|
| Self::Entry
|
||||||
|
| Self::Then
|
||||||
|
| Self::Else
|
||||||
|
| Self::Region
|
||||||
|
| Self::Loop
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1086,9 +1091,9 @@ impl fmt::Display for Kind {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Kind::CInt { value } => write!(f, "#{value}"),
|
Kind::CInt { value } => write!(f, "#{value}"),
|
||||||
Kind::Ctrl { index: u32::MAX } => write!(f, "ctrl[entry]"),
|
Kind::Entry => write!(f, "ctrl[entry]"),
|
||||||
Kind::Ctrl { index: 0 } => write!(f, "ctrl[then]"),
|
Kind::Then => write!(f, "ctrl[then]"),
|
||||||
Kind::Ctrl { index: 1 } => write!(f, "ctrl[else]"),
|
Kind::Else => write!(f, "ctrl[else]"),
|
||||||
Kind::BinOp { op } => write!(f, "{op}"),
|
Kind::BinOp { op } => write!(f, "{op}"),
|
||||||
Kind::Call { func, .. } => write!(f, "call {func}"),
|
Kind::Call { func, .. } => write!(f, "call {func}"),
|
||||||
slf => write!(f, "{slf:?}"),
|
slf => write!(f, "{slf:?}"),
|
||||||
|
@ -1099,15 +1104,15 @@ impl fmt::Display for Kind {
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
//#[repr(align(64))]
|
//#[repr(align(64))]
|
||||||
struct Node {
|
struct Node {
|
||||||
|
kind: Kind,
|
||||||
inputs: Vc,
|
inputs: Vc,
|
||||||
outputs: Vc,
|
outputs: Vc,
|
||||||
kind: Kind,
|
ty: ty::Id,
|
||||||
|
offset: Offset,
|
||||||
ralloc_backref: RallocBRef,
|
ralloc_backref: RallocBRef,
|
||||||
depth: IDomDepth,
|
depth: IDomDepth,
|
||||||
lock_rc: LockRc,
|
lock_rc: LockRc,
|
||||||
ty: ty::Id,
|
|
||||||
loop_depth: LoopDepth,
|
loop_depth: LoopDepth,
|
||||||
offset: Offset,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Node {
|
impl Node {
|
||||||
|
@ -1149,6 +1154,13 @@ struct ColorMeta {
|
||||||
loc: Loc,
|
loc: Loc,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||||
|
struct MemKey {
|
||||||
|
region: Nid,
|
||||||
|
offset: u32,
|
||||||
|
node: Nid,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct ItemCtx {
|
struct ItemCtx {
|
||||||
file: FileId,
|
file: FileId,
|
||||||
|
@ -1165,8 +1177,10 @@ struct ItemCtx {
|
||||||
filled: Vec<Nid>,
|
filled: Vec<Nid>,
|
||||||
delayed_frees: Vec<RallocBRef>,
|
delayed_frees: Vec<RallocBRef>,
|
||||||
|
|
||||||
|
stack_size: Size,
|
||||||
loops: Vec<Loop>,
|
loops: Vec<Loop>,
|
||||||
vars: Vec<Variable>,
|
vars: Vec<Variable>,
|
||||||
|
memories: Vec<MemKey>,
|
||||||
ret_relocs: Vec<Reloc>,
|
ret_relocs: Vec<Reloc>,
|
||||||
relocs: Vec<TypedReloc>,
|
relocs: Vec<TypedReloc>,
|
||||||
jump_relocs: Vec<(Nid, Reloc)>,
|
jump_relocs: Vec<(Nid, Reloc)>,
|
||||||
|
@ -1221,6 +1235,33 @@ struct Pool {
|
||||||
cis: Vec<ItemCtx>,
|
cis: Vec<ItemCtx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Regalloc {
|
||||||
|
env: regalloc2::MachineEnv,
|
||||||
|
ctx: regalloc2::Ctx,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Regalloc {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
env: regalloc2::MachineEnv {
|
||||||
|
preferred_regs_by_class: [
|
||||||
|
(1..13).map(|i| regalloc2::PReg::new(i, regalloc2::RegClass::Int)).collect(),
|
||||||
|
vec![],
|
||||||
|
vec![],
|
||||||
|
],
|
||||||
|
non_preferred_regs_by_class: [
|
||||||
|
(13..64).map(|i| regalloc2::PReg::new(i, regalloc2::RegClass::Int)).collect(),
|
||||||
|
vec![],
|
||||||
|
vec![],
|
||||||
|
],
|
||||||
|
scratch_by_class: Default::default(),
|
||||||
|
fixed_stack_slots: Default::default(),
|
||||||
|
},
|
||||||
|
ctx: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Codegen {
|
pub struct Codegen {
|
||||||
pub files: Vec<parser::Ast>,
|
pub files: Vec<parser::Ast>,
|
||||||
|
@ -1229,10 +1270,62 @@ pub struct Codegen {
|
||||||
tys: Types,
|
tys: Types,
|
||||||
ci: ItemCtx,
|
ci: ItemCtx,
|
||||||
pool: Pool,
|
pool: Pool,
|
||||||
|
ralloc: Regalloc,
|
||||||
errors: RefCell<String>,
|
errors: RefCell<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Codegen {
|
impl Codegen {
|
||||||
|
fn mem_op(&mut self, region: Nid, offset: Offset, kind: Kind, ty: ty::Id, mut inps: Vc) -> Nid {
|
||||||
|
let size = self.tys.size_of(ty);
|
||||||
|
let insert_start = self
|
||||||
|
.ci
|
||||||
|
.memories
|
||||||
|
.binary_search_by_key(&(region, offset), |k| (k.region, k.offset))
|
||||||
|
.unwrap_or_else(identity);
|
||||||
|
let insert_end = self
|
||||||
|
.ci
|
||||||
|
.memories
|
||||||
|
.binary_search_by(|k| (k.region, k.offset).cmp(&(region, offset + size)))
|
||||||
|
.unwrap_or_else(identity);
|
||||||
|
|
||||||
|
for mk in &self.ci.memories[insert_start..insert_end] {
|
||||||
|
debug_assert_eq!(mk.region, region);
|
||||||
|
debug_assert!(mk.offset >= offset);
|
||||||
|
debug_assert!(mk.offset < offset + size);
|
||||||
|
if matches!(kind, Kind::Load | Kind::Offset { .. })
|
||||||
|
|| !self.ci.nodes.unlock_remove(mk.node)
|
||||||
|
{
|
||||||
|
inps.push(mk.node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if insert_start == insert_end {
|
||||||
|
inps.push(region);
|
||||||
|
}
|
||||||
|
|
||||||
|
let new_op = self.ci.nodes.new_node(ty, kind, inps);
|
||||||
|
if !matches!(kind, Kind::Offset { .. }) {
|
||||||
|
self.ci.memories.splice(
|
||||||
|
insert_start..insert_end,
|
||||||
|
std::iter::once(MemKey { node: new_op, region, offset }),
|
||||||
|
);
|
||||||
|
self.ci.nodes.lock(new_op);
|
||||||
|
}
|
||||||
|
new_op
|
||||||
|
}
|
||||||
|
|
||||||
|
fn store_mem(&mut self, region: Nid, offset: Offset, value: Nid) -> Nid {
|
||||||
|
self.mem_op(region, offset, Kind::Stre, self.tof(value), [VOID, value].into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_mem(&mut self, region: Nid, offset: Offset, ty: ty::Id) -> Nid {
|
||||||
|
self.mem_op(region, offset, Kind::Load, ty, [VOID].into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ref_mem(&mut self, region: Nid, offset: Offset, ty: ty::Id) -> Nid {
|
||||||
|
self.mem_op(region, offset, Kind::Offset { offset }, ty, [VOID].into())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn generate(&mut self) {
|
pub fn generate(&mut self) {
|
||||||
self.find_or_declare(0, 0, None, "main");
|
self.find_or_declare(0, 0, None, "main");
|
||||||
self.make_func_reachable(0);
|
self.make_func_reachable(0);
|
||||||
|
@ -1303,7 +1396,32 @@ impl Codegen {
|
||||||
self.ci.nodes.unlock_remove(prev);
|
self.ci.nodes.unlock_remove(prev);
|
||||||
Some(VOID)
|
Some(VOID)
|
||||||
}
|
}
|
||||||
Expr::BinOp { left, op, right } => {
|
Expr::BinOp {
|
||||||
|
left: &Expr::UnOp { pos, op: TokenKind::Mul, val },
|
||||||
|
op: TokenKind::Assign,
|
||||||
|
right,
|
||||||
|
} => {
|
||||||
|
let ctx = Ctx { ty: ctx.ty.map(|ty| self.tys.make_ptr(ty)) };
|
||||||
|
let val = self.expr_ctx(val, ctx)?;
|
||||||
|
let base = match self.tof(val).expand() {
|
||||||
|
ty::Kind::Ptr(p) => self.tys.ptrs[p as usize].base,
|
||||||
|
_ => {
|
||||||
|
self.report(
|
||||||
|
pos,
|
||||||
|
format_args!(
|
||||||
|
"the '{}' can not be dereferneced",
|
||||||
|
self.ty_display(self.tof(val))
|
||||||
|
),
|
||||||
|
);
|
||||||
|
ty::NEVER.into()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let value = self.expr(right)?;
|
||||||
|
_ = self.assert_ty(right.pos(), self.tof(value), base, true, "stored value");
|
||||||
|
self.store_mem(val, 0, value);
|
||||||
|
Some(VOID)
|
||||||
|
}
|
||||||
|
Expr::BinOp { left, op, right } if op != TokenKind::Assign => {
|
||||||
let lhs = self.expr_ctx(left, ctx)?;
|
let lhs = self.expr_ctx(left, ctx)?;
|
||||||
self.ci.nodes.lock(lhs);
|
self.ci.nodes.lock(lhs);
|
||||||
let rhs = self.expr_ctx(right, Ctx::default().with_ty(self.tof(lhs)));
|
let rhs = self.expr_ctx(right, Ctx::default().with_ty(self.tof(lhs)));
|
||||||
|
@ -1319,10 +1437,46 @@ impl Codegen {
|
||||||
let inps = [VOID, lhs, rhs];
|
let inps = [VOID, lhs, rhs];
|
||||||
Some(self.ci.nodes.new_node(ty::bin_ret(ty, op), Kind::BinOp { op }, inps))
|
Some(self.ci.nodes.new_node(ty::bin_ret(ty, op), Kind::BinOp { op }, inps))
|
||||||
}
|
}
|
||||||
Expr::UnOp { pos: _, op: TokenKind::Band, val: _ } => {
|
Expr::UnOp { op: TokenKind::Band, val, .. } => {
|
||||||
todo!()
|
let ctx = Ctx {
|
||||||
|
ty: ctx.ty.and_then(|ty| match ty.expand() {
|
||||||
|
ty::Kind::Ptr(p) => Some(self.tys.ptrs[p as usize].base),
|
||||||
|
_ => None,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut val = self.expr_ctx(val, ctx)?;
|
||||||
|
let ty = self.tof(val);
|
||||||
|
if !matches!(self.ci.nodes[val].kind, Kind::Stck | Kind::Offset { .. }) {
|
||||||
|
let stck = self.ci.nodes.new_node_nop(ty, Kind::Stck, [VOID, MEM]);
|
||||||
|
self.ci.nodes[stck].offset = self.ci.stack_size;
|
||||||
|
self.ci.stack_size += self.tys.size_of(ty);
|
||||||
|
self.store_mem(stck, 0, val);
|
||||||
|
val = stck;
|
||||||
|
}
|
||||||
|
|
||||||
|
let ptr = self.tys.make_ptr(ty);
|
||||||
|
Some(self.ref_mem(val, 0, ptr))
|
||||||
}
|
}
|
||||||
Expr::UnOp { pos, op, val } => {
|
Expr::UnOp { op: TokenKind::Mul, val, pos } => {
|
||||||
|
let ctx = Ctx { ty: ctx.ty.map(|ty| self.tys.make_ptr(ty)) };
|
||||||
|
let val = self.expr_ctx(val, ctx)?;
|
||||||
|
let base = match self.tof(val).expand() {
|
||||||
|
ty::Kind::Ptr(p) => self.tys.ptrs[p as usize].base,
|
||||||
|
_ => {
|
||||||
|
self.report(
|
||||||
|
pos,
|
||||||
|
format_args!(
|
||||||
|
"the '{}' can not be dereferneced",
|
||||||
|
self.ty_display(self.tof(val))
|
||||||
|
),
|
||||||
|
);
|
||||||
|
ty::NEVER.into()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Some(self.load_mem(val, 0, base))
|
||||||
|
}
|
||||||
|
Expr::UnOp { pos, op: op @ TokenKind::Sub, val } => {
|
||||||
let val = self.expr_ctx(val, ctx)?;
|
let val = self.expr_ctx(val, ctx)?;
|
||||||
if !self.tof(val).is_integer() {
|
if !self.tof(val).is_integer() {
|
||||||
self.report(
|
self.report(
|
||||||
|
@ -1360,11 +1514,11 @@ impl Codegen {
|
||||||
self.ci.nodes.lock(el.value);
|
self.ci.nodes.lock(el.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.ci.ctrl = self.ci.nodes.new_node(ty::VOID, Kind::Ctrl { index: 0 }, [if_node]);
|
self.ci.ctrl = self.ci.nodes.new_node(ty::VOID, Kind::Then, [if_node]);
|
||||||
let lcntrl = self.expr(then).map_or(Nid::MAX, |_| self.ci.ctrl);
|
let lcntrl = self.expr(then).map_or(Nid::MAX, |_| self.ci.ctrl);
|
||||||
|
|
||||||
let mut then_scope = std::mem::replace(&mut self.ci.vars, else_scope);
|
let mut then_scope = std::mem::replace(&mut self.ci.vars, else_scope);
|
||||||
self.ci.ctrl = self.ci.nodes.new_node(ty::VOID, Kind::Ctrl { index: 1 }, [if_node]);
|
self.ci.ctrl = self.ci.nodes.new_node(ty::VOID, Kind::Else, [if_node]);
|
||||||
let rcntrl = if let Some(else_) = else_ {
|
let rcntrl = if let Some(else_) = else_ {
|
||||||
self.expr(else_).map_or(Nid::MAX, |_| self.ci.ctrl)
|
self.expr(else_).map_or(Nid::MAX, |_| self.ci.ctrl)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1568,7 +1722,10 @@ impl Codegen {
|
||||||
VOID
|
VOID
|
||||||
};
|
};
|
||||||
|
|
||||||
let inps = [self.ci.ctrl, value];
|
let mut inps = Vc::from([self.ci.ctrl, value]);
|
||||||
|
for m in self.ci.memories.iter() {
|
||||||
|
inps.push(m.node);
|
||||||
|
}
|
||||||
|
|
||||||
let out = &mut String::new();
|
let out = &mut String::new();
|
||||||
self.report_log_to(pos, "returning here", out);
|
self.report_log_to(pos, "returning here", out);
|
||||||
|
@ -1718,7 +1875,10 @@ impl Codegen {
|
||||||
debug_assert_eq!(start, VOID);
|
debug_assert_eq!(start, VOID);
|
||||||
let end = self.ci.nodes.new_node(ty::NEVER, Kind::End, []);
|
let end = self.ci.nodes.new_node(ty::NEVER, Kind::End, []);
|
||||||
debug_assert_eq!(end, NEVER);
|
debug_assert_eq!(end, NEVER);
|
||||||
self.ci.ctrl = self.ci.nodes.new_node(ty::VOID, Kind::Ctrl { index: u32::MAX }, [VOID]);
|
self.ci.ctrl = self.ci.nodes.new_node(ty::VOID, Kind::Entry, [VOID]);
|
||||||
|
debug_assert_eq!(self.ci.ctrl, ENTRY);
|
||||||
|
let mem = self.ci.nodes.new_node(ty::VOID, Kind::Mem, [VOID]);
|
||||||
|
debug_assert_eq!(mem, MEM);
|
||||||
|
|
||||||
let Expr::BinOp {
|
let Expr::BinOp {
|
||||||
left: Expr::Ident { .. },
|
left: Expr::Ident { .. },
|
||||||
|
@ -1745,6 +1905,9 @@ impl Codegen {
|
||||||
self.report(body.pos(), "expected all paths in the fucntion to return");
|
self.report(body.pos(), "expected all paths in the fucntion to return");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for mem in self.ci.memories.drain(..) {
|
||||||
|
self.ci.nodes.unlock_remove(mem.node);
|
||||||
|
}
|
||||||
for var in self.ci.vars.drain(..) {
|
for var in self.ci.vars.drain(..) {
|
||||||
self.ci.nodes.unlock(var.value);
|
self.ci.nodes.unlock(var.value);
|
||||||
}
|
}
|
||||||
|
@ -1790,7 +1953,7 @@ impl Codegen {
|
||||||
|
|
||||||
'_close_function: {
|
'_close_function: {
|
||||||
let pushed = (saved as i64 + 1) * 8;
|
let pushed = (saved as i64 + 1) * 8;
|
||||||
let stack = 0;
|
let stack = std::mem::take(&mut self.ci.stack_size) as i64;
|
||||||
|
|
||||||
write_reloc(&mut self.ci.code, 3, -(pushed + stack), 8);
|
write_reloc(&mut self.ci.code, 3, -(pushed + stack), 8);
|
||||||
write_reloc(&mut self.ci.code, 3 + 8 + 3, stack, 8);
|
write_reloc(&mut self.ci.code, 3 + 8 + 3, stack, 8);
|
||||||
|
@ -1813,153 +1976,216 @@ impl Codegen {
|
||||||
let mut nodes = std::mem::take(&mut self.ci.nodes);
|
let mut nodes = std::mem::take(&mut self.ci.nodes);
|
||||||
|
|
||||||
let func = Function::new(&mut nodes, &self.tys, sig);
|
let func = Function::new(&mut nodes, &self.tys, sig);
|
||||||
let mut env = regalloc2::MachineEnv {
|
|
||||||
preferred_regs_by_class: [
|
|
||||||
(1..5).map(|i| regalloc2::PReg::new(i, regalloc2::RegClass::Int)).collect(),
|
|
||||||
vec![],
|
|
||||||
vec![],
|
|
||||||
],
|
|
||||||
non_preferred_regs_by_class: [
|
|
||||||
(12..16).map(|i| regalloc2::PReg::new(i, regalloc2::RegClass::Int)).collect(),
|
|
||||||
vec![],
|
|
||||||
vec![],
|
|
||||||
],
|
|
||||||
scratch_by_class: Default::default(),
|
|
||||||
fixed_stack_slots: Default::default(),
|
|
||||||
};
|
|
||||||
if self.ci.call_count != 0 {
|
if self.ci.call_count != 0 {
|
||||||
std::mem::swap(&mut env.preferred_regs_by_class, &mut env.non_preferred_regs_by_class);
|
std::mem::swap(
|
||||||
|
&mut self.ralloc.env.preferred_regs_by_class,
|
||||||
|
&mut self.ralloc.env.non_preferred_regs_by_class,
|
||||||
|
);
|
||||||
};
|
};
|
||||||
let options = regalloc2::RegallocOptions { verbose_log: false, validate_ssa: false };
|
|
||||||
let iters = std::hint::black_box(10000);
|
|
||||||
|
|
||||||
//let mut ctx = regalloc2::Ctx::default();
|
let options = regalloc2::RegallocOptions {
|
||||||
//regalloc2::run_with_ctx(&func, &env, &options, &mut ctx)
|
verbose_log: false,
|
||||||
// .unwrap_or_else(|err| panic!("{err}"));
|
validate_ssa: false,
|
||||||
//let now = std::time::Instant::now();
|
algorithm: regalloc2::Algorithm::Ion,
|
||||||
//for _ in 0..iters {
|
};
|
||||||
// regalloc2::run_with_ctx(&func, &env, &options, &mut ctx)
|
regalloc2::run_with_ctx(&func, &self.ralloc.env, &options, &mut self.ralloc.ctx)
|
||||||
// .unwrap_or_else(|err| panic!("{err}"));
|
.unwrap_or_else(|err| panic!("{err}"));
|
||||||
//}
|
|
||||||
//eprintln!("took: {:?}", now.elapsed().checked_div(iters).unwrap());
|
|
||||||
|
|
||||||
let now = std::time::Instant::now();
|
if self.ci.call_count != 0 {
|
||||||
for _ in 0..iters {
|
std::mem::swap(
|
||||||
regalloc2::run(&func, &env, &options).unwrap_or_else(|err| panic!("{err}"));
|
&mut self.ralloc.env.preferred_regs_by_class,
|
||||||
|
&mut self.ralloc.env.non_preferred_regs_by_class,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut saved_regs = HashMap::<u8, u8>::default();
|
||||||
|
let mut atr = |allc: regalloc2::Allocation| {
|
||||||
|
debug_assert!(allc.is_reg());
|
||||||
|
let hvenc = regalloc2::PReg::from_index(allc.index()).hw_enc() as u8;
|
||||||
|
if hvenc <= 12 {
|
||||||
|
return hvenc;
|
||||||
|
}
|
||||||
|
let would_insert = saved_regs.len() as u8 + reg::RET_ADDR + 1;
|
||||||
|
*saved_regs.entry(hvenc).or_insert(would_insert)
|
||||||
|
};
|
||||||
|
|
||||||
|
for (i, block) in func.blocks.iter().enumerate() {
|
||||||
|
let blk = regalloc2::Block(i as _);
|
||||||
|
func.nodes[block.nid].offset = self.ci.code.len() as _;
|
||||||
|
for instr_or_edit in self.ralloc.ctx.output.block_insts_and_edits(&func, blk) {
|
||||||
|
let inst = match instr_or_edit {
|
||||||
|
regalloc2::InstOrEdit::Inst(inst) => inst,
|
||||||
|
regalloc2::InstOrEdit::Edit(®alloc2::Edit::Move { from, to }) => {
|
||||||
|
self.ci.emit(instrs::cp(atr(to), atr(from)));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let nid = func.instrs[inst.index()].nid;
|
||||||
|
if nid == NEVER {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
let allocs = self.ralloc.ctx.output.inst_allocs(inst);
|
||||||
|
let node = &func.nodes[nid];
|
||||||
|
match node.kind {
|
||||||
|
Kind::If => {
|
||||||
|
let &[_, cond] = node.inputs.as_slice() else { unreachable!() };
|
||||||
|
if let Kind::BinOp { op } = func.nodes[cond].kind
|
||||||
|
&& let Some((op, swapped)) = op.cond_op(node.ty.is_signed())
|
||||||
|
{
|
||||||
|
let rel = Reloc::new(self.ci.code.len(), 3, 2);
|
||||||
|
self.ci.jump_relocs.push((node.outputs[!swapped as usize], rel));
|
||||||
|
let &[lhs, rhs] = allocs else { unreachable!() };
|
||||||
|
self.ci.emit(op(atr(lhs), atr(rhs), 0));
|
||||||
|
} else {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Kind::Loop | Kind::Region => {
|
||||||
|
if node.ralloc_backref as usize != i + 1 {
|
||||||
|
let rel = Reloc::new(self.ci.code.len(), 1, 4);
|
||||||
|
self.ci.jump_relocs.push((nid, rel));
|
||||||
|
self.ci.emit(instrs::jmp(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Kind::Return => {
|
||||||
|
if i != func.blocks.len() - 1 {
|
||||||
|
let rel = Reloc::new(self.ci.code.len(), 1, 4);
|
||||||
|
self.ci.ret_relocs.push(rel);
|
||||||
|
self.ci.emit(instrs::jmp(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Kind::CInt { value } => {
|
||||||
|
self.ci.emit(instrs::li64(atr(allocs[0]), value as _));
|
||||||
|
}
|
||||||
|
Kind::UnOp { op } => {
|
||||||
|
let op = op.unop().expect("TODO: unary operator not supported");
|
||||||
|
let &[dst, oper] = allocs else { unreachable!() };
|
||||||
|
self.ci.emit(op(atr(dst), atr(oper)));
|
||||||
|
}
|
||||||
|
Kind::BinOp { op } => {
|
||||||
|
let &[.., rhs] = node.inputs.as_slice() else { unreachable!() };
|
||||||
|
|
||||||
|
if let Kind::CInt { value } = func.nodes[rhs].kind
|
||||||
|
&& let Some(op) =
|
||||||
|
op.imm_binop(node.ty.is_signed(), func.tys.size_of(node.ty))
|
||||||
|
{
|
||||||
|
let &[dst, lhs] = allocs else { unreachable!() };
|
||||||
|
self.ci.emit(op(atr(dst), atr(lhs), value as _));
|
||||||
|
} else if let Some(op) =
|
||||||
|
op.binop(node.ty.is_signed(), func.tys.size_of(node.ty))
|
||||||
|
{
|
||||||
|
let &[dst, lhs, rhs] = allocs else { unreachable!() };
|
||||||
|
self.ci.emit(op(atr(dst), atr(lhs), atr(rhs)));
|
||||||
|
} else if op.cond_op(node.ty.is_signed()).is_some() {
|
||||||
|
} else {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Kind::Call { func } => {
|
||||||
|
self.ci.relocs.push(TypedReloc {
|
||||||
|
target: ty::Kind::Func(func).compress(),
|
||||||
|
reloc: Reloc::new(self.ci.code.len(), 3, 4),
|
||||||
|
});
|
||||||
|
self.ci.emit(instrs::jal(reg::RET_ADDR, reg::ZERO, 0));
|
||||||
|
}
|
||||||
|
Kind::Stck => todo!(),
|
||||||
|
Kind::Load => {
|
||||||
|
let mut region = node.inputs[1];
|
||||||
|
let mut offset = 0;
|
||||||
|
let size = self.tys.size_of(node.ty);
|
||||||
|
debug_assert_eq!(size, 8, "TODO");
|
||||||
|
let (base, offset) = loop {
|
||||||
|
match func.nodes[region].kind {
|
||||||
|
Kind::Stck => {
|
||||||
|
break (
|
||||||
|
reg::STACK_PTR,
|
||||||
|
self.ci.stack_size - func.nodes[region].offset + offset
|
||||||
|
- size,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Kind::Offset { offset: o } => {
|
||||||
|
offset = o;
|
||||||
|
region = func.nodes[region].inputs[1]
|
||||||
|
}
|
||||||
|
Kind::Stre => region = func.nodes[region].inputs[2],
|
||||||
|
k => unreachable!("{k:?}"),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
let &[dst] = allocs else { unreachable!() };
|
||||||
|
self.ci.emit(instrs::ld(atr(dst), base, offset as _, size as _));
|
||||||
|
}
|
||||||
|
Kind::Stre => {
|
||||||
|
let mut region = node.inputs[2];
|
||||||
|
let mut offset = 0;
|
||||||
|
let size = self.tys.size_of(node.ty);
|
||||||
|
debug_assert_eq!(size, 8, "TODO");
|
||||||
|
let (base, offset, src) = loop {
|
||||||
|
match func.nodes[region].kind {
|
||||||
|
Kind::Stck => {
|
||||||
|
break (
|
||||||
|
reg::STACK_PTR,
|
||||||
|
self.ci.stack_size - func.nodes[region].offset + offset
|
||||||
|
- size,
|
||||||
|
allocs[0],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Kind::Arg { .. } => {
|
||||||
|
break (atr(allocs[0]), 0, allocs[1]);
|
||||||
|
}
|
||||||
|
Kind::Offset { offset: o } => {
|
||||||
|
offset = o;
|
||||||
|
region = func.nodes[region].inputs[1]
|
||||||
|
}
|
||||||
|
Kind::Stre => region = func.nodes[region].inputs[2],
|
||||||
|
k => unreachable!("{k:?}"),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
self.ci.emit(instrs::st(atr(src), base, offset as _, size as _));
|
||||||
|
}
|
||||||
|
Kind::Offset { mut offset } => {
|
||||||
|
let mut region = node.inputs[1];
|
||||||
|
let size = self.tys.size_of(node.ty);
|
||||||
|
debug_assert_eq!(size, 8, "TODO");
|
||||||
|
let (base, offset) = loop {
|
||||||
|
match func.nodes[region].kind {
|
||||||
|
Kind::Stck => {
|
||||||
|
break (
|
||||||
|
reg::STACK_PTR,
|
||||||
|
self.ci.stack_size - func.nodes[region].offset + offset
|
||||||
|
- size,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Kind::Offset { offset: o } => {
|
||||||
|
offset = o;
|
||||||
|
region = func.nodes[region].inputs[1]
|
||||||
|
}
|
||||||
|
Kind::Stre => region = func.nodes[region].inputs[2],
|
||||||
|
k => unreachable!("{k:?}"),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
let &[dst] = allocs else { unreachable!() };
|
||||||
|
self.ci.emit(instrs::addi64(atr(dst), base, offset as _));
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
eprintln!("took: {:?}", now.elapsed().checked_div(iters).unwrap());
|
|
||||||
|
|
||||||
0
|
self.ci.nodes = nodes;
|
||||||
|
|
||||||
//let mut saved_regs = HashMap::<u8, u8>::default();
|
saved_regs.len()
|
||||||
//let mut atr = |allc: regalloc2::Allocation| {
|
|
||||||
// debug_assert!(allc.is_reg());
|
|
||||||
// let hvenc = regalloc2::PReg::from_index(allc.index()).hw_enc() as u8;
|
|
||||||
// if hvenc <= 12 {
|
|
||||||
// return hvenc;
|
|
||||||
// }
|
|
||||||
// let would_insert = saved_regs.len() as u8 + reg::RET_ADDR + 1;
|
|
||||||
// *saved_regs.entry(hvenc).or_insert(would_insert)
|
|
||||||
//};
|
|
||||||
|
|
||||||
//for (i, block) in func.blocks.iter().enumerate() {
|
|
||||||
// let blk = regalloc2::Block(i as _);
|
|
||||||
// func.nodes[block.nid].offset = self.ci.code.len() as _;
|
|
||||||
// for instr_or_edit in ctx.output.block_insts_and_edits(&func, blk) {
|
|
||||||
// let inst = match instr_or_edit {
|
|
||||||
// regalloc2::InstOrEdit::Inst(inst) => inst,
|
|
||||||
// regalloc2::InstOrEdit::Edit(®alloc2::Edit::Move { from, to }) => {
|
|
||||||
// self.ci.emit(instrs::cp(atr(to), atr(from)));
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
// let nid = func.instrs[inst.index()].nid;
|
|
||||||
// if nid == NEVER {
|
|
||||||
// continue;
|
|
||||||
// };
|
|
||||||
// let allocs = ctx.output.inst_allocs(inst);
|
|
||||||
// let node = &func.nodes[nid];
|
|
||||||
// match node.kind {
|
|
||||||
// Kind::If => {
|
|
||||||
// let &[_, cond] = node.inputs.as_slice() else { unreachable!() };
|
|
||||||
// if let Kind::BinOp { op } = func.nodes[cond].kind
|
|
||||||
// && let Some((op, swapped)) = op.cond_op(node.ty.is_signed())
|
|
||||||
// {
|
|
||||||
// let rel = Reloc::new(self.ci.code.len(), 3, 2);
|
|
||||||
// self.ci.jump_relocs.push((node.outputs[!swapped as usize], rel));
|
|
||||||
// let &[lhs, rhs] = allocs else { unreachable!() };
|
|
||||||
// self.ci.emit(op(atr(lhs), atr(rhs), 0));
|
|
||||||
// } else {
|
|
||||||
// todo!()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// Kind::Loop | Kind::Region => {
|
|
||||||
// if node.ralloc_backref as usize != i + 1 {
|
|
||||||
// let rel = Reloc::new(self.ci.code.len(), 1, 4);
|
|
||||||
// self.ci.jump_relocs.push((nid, rel));
|
|
||||||
// self.ci.emit(instrs::jmp(0));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// Kind::Return => {
|
|
||||||
// if i != func.blocks.len() - 1 {
|
|
||||||
// let rel = Reloc::new(self.ci.code.len(), 1, 4);
|
|
||||||
// self.ci.ret_relocs.push(rel);
|
|
||||||
// self.ci.emit(instrs::jmp(0));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// Kind::CInt { value } => {
|
|
||||||
// self.ci.emit(instrs::li64(atr(allocs[0]), value as _));
|
|
||||||
// }
|
|
||||||
// Kind::UnOp { op } => {
|
|
||||||
// let op = op.unop().expect("TODO: unary operator not supported");
|
|
||||||
// let &[dst, oper] = allocs else { unreachable!() };
|
|
||||||
// self.ci.emit(op(atr(dst), atr(oper)));
|
|
||||||
// }
|
|
||||||
// Kind::BinOp { op } => {
|
|
||||||
// let &[.., rhs] = node.inputs.as_slice() else { unreachable!() };
|
|
||||||
|
|
||||||
// if let Kind::CInt { value } = func.nodes[rhs].kind
|
|
||||||
// && let Some(op) =
|
|
||||||
// op.imm_binop(node.ty.is_signed(), func.tys.size_of(node.ty))
|
|
||||||
// {
|
|
||||||
// let &[dst, lhs] = allocs else { unreachable!() };
|
|
||||||
// self.ci.emit(op(atr(dst), atr(lhs), value as _));
|
|
||||||
// } else if let Some(op) =
|
|
||||||
// op.binop(node.ty.is_signed(), func.tys.size_of(node.ty))
|
|
||||||
// {
|
|
||||||
// let &[dst, lhs, rhs] = allocs else { unreachable!() };
|
|
||||||
// self.ci.emit(op(atr(dst), atr(lhs), atr(rhs)));
|
|
||||||
// } else if op.cond_op(node.ty.is_signed()).is_some() {
|
|
||||||
// } else {
|
|
||||||
// todo!()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// Kind::Call { func } => {
|
|
||||||
// self.ci.relocs.push(TypedReloc {
|
|
||||||
// target: ty::Kind::Func(func).compress(),
|
|
||||||
// reloc: Reloc::new(self.ci.code.len(), 3, 4),
|
|
||||||
// });
|
|
||||||
// self.ci.emit(instrs::jal(reg::RET_ADDR, reg::ZERO, 0));
|
|
||||||
// }
|
|
||||||
// Kind::Start | Kind::End | Kind::Phi | Kind::Arg { .. } | Kind::Ctrl { .. } => {
|
|
||||||
// unreachable!()
|
|
||||||
// }
|
|
||||||
// Kind::Stck { .. } => todo!(),
|
|
||||||
// Kind::Load { .. } => todo!(),
|
|
||||||
// Kind::Stre { .. } => todo!(),
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//self.ci.nodes = nodes;
|
|
||||||
|
|
||||||
//saved_regs.len()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: sometimes its better to do this in bulk
|
// TODO: sometimes its better to do this in bulk
|
||||||
fn ty(&mut self, expr: &Expr) -> ty::Id {
|
fn ty(&mut self, expr: &Expr) -> ty::Id {
|
||||||
match *expr {
|
match *expr {
|
||||||
|
Expr::UnOp { op: TokenKind::Xor, val, .. } => {
|
||||||
|
let base = self.ty(val);
|
||||||
|
self.tys.make_ptr(base)
|
||||||
|
}
|
||||||
Expr::Ident { id, .. } if ident::is_null(id) => id.into(),
|
Expr::Ident { id, .. } if ident::is_null(id) => id.into(),
|
||||||
ref e => {
|
ref e => {
|
||||||
self.report_unhandled_ast(e, "type");
|
self.report_unhandled_ast(e, "type");
|
||||||
|
@ -2287,9 +2513,7 @@ impl<'a> Function<'a> {
|
||||||
let node = self.nodes[nid].clone();
|
let node = self.nodes[nid].clone();
|
||||||
match node.kind {
|
match node.kind {
|
||||||
Kind::Start => {
|
Kind::Start => {
|
||||||
debug_assert_matches!(self.nodes[node.outputs[0]].kind, Kind::Ctrl {
|
debug_assert_matches!(self.nodes[node.outputs[0]].kind, Kind::Entry);
|
||||||
index: u32::MAX
|
|
||||||
});
|
|
||||||
self.emit_node(node.outputs[0], VOID)
|
self.emit_node(node.outputs[0], VOID)
|
||||||
}
|
}
|
||||||
Kind::End => {}
|
Kind::End => {}
|
||||||
|
@ -2360,12 +2584,12 @@ impl<'a> Function<'a> {
|
||||||
self.add_instr(nid, ops);
|
self.add_instr(nid, ops);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Kind::Ctrl { index: u32::MAX } => {
|
Kind::Entry => {
|
||||||
self.nodes[nid].ralloc_backref = self.add_block(nid);
|
self.nodes[nid].ralloc_backref = self.add_block(nid);
|
||||||
|
|
||||||
let mut parama = self.tys.parama(self.sig.ret);
|
let mut parama = self.tys.parama(self.sig.ret);
|
||||||
for (arg, ti) in
|
for (arg, ti) in
|
||||||
self.nodes[VOID].clone().outputs.into_iter().skip(1).zip(self.sig.args.range())
|
self.nodes[VOID].clone().outputs.into_iter().skip(2).zip(self.sig.args.range())
|
||||||
{
|
{
|
||||||
let ty = self.tys.args[ti];
|
let ty = self.tys.args[ti];
|
||||||
match self.tys.size_of(ty) {
|
match self.tys.size_of(ty) {
|
||||||
|
@ -2385,7 +2609,7 @@ impl<'a> Function<'a> {
|
||||||
self.emit_node(o, nid);
|
self.emit_node(o, nid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Kind::Ctrl { .. } => {
|
Kind::Then | Kind::Else => {
|
||||||
self.nodes[nid].ralloc_backref = self.add_block(nid);
|
self.nodes[nid].ralloc_backref = self.add_block(nid);
|
||||||
self.bridge(prev, nid);
|
self.bridge(prev, nid);
|
||||||
for o in node.outputs.into_iter().rev() {
|
for o in node.outputs.into_iter().rev() {
|
||||||
|
@ -2448,10 +2672,46 @@ impl<'a> Function<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Kind::Phi | Kind::Arg { .. } => {}
|
Kind::Offset { .. } => {
|
||||||
Kind::Stck { .. } => todo!(),
|
let mut region = node.inputs[1];
|
||||||
Kind::Load { .. } => todo!(),
|
let ops = loop {
|
||||||
Kind::Stre { .. } => todo!(),
|
match self.nodes[region].kind {
|
||||||
|
Kind::Stck => break vec![self.drg(nid)],
|
||||||
|
Kind::Offset { .. } => region = self.nodes[region].inputs[1],
|
||||||
|
Kind::Stre => region = self.nodes[region].inputs[2],
|
||||||
|
k => unreachable!("{k:?}"),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
self.add_instr(nid, ops);
|
||||||
|
}
|
||||||
|
Kind::Stck | Kind::Phi | Kind::Arg { .. } | Kind::Mem => {}
|
||||||
|
Kind::Load => {
|
||||||
|
let mut region = node.inputs[1];
|
||||||
|
let ops = loop {
|
||||||
|
match self.nodes[region].kind {
|
||||||
|
Kind::Stck => break vec![self.drg(nid)],
|
||||||
|
Kind::Offset { .. } => region = self.nodes[region].inputs[1],
|
||||||
|
Kind::Stre => region = self.nodes[region].inputs[2],
|
||||||
|
k => unreachable!("{k:?}"),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
self.add_instr(nid, ops);
|
||||||
|
}
|
||||||
|
Kind::Stre => {
|
||||||
|
let mut region = node.inputs[2];
|
||||||
|
let ops = loop {
|
||||||
|
match self.nodes[region].kind {
|
||||||
|
Kind::Stck => break vec![self.urg(node.inputs[1])],
|
||||||
|
Kind::Arg { .. } => break vec![self.urg(region), self.urg(node.inputs[1])],
|
||||||
|
Kind::Offset { .. } => region = self.nodes[region].inputs[1],
|
||||||
|
Kind::Stre => region = self.nodes[region].inputs[2],
|
||||||
|
k => unreachable!("{k:?}"),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
self.add_instr(nid, ops);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2506,7 +2766,7 @@ impl<'a> regalloc2::Function for Function<'a> {
|
||||||
fn is_branch(&self, insn: regalloc2::Inst) -> bool {
|
fn is_branch(&self, insn: regalloc2::Inst) -> bool {
|
||||||
matches!(
|
matches!(
|
||||||
self.nodes[self.instrs[insn.index()].nid].kind,
|
self.nodes[self.instrs[insn.index()].nid].kind,
|
||||||
Kind::If | Kind::Ctrl { .. } | Kind::Loop | Kind::Region
|
Kind::If | Kind::Then | Kind::Else | Kind::Entry | Kind::Loop | Kind::Region
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2531,7 +2791,7 @@ impl<'a> regalloc2::Function for Function<'a> {
|
||||||
fn inst_clobbers(&self, insn: regalloc2::Inst) -> regalloc2::PRegSet {
|
fn inst_clobbers(&self, insn: regalloc2::Inst) -> regalloc2::PRegSet {
|
||||||
if matches!(self.nodes[self.instrs[insn.index()].nid].kind, Kind::Call { .. }) {
|
if matches!(self.nodes[self.instrs[insn.index()].nid].kind, Kind::Call { .. }) {
|
||||||
let mut set = regalloc2::PRegSet::default();
|
let mut set = regalloc2::PRegSet::default();
|
||||||
for i in 2..12 {
|
for i in 2..13 {
|
||||||
set.add(regalloc2::PReg::new(i, regalloc2::RegClass::Int));
|
set.add(regalloc2::PReg::new(i, regalloc2::RegClass::Int));
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
|
@ -2559,13 +2819,17 @@ fn loop_depth(target: Nid, nodes: &mut Nodes) -> LoopDepth {
|
||||||
}
|
}
|
||||||
|
|
||||||
nodes[target].loop_depth = match nodes[target].kind {
|
nodes[target].loop_depth = match nodes[target].kind {
|
||||||
Kind::Ctrl { .. } | Kind::Call { .. } | Kind::Return | Kind::If => {
|
Kind::Entry | Kind::Then | Kind::Else | Kind::Call { .. } | Kind::Return | Kind::If => {
|
||||||
loop_depth(nodes[target].inputs[0], nodes)
|
let dpth = loop_depth(nodes[target].inputs[0], nodes);
|
||||||
|
if nodes[target].loop_depth != 0 {
|
||||||
|
return nodes[target].loop_depth;
|
||||||
|
}
|
||||||
|
dpth
|
||||||
}
|
}
|
||||||
Kind::Region => {
|
Kind::Region => {
|
||||||
let l = loop_depth(nodes[target].inputs[0], nodes);
|
let l = loop_depth(nodes[target].inputs[0], nodes);
|
||||||
let r = loop_depth(nodes[target].inputs[1], nodes);
|
let r = loop_depth(nodes[target].inputs[1], nodes);
|
||||||
debug_assert_eq!(r, l);
|
debug_assert_eq!(l, r);
|
||||||
l
|
l
|
||||||
}
|
}
|
||||||
Kind::Loop => {
|
Kind::Loop => {
|
||||||
|
@ -2581,11 +2845,11 @@ fn loop_depth(target: Nid, nodes: &mut Nodes) -> LoopDepth {
|
||||||
idom(nodes, cursor)
|
idom(nodes, cursor)
|
||||||
};
|
};
|
||||||
debug_assert_ne!(next, VOID);
|
debug_assert_ne!(next, VOID);
|
||||||
if let Kind::Ctrl { index: index @ ..=1 } = nodes[cursor].kind {
|
if matches!(nodes[cursor].kind, Kind::Then | Kind::Else) {
|
||||||
let other = *nodes[next]
|
let other = *nodes[next]
|
||||||
.outputs
|
.outputs
|
||||||
.iter()
|
.iter()
|
||||||
.find(|&&n| nodes[n].kind != Kind::Ctrl { index })
|
.find(|&&n| nodes[n].kind != nodes[cursor].kind)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
if nodes[other].loop_depth == 0 {
|
if nodes[other].loop_depth == 0 {
|
||||||
nodes[other].loop_depth = depth - 1;
|
nodes[other].loop_depth = depth - 1;
|
||||||
|
@ -2599,10 +2863,6 @@ fn loop_depth(target: Nid, nodes: &mut Nodes) -> LoopDepth {
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if target == 19 {
|
|
||||||
//panic!("{}", nodes[target].loop_depth);
|
|
||||||
}
|
|
||||||
|
|
||||||
nodes[target].loop_depth
|
nodes[target].loop_depth
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,54 +20,54 @@ continue_and_state_change:
|
||||||
ADDI64 r254, r254, 40d
|
ADDI64 r254, r254, 40d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -72d
|
ADDI64 r254, r254, -80d
|
||||||
ST r31, r254, 0a, 72h
|
ST r31, r254, 0a, 80h
|
||||||
LI64 r12, 0d
|
LI64 r32, 0d
|
||||||
CP r2, r12
|
CP r2, r32
|
||||||
JAL r31, r0, :multiple_breaks
|
JAL r31, r0, :multiple_breaks
|
||||||
CP r32, r12
|
CP r33, r32
|
||||||
CP r33, r1
|
CP r34, r1
|
||||||
LI64 r1, 3d
|
LI64 r1, 3d
|
||||||
JEQ r33, r1, :0
|
JEQ r34, r1, :0
|
||||||
LI64 r1, 1d
|
LI64 r1, 1d
|
||||||
JMP :1
|
JMP :1
|
||||||
0: CP r34, r1
|
0: CP r35, r1
|
||||||
LI64 r35, 4d
|
LI64 r36, 4d
|
||||||
CP r2, r35
|
CP r2, r36
|
||||||
JAL r31, r0, :multiple_breaks
|
JAL r31, r0, :multiple_breaks
|
||||||
CP r36, r35
|
CP r37, r36
|
||||||
LI64 r37, 10d
|
LI64 r38, 10d
|
||||||
JEQ r1, r37, :2
|
JEQ r1, r38, :2
|
||||||
LI64 r1, 2d
|
LI64 r1, 2d
|
||||||
JMP :1
|
JMP :1
|
||||||
2: CP r2, r32
|
2: CP r2, r33
|
||||||
JAL r31, r0, :state_change_in_break
|
JAL r31, r0, :state_change_in_break
|
||||||
CP r38, r1
|
CP r39, r1
|
||||||
CP r1, r32
|
CP r1, r33
|
||||||
JEQ r38, r1, :3
|
JEQ r39, r1, :3
|
||||||
CP r1, r34
|
CP r1, r35
|
||||||
JMP :1
|
JMP :1
|
||||||
3: CP r32, r1
|
3: CP r33, r1
|
||||||
CP r2, r36
|
CP r2, r37
|
||||||
JAL r31, r0, :state_change_in_break
|
JAL r31, r0, :state_change_in_break
|
||||||
JEQ r1, r37, :4
|
JEQ r1, r38, :4
|
||||||
CP r1, r36
|
CP r1, r37
|
||||||
JMP :1
|
JMP :1
|
||||||
4: CP r2, r37
|
4: CP r2, r38
|
||||||
JAL r31, r0, :continue_and_state_change
|
JAL r31, r0, :continue_and_state_change
|
||||||
JEQ r1, r37, :5
|
JEQ r1, r38, :5
|
||||||
LI64 r1, 5d
|
LI64 r1, 5d
|
||||||
JMP :1
|
JMP :1
|
||||||
5: CP r2, r34
|
5: CP r2, r35
|
||||||
JAL r31, r0, :continue_and_state_change
|
JAL r31, r0, :continue_and_state_change
|
||||||
CP r39, r1
|
CP r40, r1
|
||||||
CP r1, r32
|
CP r1, r33
|
||||||
JEQ r39, r1, :6
|
JEQ r40, r1, :6
|
||||||
LI64 r1, 6d
|
LI64 r1, 6d
|
||||||
JMP :1
|
JMP :1
|
||||||
6: CP r1, r32
|
6: CP r1, r33
|
||||||
1: LD r31, r254, 0a, 72h
|
1: LD r31, r254, 0a, 80h
|
||||||
ADDI64 r254, r254, 72d
|
ADDI64 r254, r254, 80d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
multiple_breaks:
|
multiple_breaks:
|
||||||
ADDI64 r254, r254, -24d
|
ADDI64 r254, r254, -24d
|
||||||
|
|
31
hblang/tests/son_tests_pointers.txt
Normal file
31
hblang/tests/son_tests_pointers.txt
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
drop:
|
||||||
|
ADDI64 r254, r254, -8d
|
||||||
|
ST r31, r254, 0a, 8h
|
||||||
|
LD r31, r254, 0a, 8h
|
||||||
|
ADDI64 r254, r254, 8d
|
||||||
|
JALA r0, r31, 0a
|
||||||
|
main:
|
||||||
|
ADDI64 r254, r254, -32d
|
||||||
|
ST r31, r254, 8a, 24h
|
||||||
|
LI64 r32, 1d
|
||||||
|
ST r32, r254, 0a, 8h
|
||||||
|
ADDI64 r2, r254, 0d
|
||||||
|
JAL r31, r0, :modify
|
||||||
|
CP r2, r32
|
||||||
|
JAL r31, r0, :drop
|
||||||
|
LD r33, r254, 0a, 8h
|
||||||
|
ADDI64 r1, r33, -2d
|
||||||
|
LD r31, r254, 8a, 24h
|
||||||
|
ADDI64 r254, r254, 32d
|
||||||
|
JALA r0, r31, 0a
|
||||||
|
modify:
|
||||||
|
ADDI64 r254, r254, -16d
|
||||||
|
ST r31, r254, 0a, 16h
|
||||||
|
LI64 r32, 2d
|
||||||
|
ST r32, r2, 0a, 8h
|
||||||
|
LD r31, r254, 0a, 16h
|
||||||
|
ADDI64 r254, r254, 16d
|
||||||
|
JALA r0, r31, 0a
|
||||||
|
code size: 283
|
||||||
|
ret: 0
|
||||||
|
status: Ok(())
|
|
@ -1,11 +0,0 @@
|
||||||
foo := 0;
|
|
||||||
|
|
||||||
.{global, fib, Structa, create_window, WindowID} := @use("pkg.hb")
|
|
||||||
|
|
||||||
main := fn(a: int): int {
|
|
||||||
g := global
|
|
||||||
|
|
||||||
win := create_window()
|
|
||||||
|
|
||||||
return fib(g + Structa.(0, 0).foo)
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
global := 10
|
|
||||||
|
|
||||||
Structa := struct {
|
|
||||||
foo: int,
|
|
||||||
goo: int,
|
|
||||||
}
|
|
||||||
|
|
||||||
create_window := fn(): WindowID {
|
|
||||||
return WindowID.(1, 2)
|
|
||||||
}
|
|
||||||
|
|
||||||
WindowID := struct {
|
|
||||||
host_id: int,
|
|
||||||
window_id: int,
|
|
||||||
}
|
|
||||||
|
|
||||||
fib := fn(n: int): int {
|
|
||||||
return n + 1
|
|
||||||
}
|
|
Loading…
Reference in a new issue