adding packed structs
This commit is contained in:
parent
338e3f1519
commit
602249a48a
91
Cargo.lock
generated
91
Cargo.lock
generated
|
@ -2,6 +2,18 @@
|
|||
# It is not intended for manual editing.
|
||||
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]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.3"
|
||||
|
@ -60,6 +72,12 @@ dependencies = [
|
|||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.2"
|
||||
|
@ -94,6 +112,9 @@ name = "hashbrown"
|
|||
version = "0.14.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hbbytecode"
|
||||
|
@ -167,10 +188,35 @@ dependencies = [
|
|||
"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]]
|
||||
name = "regalloc2"
|
||||
version = "0.10.2"
|
||||
source = "git+https://github.com/jakubDoka/regalloc2?branch=reuse-allocations#c1c7614b3a06d38113feaac11b4e4c9ab9e8f0c8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12908dbeb234370af84d0579b9f68258a0f67e201412dd9a2814e6f45b2fc0f0"
|
||||
dependencies = [
|
||||
"hashbrown",
|
||||
"log",
|
||||
|
@ -226,12 +272,35 @@ version = "1.13.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
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]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.52.0"
|
||||
|
@ -308,3 +377,23 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
|||
[[package]]
|
||||
name = "xtask"
|
||||
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",
|
||||
]
|
||||
|
|
|
@ -3,7 +3,6 @@ resolver = "2"
|
|||
members = ["hbbytecode", "hbvm", "hbxrt", "xtask", "hblang", "hbjit"]
|
||||
|
||||
[profile.release]
|
||||
strip = true
|
||||
lto = true
|
||||
codegen-units = 1
|
||||
panic = "abort"
|
||||
|
|
|
@ -10,7 +10,8 @@ path = "src/main.rs"
|
|||
[dependencies]
|
||||
hbbytecode = { version = "0.1.0", path = "../hbbytecode" }
|
||||
hbvm = { path = "../hbvm", features = ["nightly"] }
|
||||
regalloc2 = { git = "https://github.com/jakubDoka/regalloc2", branch = "reuse-allocations", features = ["trace-log"] }
|
||||
regalloc2 = "0.10.2"
|
||||
#regalloc2 = { path = "../../regalloc2/" }#git = "https://github.com/jakubDoka/regalloc2", branch = "reuse-allocations", features = [] }
|
||||
|
||||
[dev-dependencies]
|
||||
env_logger = "0.11.5"
|
||||
|
|
220
hblang/README.md
220
hblang/README.md
|
@ -162,6 +162,10 @@ Ty2 := struct {
|
|||
}
|
||||
|
||||
main := fn(): int {
|
||||
if @sizeof(packed struct {a: u8, b: u16}) != 3 {
|
||||
return 9001
|
||||
}
|
||||
|
||||
finst := Ty2.{ty: Ty.{a: 4, b: 1}, c: 3}
|
||||
inst := odher_pass(finst)
|
||||
if inst.c == 3 {
|
||||
|
@ -505,11 +509,223 @@ main := fn(): int {
|
|||
}
|
||||
}
|
||||
|
||||
//width += 1
|
||||
width += 1
|
||||
|
||||
loop {
|
||||
if width < y break
|
||||
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
|
||||
|
|
|
@ -719,13 +719,17 @@ impl Codegen {
|
|||
self.expr_ctx(expr, Ctx::default())
|
||||
}
|
||||
|
||||
fn build_struct(&mut self, fields: &[CommentOr<StructField>]) -> ty::Struct {
|
||||
fn build_struct(
|
||||
&mut self,
|
||||
explicit_alignment: Option<u32>,
|
||||
fields: &[CommentOr<StructField>],
|
||||
) -> ty::Struct {
|
||||
let fields = fields
|
||||
.iter()
|
||||
.filter_map(CommentOr::or)
|
||||
.map(|sf| Field { name: sf.name.into(), ty: self.ty(&sf.ty) })
|
||||
.collect();
|
||||
self.tys.structs.push(Struct { fields });
|
||||
self.tys.structs.push(Struct { fields, explicit_alignment });
|
||||
self.tys.structs.len() as u32 - 1
|
||||
}
|
||||
|
||||
|
@ -733,9 +737,11 @@ impl Codegen {
|
|||
use {Expr as E, TokenKind as T};
|
||||
let value = match *expr {
|
||||
E::Mod { id, .. } => Some(Value::ty(ty::Kind::Module(id).compress())),
|
||||
E::Struct { fields, captured, .. } => {
|
||||
E::Struct { fields, captured, packed, .. } => {
|
||||
if captured.is_empty() {
|
||||
Some(Value::ty(ty::Kind::Struct(self.build_struct(fields)).compress()))
|
||||
Some(Value::ty(
|
||||
ty::Kind::Struct(self.build_struct(packed.then_some(1), fields)).compress(),
|
||||
))
|
||||
} else {
|
||||
let values = captured
|
||||
.iter()
|
||||
|
@ -1940,7 +1946,12 @@ impl Codegen {
|
|||
.unwrap_or_else(|| Loc::stack(self.ci.stack.allocate(self.tys.size_of(ty))));
|
||||
let mut offset = 0;
|
||||
for &Field { ty, .. } in self.tys.structs[stuct as usize].fields.clone().iter() {
|
||||
offset = Types::align_up(offset, self.tys.align_of(ty));
|
||||
offset = Types::align_up(
|
||||
offset,
|
||||
self.tys.structs[stuct as usize]
|
||||
.explicit_alignment
|
||||
.unwrap_or(self.tys.align_of(ty)),
|
||||
);
|
||||
let size = self.tys.size_of(ty);
|
||||
let ctx = Ctx::from(Value { ty, loc: loc.as_ref().offset(offset) });
|
||||
let left = left.as_ref().offset(offset);
|
||||
|
@ -2329,7 +2340,8 @@ impl Codegen {
|
|||
match *trap {
|
||||
trap::Trap::MakeStruct(trap::MakeStruct { file, struct_expr }) => {
|
||||
let cfile = self.files[file as usize].clone();
|
||||
let &Expr::Struct { fields, captured, .. } = struct_expr.get(&cfile).unwrap()
|
||||
let &Expr::Struct { fields, captured, packed, .. } =
|
||||
struct_expr.get(&cfile).unwrap()
|
||||
else {
|
||||
unreachable!()
|
||||
};
|
||||
|
@ -2350,7 +2362,8 @@ impl Codegen {
|
|||
});
|
||||
}
|
||||
|
||||
let stru = ty::Kind::Struct(self.build_struct(fields)).compress();
|
||||
let stru =
|
||||
ty::Kind::Struct(self.build_struct(packed.then_some(1), fields)).compress();
|
||||
self.ci.vars.truncate(prev_len);
|
||||
self.ct.vm.write_reg(1, stru.repr() as u64);
|
||||
debug_assert_ne!(stru.expand().inner(), 1);
|
||||
|
@ -2443,8 +2456,8 @@ impl Codegen {
|
|||
Expr::BinOp {
|
||||
left: &Expr::Ident { .. },
|
||||
op: TokenKind::Decl,
|
||||
right: Expr::Struct { fields, .. },
|
||||
} => ty::Kind::Struct(self.build_struct(fields)),
|
||||
right: Expr::Struct { fields, packed, .. },
|
||||
} => ty::Kind::Struct(self.build_struct(packed.then_some(1), fields)),
|
||||
Expr::BinOp { left, op: TokenKind::Decl, right } => {
|
||||
let gid = self.tys.globals.len() as ty::Global;
|
||||
self.tys.globals.push(Global { file, name: ident, ..Default::default() });
|
||||
|
|
|
@ -129,6 +129,7 @@ pub enum TokenKind {
|
|||
Continue,
|
||||
Fn,
|
||||
Struct,
|
||||
Packed,
|
||||
True,
|
||||
False,
|
||||
Idk,
|
||||
|
@ -314,6 +315,7 @@ gen_token_kind! {
|
|||
Continue = b"continue",
|
||||
Fn = b"fn",
|
||||
Struct = b"struct",
|
||||
Packed = b"packed",
|
||||
True = b"true",
|
||||
False = b"false",
|
||||
Idk = b"idk",
|
||||
|
|
|
@ -582,6 +582,7 @@ struct Field {
|
|||
}
|
||||
|
||||
struct Struct {
|
||||
explicit_alignment: Option<u32>,
|
||||
fields: Rc<[Field]>,
|
||||
}
|
||||
|
||||
|
@ -762,7 +763,7 @@ impl Types {
|
|||
let until = record.fields.iter().position(|f| f.name.as_ref() == field)?;
|
||||
let mut offset = 0;
|
||||
for &Field { ty, .. } in &record.fields[..until] {
|
||||
offset = Self::align_up(offset, self.align_of(ty));
|
||||
offset = Self::align_up(offset, record.explicit_alignment.unwrap_or(self.align_of(ty)));
|
||||
offset += self.size_of(ty);
|
||||
}
|
||||
Some((offset, record.fields[until].ty))
|
||||
|
@ -833,7 +834,7 @@ impl Types {
|
|||
let mut offset = 0u32;
|
||||
let record = &self.structs[stru as usize];
|
||||
for &Field { ty, .. } in record.fields.iter() {
|
||||
let align = self.align_of(ty);
|
||||
let align = record.explicit_alignment.unwrap_or(self.align_of(ty));
|
||||
offset = Self::align_up(offset, align);
|
||||
offset += self.size_of(ty);
|
||||
}
|
||||
|
@ -845,12 +846,16 @@ impl Types {
|
|||
|
||||
fn align_of(&self, ty: ty::Id) -> Size {
|
||||
match ty.expand() {
|
||||
ty::Kind::Struct(stru) => self.structs[stru as usize]
|
||||
ty::Kind::Struct(stru) => {
|
||||
self.structs[stru as usize].explicit_alignment.unwrap_or_else(|| {
|
||||
self.structs[stru as usize]
|
||||
.fields
|
||||
.iter()
|
||||
.map(|&Field { ty, .. }| self.align_of(ty))
|
||||
.max()
|
||||
.unwrap(),
|
||||
.unwrap()
|
||||
})
|
||||
}
|
||||
ty::Kind::Slice(arr) => {
|
||||
let arr = &self.arrays[arr as usize];
|
||||
match arr.len {
|
||||
|
|
|
@ -64,6 +64,7 @@ pub struct Parser<'a, 'b> {
|
|||
symbols: &'b mut Symbols,
|
||||
ns_bound: usize,
|
||||
trailing_sep: bool,
|
||||
packed: bool,
|
||||
idents: Vec<ScopeIdent>,
|
||||
captured: Vec<Ident>,
|
||||
}
|
||||
|
@ -80,6 +81,7 @@ impl<'a, 'b> Parser<'a, 'b> {
|
|||
symbols,
|
||||
ns_bound: 0,
|
||||
trailing_sep: false,
|
||||
packed: false,
|
||||
idents: Vec::new(),
|
||||
captured: Vec::new(),
|
||||
}
|
||||
|
@ -286,7 +288,20 @@ impl<'a, 'b> Parser<'a, 'b> {
|
|||
T::False => E::Bool { pos, value: false },
|
||||
T::Idk => E::Idk { pos },
|
||||
T::DQuote => E::String { pos, literal: self.move_str(token) },
|
||||
T::Packed => {
|
||||
self.packed = true;
|
||||
let expr = self.unit_expr();
|
||||
if self.packed {
|
||||
self.report(
|
||||
expr.pos(),
|
||||
"this can not be packed \
|
||||
(unlike your mom that gets packed every day by me)",
|
||||
);
|
||||
}
|
||||
expr
|
||||
}
|
||||
T::Struct => E::Struct {
|
||||
packed: std::mem::take(&mut self.packed),
|
||||
fields: {
|
||||
self.ns_bound = self.idents.len();
|
||||
self.expect_advance(T::LBrace);
|
||||
|
@ -746,6 +761,7 @@ generate_expr! {
|
|||
fields: &'a [CommentOr<'a, StructField<'a>>],
|
||||
captured: &'a [Ident],
|
||||
trailing_comma: bool,
|
||||
packed: bool,
|
||||
},
|
||||
/// `[Expr] LIST('.{', ',', '}', Ident [':' Expr])`
|
||||
Ctor {
|
||||
|
@ -1032,7 +1048,11 @@ impl<'a> fmt::Display for Expr<'a> {
|
|||
write!(f, "@{name}(")?;
|
||||
fmt_list(f, false, ")", ",", args, fmt::Display::fmt)
|
||||
}
|
||||
Self::Struct { fields, trailing_comma, .. } => {
|
||||
Self::Struct { fields, trailing_comma, packed, .. } => {
|
||||
if packed {
|
||||
write!(f, "packed ")?;
|
||||
}
|
||||
|
||||
write!(f, "struct {{")?;
|
||||
fmt_list_low(f, trailing_comma, "}", ",", fields, |field, f| {
|
||||
match field {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
use {
|
||||
crate::{
|
||||
ident::{self, Ident},
|
||||
instrs::{self},
|
||||
instrs,
|
||||
lexer::{self, TokenKind},
|
||||
log,
|
||||
parser::{
|
||||
|
@ -12,7 +12,7 @@ use {
|
|||
},
|
||||
task,
|
||||
ty::{self},
|
||||
Field, Func, HashMap, Offset, Reloc, Sig, Size, Struct, SymKey, TypedReloc, Types,
|
||||
Field, Func, Offset, Reloc, Sig, Size, Struct, SymKey, TypedReloc, Types,
|
||||
},
|
||||
core::fmt,
|
||||
regalloc2::VReg,
|
||||
|
@ -1251,13 +1251,17 @@ impl Codegen {
|
|||
self.expr_ctx(expr, Ctx::default())
|
||||
}
|
||||
|
||||
fn build_struct(&mut self, fields: &[CommentOr<StructField>]) -> ty::Struct {
|
||||
fn build_struct(
|
||||
&mut self,
|
||||
explicit_alignment: Option<u32>,
|
||||
fields: &[CommentOr<StructField>],
|
||||
) -> ty::Struct {
|
||||
let fields = fields
|
||||
.iter()
|
||||
.filter_map(CommentOr::or)
|
||||
.map(|sf| Field { name: sf.name.into(), ty: self.ty(&sf.ty) })
|
||||
.collect();
|
||||
self.tys.structs.push(Struct { fields });
|
||||
self.tys.structs.push(Struct { fields, explicit_alignment });
|
||||
self.tys.structs.len() as u32 - 1
|
||||
}
|
||||
|
||||
|
@ -1315,7 +1319,7 @@ impl Codegen {
|
|||
let inps = [VOID, lhs, rhs];
|
||||
Some(self.ci.nodes.new_node(ty::bin_ret(ty, op), Kind::BinOp { op }, inps))
|
||||
}
|
||||
Expr::UnOp { pos, op: TokenKind::Band, val } => {
|
||||
Expr::UnOp { pos: _, op: TokenKind::Band, val: _ } => {
|
||||
todo!()
|
||||
}
|
||||
Expr::UnOp { pos, op, val } => {
|
||||
|
@ -1466,6 +1470,11 @@ impl Codegen {
|
|||
self.ci.nodes.modify_input(scope_var.value, 2, loop_var.value);
|
||||
self.ci.nodes.lock(scope_var.value);
|
||||
} else {
|
||||
if dest_var.value == scope_var.value {
|
||||
self.ci.nodes.unlock(dest_var.value);
|
||||
dest_var.value = VOID;
|
||||
self.ci.nodes.lock(dest_var.value);
|
||||
}
|
||||
let phi = &self.ci.nodes[scope_var.value];
|
||||
debug_assert_eq!(phi.kind, Kind::Phi);
|
||||
debug_assert_eq!(phi.inputs[2], VOID);
|
||||
|
@ -1482,6 +1491,11 @@ impl Codegen {
|
|||
self.ci.nodes.lock(dest_var.value);
|
||||
}
|
||||
|
||||
debug_assert!(
|
||||
self.ci.nodes[dest_var.value].kind != Kind::Phi
|
||||
|| self.ci.nodes[dest_var.value].inputs[2] != 0
|
||||
);
|
||||
|
||||
self.ci.nodes.unlock_remove(scope_var.value);
|
||||
}
|
||||
|
||||
|
@ -1748,7 +1762,7 @@ impl Codegen {
|
|||
self.ci.emit(instrs::st(reg::RET_ADDR, reg::STACK_PTR, 0, 0));
|
||||
}
|
||||
|
||||
self.ci.nodes.basic_blocks();
|
||||
//self.ci.nodes.basic_blocks();
|
||||
//self.ci.nodes.graphviz();
|
||||
|
||||
self.ci.vars = orig_vars;
|
||||
|
@ -1799,15 +1813,14 @@ impl Codegen {
|
|||
let mut nodes = std::mem::take(&mut self.ci.nodes);
|
||||
|
||||
let func = Function::new(&mut nodes, &self.tys, sig);
|
||||
dbg!(&func);
|
||||
let mut env = regalloc2::MachineEnv {
|
||||
preferred_regs_by_class: [
|
||||
(1..12).map(|i| regalloc2::PReg::new(i, regalloc2::RegClass::Int)).collect(),
|
||||
(1..5).map(|i| regalloc2::PReg::new(i, regalloc2::RegClass::Int)).collect(),
|
||||
vec![],
|
||||
vec![],
|
||||
],
|
||||
non_preferred_regs_by_class: [
|
||||
(12..64).map(|i| regalloc2::PReg::new(i, regalloc2::RegClass::Int)).collect(),
|
||||
(12..16).map(|i| regalloc2::PReg::new(i, regalloc2::RegClass::Int)).collect(),
|
||||
vec![],
|
||||
vec![],
|
||||
],
|
||||
|
@ -1817,131 +1830,131 @@ impl Codegen {
|
|||
if self.ci.call_count != 0 {
|
||||
std::mem::swap(&mut env.preferred_regs_by_class, &mut env.non_preferred_regs_by_class);
|
||||
};
|
||||
let options = regalloc2::RegallocOptions { verbose_log: false, validate_ssa: true };
|
||||
let iters = std::time::SystemTime::now()
|
||||
.duration_since(std::time::SystemTime::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_nanos() as u32
|
||||
% 300
|
||||
+ 300;
|
||||
let mut output =
|
||||
regalloc2::run(&func, &env, &options).unwrap_or_else(|err| panic!("{err}"));
|
||||
let options = regalloc2::RegallocOptions { verbose_log: false, validate_ssa: false };
|
||||
let iters = std::hint::black_box(10000);
|
||||
|
||||
//let mut ctx = regalloc2::Ctx::default();
|
||||
//regalloc2::run_with_ctx(&func, &env, &options, &mut ctx)
|
||||
// .unwrap_or_else(|err| panic!("{err}"));
|
||||
//let now = std::time::Instant::now();
|
||||
//for _ in 0..iters {
|
||||
// regalloc2::run_with_ctx(&func, &env, &options, &mut ctx)
|
||||
// .unwrap_or_else(|err| panic!("{err}"));
|
||||
//}
|
||||
//eprintln!("took: {:?}", now.elapsed().checked_div(iters).unwrap());
|
||||
|
||||
let now = std::time::Instant::now();
|
||||
for i in 0..iters {
|
||||
output = regalloc2::run(&func, &env, &options).unwrap_or_else(|err| panic!("{err}"));
|
||||
if (iters + i) % 2 == 0 {
|
||||
std::mem::swap(
|
||||
&mut env.preferred_regs_by_class,
|
||||
&mut env.non_preferred_regs_by_class,
|
||||
);
|
||||
}
|
||||
for _ in 0..iters {
|
||||
regalloc2::run(&func, &env, &options).unwrap_or_else(|err| panic!("{err}"));
|
||||
}
|
||||
eprintln!("took: {:?}", now.elapsed().checked_div(iters).unwrap());
|
||||
|
||||
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)
|
||||
};
|
||||
0
|
||||
|
||||
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 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 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)
|
||||
//};
|
||||
|
||||
let nid = func.instrs[inst.index()].nid;
|
||||
if nid == NEVER {
|
||||
continue;
|
||||
};
|
||||
let allocs = 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!() };
|
||||
//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;
|
||||
// }
|
||||
// };
|
||||
|
||||
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!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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!() };
|
||||
|
||||
self.ci.nodes = nodes;
|
||||
// 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!(),
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
saved_regs.len()
|
||||
//self.ci.nodes = nodes;
|
||||
|
||||
//saved_regs.len()
|
||||
}
|
||||
|
||||
// TODO: sometimes its better to do this in bulk
|
||||
|
@ -2042,7 +2055,7 @@ impl Codegen {
|
|||
left: &Expr::Ident { .. },
|
||||
op: TokenKind::Decl,
|
||||
right: Expr::Struct { fields, .. },
|
||||
} => ty::Kind::Struct(self.build_struct(fields)),
|
||||
} => ty::Kind::Struct(self.build_struct(None, fields)),
|
||||
Expr::BinOp { .. } => {
|
||||
todo!()
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue