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.
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",
]

View file

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

View file

@ -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"

View file

@ -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

View file

@ -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() });

View file

@ -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",

View file

@ -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]
.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 {

View file

@ -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 {

View file

@ -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(&regalloc2::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(&regalloc2::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!()
}