diff --git a/.gitignore b/.gitignore index af441a4..ae3b53d 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ db.sqlite-journal # assets /depell/src/*.gz /depell/src/*.wasm +**/*-sv.rs /bytecode/src/instrs.rs diff --git a/depell/wasm-hbc/src/lib.rs b/depell/wasm-hbc/src/lib.rs index 7b67dc5..a0505d8 100644 --- a/depell/wasm-hbc/src/lib.rs +++ b/depell/wasm-hbc/src/lib.rs @@ -6,7 +6,7 @@ use { alloc::{string::String, vec::Vec}, hblang::{ parser::FileId, - son::{Codegen, CodegenCtx}, + son::{hbvm::HbvmBackend, Codegen, CodegenCtx}, }, }; @@ -78,14 +78,15 @@ unsafe fn compile_and_run(mut fuel: usize) { }; let mut ct = { - Codegen::new(&files, &mut ctx).generate(root as FileId); + let mut backend = HbvmBackend::default(); + Codegen::new(&mut backend, &files, &mut ctx).generate(root as FileId); if !ctx.parser.errors.borrow().is_empty() { log::error!("{}", ctx.parser.errors.borrow()); return; } - let mut c = Codegen::new(&files, &mut ctx); + let mut c = Codegen::new(&mut backend, &files, &mut ctx); c.assemble_comptime() }; diff --git a/lang/src/fs.rs b/lang/src/fs.rs index 6a628f7..8a80696 100644 --- a/lang/src/fs.rs +++ b/lang/src/fs.rs @@ -1,7 +1,7 @@ use { crate::{ parser::{self, Ast, Ctx, FileKind}, - son, + son::{self, hbvm::HbvmBackend}, }, alloc::{string::String, vec::Vec}, core::{fmt::Write, num::NonZeroUsize, ops::Deref}, @@ -88,9 +88,10 @@ pub fn run_compiler(root_file: &str, options: Options, out: &mut Vec) -> std let ast = parsed.ast.into_iter().next().unwrap(); write!(out, "{ast}").unwrap(); } else { + let mut backend = HbvmBackend::default(); let mut ctx = crate::son::CodegenCtx::default(); *ctx.parser.errors.get_mut() = parsed.errors; - let mut codegen = son::Codegen::new(&parsed.ast, &mut ctx); + let mut codegen = son::Codegen::new(&mut backend, &parsed.ast, &mut ctx); codegen.push_embeds(parsed.embeds); codegen.generate(0); @@ -100,12 +101,12 @@ pub fn run_compiler(root_file: &str, options: Options, out: &mut Vec) -> std return Err(std::io::Error::other("compilation faoled")); } + codegen.assemble(out); + if options.dump_asm { - codegen - .disasm(unsafe { std::mem::transmute::<&mut Vec, &mut String>(out) }) - .map_err(|e| io::Error::other(e.to_string()))?; - } else { - codegen.assemble(out); + let mut disasm = String::new(); + codegen.disasm(&mut disasm, out).map_err(|e| io::Error::other(e.to_string()))?; + *out = disasm.into_bytes(); } } diff --git a/lang/src/fuzz.rs b/lang/src/fuzz.rs index 54fe874..dc881e8 100644 --- a/lang/src/fuzz.rs +++ b/lang/src/fuzz.rs @@ -2,7 +2,7 @@ use { crate::{ lexer::TokenKind, parser, - son::{Codegen, CodegenCtx}, + son::{hbvm::HbvmBackend, Codegen, CodegenCtx}, }, alloc::string::String, core::{fmt::Write, hash::BuildHasher, ops::Range}, @@ -133,7 +133,8 @@ pub fn fuzz(seed_range: Range) { assert!(ctx.parser.errors.get_mut().is_empty()); - let mut cdg = Codegen::new(core::slice::from_ref(&parsed), &mut ctx); + let mut backend = HbvmBackend::default(); + let mut cdg = Codegen::new(&mut backend, core::slice::from_ref(&parsed), &mut ctx); cdg.generate(0); } } diff --git a/lang/src/lib.rs b/lang/src/lib.rs index 5d03b58..fc69e91 100644 --- a/lang/src/lib.rs +++ b/lang/src/lib.rs @@ -219,26 +219,6 @@ mod ctx_map { } } -mod task { - use super::Offset; - - pub fn unpack(offset: Offset) -> Result { - if offset >> 31 != 0 { - Err((offset & !(1 << 31)) as usize) - } else { - Ok(offset) - } - } - - pub fn is_done(offset: Offset) -> bool { - unpack(offset).is_ok() - } - - pub fn id(index: usize) -> Offset { - 1 << 31 | index as u32 - } -} - #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug)] pub struct Ident(u32); @@ -567,6 +547,7 @@ mod ty { };)* } + #[expect(dead_code)] impl Id { $(pub const $name: Self = Kind::Builtin($name).compress();)* } @@ -758,7 +739,7 @@ pub enum SymKey<'a> { } #[derive(Clone, Copy)] -struct Sig { +pub struct Sig { args: ty::Tuple, ret: ty::Id, } @@ -769,10 +750,7 @@ struct Func { base: Option, expr: ExprRef, sig: Option, - offset: Offset, - // TODO: change to indices into common vec - relocs: Vec, - code: Vec, + comp_state: [CompState; 2], } impl Default for Func { @@ -783,13 +761,19 @@ impl Default for Func { base: None, expr: Default::default(), sig: None, - offset: u32::MAX, - relocs: Default::default(), - code: Default::default(), + comp_state: Default::default(), } } } +#[derive(Default, PartialEq, Eq)] +enum CompState { + #[default] + Dead, + Queued(usize), + Compiled, +} + #[derive(Clone, Copy)] struct TypedReloc { target: ty::Id, @@ -801,7 +785,6 @@ struct Global { file: FileId, name: Ident, ty: ty::Id, - offset: Offset, data: Vec, } @@ -809,7 +792,6 @@ impl Default for Global { fn default() -> Self { Self { ty: Default::default(), - offset: u32::MAX, data: Default::default(), file: u32::MAX, name: Default::default(), @@ -947,9 +929,6 @@ impl IdentInterner { #[derive(Default)] struct TypesTmp { fields: Vec, - frontier: Vec, - globals: Vec, - funcs: Vec, args: Vec, } @@ -968,6 +947,7 @@ pub struct TypeIns { struct FTask { file: FileId, id: ty::Func, + ct: bool, } struct StringRef(ty::Global); @@ -982,7 +962,7 @@ impl ctx_map::CtxEntry for StringRef { } #[derive(Default)] -struct Types { +pub struct Types { syms: ctx_map::CtxMap, names: IdentInterner, strings: ctx_map::CtxMap, @@ -1222,12 +1202,6 @@ impl Types { &self.ins.fields[self.struct_field_range(strct)] } - fn reassemble(&mut self, buf: &mut Vec) { - self.ins.funcs.iter_mut().for_each(|f| f.offset = u32::MAX); - self.ins.globals.iter_mut().for_each(|g| g.offset = u32::MAX); - self.assemble(buf) - } - fn parama(&self, ret: impl Into) -> (Option, ParamAlloc) { let mut iter = ParamAlloc(1..12); let ret = iter.next(ret.into(), self); @@ -1395,9 +1369,6 @@ impl Types { self.ins.slices.clear(); debug_assert_eq!(self.tmp.fields.len(), 0); - debug_assert_eq!(self.tmp.frontier.len(), 0); - debug_assert_eq!(self.tmp.globals.len(), 0); - debug_assert_eq!(self.tmp.funcs.len(), 0); debug_assert_eq!(self.tmp.args.len(), 0); debug_assert_eq!(self.tasks.len(), 0); diff --git a/lang/src/son.rs b/lang/src/son.rs index aff77c0..46ade6a 100644 --- a/lang/src/son.rs +++ b/lang/src/son.rs @@ -1,5 +1,8 @@ use { - self::{hbvm::Comptime, strong_ref::StrongRef}, + self::{ + hbvm::{Comptime, HbvmBackend}, + strong_ref::StrongRef, + }, crate::{ ctx_map::CtxEntry, debug, @@ -9,11 +12,10 @@ use { idfl::{self}, CtorField, Expr, FileId, Pos, }, - task, ty::{self, Arg, ArrayLen, Loc, Tuple}, utils::{BitSet, Vc}, - FTask, Func, Global, Ident, Offset, OffsetIter, OptLayout, Reloc, Sig, StringRef, SymKey, - TypeParser, TypedReloc, Types, + CompState, FTask, Func, Global, Ident, Offset, OffsetIter, OptLayout, Sig, StringRef, + SymKey, TypeParser, Types, }, alloc::{string::String, vec::Vec}, core::{ @@ -41,6 +43,38 @@ pub mod hbvm; type Nid = u16; type AClassId = i16; +pub struct AssemblySpec { + entry: u64, + code_length: u64, + data_length: u64, +} + +pub trait Backend { + fn assemble_reachable( + &mut self, + from: ty::Func, + types: &Types, + to: &mut Vec, + ) -> AssemblySpec; + fn disasm<'a>( + &'a self, + sluce: &[u8], + eca_handler: &mut dyn FnMut(&mut &[u8]), + types: &'a Types, + files: &'a [parser::Ast], + output: &mut String, + ) -> Result<(), hbbytecode::DisasmError<'a>>; + fn emit_body(&mut self, id: ty::Func, ci: &mut Nodes, tys: &Types, files: &[parser::Ast]); + + fn emit_ct_body(&mut self, id: ty::Func, ci: &mut Nodes, tys: &Types, files: &[parser::Ast]) { + self.emit_body(id, ci, tys, files); + } + + fn assemble_bin(&mut self, from: ty::Func, types: &Types, to: &mut Vec) { + self.assemble_reachable(from, types, to); + } +} + type Lookup = crate::ctx_map::CtxMap; impl crate::ctx_map::CtxEntry for Nid { @@ -71,23 +105,15 @@ macro_rules! inference { } #[derive(Clone)] -struct Nodes { +pub struct Nodes { values: Vec>, - visited: BitSet, free: Nid, lookup: Lookup, - complete: bool, } impl Default for Nodes { fn default() -> Self { - Self { - values: Default::default(), - free: Nid::MAX, - lookup: Default::default(), - visited: Default::default(), - complete: false, - } + Self { values: Default::default(), free: Nid::MAX, lookup: Default::default() } } } @@ -183,15 +209,15 @@ impl Nodes { } } - fn push_up_impl(&mut self, node: Nid) { - if !self.visited.set(node) { + fn push_up_impl(&mut self, node: Nid, visited: &mut BitSet) { + if !visited.set(node) { return; } for i in 1..self[node].inputs.len() { let inp = self[node].inputs[i]; if !self[inp].kind.is_pinned() { - self.push_up_impl(inp); + self.push_up_impl(inp, visited); } } @@ -230,32 +256,32 @@ impl Nodes { self[deepest].outputs.push(node); } - fn collect_rpo(&mut self, node: Nid, rpo: &mut Vec) { - if !self.is_cfg(node) || !self.visited.set(node) { + fn collect_rpo(&mut self, node: Nid, rpo: &mut Vec, visited: &mut BitSet) { + if !self.is_cfg(node) || !visited.set(node) { return; } for i in 0..self[node].outputs.len() { - self.collect_rpo(self[node].outputs[i], rpo); + self.collect_rpo(self[node].outputs[i], rpo, visited); } rpo.push(node); } - fn push_up(&mut self, rpo: &mut Vec) { + fn push_up(&mut self, rpo: &mut Vec, visited: &mut BitSet) { debug_assert!(rpo.is_empty()); - self.collect_rpo(VOID, rpo); + self.collect_rpo(VOID, rpo, visited); for &node in rpo.iter().rev() { self.loop_depth(node); for i in 0..self[node].inputs.len() { - self.push_up_impl(self[node].inputs[i]); + self.push_up_impl(self[node].inputs[i], visited); } if matches!(self[node].kind, Kind::Loop | Kind::Region) { for i in 0..self[node].outputs.len() { let usage = self[node].outputs[i]; if self[usage].kind == Kind::Phi { - self.push_up_impl(usage); + self.push_up_impl(usage, visited); } } } @@ -264,13 +290,13 @@ impl Nodes { debug_assert_eq!( self.iter() .map(|(n, _)| n) - .filter(|&n| !self.visited.get(n) + .filter(|&n| !visited.get(n) && !matches!(self[n].kind, Kind::Arg | Kind::Mem | Kind::Loops)) .collect::>(), vec![], "{:?}", self.iter() - .filter(|&(n, nod)| !self.visited.get(n) + .filter(|&(n, nod)| !visited.get(n) && !matches!(nod.kind, Kind::Arg | Kind::Mem | Kind::Loops)) .collect::>() ); @@ -295,20 +321,20 @@ impl Nodes { } } - fn push_down(&mut self, node: Nid) { - if !self.visited.set(node) { + fn push_down(&mut self, node: Nid, visited: &mut BitSet) { + if !visited.set(node) { return; } for usage in self[node].outputs.clone() { if self.is_forward_edge(usage, node) && self[node].kind == Kind::Stre { - self.push_down(usage); + self.push_down(usage, visited); } } for usage in self[node].outputs.clone() { if self.is_forward_edge(usage, node) { - self.push_down(usage); + self.push_down(usage, visited); } } @@ -488,12 +514,7 @@ impl Nodes { } } - fn graphviz_low( - &self, - tys: &Types, - files: &[parser::Ast], - out: &mut String, - ) -> core::fmt::Result { + fn graphviz_low(&self, disp: ty::Display, out: &mut String) -> core::fmt::Result { use core::fmt::Write; writeln!(out)?; @@ -518,7 +539,7 @@ impl Nodes { out, " node{i}[label=\"{i} {} {} {}\" color={color}]", node.kind, - ty::Display::new(tys, files, node.ty), + disp.rety(node.ty), node.aclass, )?; } else { @@ -545,17 +566,17 @@ impl Nodes { Ok(()) } - fn graphviz(&self, tys: &Types, files: &[parser::Ast]) { + fn graphviz(&self, disp: ty::Display) { let out = &mut String::new(); - _ = self.graphviz_low(tys, files, out); + _ = self.graphviz_low(disp, out); log::info!("{out}"); } - fn graphviz_in_browser(&self, _tys: &Types, _files: &[parser::Ast]) { + fn graphviz_in_browser(&self, disp: ty::Display) { #[cfg(all(debug_assertions, feature = "std"))] { let out = &mut String::new(); - _ = self.graphviz_low(_tys, _files, out); + _ = self.graphviz_low(disp, out); if !std::process::Command::new("brave") .arg(format!("https://dreampuf.github.io/GraphvizOnline/#{out}")) .status() @@ -567,24 +588,22 @@ impl Nodes { } } - fn gcm(&mut self, rpo: &mut Vec) { + fn gcm(&mut self, rpo: &mut Vec, visited: &mut BitSet) { self.fix_loops(); - self.visited.clear(self.values.len()); - self.push_up(rpo); - self.visited.clear(self.values.len()); - self.push_down(VOID); + visited.clear(self.values.len()); + self.push_up(rpo, visited); + visited.clear(self.values.len()); + self.push_down(VOID, visited); } fn clear(&mut self) { self.values.clear(); self.lookup.clear(); self.free = Nid::MAX; - self.complete = false; } fn new_node_nop(&mut self, ty: ty::Id, kind: Kind, inps: impl Into) -> Nid { - let node = - Node { ralloc_backref: u16::MAX, inputs: inps.into(), kind, ty, ..Default::default() }; + let node = Node { inputs: inps.into(), kind, ty, ..Default::default() }; if node.kind == Kind::Phi && node.ty != ty::Id::VOID { debug_assert_ne!( @@ -765,7 +784,7 @@ impl Nodes { stack.iter().skip(prev_len).for_each(|&n| self.lock(n)); } - pub fn aclass_index(&self, region: Nid) -> (usize, Nid) { + fn aclass_index(&self, region: Nid) -> (usize, Nid) { if self[region].aclass >= 0 { (self[region].aclass as _, region) } else { @@ -1336,9 +1355,6 @@ impl Nodes { #[expect(clippy::format_in_format_args)] fn basic_blocks_instr(&mut self, out: &mut String, node: Nid) -> core::fmt::Result { - if self[node].kind != Kind::Loop && self[node].kind != Kind::Region { - write!(out, " {node:>2}-c{:>2}: ", self[node].ralloc_backref)?; - } match self[node].kind { Kind::Assert { .. } | Kind::Start => unreachable!("{} {out}", self[node].kind), Kind::End => return Ok(()), @@ -1382,9 +1398,14 @@ impl Nodes { Ok(()) } - fn basic_blocks_low(&mut self, out: &mut String, mut node: Nid) -> core::fmt::Result { + fn basic_blocks_low( + &mut self, + out: &mut String, + mut node: Nid, + visited: &mut BitSet, + ) -> core::fmt::Result { let iter = |nodes: &Nodes, node| nodes[node].outputs.clone().into_iter().rev(); - while self.visited.set(node) { + while visited.set(node) { match self[node].kind { Kind::Start => { writeln!(out, "start: {}", self[node].depth.get())?; @@ -1399,7 +1420,7 @@ impl Nodes { } Kind::End => break, Kind::If => { - self.basic_blocks_low(out, self[node].outputs[0])?; + self.basic_blocks_low(out, self[node].outputs[0], visited)?; node = self[node].outputs[1]; } Kind::Region => { @@ -1480,8 +1501,8 @@ impl Nodes { fn basic_blocks(&mut self) { let mut out = String::new(); - self.visited.clear(self.values.len()); - self.basic_blocks_low(&mut out, VOID).unwrap(); + let mut visited = BitSet::default(); + self.basic_blocks_low(&mut out, VOID, &mut visited).unwrap(); log::info!("{out}"); } @@ -1489,7 +1510,7 @@ impl Nodes { self[o].kind.is_cfg() } - fn check_final_integrity(&self, tys: &Types, files: &[parser::Ast]) { + fn check_final_integrity(&self, disp: ty::Display) { if !cfg!(debug_assertions) { return; } @@ -1517,7 +1538,7 @@ impl Nodes { } if failed { - self.graphviz_in_browser(tys, files); + self.graphviz_in_browser(disp); panic!() } } @@ -1743,8 +1764,6 @@ pub struct Node { peep_triggers: Vc, clobbers: BitSet, ty: ty::Id, - offset: Offset, - ralloc_backref: RallocBRef, depth: Cell, lock_rc: LockRc, loop_depth: LoopDepth, @@ -1963,7 +1982,7 @@ impl Scope { } #[derive(Default, Clone)] -struct ItemCtx { +pub struct ItemCtx { file: FileId, ret: Option, task_base: usize, @@ -1973,25 +1992,19 @@ struct ItemCtx { inline_ret: Option<(Value, StrongRef, Scope)>, nodes: Nodes, ctrl: StrongRef, - call_count: u16, loops: Vec, scope: Scope, - ret_relocs: Vec, - relocs: Vec, - jump_relocs: Vec<(Nid, Reloc)>, - code: Vec, } impl ItemCtx { fn init(&mut self, file: FileId, ret: Option, task_base: usize) { debug_assert_eq!(self.loops.len(), 0); debug_assert_eq!(self.scope.vars.len(), 0); - debug_assert_eq!(self.ret_relocs.len(), 0); - debug_assert_eq!(self.relocs.len(), 0); - debug_assert_eq!(self.jump_relocs.len(), 0); - debug_assert_eq!(self.code.len(), 0); - - self.call_count = 0; + debug_assert_eq!(self.scope.aclasses.len(), 0); + debug_assert!(self.inline_ret.is_none()); + debug_assert_eq!(self.inline_depth, 0); + debug_assert_eq!(self.inline_var_base, 0); + debug_assert_eq!(self.inline_aclass_base, 0); self.file = file; self.ret = ret; @@ -2043,21 +2056,21 @@ struct Ctx { } impl Ctx { - pub fn with_ty(self, ty: ty::Id) -> Self { + fn with_ty(self, ty: ty::Id) -> Self { Self { ty: Some(ty) } } } #[derive(Default)] -struct Pool { +pub struct Pool { cis: Vec, used_cis: usize, - ralloc: Regalloc, nid_stack: Vec, + nid_set: BitSet, } impl Pool { - pub fn push_ci( + fn push_ci( &mut self, file: FileId, ret: Option, @@ -2074,7 +2087,7 @@ impl Pool { self.used_cis += 1; } - pub fn pop_ci(&mut self, target: &mut ItemCtx) { + fn pop_ci(&mut self, target: &mut ItemCtx) { self.used_cis -= 1; mem::swap(&mut self.cis[self.used_cis], target); } @@ -2100,33 +2113,6 @@ impl Pool { } } -struct Regalloc { - env: regalloc2::MachineEnv, - ctx: regalloc2::Ctx, -} - -impl Default for Regalloc { - fn default() -> Self { - Self { - env: regalloc2::MachineEnv { - preferred_regs_by_class: [ - (1..13).map(|i| regalloc2::PReg::new(i, regalloc2::RegClass::Int)).collect(), - vec![], - vec![], - ], - non_preferred_regs_by_class: [ - (13..64).map(|i| regalloc2::PReg::new(i, regalloc2::RegClass::Int)).collect(), - vec![], - vec![], - ], - scratch_by_class: Default::default(), - fixed_stack_slots: Default::default(), - }, - ctx: Default::default(), - } - } -} - #[derive(Default, Clone, Copy, PartialEq, Eq, Debug)] struct Value { ty: ty::Id, @@ -2140,20 +2126,20 @@ impl Value { Some(Self { ty: ty::Id::NEVER, var: false, ptr: false, id: NEVER }); const VOID: Value = Self { ty: ty::Id::VOID, var: false, ptr: false, id: VOID }; - pub fn new(id: Nid) -> Self { + fn new(id: Nid) -> Self { Self { id, ..Default::default() } } - pub fn var(id: usize) -> Self { + fn var(id: usize) -> Self { Self { id: u16::MAX - (id as Nid), var: true, ..Default::default() } } - pub fn ptr(id: Nid) -> Self { + fn ptr(id: Nid) -> Self { Self { id, ptr: true, ..Default::default() } } #[inline(always)] - pub fn ty(self, ty: impl Into) -> Self { + fn ty(self, ty: impl Into) -> Self { Self { ty: ty.into(), ..self } } } @@ -2164,6 +2150,7 @@ pub struct CodegenCtx { tys: Types, pool: Pool, ct: Comptime, + ct_backend: HbvmBackend, } impl CodegenCtx { @@ -2200,10 +2187,16 @@ pub struct Codegen<'a> { ci: ItemCtx, pool: &'a mut Pool, ct: &'a mut Comptime, + ct_backend: &'a mut HbvmBackend, + backend: &'a mut dyn Backend, } impl<'a> Codegen<'a> { - pub fn new(files: &'a [parser::Ast], ctx: &'a mut CodegenCtx) -> Self { + pub fn new( + backend: &'a mut dyn Backend, + files: &'a [parser::Ast], + ctx: &'a mut CodegenCtx, + ) -> Self { Self { files, errors: Errors(&ctx.parser.errors), @@ -2211,9 +2204,46 @@ impl<'a> Codegen<'a> { ci: Default::default(), pool: &mut ctx.pool, ct: &mut ctx.ct, + ct_backend: &mut ctx.ct_backend, + backend, } } + pub fn generate(&mut self, entry: FileId) { + self.find_type(0, entry, entry, Err("main"), self.files); + if self.tys.ins.funcs.is_empty() { + return; + } + self.make_func_reachable(0); + self.complete_call_graph(); + } + + pub fn assemble_comptime(&mut self) -> Comptime { + self.ct.code.clear(); + self.ct_backend.assemble_bin(0, self.tys, &mut self.ct.code); + self.ct.reset(); + core::mem::take(self.ct) + } + + pub fn assemble(&mut self, buf: &mut Vec) { + self.backend.assemble_bin(0, self.tys, buf); + } + + pub fn disasm(&mut self, output: &mut String, bin: &[u8]) -> Result<(), DisasmError> { + self.backend.disasm(bin, &mut |_| {}, self.tys, self.files, output) + } + + pub fn push_embeds(&mut self, embeds: Vec>) { + self.tys.ins.globals = embeds + .into_iter() + .map(|data| Global { + ty: self.tys.make_array(ty::Id::U8, data.len() as _), + data, + ..Default::default() + }) + .collect(); + } + fn emit_and_eval(&mut self, file: FileId, ret: ty::Id, ret_loc: &mut [u8]) -> u64 { let mut rets = self.ci.nodes[NEVER].inputs.iter().filter(|&&i| self.ci.nodes[i].kind == Kind::Return); @@ -2231,46 +2261,33 @@ impl<'a> Codegen<'a> { return 1; } - self.ci.emit_ct_body(self.tys, self.files, Sig { args: Tuple::empty(), ret }, self.pool); - - let func = Func { + let fuc = self.tys.ins.funcs.len() as ty::Func; + self.tys.ins.funcs.push(Func { file, - relocs: mem::take(&mut self.ci.relocs), - code: mem::take(&mut self.ci.code), + sig: Some(Sig { args: Tuple::empty(), ret }), ..Default::default() - }; + }); + + self.ct_backend.emit_ct_body(fuc, &mut self.ci.nodes, self.tys, self.files); // TODO: return them back - let fuc = self.tys.ins.funcs.len() as ty::Func; - self.tys.ins.funcs.push(func); - self.tys.dump_reachable(fuc, &mut self.ct.code); - self.dump_ct_asm(); + let entry = + self.ct_backend.assemble_reachable(fuc, self.tys, &mut self.ct.code).entry as u32; - self.ct.run(ret_loc, self.tys.ins.funcs[fuc as usize].offset) - } - - fn dump_ct_asm(&self) { #[cfg(debug_assertions)] { let mut vc = String::new(); - if let Err(e) = self.tys.disasm(&self.ct.code, self.files, &mut vc, |_| {}) { + if let Err(e) = + self.ct_backend.disasm(&self.ct.code, &mut |_| {}, self.tys, self.files, &mut vc) + { panic!("{e} {}", vc); } else { log::trace!("{}", vc); } } - } - pub fn push_embeds(&mut self, embeds: Vec>) { - self.tys.ins.globals = embeds - .into_iter() - .map(|data| Global { - ty: self.tys.make_array(ty::Id::U8, data.len() as _), - data, - ..Default::default() - }) - .collect(); + self.ct.run(ret_loc, entry) } fn new_stack(&mut self, ty: ty::Id) -> Nid { @@ -2348,12 +2365,12 @@ impl<'a> Codegen<'a> { debug_assert_ne!(region, VOID); debug_assert_ne!({ self.ci.nodes[region].ty }, ty::Id::VOID, "{:?}", { self.ci.nodes[region].lock_rc = Nid::MAX; - self.ci.nodes.graphviz_in_browser(self.tys, self.files); + self.ci.nodes.graphviz_in_browser(self.ty_display(ty::Id::VOID)); }); debug_assert!( self.ci.nodes[region].kind != Kind::Load || self.ci.nodes[region].ty.is_pointer(), "{:?} {} {}", - self.ci.nodes.graphviz_in_browser(self.tys, self.files), + self.ci.nodes.graphviz_in_browser(self.ty_display(ty::Id::VOID)), self.file().path, self.ty_display(self.ci.nodes[region].ty) ); @@ -2365,37 +2382,12 @@ impl<'a> Codegen<'a> { self.ci.nodes.new_node(ty, Kind::Load, vc) } - pub fn generate(&mut self, entry: FileId) { - self.find_type(0, entry, entry, Err("main"), self.files); - if self.tys.ins.funcs.is_empty() { - return; - } - self.make_func_reachable(0); - self.complete_call_graph(); - } - - pub fn assemble_comptime(&mut self) -> Comptime { - self.ct.code.clear(); - self.tys.reassemble(&mut self.ct.code); - self.ct.reset(); - core::mem::take(self.ct) - } - - pub fn assemble(&mut self, buf: &mut Vec) { - self.tys.reassemble(buf); - } - - pub fn disasm(&mut self, output: &mut String) -> Result<(), DisasmError> { - let mut bin = Vec::new(); - self.assemble(&mut bin); - self.tys.disasm(&bin, self.files, output, |_| {}) - } - fn make_func_reachable(&mut self, func: ty::Func) { + let state_slot = self.ct.active() as usize; let fuc = &mut self.tys.ins.funcs[func as usize]; - if fuc.offset == u32::MAX { - fuc.offset = task::id(self.tys.tasks.len() as _); - self.tys.tasks.push(Some(FTask { file: fuc.file, id: func })); + if fuc.comp_state[state_slot] == CompState::Dead { + fuc.comp_state[state_slot] = CompState::Queued(self.tys.tasks.len() as _); + self.tys.tasks.push(Some(FTask { file: fuc.file, id: func, ct: self.ct.active() })); } } @@ -3072,7 +3064,6 @@ impl<'a> Codegen<'a> { alt_value.or(Some(Value::new(self.ci.ctrl.get()).ty(ty))) } Expr::Call { func, args, .. } => { - self.ci.call_count += 1; let ty = self.ty(func); let ty::Kind::Func(mut fu) = ty.expand() else { self.report( @@ -4005,10 +3996,12 @@ impl<'a> Codegen<'a> { self.errors.borrow().len() == prev_err_len } - fn emit_func(&mut self, FTask { file, id }: FTask) { + fn emit_func(&mut self, FTask { file, id, ct }: FTask) { let func = &mut self.tys.ins.funcs[id as usize]; debug_assert_eq!(func.file, file); - func.offset = u32::MAX - 1; + let cct = self.ct.active(); + debug_assert_eq!(cct, ct); + func.comp_state[cct as usize] = CompState::Compiled; let sig = func.sig.expect("to emmit only concrete functions"); let ast = &self.files[file as usize]; let expr = func.expr.get(ast); @@ -4075,9 +4068,8 @@ impl<'a> Codegen<'a> { self.ci.scope.vars.drain(..).for_each(|v| v.remove_ignore_arg(&mut self.ci.nodes)); if self.finalize(prev_err_len) { - self.ci.emit_body(self.tys, self.files, sig, self.pool); - self.tys.ins.funcs[id as usize].code.append(&mut self.ci.code); - self.tys.ins.funcs[id as usize].relocs.append(&mut self.ci.relocs); + let backend = if !cct { &mut *self.backend } else { &mut *self.ct_backend }; + backend.emit_body(id, &mut self.ci.nodes, self.tys, self.files); } self.pool.pop_ci(&mut self.ci); @@ -4087,6 +4079,7 @@ impl<'a> Codegen<'a> { use {AssertKind as AK, CondOptRes as CR}; self.ci.finalize(&mut self.pool.nid_stack, self.tys, self.files); + let mut to_remove = vec![]; for (id, node) in self.ci.nodes.iter() { let Kind::Assert { kind, pos } = node.kind else { continue }; @@ -4153,7 +4146,17 @@ impl<'a> Codegen<'a> { self.ci.nodes[n].outputs.iter().map(|&o| &self.ci.nodes[o]).collect::>(), ); }); + self.ci.unlock(); + + if self.errors.borrow().len() == prev_err_len { + self.ci.nodes.check_final_integrity(self.ty_display(ty::Id::VOID)); + self.ci.nodes.graphviz(self.ty_display(ty::Id::VOID)); + self.ci.nodes.gcm(&mut self.pool.nid_stack, &mut self.pool.nid_set); + self.ci.nodes.basic_blocks(); + self.ci.nodes.graphviz(self.ty_display(ty::Id::VOID)); + } + self.errors.borrow().len() == prev_err_len } @@ -4399,6 +4402,7 @@ impl TypeParser for Codegen<'_> { } fn eval_const(&mut self, file: FileId, expr: &Expr, ret: ty::Id) -> u64 { + self.ct.activate(); let mut scope = mem::take(&mut self.ci.scope.vars); self.pool.push_ci(file, Some(ret), self.tys.tasks.len(), &mut self.ci); self.ci.scope.vars = scope; @@ -4415,6 +4419,7 @@ impl TypeParser for Codegen<'_> { self.pool.pop_ci(&mut self.ci); self.ci.scope.vars = scope; + self.ct.deactivate(); res } @@ -4427,18 +4432,21 @@ impl TypeParser for Codegen<'_> { } fn on_reuse(&mut self, existing: ty::Id) { + let state_slot = self.ct.active() as usize; if let ty::Kind::Func(id) = existing.expand() && let func = &mut self.tys.ins.funcs[id as usize] - && let Err(idx) = task::unpack(func.offset) + && let CompState::Queued(idx) = func.comp_state[state_slot] && idx < self.tys.tasks.len() { - func.offset = task::id(self.tys.tasks.len()); + func.comp_state[state_slot] = CompState::Queued(self.tys.tasks.len()); let task = self.tys.tasks[idx].take(); self.tys.tasks.push(task); } } fn eval_global(&mut self, file: FileId, name: Ident, expr: &Expr) -> ty::Id { + self.ct.activate(); + let gid = self.tys.ins.globals.len() as ty::Global; self.tys.ins.globals.push(Global { file, name, ..Default::default() }); @@ -4458,6 +4466,7 @@ impl TypeParser for Codegen<'_> { self.pool.pop_ci(&mut self.ci); self.tys.ins.globals[gid as usize].ty = ret; + self.ct.deactivate(); ty.compress() } @@ -4475,7 +4484,7 @@ impl TypeParser for Codegen<'_> { #[cfg(test)] mod tests { use { - super::CodegenCtx, + super::{hbvm::HbvmBackend, CodegenCtx}, alloc::{string::String, vec::Vec}, core::fmt::Write, }; @@ -4487,7 +4496,8 @@ mod tests { let mut ctx = CodegenCtx::default(); let (ref files, embeds) = crate::test_parse_files(ident, input, &mut ctx.parser); - let mut codegen = super::Codegen::new(files, &mut ctx); + let mut backend = HbvmBackend::default(); + let mut codegen = super::Codegen::new(&mut backend, files, &mut ctx); codegen.push_embeds(embeds); codegen.generate(0); @@ -4501,9 +4511,9 @@ mod tests { } let mut out = Vec::new(); - codegen.tys.reassemble(&mut out); + codegen.assemble(&mut out); - let err = codegen.tys.disasm(&out, codegen.files, output, |_| {}); + let err = codegen.disasm(output, &out); if let Err(e) = err { writeln!(output, "!!! asm is invalid: {e}").unwrap(); return; diff --git a/lang/src/son/hbvm.rs b/lang/src/son/hbvm.rs index 67043b1..ae11bee 100644 --- a/lang/src/son/hbvm.rs +++ b/lang/src/son/hbvm.rs @@ -1,10 +1,9 @@ use { - super::{ItemCtx, Nid, Nodes, Pool, RallocBRef, Regalloc, ARG_START, NEVER, VOID}, + super::{AssemblySpec, Backend, ItemCtx, Nid, Nodes, RallocBRef, ARG_START, NEVER, VOID}, crate::{ lexer::TokenKind, parser, reg, son::{write_reloc, Kind, MEM}, - task, ty::{self, Arg, Loc}, utils::{BitSet, Vc}, HashMap, Offset, PLoc, Reloc, Sig, Size, TypedReloc, Types, @@ -14,139 +13,94 @@ use { hbbytecode::{self as instrs, *}, }; -impl Types { - pub fn assemble(&mut self, to: &mut Vec) { - to.extend([0u8; HEADER_SIZE]); +struct FuncDt { + offset: Offset, + // TODO: change to indices into common vec + relocs: Vec, + code: Vec, +} - binary_prelude(to); - let exe = self.dump_reachable(0, to); - Reloc::new(HEADER_SIZE, 3, 4).apply_jump(to, self.ins.funcs[0].offset, 0); - - unsafe { *to.as_mut_ptr().cast::() = exe } - } - - pub fn dump_reachable(&mut self, from: ty::Func, to: &mut Vec) -> AbleOsExecutableHeader { - debug_assert!(self.tmp.frontier.is_empty()); - debug_assert!(self.tmp.funcs.is_empty()); - debug_assert!(self.tmp.globals.is_empty()); - - self.tmp.frontier.push(ty::Kind::Func(from).compress()); - while let Some(itm) = self.tmp.frontier.pop() { - match itm.expand() { - ty::Kind::Func(func) => { - let fuc = &mut self.ins.funcs[func as usize]; - if task::is_done(fuc.offset) { - continue; - } - fuc.offset = 0; - self.tmp.funcs.push(func); - self.tmp.frontier.extend(fuc.relocs.iter().map(|r| r.target)); - } - ty::Kind::Global(glob) => { - let glb = &mut self.ins.globals[glob as usize]; - if task::is_done(glb.offset) { - continue; - } - glb.offset = 0; - self.tmp.globals.push(glob); - } - _ => unreachable!(), - } - } - - for &func in &self.tmp.funcs { - let fuc = &mut self.ins.funcs[func as usize]; - fuc.offset = to.len() as _; - debug_assert!(!fuc.code.is_empty()); - to.extend(&fuc.code); - } - - let code_length = to.len(); - - for global in self.tmp.globals.drain(..) { - let global = &mut self.ins.globals[global as usize]; - global.offset = to.len() as _; - to.extend(&global.data); - } - - let data_length = to.len() - code_length; - - for func in self.tmp.funcs.drain(..) { - let fuc = &self.ins.funcs[func as usize]; - for rel in &fuc.relocs { - let offset = match rel.target.expand() { - ty::Kind::Func(fun) => self.ins.funcs[fun as usize].offset, - ty::Kind::Global(glo) => self.ins.globals[glo as usize].offset, - _ => unreachable!(), - }; - rel.reloc.apply_jump(to, offset, fuc.offset); - } - } - - AbleOsExecutableHeader { - magic_number: [0x15, 0x91, 0xD2], - executable_version: 0, - code_length: code_length.saturating_sub(HEADER_SIZE) as _, - data_length: data_length as _, - debug_length: 0, - config_length: 0, - metadata_length: 0, - } - } - - pub fn disasm<'a>( - &'a self, - mut sluce: &[u8], - files: &'a [parser::Ast], - output: &mut String, - eca_handler: impl FnMut(&mut &[u8]), - ) -> Result<(), hbbytecode::DisasmError<'a>> { - use hbbytecode::DisasmItem; - let functions = self - .ins - .funcs - .iter() - .filter(|f| task::is_done(f.offset)) - .map(|f| { - let name = if f.file != u32::MAX { - let file = &files[f.file as usize]; - file.ident_str(f.name) - } else { - "target_fn" - }; - (f.offset, (name, f.code.len() as u32, DisasmItem::Func)) - }) - .chain(self.ins.globals.iter().filter(|g| task::is_done(g.offset)).map(|g| { - let name = if g.file == u32::MAX { - core::str::from_utf8(&g.data).unwrap_or("invalid utf-8") - } else { - let file = &files[g.file as usize]; - file.ident_str(g.name) - }; - (g.offset, (name, g.data.len() as Size, DisasmItem::Global)) - })) - .collect::>(); - hbbytecode::disasm(&mut sluce, &functions, output, eca_handler) +impl Default for FuncDt { + fn default() -> Self { + Self { offset: u32::MAX, relocs: Default::default(), code: Default::default() } } } -impl ItemCtx { +struct GlobalDt { + offset: Offset, +} + +impl Default for GlobalDt { + fn default() -> Self { + Self { offset: u32::MAX } + } +} + +#[derive(Default)] +struct Assembler { + frontier: Vec, + globals: Vec, + funcs: Vec, +} + +struct Regalloc { + env: regalloc2::MachineEnv, + ctx: regalloc2::Ctx, +} + +impl Default for Regalloc { + fn default() -> Self { + Self { + env: regalloc2::MachineEnv { + preferred_regs_by_class: [ + (1..13).map(|i| regalloc2::PReg::new(i, regalloc2::RegClass::Int)).collect(), + vec![], + vec![], + ], + non_preferred_regs_by_class: [ + (13..64).map(|i| regalloc2::PReg::new(i, regalloc2::RegClass::Int)).collect(), + vec![], + vec![], + ], + scratch_by_class: Default::default(), + fixed_stack_slots: Default::default(), + }, + ctx: Default::default(), + } + } +} + +#[derive(Default)] +pub struct HbvmBackend { + funcs: Vec, + globals: Vec, + asm: Assembler, + ralloc: Regalloc, + + ret_relocs: Vec, + relocs: Vec, + jump_relocs: Vec<(Nid, Reloc)>, + code: Vec, + offsets: Vec, +} + +impl HbvmBackend { fn emit(&mut self, instr: (usize, [u8; instrs::MAX_SIZE])) { emit(&mut self.code, instr); } fn emit_body_code( &mut self, + nodes: &mut Nodes, sig: Sig, tys: &Types, files: &[parser::Ast], - ralloc: &mut Regalloc, - ) -> usize { - let mut nodes = mem::take(&mut self.nodes); + ) -> (usize, bool) { + let mut ralloc = mem::take(&mut self.ralloc); - let fuc = Function::new(&mut nodes, tys, sig); + let fuc = Function::new(nodes, tys, sig); log::info!("{:?}", fuc); - if self.call_count != 0 { + if !fuc.tail { mem::swap( &mut ralloc.env.preferred_regs_by_class, &mut ralloc.env.non_preferred_regs_by_class, @@ -164,12 +118,12 @@ impl ItemCtx { fuc.nodes[vreg.vreg() as Nid].lock_rc = Nid::MAX; fuc.nodes[fuc.instrs[inst.index()].nid].lock_rc = Nid::MAX - 1; } - fuc.nodes.graphviz_in_browser(tys, files); + fuc.nodes.graphviz_in_browser(ty::Display::new(tys, files, ty::Id::VOID)); panic!("{err}") }, ); - if self.call_count != 0 { + if !fuc.tail { mem::swap( &mut ralloc.env.preferred_regs_by_class, &mut ralloc.env.non_preferred_regs_by_class, @@ -187,6 +141,11 @@ impl ItemCtx { *saved_regs.entry(hvenc).or_insert(would_insert) }; + '_open_function: { + self.emit(instrs::addi64(reg::STACK_PTR, reg::STACK_PTR, 0)); + self.emit(instrs::st(reg::RET_ADDR + fuc.tail as u8, reg::STACK_PTR, 0, 0)); + } + let (retl, mut parama) = tys.parama(sig.ret); let mut typs = sig.args.args(); let mut args = fuc.nodes[VOID].outputs[ARG_START..].iter(); @@ -199,15 +158,15 @@ impl ItemCtx { PLoc::Reg(rg, size) if ty.loc(tys) == Loc::Stack => (rg, size), PLoc::Reg(..) | PLoc::Ref(..) => continue, }; - self.emit(instrs::st(rg, reg::STACK_PTR, fuc.nodes[arg].offset as _, size)); + self.emit(instrs::st(rg, reg::STACK_PTR, self.offsets[arg as usize] as _, size)); if fuc.nodes[arg].lock_rc == 0 { - self.emit(instrs::addi64(rg, reg::STACK_PTR, fuc.nodes[arg].offset as _)); + self.emit(instrs::addi64(rg, reg::STACK_PTR, self.offsets[arg as usize] as _)); } } for (i, block) in fuc.blocks.iter().enumerate() { let blk = regalloc2::Block(i as _); - fuc.nodes[block.nid].offset = self.code.len() as _; + self.offsets[block.nid as usize] = self.code.len() as _; for instr_or_edit in ralloc.ctx.output.block_insts_and_edits(&fuc, blk) { let inst = match instr_or_edit { regalloc2::InstOrEdit::Inst(inst) => inst, @@ -223,6 +182,7 @@ impl ItemCtx { }; let allocs = ralloc.ctx.output.inst_allocs(inst); let node = &fuc.nodes[nid]; + let backref = fuc.backrefs[nid as usize]; let mut extend = |base: ty::Id, dest: ty::Id, from: usize, to: usize| { let (bsize, dsize) = (tys.size_of(base), tys.size_of(dest)); @@ -270,7 +230,7 @@ impl ItemCtx { } } Kind::Loop | Kind::Region => { - if node.ralloc_backref as usize != i + 1 { + if backref as usize != i + 1 { let rel = Reloc::new(self.code.len(), 1, 4); self.jump_relocs.push((nid, rel)); self.emit(instrs::jmp(0)); @@ -418,7 +378,7 @@ impl ItemCtx { fuc.nodes[*node.inputs.last().unwrap()].kind, Kind::Stck ); - let stck = fuc.nodes[*node.inputs.last().unwrap()].offset; + let stck = self.offsets[*node.inputs.last().unwrap() as usize]; self.emit(instrs::st(r, reg::STACK_PTR, stck as _, size)); } if let Some(PLoc::Reg(r, size)) = ret @@ -428,7 +388,7 @@ impl ItemCtx { fuc.nodes[*node.inputs.last().unwrap()].kind, Kind::Stck ); - let stck = fuc.nodes[*node.inputs.last().unwrap()].offset; + let stck = self.offsets[*node.inputs.last().unwrap() as usize]; self.emit(instrs::st(r, reg::STACK_PTR, stck as _, size)); } } @@ -442,7 +402,7 @@ impl ItemCtx { } Kind::Stck => { let base = reg::STACK_PTR; - let offset = fuc.nodes[nid].offset; + let offset = self.offsets[nid as usize]; self.emit(instrs::addi64(atr(allocs[0]), base, offset as _)); } Kind::Load => { @@ -458,7 +418,9 @@ impl ItemCtx { let size = tys.size_of(node.ty); if node.ty.loc(tys) != Loc::Stack { let (base, offset) = match fuc.nodes[region].kind { - Kind::Stck => (reg::STACK_PTR, fuc.nodes[region].offset + offset), + Kind::Stck => { + (reg::STACK_PTR, self.offsets[region as usize] + offset) + } _ => (atr(allocs[1]), offset), }; self.emit(instrs::ld(atr(allocs[0]), base, offset as _, size as _)); @@ -480,7 +442,7 @@ impl ItemCtx { let nd = &fuc.nodes[region]; let (base, offset, src) = match nd.kind { Kind::Stck if node.ty.loc(tys) == Loc::Reg => { - (reg::STACK_PTR, nd.offset + offset, allocs[0]) + (reg::STACK_PTR, self.offsets[region as usize] + offset, allocs[0]) } _ => (atr(allocs[0]), offset, allocs[1]), }; @@ -507,69 +469,204 @@ impl ItemCtx { } } - self.nodes = nodes; + self.ralloc = ralloc; - saved_regs.len() + (saved_regs.len(), fuc.tail) + } +} + +impl Backend for HbvmBackend { + fn assemble_bin(&mut self, entry: ty::Func, types: &Types, to: &mut Vec) { + to.extend([0u8; HEADER_SIZE]); + + binary_prelude(to); + let AssemblySpec { code_length, data_length, entry } = + self.assemble_reachable(entry, types, to); + + let exe = AbleOsExecutableHeader { + magic_number: [0x15, 0x91, 0xD2], + executable_version: 0, + code_length, + data_length, + debug_length: 0, + config_length: 0, + metadata_length: 0, + }; + Reloc::new(HEADER_SIZE, 3, 4).apply_jump(to, entry as _, 0); + + unsafe { *to.as_mut_ptr().cast::() = exe } } - pub fn emit_ct_body( + fn assemble_reachable( &mut self, - tys: &mut Types, - files: &[parser::Ast], - sig: Sig, - pool: &mut Pool, - ) { - self.emit_body(tys, files, sig, pool); - self.code.truncate(self.code.len() - instrs::jala(0, 0, 0).0); - self.emit(instrs::tx()); + from: ty::Func, + types: &Types, + to: &mut Vec, + ) -> AssemblySpec { + debug_assert!(self.asm.frontier.is_empty()); + debug_assert!(self.asm.funcs.is_empty()); + debug_assert!(self.asm.globals.is_empty()); + + self.globals.resize_with(types.ins.globals.len(), Default::default); + + self.asm.frontier.push(ty::Kind::Func(from).compress()); + while let Some(itm) = self.asm.frontier.pop() { + match itm.expand() { + ty::Kind::Func(func) => { + let fuc = &mut self.funcs[func as usize]; + if fuc.offset != u32::MAX { + continue; + } + fuc.offset = 0; + self.asm.funcs.push(func); + self.asm.frontier.extend(fuc.relocs.iter().map(|r| r.target)); + } + ty::Kind::Global(glob) => { + let glb = &mut self.globals[glob as usize]; + if glb.offset != u32::MAX { + continue; + } + glb.offset = 0; + self.asm.globals.push(glob); + } + _ => unreachable!(), + } + } + + let init_len = to.len(); + + for &func in &self.asm.funcs { + let fuc = &mut self.funcs[func as usize]; + fuc.offset = to.len() as _; + debug_assert!(!fuc.code.is_empty()); + to.extend(&fuc.code); + } + + let code_length = to.len() - init_len; + + for global in self.asm.globals.drain(..) { + self.globals[global as usize].offset = to.len() as _; + to.extend(&types.ins.globals[global as usize].data); + } + + let data_length = to.len() - code_length - init_len; + + for func in self.asm.funcs.drain(..) { + let fuc = &self.funcs[func as usize]; + for rel in &fuc.relocs { + let offset = match rel.target.expand() { + ty::Kind::Func(fun) => self.funcs[fun as usize].offset, + ty::Kind::Global(glo) => self.globals[glo as usize].offset, + _ => unreachable!(), + }; + rel.reloc.apply_jump(to, offset, fuc.offset); + } + } + + AssemblySpec { + code_length: code_length as _, + data_length: data_length as _, + entry: self.funcs[from as usize].offset as _, + } } - pub fn emit_body(&mut self, tys: &mut Types, files: &[parser::Ast], sig: Sig, pool: &mut Pool) { - self.nodes.check_final_integrity(tys, files); - self.nodes.graphviz(tys, files); - self.nodes.gcm(&mut pool.nid_stack); - self.nodes.basic_blocks(); - self.nodes.graphviz(tys, files); + fn disasm<'a>( + &'a self, + mut sluce: &[u8], + eca_handler: &mut dyn FnMut(&mut &[u8]), + types: &'a Types, + files: &'a [parser::Ast], + output: &mut String, + ) -> Result<(), hbbytecode::DisasmError<'a>> { + use hbbytecode::DisasmItem; + let functions = types + .ins + .funcs + .iter() + .zip(&self.funcs) + .filter(|(_, f)| f.offset != u32::MAX) + .map(|(f, fd)| { + let name = if f.file != u32::MAX { + let file = &files[f.file as usize]; + file.ident_str(f.name) + } else { + "target_fn" + }; + (fd.offset, (name, fd.code.len() as u32, DisasmItem::Func)) + }) + .chain( + types + .ins + .globals + .iter() + .zip(&self.globals) + .filter(|(_, g)| g.offset != u32::MAX) + .map(|(g, gd)| { + let name = if g.file == u32::MAX { + core::str::from_utf8(&g.data).unwrap_or("invalid utf-8") + } else { + let file = &files[g.file as usize]; + file.ident_str(g.name) + }; + (gd.offset, (name, g.data.len() as Size, DisasmItem::Global)) + }), + ) + .collect::>(); + hbbytecode::disasm(&mut sluce, &functions, output, eca_handler) + } + + fn emit_ct_body( + &mut self, + id: ty::Func, + nodes: &mut Nodes, + tys: &Types, + files: &[parser::Ast], + ) { + self.emit_body(id, nodes, tys, files); + let fd = &mut self.funcs[id as usize]; + fd.code.truncate(fd.code.len() - instrs::jala(0, 0, 0).0); + emit(&mut fd.code, instrs::tx()); + } + + fn emit_body(&mut self, id: ty::Func, nodes: &mut Nodes, tys: &Types, files: &[parser::Ast]) { + let sig = tys.ins.funcs[id as usize].sig.unwrap(); debug_assert!(self.code.is_empty()); - let tail = mem::take(&mut self.call_count) == 0; - '_open_function: { - self.emit(instrs::addi64(reg::STACK_PTR, reg::STACK_PTR, 0)); - self.emit(instrs::st(reg::RET_ADDR + tail as u8, reg::STACK_PTR, 0, 0)); - } + self.offsets.clear(); + self.offsets.resize(nodes.values.len(), Offset::MAX); let mut stack_size = 0; '_compute_stack: { - let mems = mem::take(&mut self.nodes[MEM].outputs); + let mems = mem::take(&mut nodes[MEM].outputs); for &stck in mems.iter() { - if !matches!(self.nodes[stck].kind, Kind::Stck | Kind::Arg) { + if !matches!(nodes[stck].kind, Kind::Stck | Kind::Arg) { debug_assert_matches!( - self.nodes[stck].kind, + nodes[stck].kind, Kind::Phi | Kind::Return | Kind::Load | Kind::Call { .. } | Kind::Stre ); continue; } - stack_size += tys.size_of(self.nodes[stck].ty); - self.nodes[stck].offset = stack_size; + stack_size += tys.size_of(nodes[stck].ty); + self.offsets[stck as usize] = stack_size; } for &stck in mems.iter() { - if !matches!(self.nodes[stck].kind, Kind::Stck | Kind::Arg) { + if !matches!(nodes[stck].kind, Kind::Stck | Kind::Arg) { continue; } - self.nodes[stck].offset = stack_size - self.nodes[stck].offset; + self.offsets[stck as usize] = stack_size - self.offsets[stck as usize]; } - self.nodes[MEM].outputs = mems; + nodes[MEM].outputs = mems; } - let saved = self.emit_body_code(sig, tys, files, &mut pool.ralloc); + let (saved, tail) = self.emit_body_code(nodes, sig, tys, files); if let Some(last_ret) = self.ret_relocs.last() && last_ret.offset as usize == self.code.len() - 5 && self .jump_relocs .last() - .map_or(true, |&(r, _)| self.nodes[r].offset as usize != self.code.len()) + .map_or(true, |&(r, _)| self.offsets[r as usize] as usize != self.code.len()) { self.code.truncate(self.code.len() - 5); self.ret_relocs.pop(); @@ -577,7 +674,7 @@ impl ItemCtx { // FIXME: maybe do this incrementally for (nd, rel) in self.jump_relocs.drain(..) { - let offset = self.nodes[nd].offset; + let offset = self.offsets[nd as usize]; //debug_assert!(offset < self.code.len() as u32 - 1); rel.apply_jump(&mut self.code, offset, 0); } @@ -592,17 +689,20 @@ impl ItemCtx { let pushed = (saved as i64 + !tail as i64) * 8; let stack = stack_size as i64; + let add_len = instrs::addi64(0, 0, 0).0; + let st_len = instrs::st(0, 0, 0, 0).0; + match (pushed, stack) { (0, 0) => { - stripped_prelude_size = instrs::addi64(0, 0, 0).0 + instrs::st(0, 0, 0, 0).0; + stripped_prelude_size = add_len + st_len; self.code.drain(0..stripped_prelude_size); break '_close_function; } (0, stack) => { write_reloc(&mut self.code, 3, -stack, 8); - stripped_prelude_size = instrs::st(0, 0, 0, 0).0; - let end = instrs::addi64(0, 0, 0).0 + instrs::st(0, 0, 0, 0).0; - self.code.drain(instrs::addi64(0, 0, 0).0..end); + stripped_prelude_size = st_len; + let end = add_len + st_len; + self.code.drain(add_len..end); self.emit(instrs::addi64(reg::STACK_PTR, reg::STACK_PTR, stack as _)); break '_close_function; } @@ -625,9 +725,22 @@ impl ItemCtx { if sig.ret != ty::Id::NEVER { self.emit(instrs::jala(reg::ZERO, reg::RET_ADDR, 0)); } + + if self.funcs.get(id as usize).is_none() { + self.funcs.resize_with(id as usize + 1, Default::default); + } + self.funcs[id as usize].code = mem::take(&mut self.code); + self.funcs[id as usize].relocs = mem::take(&mut self.relocs); + + debug_assert_eq!(self.ret_relocs.len(), 0); + debug_assert_eq!(self.relocs.len(), 0); + debug_assert_eq!(self.jump_relocs.len(), 0); + debug_assert_eq!(self.code.len(), 0); } } +impl ItemCtx {} + #[derive(Debug)] struct Block { nid: Nid, @@ -648,6 +761,9 @@ pub struct Function<'a> { sig: Sig, nodes: &'a mut Nodes, tys: &'a Types, + tail: bool, + visited: BitSet, + backrefs: Vec, blocks: Vec, instrs: Vec, } @@ -670,9 +786,17 @@ impl core::fmt::Debug for Function<'_> { impl<'a> Function<'a> { fn new(nodes: &'a mut Nodes, tys: &'a Types, sig: Sig) -> Self { - let mut s = - Self { nodes, tys, sig, blocks: Default::default(), instrs: Default::default() }; - s.nodes.visited.clear(s.nodes.values.len()); + let mut s = Self { + tys, + sig, + tail: true, + visited: Default::default(), + backrefs: vec![u16::MAX; nodes.values.len()], + blocks: Default::default(), + instrs: Default::default(), + nodes, + }; + s.visited.clear(s.nodes.values.len()); s.emit_node(VOID, VOID); s.add_block(0); s.blocks.pop(); @@ -726,7 +850,7 @@ impl<'a> Function<'a> { fn emit_node(&mut self, nid: Nid, prev: Nid) { if matches!(self.nodes[nid].kind, Kind::Region | Kind::Loop) { - let prev_bref = self.nodes[prev].ralloc_backref; + let prev_bref = self.backrefs[prev as usize]; let node = self.nodes[nid].clone(); let idx = 1 + node.inputs.iter().position(|&i| i == prev).unwrap(); @@ -742,7 +866,7 @@ impl<'a> Function<'a> { self.add_instr(nid, vec![]); - match (self.nodes[nid].kind, self.nodes.visited.set(nid)) { + match (self.nodes[nid].kind, self.visited.set(nid)) { (Kind::Loop, false) => { for i in node.inputs { self.bridge(i, nid); @@ -752,7 +876,7 @@ impl<'a> Function<'a> { (Kind::Region, true) => return, _ => {} } - } else if !self.nodes.visited.set(nid) { + } else if !self.visited.set(nid) { return; } @@ -763,7 +887,7 @@ impl<'a> Function<'a> { self.emit_node(node.outputs[0], VOID) } Kind::If => { - self.nodes[nid].ralloc_backref = self.nodes[prev].ralloc_backref; + self.backrefs[nid as usize] = self.backrefs[prev as usize]; let &[_, cond] = node.inputs.as_slice() else { unreachable!() }; let &[mut then, mut else_] = node.outputs.as_slice() else { unreachable!() }; @@ -787,7 +911,7 @@ impl<'a> Function<'a> { self.emit_node(else_, nid); } Kind::Region | Kind::Loop => { - self.nodes[nid].ralloc_backref = self.add_block(nid); + self.backrefs[nid as usize] = self.add_block(nid); if node.kind == Kind::Region { for i in node.inputs { self.bridge(i, nid); @@ -800,7 +924,7 @@ impl<'a> Function<'a> { } block.push(self.rg(ph)); } - self.blocks[self.nodes[nid].ralloc_backref as usize].params = block; + self.blocks[self.backrefs[nid as usize] as usize].params = block; self.reschedule_block(nid, &mut node.outputs); for o in node.outputs.into_iter().rev() { self.emit_node(o, nid); @@ -849,7 +973,7 @@ impl<'a> Function<'a> { self.add_instr(nid, ops); } Kind::Entry => { - self.nodes[nid].ralloc_backref = self.add_block(nid); + self.backrefs[nid as usize] = self.add_block(nid); let (ret, mut parama) = self.tys.parama(self.sig.ret); let mut typs = self.sig.args.args(); @@ -882,7 +1006,7 @@ impl<'a> Function<'a> { } } Kind::Then | Kind::Else => { - self.nodes[nid].ralloc_backref = self.add_block(nid); + self.backrefs[nid as usize] = self.add_block(nid); self.bridge(prev, nid); self.reschedule_block(nid, &mut node.outputs); for o in node.outputs.into_iter().rev() { @@ -922,8 +1046,9 @@ impl<'a> Function<'a> { let ops = vec![self.drg(nid), self.urg(node.inputs[1])]; self.add_instr(nid, ops); } - Kind::Call { args, .. } => { - self.nodes[nid].ralloc_backref = self.nodes[prev].ralloc_backref; + Kind::Call { args, func } => { + self.tail &= func == ty::ECA; + self.backrefs[nid as usize] = self.backrefs[prev as usize]; let mut ops = vec![]; let (ret, mut parama) = self.tys.parama(node.ty); @@ -1079,17 +1204,15 @@ impl<'a> Function<'a> { } fn bridge(&mut self, pred: u16, succ: u16) { - if self.nodes[pred].ralloc_backref == u16::MAX - || self.nodes[succ].ralloc_backref == u16::MAX - { + if self.backrefs[pred as usize] == u16::MAX || self.backrefs[succ as usize] == u16::MAX { return; } - self.blocks[self.nodes[pred].ralloc_backref as usize] + self.blocks[self.backrefs[pred as usize] as usize] .succs - .push(regalloc2::Block::new(self.nodes[succ].ralloc_backref as usize)); - self.blocks[self.nodes[succ].ralloc_backref as usize] + .push(regalloc2::Block::new(self.backrefs[succ as usize] as usize)); + self.blocks[self.backrefs[succ as usize] as usize] .preds - .push(regalloc2::Block::new(self.nodes[pred].ralloc_backref as usize)); + .push(regalloc2::Block::new(self.backrefs[pred as usize] as usize)); } fn reschedule_block(&mut self, from: Nid, outputs: &mut Vc) { @@ -1245,7 +1368,7 @@ impl regalloc2::Function for Function<'_> { } impl TokenKind { - pub fn cmp_against(self) -> Option { + fn cmp_against(self) -> Option { Some(match self { TokenKind::Le | TokenKind::Gt => 1, TokenKind::Ne | TokenKind::Eq => 0, @@ -1254,7 +1377,7 @@ impl TokenKind { }) } - pub fn float_cmp(self, ty: ty::Id) -> Option EncodedInstr> { + fn float_cmp(self, ty: ty::Id) -> Option EncodedInstr> { if !ty.is_float() { return None; } @@ -1369,7 +1492,7 @@ impl TokenKind { Some(ops[size.ilog2() as usize]) } - pub fn unop(&self, dst: ty::Id, src: ty::Id) -> Option EncodedInstr> { + fn unop(&self, dst: ty::Id, src: ty::Id) -> Option EncodedInstr> { let src_idx = src.simple_size().unwrap().ilog2() as usize - 2; Some(match self { Self::Sub => instrs::neg, @@ -1392,7 +1515,7 @@ fn emit(out: &mut Vec, (len, instr): EncodedInstr) { out.extend_from_slice(&instr[..len]); } -pub fn binary_prelude(to: &mut Vec) { +fn binary_prelude(to: &mut Vec) { emit(to, instrs::jal(reg::RET_ADDR, reg::ZERO, 0)); emit(to, instrs::tx()); } @@ -1501,6 +1624,7 @@ pub struct Comptime { pub vm: hbvm::Vm, stack: Box<[u8; VM_STACK_SIZE]>, pub code: Vec, + depth: usize, } impl Comptime { @@ -1544,6 +1668,19 @@ impl Comptime { pub fn clear(&mut self) { self.code.clear(); } + + #[must_use] + pub fn active(&self) -> bool { + self.depth != 0 + } + + pub fn activate(&mut self) { + self.depth += 1; + } + + pub fn deactivate(&mut self) { + self.depth -= 1; + } } impl Default for Comptime { @@ -1552,7 +1689,7 @@ impl Default for Comptime { let mut vm = hbvm::Vm::default(); let ptr = unsafe { stack.as_mut_ptr().cast::().add(VM_STACK_SIZE) as u64 }; vm.write_reg(reg::STACK_PTR, ptr); - Self { vm, stack: unsafe { stack.assume_init() }, code: Default::default() } + Self { vm, stack: unsafe { stack.assume_init() }, code: Default::default(), depth: 0 } } } diff --git a/lang/tests/son_tests_arrays.txt b/lang/tests/son_tests_arrays.txt index eaad767..b8c50e3 100644 --- a/lang/tests/son_tests_arrays.txt +++ b/lang/tests/son_tests_arrays.txt @@ -1,17 +1,17 @@ main: - ADDI64 r254, r254, -40d - ST r31, r254, 24a, 16h + ADDI64 r254, r254, -56d + ST r31, r254, 24a, 32h LI64 r32, 1d ADDI64 r2, r254, 0d ST r32, r254, 0a, 8h - LI64 r5, 2d - ST r5, r254, 8a, 8h - LI64 r8, 4d - ST r8, r254, 16a, 8h + LI64 r33, 2d + ST r33, r254, 8a, 8h + LI64 r34, 4d + ST r34, r254, 16a, 8h JAL r31, r0, :pass ADD64 r1, r1, r32 - LD r31, r254, 24a, 16h - ADDI64 r254, r254, 40d + LD r31, r254, 24a, 32h + ADDI64 r254, r254, 56d JALA r0, r31, 0a pass: LD r4, r2, 8a, 8h diff --git a/lang/tests/son_tests_c_strings.txt b/lang/tests/son_tests_c_strings.txt index 782ffb0..0aa31af 100644 --- a/lang/tests/son_tests_c_strings.txt +++ b/lang/tests/son_tests_c_strings.txt @@ -6,8 +6,7 @@ main: CP r32, r1 LRA r2, r0, :"fff\0" JAL r31, r0, :str_len - CP r10, r32 - ADD64 r1, r1, r10 + ADD64 r1, r1, r32 LD r31, r254, 0a, 16h ADDI64 r254, r254, 16d JALA r0, r31, 0a @@ -23,6 +22,6 @@ str_len: ADDI64 r1, r1, 1d JMP :2 1: JALA r0, r31, 0a -code size: 219 +code size: 216 ret: 16 status: Ok(()) diff --git a/lang/tests/son_tests_conditional_stores.txt b/lang/tests/son_tests_conditional_stores.txt index b7fc3d2..a9a2494 100644 --- a/lang/tests/son_tests_conditional_stores.txt +++ b/lang/tests/son_tests_conditional_stores.txt @@ -2,18 +2,18 @@ cond: LI64 r1, 0d JALA r0, r31, 0a main: - ADDI64 r254, r254, -8d - ST r31, r254, 0a, 8h + ADDI64 r254, r254, -24d + ST r31, r254, 0a, 24h JAL r31, r0, :cond - LI64 r5, 0d - CP r7, r5 - JNE r1, r7, :0 - CP r5, r7 - CP r1, r5 + LI64 r32, 0d + CP r33, r32 + JNE r1, r33, :0 + CP r32, r33 + CP r1, r32 JMP :1 0: LI64 r1, 2d - 1: LD r31, r254, 0a, 8h - ADDI64 r254, r254, 8d + 1: LD r31, r254, 0a, 24h + ADDI64 r254, r254, 24d JALA r0, r31, 0a code size: 134 ret: 0 diff --git a/lang/tests/son_tests_exhaustive_loop_testing.txt b/lang/tests/son_tests_exhaustive_loop_testing.txt index e113d00..eaf456d 100644 --- a/lang/tests/son_tests_exhaustive_loop_testing.txt +++ b/lang/tests/son_tests_exhaustive_loop_testing.txt @@ -30,50 +30,50 @@ infinite_loop: ADDI64 r254, r254, 24d JALA r0, r31, 0a main: - ADDI64 r254, r254, -56d - ST r31, r254, 0a, 56h + ADDI64 r254, r254, -64d + ST r31, r254, 0a, 64h LI64 r32, 0d CP r2, r32 JAL r31, r0, :multiple_breaks - CP r2, r1 + CP r33, r1 LI64 r1, 3d - JEQ r2, r1, :0 + JEQ r33, r1, :0 LI64 r1, 1d JMP :1 - 0: CP r33, r1 - LI64 r34, 4d - CP r2, r34 + 0: CP r34, r1 + LI64 r35, 4d + CP r2, r35 JAL r31, r0, :multiple_breaks - CP r35, r34 - LI64 r36, 10d - JEQ r1, r36, :2 + CP r36, r35 + LI64 r37, 10d + JEQ r1, r37, :2 LI64 r1, 2d JMP :1 2: CP r2, r32 JAL r31, r0, :state_change_in_break JEQ r1, r32, :3 - CP r1, r33 + CP r1, r34 JMP :1 - 3: CP r2, r35 + 3: CP r2, r36 JAL r31, r0, :state_change_in_break - JEQ r1, r36, :4 - CP r1, r35 + JEQ r1, r37, :4 + CP r1, r36 JMP :1 - 4: CP r2, r36 + 4: CP r2, r37 JAL r31, r0, :continue_and_state_change - JEQ r1, r36, :5 + JEQ r1, r37, :5 LI64 r1, 5d JMP :1 - 5: CP r2, r33 + 5: CP r2, r34 JAL r31, r0, :continue_and_state_change JEQ r1, r32, :6 LI64 r1, 6d JMP :1 - 6: CP r37, r32 + 6: CP r38, r32 JAL r31, r0, :infinite_loop - CP r1, r37 - 1: LD r31, r254, 0a, 56h - ADDI64 r254, r254, 56d + CP r1, r38 + 1: LD r31, r254, 0a, 64h + ADDI64 r254, r254, 64d JALA r0, r31, 0a multiple_breaks: LI64 r6, 3d diff --git a/lang/tests/son_tests_fb_driver.txt b/lang/tests/son_tests_fb_driver.txt index a4bf731..ae33add 100644 --- a/lang/tests/son_tests_fb_driver.txt +++ b/lang/tests/son_tests_fb_driver.txt @@ -6,42 +6,40 @@ check_platform: ADDI64 r254, r254, 8d JALA r0, r31, 0a main: - ADDI64 r254, r254, -48d - ST r31, r254, 0a, 48h + ADDI64 r254, r254, -64d + ST r31, r254, 0a, 64h JAL r31, r0, :check_platform LI64 r32, 0d LI64 r33, 30d LI64 r34, 100d - CP r10, r32 CP r35, r32 CP r36, r32 - 5: JLTU r10, r33, :0 - ADDI64 r35, r35, 1d + CP r37, r32 + 5: JLTU r35, r33, :0 + ADDI64 r36, r36, 1d CP r2, r32 - CP r3, r35 + CP r3, r36 CP r4, r33 JAL r31, r0, :set_pixel - CP r2, r36 - JEQ r1, r2, :1 + JEQ r1, r37, :1 CP r1, r32 JMP :2 - 1: CP r5, r32 - CP r36, r2 - JNE r35, r34, :3 - CP r1, r36 + 1: CP r38, r32 + JNE r36, r34, :3 + CP r1, r37 JMP :2 - 3: CP r1, r36 - CP r10, r5 + 3: CP r1, r37 + CP r35, r38 JMP :4 - 0: CP r1, r36 - CP r5, r32 + 0: CP r1, r37 + CP r38, r32 ADDI64 r1, r1, 1d - ADDI64 r10, r10, 1d - 4: CP r32, r5 - CP r36, r1 + ADDI64 r35, r35, 1d + 4: CP r32, r38 + CP r37, r1 JMP :5 - 2: LD r31, r254, 0a, 48h - ADDI64 r254, r254, 48d + 2: LD r31, r254, 0a, 64h + ADDI64 r254, r254, 64d JALA r0, r31, 0a set_pixel: MUL64 r7, r3, r4 @@ -50,6 +48,6 @@ set_pixel: x86_fb_ptr: LI64 r1, 100d JALA r0, r31, 0a -code size: 336 +code size: 330 ret: 3000 status: Ok(()) diff --git a/lang/tests/son_tests_functions.txt b/lang/tests/son_tests_functions.txt index f5291f3..686e680 100644 --- a/lang/tests/son_tests_functions.txt +++ b/lang/tests/son_tests_functions.txt @@ -12,11 +12,10 @@ main: CP r32, r1 LI64 r2, 20d JAL r31, r0, :add_two - CP r10, r32 - ADD64 r1, r1, r10 + ADD64 r1, r1, r32 LD r31, r254, 0a, 16h ADDI64 r254, r254, 16d JALA r0, r31, 0a -code size: 155 +code size: 152 ret: 33 status: Ok(()) diff --git a/lang/tests/son_tests_generic_functions.txt b/lang/tests/son_tests_generic_functions.txt index eb53bd7..94db254 100644 --- a/lang/tests/son_tests_generic_functions.txt +++ b/lang/tests/son_tests_generic_functions.txt @@ -5,8 +5,8 @@ add: ADD32 r1, r2, r3 JALA r0, r31, 0a main: - ADDI64 r254, r254, -16d - ST r31, r254, 0a, 16h + ADDI64 r254, r254, -24d + ST r31, r254, 0a, 24h LI32 r3, 2w CP r2, r3 JAL r31, r0, :add @@ -14,12 +14,11 @@ main: LI64 r3, 3d LI64 r2, 1d JAL r31, r0, :add - CP r2, r32 - ANDI r11, r2, 4294967295d - SUB64 r1, r11, r1 - LD r31, r254, 0a, 16h - ADDI64 r254, r254, 16d + ANDI r33, r32, 4294967295d + SUB64 r1, r33, r1 + LD r31, r254, 0a, 24h + ADDI64 r254, r254, 24d JALA r0, r31, 0a -code size: 161 +code size: 158 ret: 0 status: Ok(()) diff --git a/lang/tests/son_tests_generic_types.txt b/lang/tests/son_tests_generic_types.txt index 755dcb1..644fc7b 100644 --- a/lang/tests/son_tests_generic_types.txt +++ b/lang/tests/son_tests_generic_types.txt @@ -1,17 +1,17 @@ deinit: - ADDI64 r254, r254, -16d - ST r31, r254, 0a, 16h + ADDI64 r254, r254, -32d + ST r31, r254, 0a, 32h CP r32, r2 - LD r5, r2, 16a, 8h + LD r33, r2, 16a, 8h LI64 r4, 8d - MUL64 r3, r5, r4 - CP r5, r32 - LD r2, r5, 0a, 8h + MUL64 r3, r33, r4 + CP r34, r32 + LD r2, r34, 0a, 8h JAL r31, r0, :free CP r1, r32 JAL r31, r0, :new - LD r31, r254, 0a, 16h - ADDI64 r254, r254, 16d + LD r31, r254, 0a, 32h + ADDI64 r254, r254, 32d JALA r0, r31, 0a free: CP r10, r2 @@ -23,21 +23,21 @@ free: ECA JALA r0, r31, 0a main: - ADDI64 r254, r254, -48d - ST r31, r254, 24a, 24h + ADDI64 r254, r254, -56d + ST r31, r254, 24a, 32h ADDI64 r32, r254, 0d CP r1, r32 JAL r31, r0, :new LI64 r3, 69d CP r2, r32 JAL r31, r0, :push - LD r9, r254, 0a, 8h - LD r33, r9, 0a, 8h + LD r33, r254, 0a, 8h + LD r34, r33, 0a, 8h CP r2, r32 JAL r31, r0, :deinit - CP r1, r33 - LD r31, r254, 24a, 24h - ADDI64 r254, r254, 48d + CP r1, r34 + LD r31, r254, 24a, 32h + ADDI64 r254, r254, 56d JALA r0, r31, 0a malloc: CP r9, r2 @@ -58,69 +58,69 @@ new: ADDI64 r254, r254, 24d JALA r0, r31, 0a push: - ADDI64 r254, r254, -72d - ST r31, r254, 0a, 72h + ADDI64 r254, r254, -192d + ST r31, r254, 0a, 192h CP r32, r3 LI64 r33, 1d - LD r6, r2, 8a, 8h - LD r8, r2, 16a, 8h - CP r34, r2 - JNE r8, r6, :0 - LI64 r35, 0d - JNE r8, r35, :1 - CP r36, r33 + LD r34, r2, 8a, 8h + LD r35, r2, 16a, 8h + CP r36, r2 + JNE r35, r34, :0 + LI64 r37, 0d + JNE r35, r37, :1 + CP r38, r33 JMP :2 - 1: MULI64 r36, r8, 2d - 2: LI64 r37, 8d - MUL64 r2, r36, r37 - CP r3, r37 + 1: MULI64 r38, r35, 2d + 2: LI64 r39, 8d + MUL64 r2, r38, r39 + CP r3, r39 JAL r31, r0, :malloc - CP r38, r1 - CP r39, r34 - ST r36, r39, 16a, 8h + CP r40, r1 + CP r41, r36 + ST r38, r41, 16a, 8h LI64 r1, 0d - CP r7, r38 - JNE r7, r1, :3 + CP r42, r40 + JNE r42, r1, :3 JMP :4 - 3: CP r38, r7 - LD r8, r39, 8a, 8h - MULI64 r10, r8, 8d - LD r3, r39, 0a, 8h - ADD64 r7, r3, r10 - CP r5, r38 - 9: LD r2, r39, 0a, 8h - LD r10, r39, 8a, 8h - JNE r7, r3, :5 - JEQ r10, r35, :6 - CP r4, r37 - MUL64 r3, r10, r4 + 3: CP r40, r42 + LD r36, r41, 8a, 8h + MULI64 r43, r36, 8d + LD r44, r41, 0a, 8h + ADD64 r45, r44, r43 + CP r46, r40 + 9: LD r2, r41, 0a, 8h + LD r47, r41, 8a, 8h + JNE r45, r44, :5 + JEQ r47, r37, :6 + CP r4, r39 + MUL64 r3, r47, r4 JAL r31, r0, :free - CP r6, r38 + CP r1, r40 JMP :7 - 6: CP r6, r38 - 7: ST r6, r39, 0a, 8h + 6: CP r1, r40 + 7: ST r1, r41, 0a, 8h JMP :8 - 5: CP r4, r37 - CP r6, r38 - ADDI64 r8, r5, 8d - ADDI64 r9, r3, 8d - LD r10, r3, 0a, 8h - ST r10, r5, 0a, 8h - CP r3, r9 - CP r5, r8 + 5: CP r1, r40 + CP r4, r39 + ADDI64 r48, r46, 8d + ADDI64 r42, r44, 8d + LD r49, r44, 0a, 8h + ST r49, r46, 0a, 8h + CP r44, r42 + CP r46, r48 JMP :9 - 0: CP r39, r34 - 8: LD r5, r39, 8a, 8h - MULI64 r7, r5, 8d - LD r6, r39, 0a, 8h - ADD64 r1, r6, r7 + 0: CP r41, r36 + 8: LD r50, r41, 8a, 8h + MULI64 r51, r50, 8d + LD r52, r41, 0a, 8h + ADD64 r1, r52, r51 CP r3, r32 ST r3, r1, 0a, 8h - LD r2, r39, 8a, 8h - ADD64 r3, r2, r33 - ST r3, r39, 8a, 8h - 4: LD r31, r254, 0a, 72h - ADDI64 r254, r254, 72d + LD r53, r41, 8a, 8h + ADD64 r54, r53, r33 + ST r54, r41, 8a, 8h + 4: LD r31, r254, 0a, 192h + ADDI64 r254, r254, 192d JALA r0, r31, 0a code size: 955 ret: 69 diff --git a/lang/tests/son_tests_global_aliasing_overptimization.txt b/lang/tests/son_tests_global_aliasing_overptimization.txt index 5d1a573..9fe9282 100644 --- a/lang/tests/son_tests_global_aliasing_overptimization.txt +++ b/lang/tests/son_tests_global_aliasing_overptimization.txt @@ -4,15 +4,15 @@ clobber: ST r3, r1, 0a, 8h JALA r0, r31, 0a main: - ADDI64 r254, r254, -16d - ST r31, r254, 0a, 16h + ADDI64 r254, r254, -24d + ST r31, r254, 0a, 24h LRA r32, r0, :var - LI64 r3, 2d - ST r3, r32, 0a, 8h + LI64 r33, 2d + ST r33, r32, 0a, 8h JAL r31, r0, :clobber LD r1, r32, 0a, 8h - LD r31, r254, 0a, 16h - ADDI64 r254, r254, 16d + LD r31, r254, 0a, 24h + ADDI64 r254, r254, 24d JALA r0, r31, 0a code size: 166 ret: 0 diff --git a/lang/tests/son_tests_if_statements.txt b/lang/tests/son_tests_if_statements.txt index 65a7815..852e400 100644 --- a/lang/tests/son_tests_if_statements.txt +++ b/lang/tests/son_tests_if_statements.txt @@ -1,22 +1,21 @@ fib: - ADDI64 r254, r254, -32d - ST r31, r254, 0a, 32h + ADDI64 r254, r254, -40d + ST r31, r254, 0a, 40h LI64 r1, 1d LI64 r32, 2d JGTU r2, r32, :0 JMP :1 - 0: CP r6, r2 - SUB64 r2, r6, r1 - CP r33, r6 + 0: CP r33, r2 + SUB64 r2, r33, r1 + CP r34, r33 JAL r31, r0, :fib - CP r2, r33 - CP r34, r1 + CP r2, r34 + CP r35, r1 SUB64 r2, r2, r32 JAL r31, r0, :fib - CP r8, r34 - ADD64 r1, r1, r8 - 1: LD r31, r254, 0a, 32h - ADDI64 r254, r254, 32d + ADD64 r1, r1, r35 + 1: LD r31, r254, 0a, 40h + ADDI64 r254, r254, 40d JALA r0, r31, 0a main: ADDI64 r254, r254, -8d @@ -26,6 +25,6 @@ main: LD r31, r254, 0a, 8h ADDI64 r254, r254, 8d JALA r0, r31, 0a -code size: 214 +code size: 211 ret: 55 status: Ok(()) diff --git a/lang/tests/son_tests_inline_test.txt b/lang/tests/son_tests_inline_test.txt index 77d182b..035bb3f 100644 --- a/lang/tests/son_tests_inline_test.txt +++ b/lang/tests/son_tests_inline_test.txt @@ -1,22 +1,21 @@ main: - ADDI64 r254, r254, -16d - ST r31, r254, 0a, 16h + ADDI64 r254, r254, -32d + ST r31, r254, 0a, 32h JAL r31, r0, :scalar_values - LI64 r3, 0d - CP r8, r3 - JEQ r1, r8, :0 + LI64 r32, 0d + CP r33, r32 + JEQ r1, r33, :0 LI64 r1, 1d JMP :1 - 0: CP r32, r8 - JAL r31, r0, :structs - CP r3, r32 - JEQ r1, r3, :2 + 0: JAL r31, r0, :structs + CP r34, r33 + JEQ r1, r34, :2 JAL r31, r0, :structs JMP :1 - 2: CP r1, r3 - CP r32, r3 - 1: LD r31, r254, 0a, 16h - ADDI64 r254, r254, 16d + 2: CP r1, r34 + CP r33, r34 + 1: LD r31, r254, 0a, 32h + ADDI64 r254, r254, 32d JALA r0, r31, 0a scalar_values: LI64 r1, 0d @@ -35,6 +34,6 @@ structs: SUB64 r1, r1, r10 ADDI64 r254, r254, 32d JALA r0, r31, 0a -code size: 310 +code size: 307 ret: 0 status: Ok(()) diff --git a/lang/tests/son_tests_inlining_issues.txt b/lang/tests/son_tests_inlining_issues.txt index 318c5a1..c4608ce 100644 --- a/lang/tests/son_tests_inlining_issues.txt +++ b/lang/tests/son_tests_inlining_issues.txt @@ -1,32 +1,32 @@ main: - ADDI64 r254, r254, -66d - ST r31, r254, 58a, 8h - ADDI64 r3, r254, 33d + ADDI64 r254, r254, -106d + ST r31, r254, 58a, 48h + ADDI64 r32, r254, 33d ADDI64 r2, r254, 34d ADDI64 r6, r254, 1d - LI64 r9, 0d + LI64 r33, 0d ADDI64 r4, r254, 17d - ST r3, r254, 34a, 8h - LI64 r10, 100d + ST r32, r254, 34a, 8h + LI64 r34, 100d ADDI64 r7, r254, 0d - LI8 r5, 1b - ST r9, r254, 1a, 8h - ST r9, r254, 17a, 8h - ST r10, r254, 42a, 8h - LI8 r3, 0b - ST r5, r254, 0a, 1h - ST r9, r254, 9a, 8h - ST r9, r254, 25a, 8h - ST r10, r254, 50a, 8h - ST r3, r254, 33a, 1h + LI8 r35, 1b + ST r33, r254, 1a, 8h + ST r33, r254, 17a, 8h + ST r34, r254, 42a, 8h + LI8 r36, 0b + ST r35, r254, 0a, 1h + ST r33, r254, 9a, 8h + ST r33, r254, 25a, 8h + ST r34, r254, 50a, 8h + ST r36, r254, 33a, 1h CP r3, r4 CP r5, r6 LD r3, r3, 0a, 16h LD r5, r5, 0a, 16h LD r7, r7, 0a, 1h JAL r31, r0, :put_filled_rect - LD r31, r254, 58a, 8h - ADDI64 r254, r254, 66d + LD r31, r254, 58a, 48h + ADDI64 r254, r254, 106d JALA r0, r31, 0a put_filled_rect: ADDI64 r254, r254, -212d diff --git a/lang/tests/son_tests_intcast_store.txt b/lang/tests/son_tests_intcast_store.txt index 05870f6..8e8874c 100644 --- a/lang/tests/son_tests_intcast_store.txt +++ b/lang/tests/son_tests_intcast_store.txt @@ -1,16 +1,16 @@ main: - ADDI64 r254, r254, -24d - ST r31, r254, 16a, 8h + ADDI64 r254, r254, -32d + ST r31, r254, 16a, 16h ADDI64 r3, r254, 0d ADDI64 r2, r254, 8d - LI64 r4, 0d - ST r4, r254, 0a, 8h - ST r4, r254, 8a, 8h + LI64 r32, 0d + ST r32, r254, 0a, 8h + ST r32, r254, 8a, 8h LI64 r4, 1024d JAL r31, r0, :set ANDI r1, r1, 4294967295d - LD r31, r254, 16a, 8h - ADDI64 r254, r254, 24d + LD r31, r254, 16a, 16h + ADDI64 r254, r254, 32d JALA r0, r31, 0a set: CP r1, r4 diff --git a/lang/tests/son_tests_more_if_opts.txt b/lang/tests/son_tests_more_if_opts.txt index 370ebd2..378e925 100644 --- a/lang/tests/son_tests_more_if_opts.txt +++ b/lang/tests/son_tests_more_if_opts.txt @@ -1,23 +1,23 @@ main: - ADDI64 r254, r254, -16d - ST r31, r254, 0a, 16h + ADDI64 r254, r254, -32d + ST r31, r254, 0a, 32h JAL r31, r0, :opaque CP r32, r1 JAL r31, r0, :opaque - LI64 r6, 0d + LI64 r33, 0d CP r1, r32 - JNE r1, r6, :0 + JNE r1, r33, :0 CP r32, r1 LI64 r1, 0d - CP r3, r32 + CP r34, r32 JMP :1 - 0: CP r3, r1 - LD r1, r3, 0a, 8h - 1: JEQ r3, r6, :2 - LD r1, r3, 0a, 8h + 0: CP r34, r1 + LD r1, r34, 0a, 8h + 1: JEQ r34, r33, :2 + LD r1, r34, 0a, 8h JMP :2 - 2: LD r31, r254, 0a, 16h - ADDI64 r254, r254, 16d + 2: LD r31, r254, 0a, 32h + ADDI64 r254, r254, 32d JALA r0, r31, 0a opaque: LI64 r1, 0d diff --git a/lang/tests/son_tests_null_check_test.txt b/lang/tests/son_tests_null_check_test.txt index d3bf60f..dc24071 100644 --- a/lang/tests/son_tests_null_check_test.txt +++ b/lang/tests/son_tests_null_check_test.txt @@ -4,22 +4,22 @@ get_ptr: ADDI64 r254, r254, 8d JALA r0, r31, 0a main: - ADDI64 r254, r254, -8d - ST r31, r254, 0a, 8h + ADDI64 r254, r254, -40d + ST r31, r254, 0a, 40h JAL r31, r0, :get_ptr - LI64 r3, 0d - JNE r1, r3, :0 + LI64 r32, 0d + JNE r1, r32, :0 LI64 r1, 0d JMP :1 - 0: LI64 r10, 10d - CP r2, r1 - 2: LD r1, r2, 0a, 8h - JEQ r1, r10, :1 - ADDI64 r3, r1, 1d - ST r3, r2, 0a, 8h + 0: LI64 r33, 10d + CP r34, r1 + 2: LD r1, r34, 0a, 8h + JEQ r1, r33, :1 + ADDI64 r35, r1, 1d + ST r35, r34, 0a, 8h JMP :2 - 1: LD r31, r254, 0a, 8h - ADDI64 r254, r254, 8d + 1: LD r31, r254, 0a, 40h + ADDI64 r254, r254, 40d JALA r0, r31, 0a code size: 208 ret: 10 diff --git a/lang/tests/son_tests_nullable_types.txt b/lang/tests/son_tests_nullable_types.txt index 2acf9c2..0afdada 100644 --- a/lang/tests/son_tests_nullable_types.txt +++ b/lang/tests/son_tests_nullable_types.txt @@ -2,77 +2,77 @@ decide: LI8 r1, 1b JALA r0, r31, 0a main: - ADDI64 r254, r254, -136d - ST r31, r254, 80a, 56h + ADDI64 r254, r254, -224d + ST r31, r254, 80a, 144h JAL r31, r0, :decide - LI64 r4, 0d + LI64 r32, 0d ADDI64 r2, r254, 72d - CP r32, r2 + CP r33, r2 ANDI r1, r1, 255d JNE r1, r0, :0 - CP r33, r4 + CP r34, r32 JMP :1 - 0: CP r33, r32 - 1: JNE r33, r4, :2 + 0: CP r34, r33 + 1: JNE r34, r32, :2 LI64 r1, 9001d JMP :3 2: JAL r31, r0, :decide - LI8 r34, 0b + LI8 r35, 0b ANDI r1, r1, 255d JNE r1, r0, :4 - LI8 r8, 1b - ST r8, r254, 56a, 1h - LD r9, r33, 0a, 8h - ST r9, r254, 64a, 8h + LI8 r36, 1b + ST r36, r254, 56a, 1h + LD r36, r34, 0a, 8h + ST r36, r254, 64a, 8h JMP :5 - 4: ST r34, r254, 56a, 1h - 5: LD r6, r254, 56a, 1h - ANDI r6, r6, 255d - ANDI r34, r34, 255d - JEQ r6, r34, :6 + 4: ST r35, r254, 56a, 1h + 5: LD r37, r254, 56a, 1h + ANDI r37, r37, 255d + ANDI r35, r35, 255d + JEQ r37, r35, :6 LI64 r1, 42d JMP :3 6: JAL r31, r0, :decide - LI32 r2, 0w + LI32 r38, 0w ANDI r1, r1, 255d JNE r1, r0, :7 - CP r35, r2 + CP r39, r38 JMP :8 - 7: LI32 r35, 8388609w - 8: ANDI r35, r35, 4294967295d - ANDI r2, r2, 4294967295d - JNE r35, r2, :9 + 7: LI32 r39, 8388609w + 8: ANDI r39, r39, 4294967295d + ANDI r38, r38, 4294967295d + JNE r39, r38, :9 LI64 r1, 69d JMP :3 9: ADDI64 r3, r254, 40d - CP r36, r3 + CP r40, r3 JAL r31, r0, :new_foo ST r1, r254, 40a, 16h - LI64 r37, 0d - LD r7, r254, 40a, 8h - JNE r7, r37, :10 + LI64 r32, 0d + LD r41, r254, 40a, 8h + JNE r41, r32, :10 LI64 r1, 999d JMP :3 10: LRA r4, r0, :"foo\0" - CP r3, r36 + CP r3, r40 CP r2, r3 LD r2, r2, 0a, 16h JAL r31, r0, :use_foo - ADDI64 r6, r254, 0d + ADDI64 r42, r254, 0d JAL r31, r0, :no_foo ST r1, r254, 0a, 16h JAL r31, r0, :decide ANDI r1, r1, 255d JNE r1, r0, :11 - CP r2, r32 + CP r2, r33 JMP :12 -11: CP r2, r32 +11: CP r2, r33 ST r2, r254, 0a, 8h - LI64 r12, 1d - ST r12, r254, 8a, 8h - ST r12, r254, 72a, 8h -12: LD r6, r254, 0a, 8h - JNE r6, r37, :13 + LI64 r43, 1d + ST r43, r254, 8a, 8h + ST r43, r254, 72a, 8h +12: LD r44, r254, 0a, 8h + JNE r44, r32, :13 LI64 r1, 34d JMP :3 13: ADDI64 r1, r254, 16d @@ -81,19 +81,19 @@ main: ANDI r1, r1, 255d JNE r1, r0, :14 JMP :15 -14: ST r34, r254, 16a, 1h -15: LD r10, r254, 16a, 1h - ANDI r10, r10, 255d - ANDI r34, r34, 255d - JEQ r10, r34, :16 +14: ST r35, r254, 16a, 1h +15: LD r45, r254, 16a, 1h + ANDI r45, r45, 255d + ANDI r35, r35, 255d + JEQ r45, r35, :16 LI64 r1, 420d JMP :3 -16: LD r4, r254, 0a, 8h - LD r6, r4, 0a, 8h - ANDI r8, r35, 65535d - SUB64 r1, r8, r6 - 3: LD r31, r254, 80a, 56h - ADDI64 r254, r254, 136d +16: LD r46, r254, 0a, 8h + LD r47, r46, 0a, 8h + ANDI r48, r39, 65535d + SUB64 r1, r48, r47 + 3: LD r31, r254, 80a, 144h + ADDI64 r254, r254, 224d JALA r0, r31, 0a new_bar: ADDI64 r254, r254, -24d diff --git a/lang/tests/son_tests_only_break_loop.txt b/lang/tests/son_tests_only_break_loop.txt index 93b55da..b353a8c 100644 --- a/lang/tests/son_tests_only_break_loop.txt +++ b/lang/tests/son_tests_only_break_loop.txt @@ -2,14 +2,14 @@ inb: CP r1, r2 JALA r0, r31, 0a main: - ADDI64 r254, r254, -24d - ST r31, r254, 0a, 24h + ADDI64 r254, r254, -32d + ST r31, r254, 0a, 32h LI64 r32, 0d LI64 r33, 100d 4: CP r2, r33 JAL r31, r0, :inb - ANDI r7, r1, 2d - JNE r7, r32, :0 + ANDI r34, r1, 2d + JNE r34, r32, :0 LI64 r2, 96d CP r3, r32 JAL r31, r0, :outb @@ -20,8 +20,8 @@ main: JMP :2 1: JMP :3 0: JMP :4 - 2: LD r31, r254, 0a, 24h - ADDI64 r254, r254, 24d + 2: LD r31, r254, 0a, 32h + ADDI64 r254, r254, 32d JALA r0, r31, 0a outb: JALA r0, r31, 0a diff --git a/lang/tests/son_tests_overwrite_aliasing_overoptimization.txt b/lang/tests/son_tests_overwrite_aliasing_overoptimization.txt index 72aae6b..ec02dec 100644 --- a/lang/tests/son_tests_overwrite_aliasing_overoptimization.txt +++ b/lang/tests/son_tests_overwrite_aliasing_overoptimization.txt @@ -1,23 +1,23 @@ main: - ADDI64 r254, r254, -48d - ST r31, r254, 40a, 8h - LI64 r4, 4d - ADDI64 r3, r254, 24d - ADDI64 r6, r254, 0d - ST r4, r254, 24a, 8h - LI64 r5, 1d - ST r5, r254, 32a, 8h - ST r5, r254, 16a, 8h - BMC r3, r6, 16h + ADDI64 r254, r254, -104d + ST r31, r254, 40a, 64h + LI64 r32, 4d + ADDI64 r33, r254, 24d + ADDI64 r34, r254, 0d + ST r32, r254, 24a, 8h + LI64 r35, 1d + ST r35, r254, 32a, 8h + ST r35, r254, 16a, 8h + BMC r33, r34, 16h JAL r31, r0, :opaque ST r1, r254, 0a, 16h - LD r4, r254, 8a, 8h - LD r6, r254, 16a, 8h - ADD64 r8, r6, r4 - LD r6, r254, 0a, 8h - SUB64 r1, r6, r8 - LD r31, r254, 40a, 8h - ADDI64 r254, r254, 48d + LD r36, r254, 8a, 8h + LD r37, r254, 16a, 8h + ADD64 r38, r37, r36 + LD r37, r254, 0a, 8h + SUB64 r1, r37, r38 + LD r31, r254, 40a, 64h + ADDI64 r254, r254, 104d JALA r0, r31, 0a opaque: ADDI64 r254, r254, -16d diff --git a/lang/tests/son_tests_pointer_opts.txt b/lang/tests/son_tests_pointer_opts.txt index bbf3ccb..f8db122 100644 --- a/lang/tests/son_tests_pointer_opts.txt +++ b/lang/tests/son_tests_pointer_opts.txt @@ -3,17 +3,17 @@ clobber: ST r3, r2, 0a, 8h JALA r0, r31, 0a main: - ADDI64 r254, r254, -16d - ST r31, r254, 8a, 8h + ADDI64 r254, r254, -40d + ST r31, r254, 8a, 32h ADDI64 r2, r254, 0d - LI64 r3, 2d - ST r3, r254, 0a, 8h + LI64 r32, 2d + ST r32, r254, 0a, 8h JAL r31, r0, :clobber - LD r8, r254, 0a, 8h - LI64 r9, 4d - SUB64 r1, r9, r8 - LD r31, r254, 8a, 8h - ADDI64 r254, r254, 16d + LD r33, r254, 0a, 8h + LI64 r34, 4d + SUB64 r1, r34, r33 + LD r31, r254, 8a, 32h + ADDI64 r254, r254, 40d JALA r0, r31, 0a code size: 169 ret: 0 diff --git a/lang/tests/son_tests_pointers.txt b/lang/tests/son_tests_pointers.txt index ec81e27..3376e76 100644 --- a/lang/tests/son_tests_pointers.txt +++ b/lang/tests/son_tests_pointers.txt @@ -1,18 +1,18 @@ drop: JALA r0, r31, 0a main: - ADDI64 r254, r254, -24d - ST r31, r254, 8a, 16h + ADDI64 r254, r254, -32d + ST r31, r254, 8a, 24h ADDI64 r2, r254, 0d LI64 r32, 1d ST r32, r254, 0a, 8h JAL r31, r0, :modify CP r2, r32 JAL r31, r0, :drop - LD r8, r254, 0a, 8h - ADDI64 r1, r8, -2d - LD r31, r254, 8a, 16h - ADDI64 r254, r254, 24d + LD r33, r254, 0a, 8h + ADDI64 r1, r33, -2d + LD r31, r254, 8a, 24h + ADDI64 r254, r254, 32d JALA r0, r31, 0a modify: LI64 r3, 2d diff --git a/lang/tests/son_tests_request_page.txt b/lang/tests/son_tests_request_page.txt index 03c37f1..e249c8f 100644 --- a/lang/tests/son_tests_request_page.txt +++ b/lang/tests/son_tests_request_page.txt @@ -1,6 +1,6 @@ create_back_buffer: - ADDI64 r254, r254, -48d - ST r31, r254, 0a, 48h + ADDI64 r254, r254, -56d + ST r31, r254, 0a, 56h LI64 r32, 255d JGTS r2, r32, :0 JAL r31, r0, :request_page @@ -9,23 +9,23 @@ create_back_buffer: LI8 r34, 255b CP r2, r34 JAL r31, r0, :request_page - CP r35, r1 - LI64 r36, 0d + LI64 r35, 0d CP r2, r33 - SUB64 r33, r2, r32 - 5: JGTS r33, r36, :2 - CP r1, r35 + SUB64 r36, r2, r32 + 5: JGTS r36, r35, :2 JMP :1 - 2: JLTS r33, r32, :3 + 2: CP r37, r1 + JLTS r36, r32, :3 CP r2, r34 JAL r31, r0, :request_page JMP :4 - 3: CP r2, r33 + 3: CP r2, r36 JAL r31, r0, :request_page - 4: SUB64 r33, r33, r32 + 4: SUB64 r36, r36, r32 + CP r1, r37 JMP :5 - 1: LD r31, r254, 0a, 48h - ADDI64 r254, r254, 48d + 1: LD r31, r254, 0a, 56h + ADDI64 r254, r254, 56d JALA r0, r31, 0a main: ADDI64 r254, r254, -8d diff --git a/lang/tests/son_tests_returning_global_struct.txt b/lang/tests/son_tests_returning_global_struct.txt index 6f3bca0..ea20c83 100644 --- a/lang/tests/son_tests_returning_global_struct.txt +++ b/lang/tests/son_tests_returning_global_struct.txt @@ -1,22 +1,22 @@ main: - ADDI64 r254, r254, -12d - ST r31, r254, 4a, 8h - ADDI64 r2, r254, 0d + ADDI64 r254, r254, -100d + ST r31, r254, 4a, 96h + ADDI64 r32, r254, 0d JAL r31, r0, :random_color ST r1, r254, 0a, 4h - LD r5, r254, 0a, 1h - LD r8, r254, 1a, 1h - LD r12, r254, 2a, 1h - ANDI r9, r5, 255d - ANDI r1, r8, 255d - LD r6, r254, 3a, 1h - ANDI r5, r12, 255d - ADD64 r4, r1, r9 - ANDI r10, r6, 255d - ADD64 r9, r4, r5 - ADD64 r1, r9, r10 - LD r31, r254, 4a, 8h - ADDI64 r254, r254, 12d + LD r33, r254, 0a, 1h + LD r34, r254, 1a, 1h + LD r35, r254, 2a, 1h + ANDI r36, r33, 255d + ANDI r37, r34, 255d + LD r38, r254, 3a, 1h + ANDI r39, r35, 255d + ADD64 r40, r37, r36 + ANDI r41, r38, 255d + ADD64 r42, r40, r39 + ADD64 r1, r42, r41 + LD r31, r254, 4a, 96h + ADDI64 r254, r254, 100d JALA r0, r31, 0a random_color: LRA r1, r0, :white diff --git a/lang/tests/son_tests_small_struct_bitcast.txt b/lang/tests/son_tests_small_struct_bitcast.txt index 7ecaf98..0e299b4 100644 --- a/lang/tests/son_tests_small_struct_bitcast.txt +++ b/lang/tests/son_tests_small_struct_bitcast.txt @@ -1,25 +1,25 @@ main: - ADDI64 r254, r254, -12d - ST r31, r254, 4a, 8h - LRA r1, r0, :white - ADDI64 r4, r254, 0d - LD r2, r1, 0a, 4h + ADDI64 r254, r254, -36d + ST r31, r254, 4a, 32h + LRA r32, r0, :white + ADDI64 r33, r254, 0d + LD r2, r32, 0a, 4h JAL r31, r0, :u32_to_color ST r1, r254, 0a, 4h - LD r9, r254, 0a, 1h - ANDI r1, r9, 255d - LD r31, r254, 4a, 8h - ADDI64 r254, r254, 12d + LD r34, r254, 0a, 1h + ANDI r1, r34, 255d + LD r31, r254, 4a, 32h + ADDI64 r254, r254, 36d JALA r0, r31, 0a u32_to_color: - ADDI64 r254, r254, -12d - ST r31, r254, 4a, 8h + ADDI64 r254, r254, -20d + ST r31, r254, 4a, 16h JAL r31, r0, :u32_to_u32 - ADDI64 r5, r254, 0d + ADDI64 r32, r254, 0d ST r1, r254, 0a, 4h - LD r1, r5, 0a, 4h - LD r31, r254, 4a, 8h - ADDI64 r254, r254, 12d + LD r1, r32, 0a, 4h + LD r31, r254, 4a, 16h + ADDI64 r254, r254, 20d JALA r0, r31, 0a u32_to_u32: CP r1, r2 diff --git a/lang/tests/son_tests_struct_patterns.txt b/lang/tests/son_tests_struct_patterns.txt index 46b7218..28b22bb 100644 --- a/lang/tests/son_tests_struct_patterns.txt +++ b/lang/tests/son_tests_struct_patterns.txt @@ -4,15 +4,14 @@ fib: CP r32, r2 LI64 r33, 2d JLTU r2, r33, :0 - CP r6, r32 - ADDI64 r2, r6, -1d + CP r34, r32 + ADDI64 r2, r34, -1d JAL r31, r0, :fib CP r2, r32 CP r34, r1 SUB64 r2, r2, r33 JAL r31, r0, :fib - CP r6, r34 - ADD64 r1, r1, r6 + ADD64 r1, r1, r34 JMP :1 0: CP r1, r32 1: LD r31, r254, 0a, 32h @@ -41,11 +40,10 @@ main: CP r2, r32 CP r33, r1 JAL r31, r0, :fib_iter - CP r9, r33 - SUB64 r1, r9, r1 + SUB64 r1, r33, r1 LD r31, r254, 0a, 24h ADDI64 r254, r254, 24d JALA r0, r31, 0a -code size: 306 +code size: 300 ret: 0 status: Ok(()) diff --git a/lang/tests/son_tests_struct_return_from_module_function.txt b/lang/tests/son_tests_struct_return_from_module_function.txt index 3d0e7cc..c17dbb3 100644 --- a/lang/tests/son_tests_struct_return_from_module_function.txt +++ b/lang/tests/son_tests_struct_return_from_module_function.txt @@ -10,28 +10,28 @@ foo: ADDI64 r254, r254, 16d JALA r0, r31, 0a main: - ADDI64 r254, r254, -56d - ST r31, r254, 48a, 8h - ADDI64 r2, r254, 32d + ADDI64 r254, r254, -128d + ST r31, r254, 48a, 80h + ADDI64 r32, r254, 32d JAL r31, r0, :foo ST r1, r254, 32a, 16h - ADDI64 r7, r254, 16d + ADDI64 r33, r254, 16d JAL r31, r0, :foo ST r1, r254, 16a, 16h - ADDI64 r2, r254, 0d + ADDI64 r34, r254, 0d JAL r31, r0, :foo ST r1, r254, 0a, 16h - LD r1, r254, 24a, 4h - LD r7, r254, 12a, 4h - ANDI r4, r1, 4294967295d - LD r1, r254, 32a, 8h - ANDI r11, r7, 4294967295d - ADD64 r8, r1, r4 - ADD64 r2, r8, r11 - LI64 r3, 7d - SUB64 r1, r3, r2 - LD r31, r254, 48a, 8h - ADDI64 r254, r254, 56d + LD r35, r254, 24a, 4h + LD r36, r254, 12a, 4h + ANDI r37, r35, 4294967295d + LD r35, r254, 32a, 8h + ANDI r38, r36, 4294967295d + ADD64 r39, r35, r37 + ADD64 r40, r39, r38 + LI64 r34, 7d + SUB64 r1, r34, r40 + LD r31, r254, 48a, 80h + ADDI64 r254, r254, 128d JALA r0, r31, 0a code size: 355 ret: 0 diff --git a/lang/tests/son_tests_structs.txt b/lang/tests/son_tests_structs.txt index c630e38..7a590a3 100644 --- a/lang/tests/son_tests_structs.txt +++ b/lang/tests/son_tests_structs.txt @@ -1,24 +1,24 @@ main: - ADDI64 r254, r254, -56d - ST r31, r254, 32a, 24h - LI64 r2, 4d + ADDI64 r254, r254, -72d + ST r31, r254, 32a, 40h + LI64 r32, 4d ADDI64 r4, r254, 16d - ST r2, r254, 16a, 8h - LI64 r32, 3d - ST r32, r254, 24a, 8h - ADDI64 r33, r254, 0d + ST r32, r254, 16a, 8h + LI64 r33, 3d + ST r33, r254, 24a, 8h + ADDI64 r34, r254, 0d CP r3, r4 LD r3, r3, 0a, 16h JAL r31, r0, :odher_pass ST r1, r254, 0a, 16h - LD r2, r254, 8a, 8h - JNE r2, r32, :0 - CP r2, r33 + LD r35, r254, 8a, 8h + JNE r35, r33, :0 + CP r2, r34 JAL r31, r0, :pass JMP :1 0: LI64 r1, 0d - 1: LD r31, r254, 32a, 24h - ADDI64 r254, r254, 56d + 1: LD r31, r254, 32a, 40h + ADDI64 r254, r254, 72d JALA r0, r31, 0a odher_pass: ADDI64 r254, r254, -16d diff --git a/lang/tests/son_tests_wide_ret.txt b/lang/tests/son_tests_wide_ret.txt index baac64a..2d01e04 100644 --- a/lang/tests/son_tests_wide_ret.txt +++ b/lang/tests/son_tests_wide_ret.txt @@ -1,47 +1,47 @@ main: - ADDI64 r254, r254, -24d - ST r31, r254, 16a, 8h - ADDI64 r3, r254, 0d + ADDI64 r254, r254, -56d + ST r31, r254, 16a, 40h + ADDI64 r32, r254, 0d LI64 r4, 0d CP r3, r4 JAL r31, r0, :maina ST r1, r254, 0a, 16h - LD r8, r254, 12a, 1h - LD r9, r254, 3a, 1h - SUB8 r11, r9, r8 - ANDI r1, r11, 255d - LD r31, r254, 16a, 8h - ADDI64 r254, r254, 24d + LD r33, r254, 12a, 1h + LD r34, r254, 3a, 1h + SUB8 r35, r34, r33 + ANDI r1, r35, 255d + LD r31, r254, 16a, 40h + ADDI64 r254, r254, 56d JALA r0, r31, 0a maina: - ADDI64 r254, r254, -28d - ST r31, r254, 20a, 8h - ADDI64 r5, r254, 16d + ADDI64 r254, r254, -68d + ST r31, r254, 20a, 48h + ADDI64 r32, r254, 16d JAL r31, r0, :small_struct ST r1, r254, 16a, 4h - LI8 r9, 0b - ADDI64 r1, r254, 0d - ST r9, r254, 0a, 1h - ST r9, r254, 1a, 1h - ST r9, r254, 2a, 1h - LI8 r3, 3b - ST r3, r254, 3a, 1h - LI8 r6, 1b - ST r6, r254, 4a, 1h - ST r9, r254, 5a, 1h - ST r9, r254, 6a, 1h - ST r9, r254, 7a, 1h - ST r9, r254, 8a, 1h - ST r9, r254, 9a, 1h - ST r9, r254, 10a, 1h - ST r3, r254, 11a, 1h - ST r6, r254, 12a, 1h - ST r9, r254, 13a, 1h - ST r9, r254, 14a, 1h - ST r9, r254, 15a, 1h - LD r1, r1, 0a, 16h - LD r31, r254, 20a, 8h - ADDI64 r254, r254, 28d + LI8 r33, 0b + ADDI64 r34, r254, 0d + ST r33, r254, 0a, 1h + ST r33, r254, 1a, 1h + ST r33, r254, 2a, 1h + LI8 r35, 3b + ST r35, r254, 3a, 1h + LI8 r36, 1b + ST r36, r254, 4a, 1h + ST r33, r254, 5a, 1h + ST r33, r254, 6a, 1h + ST r33, r254, 7a, 1h + ST r33, r254, 8a, 1h + ST r33, r254, 9a, 1h + ST r33, r254, 10a, 1h + ST r35, r254, 11a, 1h + ST r36, r254, 12a, 1h + ST r33, r254, 13a, 1h + ST r33, r254, 14a, 1h + ST r33, r254, 15a, 1h + LD r1, r34, 0a, 16h + LD r31, r254, 20a, 48h + ADDI64 r254, r254, 68d JALA r0, r31, 0a small_struct: ADDI64 r254, r254, -4d