From 602249a48ad1e160fde485680f033114ac22e81d Mon Sep 17 00:00:00 2001 From: mlokr Date: Sun, 22 Sep 2024 18:17:30 +0200 Subject: [PATCH] adding packed structs --- Cargo.lock | 91 ++++++++++++++- Cargo.toml | 1 - hblang/Cargo.toml | 3 +- hblang/README.md | 222 ++++++++++++++++++++++++++++++++++- hblang/src/codegen.rs | 31 +++-- hblang/src/lexer.rs | 2 + hblang/src/lib.rs | 21 ++-- hblang/src/parser.rs | 22 +++- hblang/src/son.rs | 265 ++++++++++++++++++++++-------------------- 9 files changed, 508 insertions(+), 150 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8a30767..c2c4475 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", +] diff --git a/Cargo.toml b/Cargo.toml index acb9024..66561e2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,6 @@ resolver = "2" members = ["hbbytecode", "hbvm", "hbxrt", "xtask", "hblang", "hbjit"] [profile.release] -strip = true lto = true codegen-units = 1 panic = "abort" diff --git a/hblang/Cargo.toml b/hblang/Cargo.toml index 5ca1cf1..c89edf6 100644 --- a/hblang/Cargo.toml +++ b/hblang/Cargo.toml @@ -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" diff --git a/hblang/README.md b/hblang/README.md index ece38f1..8f6529b 100644 --- a/hblang/README.md +++ b/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 - y += 1 + 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 diff --git a/hblang/src/codegen.rs b/hblang/src/codegen.rs index eb4796d..d3eee41 100644 --- a/hblang/src/codegen.rs +++ b/hblang/src/codegen.rs @@ -719,13 +719,17 @@ impl Codegen { self.expr_ctx(expr, Ctx::default()) } - fn build_struct(&mut self, fields: &[CommentOr]) -> ty::Struct { + fn build_struct( + &mut self, + explicit_alignment: Option, + fields: &[CommentOr], + ) -> 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() }); diff --git a/hblang/src/lexer.rs b/hblang/src/lexer.rs index 99a6115..9c1551d 100644 --- a/hblang/src/lexer.rs +++ b/hblang/src/lexer.rs @@ -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", diff --git a/hblang/src/lib.rs b/hblang/src/lib.rs index 3ab0dd1..7d44727 100644 --- a/hblang/src/lib.rs +++ b/hblang/src/lib.rs @@ -582,6 +582,7 @@ struct Field { } struct Struct { + explicit_alignment: Option, 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] - .fields - .iter() - .map(|&Field { ty, .. }| self.align_of(ty)) - .max() - .unwrap(), + 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() + }) + } ty::Kind::Slice(arr) => { let arr = &self.arrays[arr as usize]; match arr.len { diff --git a/hblang/src/parser.rs b/hblang/src/parser.rs index 8a6ed8e..960d115 100644 --- a/hblang/src/parser.rs +++ b/hblang/src/parser.rs @@ -64,6 +64,7 @@ pub struct Parser<'a, 'b> { symbols: &'b mut Symbols, ns_bound: usize, trailing_sep: bool, + packed: bool, idents: Vec, captured: Vec, } @@ -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 { diff --git a/hblang/src/son.rs b/hblang/src/son.rs index 692af13..35310b0 100644 --- a/hblang/src/son.rs +++ b/hblang/src/son.rs @@ -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]) -> ty::Struct { + fn build_struct( + &mut self, + explicit_alignment: Option, + fields: &[CommentOr], + ) -> 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::::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::::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!() }