adding packed structs

This commit is contained in:
mlokr 2024-09-22 18:17:30 +02:00
parent 338e3f1519
commit 602249a48a
No known key found for this signature in database
GPG key ID: DEA147DDEE644993
9 changed files with 508 additions and 150 deletions

91
Cargo.lock generated
View file

@ -2,6 +2,18 @@
# 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"
@ -60,6 +72,12 @@ dependencies = [
"windows-sys", "windows-sys",
] ]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "colorchoice" name = "colorchoice"
version = "1.0.2" version = "1.0.2"
@ -94,6 +112,9 @@ 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"
@ -167,10 +188,35 @@ 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 = "git+https://github.com/jakubDoka/regalloc2?branch=reuse-allocations#c1c7614b3a06d38113feaac11b4e4c9ab9e8f0c8" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12908dbeb234370af84d0579b9f68258a0f67e201412dd9a2814e6f45b2fc0f0"
dependencies = [ dependencies = [
"hashbrown", "hashbrown",
"log", "log",
@ -226,12 +272,35 @@ 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"
@ -308,3 +377,23 @@ 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",
]

View file

@ -3,7 +3,6 @@ resolver = "2"
members = ["hbbytecode", "hbvm", "hbxrt", "xtask", "hblang", "hbjit"] members = ["hbbytecode", "hbvm", "hbxrt", "xtask", "hblang", "hbjit"]
[profile.release] [profile.release]
strip = true
lto = true lto = true
codegen-units = 1 codegen-units = 1
panic = "abort" panic = "abort"

View file

@ -10,7 +10,8 @@ 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 = { 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] [dev-dependencies]
env_logger = "0.11.5" env_logger = "0.11.5"

View file

@ -162,6 +162,10 @@ Ty2 := struct {
} }
main := fn(): int { main := fn(): int {
if @sizeof(packed struct {a: u8, b: u16}) != 3 {
return 9001
}
finst := Ty2.{ty: Ty.{a: 4, b: 1}, c: 3} finst := Ty2.{ty: Ty.{a: 4, b: 1}, c: 3}
inst := odher_pass(finst) inst := odher_pass(finst)
if inst.c == 3 { if inst.c == 3 {
@ -505,11 +509,223 @@ main := fn(): int {
} }
} }
//width += 1 width += 1
loop { loop {
if width < y break if x < height {
//t += set_pixel(x, y, height)
x += 1
i += 1
} else {
x = 0
y += 1 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

View file

@ -719,13 +719,17 @@ impl Codegen {
self.expr_ctx(expr, Ctx::default()) 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 let fields = fields
.iter() .iter()
.filter_map(CommentOr::or) .filter_map(CommentOr::or)
.map(|sf| Field { name: sf.name.into(), ty: self.ty(&sf.ty) }) .map(|sf| Field { name: sf.name.into(), ty: self.ty(&sf.ty) })
.collect(); .collect();
self.tys.structs.push(Struct { fields }); self.tys.structs.push(Struct { fields, explicit_alignment });
self.tys.structs.len() as u32 - 1 self.tys.structs.len() as u32 - 1
} }
@ -733,9 +737,11 @@ impl Codegen {
use {Expr as E, TokenKind as T}; use {Expr as E, TokenKind as T};
let value = match *expr { let value = match *expr {
E::Mod { id, .. } => Some(Value::ty(ty::Kind::Module(id).compress())), E::Mod { id, .. } => Some(Value::ty(ty::Kind::Module(id).compress())),
E::Struct { fields, captured, .. } => { E::Struct { fields, captured, packed, .. } => {
if captured.is_empty() { 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 { } else {
let values = captured let values = captured
.iter() .iter()
@ -1940,7 +1946,12 @@ impl Codegen {
.unwrap_or_else(|| Loc::stack(self.ci.stack.allocate(self.tys.size_of(ty)))); .unwrap_or_else(|| Loc::stack(self.ci.stack.allocate(self.tys.size_of(ty))));
let mut offset = 0; let mut offset = 0;
for &Field { ty, .. } in self.tys.structs[stuct as usize].fields.clone().iter() { 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 size = self.tys.size_of(ty);
let ctx = Ctx::from(Value { ty, loc: loc.as_ref().offset(offset) }); let ctx = Ctx::from(Value { ty, loc: loc.as_ref().offset(offset) });
let left = left.as_ref().offset(offset); let left = left.as_ref().offset(offset);
@ -2329,7 +2340,8 @@ impl Codegen {
match *trap { match *trap {
trap::Trap::MakeStruct(trap::MakeStruct { file, struct_expr }) => { trap::Trap::MakeStruct(trap::MakeStruct { file, struct_expr }) => {
let cfile = self.files[file as usize].clone(); 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 { else {
unreachable!() 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.ci.vars.truncate(prev_len);
self.ct.vm.write_reg(1, stru.repr() as u64); self.ct.vm.write_reg(1, stru.repr() as u64);
debug_assert_ne!(stru.expand().inner(), 1); debug_assert_ne!(stru.expand().inner(), 1);
@ -2443,8 +2456,8 @@ impl Codegen {
Expr::BinOp { Expr::BinOp {
left: &Expr::Ident { .. }, left: &Expr::Ident { .. },
op: TokenKind::Decl, op: TokenKind::Decl,
right: Expr::Struct { fields, .. }, right: Expr::Struct { fields, packed, .. },
} => ty::Kind::Struct(self.build_struct(fields)), } => ty::Kind::Struct(self.build_struct(packed.then_some(1), fields)),
Expr::BinOp { left, op: TokenKind::Decl, right } => { Expr::BinOp { left, op: TokenKind::Decl, right } => {
let gid = self.tys.globals.len() as ty::Global; let gid = self.tys.globals.len() as ty::Global;
self.tys.globals.push(Global { file, name: ident, ..Default::default() }); self.tys.globals.push(Global { file, name: ident, ..Default::default() });

View file

@ -129,6 +129,7 @@ pub enum TokenKind {
Continue, Continue,
Fn, Fn,
Struct, Struct,
Packed,
True, True,
False, False,
Idk, Idk,
@ -314,6 +315,7 @@ gen_token_kind! {
Continue = b"continue", Continue = b"continue",
Fn = b"fn", Fn = b"fn",
Struct = b"struct", Struct = b"struct",
Packed = b"packed",
True = b"true", True = b"true",
False = b"false", False = b"false",
Idk = b"idk", Idk = b"idk",

View file

@ -582,6 +582,7 @@ struct Field {
} }
struct Struct { struct Struct {
explicit_alignment: Option<u32>,
fields: Rc<[Field]>, fields: Rc<[Field]>,
} }
@ -762,7 +763,7 @@ impl Types {
let until = record.fields.iter().position(|f| f.name.as_ref() == field)?; let until = record.fields.iter().position(|f| f.name.as_ref() == field)?;
let mut offset = 0; let mut offset = 0;
for &Field { ty, .. } in &record.fields[..until] { 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); offset += self.size_of(ty);
} }
Some((offset, record.fields[until].ty)) Some((offset, record.fields[until].ty))
@ -833,7 +834,7 @@ impl Types {
let mut offset = 0u32; let mut offset = 0u32;
let record = &self.structs[stru as usize]; let record = &self.structs[stru as usize];
for &Field { ty, .. } in record.fields.iter() { 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::align_up(offset, align);
offset += self.size_of(ty); offset += self.size_of(ty);
} }
@ -845,12 +846,16 @@ impl Types {
fn align_of(&self, ty: ty::Id) -> Size { fn align_of(&self, ty: ty::Id) -> Size {
match ty.expand() { 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 .fields
.iter() .iter()
.map(|&Field { ty, .. }| self.align_of(ty)) .map(|&Field { ty, .. }| self.align_of(ty))
.max() .max()
.unwrap(), .unwrap()
})
}
ty::Kind::Slice(arr) => { ty::Kind::Slice(arr) => {
let arr = &self.arrays[arr as usize]; let arr = &self.arrays[arr as usize];
match arr.len { match arr.len {

View file

@ -64,6 +64,7 @@ pub struct Parser<'a, 'b> {
symbols: &'b mut Symbols, symbols: &'b mut Symbols,
ns_bound: usize, ns_bound: usize,
trailing_sep: bool, trailing_sep: bool,
packed: bool,
idents: Vec<ScopeIdent>, idents: Vec<ScopeIdent>,
captured: Vec<Ident>, captured: Vec<Ident>,
} }
@ -80,6 +81,7 @@ impl<'a, 'b> Parser<'a, 'b> {
symbols, symbols,
ns_bound: 0, ns_bound: 0,
trailing_sep: false, trailing_sep: false,
packed: false,
idents: Vec::new(), idents: Vec::new(),
captured: Vec::new(), captured: Vec::new(),
} }
@ -286,7 +288,20 @@ impl<'a, 'b> Parser<'a, 'b> {
T::False => E::Bool { pos, value: false }, T::False => E::Bool { pos, value: false },
T::Idk => E::Idk { pos }, T::Idk => E::Idk { pos },
T::DQuote => E::String { pos, literal: self.move_str(token) }, 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 { T::Struct => E::Struct {
packed: std::mem::take(&mut self.packed),
fields: { fields: {
self.ns_bound = self.idents.len(); self.ns_bound = self.idents.len();
self.expect_advance(T::LBrace); self.expect_advance(T::LBrace);
@ -746,6 +761,7 @@ generate_expr! {
fields: &'a [CommentOr<'a, StructField<'a>>], fields: &'a [CommentOr<'a, StructField<'a>>],
captured: &'a [Ident], captured: &'a [Ident],
trailing_comma: bool, trailing_comma: bool,
packed: bool,
}, },
/// `[Expr] LIST('.{', ',', '}', Ident [':' Expr])` /// `[Expr] LIST('.{', ',', '}', Ident [':' Expr])`
Ctor { Ctor {
@ -1032,7 +1048,11 @@ impl<'a> fmt::Display for Expr<'a> {
write!(f, "@{name}(")?; write!(f, "@{name}(")?;
fmt_list(f, false, ")", ",", args, fmt::Display::fmt) 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 {{")?; write!(f, "struct {{")?;
fmt_list_low(f, trailing_comma, "}", ",", fields, |field, f| { fmt_list_low(f, trailing_comma, "}", ",", fields, |field, f| {
match field { match field {

View file

@ -2,7 +2,7 @@
use { use {
crate::{ crate::{
ident::{self, Ident}, ident::{self, Ident},
instrs::{self}, instrs,
lexer::{self, TokenKind}, lexer::{self, TokenKind},
log, log,
parser::{ parser::{
@ -12,7 +12,7 @@ use {
}, },
task, task,
ty::{self}, 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, core::fmt,
regalloc2::VReg, regalloc2::VReg,
@ -1251,13 +1251,17 @@ impl Codegen {
self.expr_ctx(expr, Ctx::default()) 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 let fields = fields
.iter() .iter()
.filter_map(CommentOr::or) .filter_map(CommentOr::or)
.map(|sf| Field { name: sf.name.into(), ty: self.ty(&sf.ty) }) .map(|sf| Field { name: sf.name.into(), ty: self.ty(&sf.ty) })
.collect(); .collect();
self.tys.structs.push(Struct { fields }); self.tys.structs.push(Struct { fields, explicit_alignment });
self.tys.structs.len() as u32 - 1 self.tys.structs.len() as u32 - 1
} }
@ -1315,7 +1319,7 @@ 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 { pos: _, op: TokenKind::Band, val: _ } => {
todo!() todo!()
} }
Expr::UnOp { pos, op, val } => { 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.modify_input(scope_var.value, 2, loop_var.value);
self.ci.nodes.lock(scope_var.value); self.ci.nodes.lock(scope_var.value);
} else { } 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]; let phi = &self.ci.nodes[scope_var.value];
debug_assert_eq!(phi.kind, Kind::Phi); debug_assert_eq!(phi.kind, Kind::Phi);
debug_assert_eq!(phi.inputs[2], VOID); debug_assert_eq!(phi.inputs[2], VOID);
@ -1482,6 +1491,11 @@ impl Codegen {
self.ci.nodes.lock(dest_var.value); 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); 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.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.nodes.graphviz();
self.ci.vars = orig_vars; self.ci.vars = orig_vars;
@ -1799,15 +1813,14 @@ 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);
dbg!(&func);
let mut env = regalloc2::MachineEnv { let mut env = regalloc2::MachineEnv {
preferred_regs_by_class: [ 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![],
vec![], vec![],
], ],
non_preferred_regs_by_class: [ 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![],
vec![], vec![],
], ],
@ -1817,131 +1830,131 @@ impl Codegen {
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 env.preferred_regs_by_class, &mut env.non_preferred_regs_by_class);
}; };
let options = regalloc2::RegallocOptions { verbose_log: false, validate_ssa: true }; let options = regalloc2::RegallocOptions { verbose_log: false, validate_ssa: false };
let iters = std::time::SystemTime::now() let iters = std::hint::black_box(10000);
.duration_since(std::time::SystemTime::UNIX_EPOCH)
.unwrap() //let mut ctx = regalloc2::Ctx::default();
.as_nanos() as u32 //regalloc2::run_with_ctx(&func, &env, &options, &mut ctx)
% 300 // .unwrap_or_else(|err| panic!("{err}"));
+ 300; //let now = std::time::Instant::now();
let mut output = //for _ in 0..iters {
regalloc2::run(&func, &env, &options).unwrap_or_else(|err| panic!("{err}")); // 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(); let now = std::time::Instant::now();
for i in 0..iters { for _ in 0..iters {
output = regalloc2::run(&func, &env, &options).unwrap_or_else(|err| panic!("{err}")); 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,
);
}
} }
eprintln!("took: {:?}", now.elapsed().checked_div(iters).unwrap()); eprintln!("took: {:?}", now.elapsed().checked_div(iters).unwrap());
let mut saved_regs = HashMap::<u8, u8>::default(); 0
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 mut saved_regs = HashMap::<u8, u8>::default();
let blk = regalloc2::Block(i as _); //let mut atr = |allc: regalloc2::Allocation| {
func.nodes[block.nid].offset = self.ci.code.len() as _; // debug_assert!(allc.is_reg());
for instr_or_edit in output.block_insts_and_edits(&func, blk) { // let hvenc = regalloc2::PReg::from_index(allc.index()).hw_enc() as u8;
let inst = match instr_or_edit { // if hvenc <= 12 {
regalloc2::InstOrEdit::Inst(inst) => inst, // return hvenc;
regalloc2::InstOrEdit::Edit(&regalloc2::Edit::Move { from, to }) => { // }
self.ci.emit(instrs::cp(atr(to), atr(from))); // let would_insert = saved_regs.len() as u8 + reg::RET_ADDR + 1;
continue; // *saved_regs.entry(hvenc).or_insert(would_insert)
} //};
};
let nid = func.instrs[inst.index()].nid; //for (i, block) in func.blocks.iter().enumerate() {
if nid == NEVER { // let blk = regalloc2::Block(i as _);
continue; // func.nodes[block.nid].offset = self.ci.code.len() as _;
}; // for instr_or_edit in ctx.output.block_insts_and_edits(&func, blk) {
let allocs = output.inst_allocs(inst); // let inst = match instr_or_edit {
let node = &func.nodes[nid]; // regalloc2::InstOrEdit::Inst(inst) => inst,
match node.kind { // regalloc2::InstOrEdit::Edit(&regalloc2::Edit::Move { from, to }) => {
Kind::If => { // self.ci.emit(instrs::cp(atr(to), atr(from)));
let &[_, cond] = node.inputs.as_slice() else { unreachable!() }; // continue;
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 nid = func.instrs[inst.index()].nid;
&& let Some(op) = // if nid == NEVER {
op.imm_binop(node.ty.is_signed(), func.tys.size_of(node.ty)) // continue;
{ // };
let &[dst, lhs] = allocs else { unreachable!() }; // let allocs = ctx.output.inst_allocs(inst);
self.ci.emit(op(atr(dst), atr(lhs), value as _)); // let node = &func.nodes[nid];
} else if let Some(op) = // match node.kind {
op.binop(node.ty.is_signed(), func.tys.size_of(node.ty)) // Kind::If => {
{ // let &[_, cond] = node.inputs.as_slice() else { unreachable!() };
let &[dst, lhs, rhs] = allocs else { unreachable!() }; // if let Kind::BinOp { op } = func.nodes[cond].kind
self.ci.emit(op(atr(dst), atr(lhs), atr(rhs))); // && let Some((op, swapped)) = op.cond_op(node.ty.is_signed())
} else if op.cond_op(node.ty.is_signed()).is_some() { // {
} else { // let rel = Reloc::new(self.ci.code.len(), 3, 2);
todo!() // 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));
Kind::Call { func } => { // } else {
self.ci.relocs.push(TypedReloc { // todo!()
target: ty::Kind::Func(func).compress(), // }
reloc: Reloc::new(self.ci.code.len(), 3, 4), // }
}); // Kind::Loop | Kind::Region => {
self.ci.emit(instrs::jal(reg::RET_ADDR, reg::ZERO, 0)); // if node.ralloc_backref as usize != i + 1 {
} // let rel = Reloc::new(self.ci.code.len(), 1, 4);
Kind::Start | Kind::End | Kind::Phi | Kind::Arg { .. } | Kind::Ctrl { .. } => { // self.ci.jump_relocs.push((nid, rel));
unreachable!() // self.ci.emit(instrs::jmp(0));
} // }
Kind::Stck { .. } => todo!(), // }
Kind::Load { .. } => todo!(), // Kind::Return => {
Kind::Stre { .. } => todo!(), // 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 // TODO: sometimes its better to do this in bulk
@ -2042,7 +2055,7 @@ impl Codegen {
left: &Expr::Ident { .. }, left: &Expr::Ident { .. },
op: TokenKind::Decl, op: TokenKind::Decl,
right: Expr::Struct { fields, .. }, right: Expr::Struct { fields, .. },
} => ty::Kind::Struct(self.build_struct(fields)), } => ty::Kind::Struct(self.build_struct(None, fields)),
Expr::BinOp { .. } => { Expr::BinOp { .. } => {
todo!() todo!()
} }