diff --git a/lang/src/codegen.rs b/lang/src/codegen.rs index 625512b..1869abb 100644 --- a/lang/src/codegen.rs +++ b/lang/src/codegen.rs @@ -1,4 +1,3 @@ -pub use self::reg::{RET_ADDR, STACK_PTR, ZERO}; use { crate::{ ident::{self, Ident}, @@ -7,13 +6,13 @@ use { parser::{ self, find_symbol, idfl, CommentOr, CtorField, Expr, ExprRef, FileId, Pos, StructField, }, + reg, ty::{self, TyCheck}, - Field, Func, Global, LoggedMem, OffsetIter, ParamAlloc, Reloc, Sig, Struct, SymKey, - TypedReloc, Types, HEADER_SIZE, + Comptime, Field, Func, Global, OffsetIter, ParamAlloc, Reloc, Sig, Struct, SymKey, + TypedReloc, Types, }, - alloc::{boxed::Box, string::String, vec::Vec}, - core::fmt::Display, - std::assert_matches::debug_assert_matches, + alloc::{string::String, vec::Vec}, + core::{assert_matches::debug_assert_matches, fmt::Display}, }; type Offset = u32; @@ -163,13 +162,8 @@ mod stack { } } -mod reg { - use alloc::vec::Vec; - - pub const STACK_PTR: Reg = 254; - pub const ZERO: Reg = 0; - pub const RET: Reg = 1; - pub const RET_ADDR: Reg = 31; +mod rall { + use {crate::reg::*, alloc::vec::Vec}; type Reg = u8; @@ -323,7 +317,7 @@ struct CtValue(u64); #[derive(Debug, PartialEq, Eq)] enum Loc { - Rt { derefed: bool, reg: reg::Id, stack: Option, offset: Offset }, + Rt { derefed: bool, reg: rall::Id, stack: Option, offset: Offset }, Ct { derefed: bool, value: CtValue }, } @@ -332,7 +326,7 @@ impl Loc { Self::Rt { stack: Some(stack), reg: reg::STACK_PTR.into(), derefed: true, offset: 0 } } - fn reg(reg: impl Into) -> Self { + fn reg(reg: impl Into) -> Self { let reg = reg.into(); assert!(reg.get() != 0); Self::Rt { derefed: false, reg, stack: None, offset: 0 } @@ -406,7 +400,7 @@ impl Loc { } fn is_stack(&self) -> bool { - matches!(self, Self::Rt { derefed: true, reg, stack: Some(_), offset: 0 } if reg.get() == STACK_PTR) + matches!(self, Self::Rt { derefed: true, reg, stack: Some(_), offset: 0 } if reg.get() == reg::STACK_PTR) } fn is_reg(&self) -> bool { @@ -414,8 +408,8 @@ impl Loc { } } -impl From for Loc { - fn from(reg: reg::Id) -> Self { +impl From for Loc { + fn from(reg: rall::Id) -> Self { Loc::reg(reg) } } @@ -451,13 +445,13 @@ struct ItemCtx { file: FileId, id: ty::Kind, ret: Option, - ret_reg: reg::Id, + ret_reg: rall::Id, inline_ret_loc: Loc, task_base: usize, stack: stack::Alloc, - regs: reg::Alloc, + regs: rall::Alloc, loops: Vec, vars: Vec, @@ -510,12 +504,12 @@ impl ItemCtx { } fn emit_prelude(&mut self) { - self.emit(instrs::addi64(STACK_PTR, STACK_PTR, 0)); - self.emit(instrs::st(RET_ADDR, STACK_PTR, 0, 0)); + self.emit(instrs::addi64(reg::STACK_PTR, reg::STACK_PTR, 0)); + self.emit(instrs::st(reg::RET_ADDR, reg::STACK_PTR, 0, 0)); } fn emit_entry_prelude(&mut self) { - self.emit(jal(RET_ADDR, reg::ZERO, 0)); + self.emit(jal(reg::RET_ADDR, reg::ZERO, 0)); self.emit(tx()); } @@ -642,32 +636,6 @@ struct Pool { arg_locs: Vec, } -const VM_STACK_SIZE: usize = 1024 * 64; - -pub struct Comptime { - pub vm: hbvm::Vm, - stack: Box<[u8; VM_STACK_SIZE]>, - code: Vec, -} -impl Comptime { - fn reset(&mut self) { - let ptr = unsafe { self.stack.as_mut_ptr().cast::().add(VM_STACK_SIZE) as u64 }; - self.vm.registers.fill(hbvm::value::Value(0)); - self.vm.write_reg(STACK_PTR, ptr); - self.vm.pc = hbvm::mem::Address::new(self.code.as_ptr() as u64 + HEADER_SIZE as u64); - } -} - -impl Default for Comptime { - fn default() -> Self { - let mut stack = Box::<[u8; VM_STACK_SIZE]>::new_uninit(); - let mut vm = hbvm::Vm::default(); - let ptr = unsafe { stack.as_mut_ptr().cast::().add(VM_STACK_SIZE) as u64 }; - vm.write_reg(STACK_PTR, ptr); - Self { vm, stack: unsafe { stack.assume_init() }, code: Default::default() } - } -} - mod trap { use { super::ty, @@ -834,7 +802,7 @@ impl Codegen { ptr = ptr.offset(size); } - self.stack_offset(2, STACK_PTR, Some(&stack), 0); + self.stack_offset(2, reg::STACK_PTR, Some(&stack), 0); let val = self.eca( trap::Trap::MakeStruct(trap::MakeStruct { file: self.ci.file, @@ -1427,7 +1395,7 @@ impl Codegen { let reloc = Reloc::new(self.ci.code.len(), 3, 4); self.ci.relocs.push(TypedReloc { target: ty::Kind::Func(func).compress(), reloc }); - self.ci.emit(jal(RET_ADDR, ZERO, 0)); + self.ci.emit(jal(reg::RET_ADDR, reg::ZERO, 0)); self.make_func_reachable(func); if should_momize { @@ -2194,7 +2162,7 @@ impl Codegen { self.ci.emit(instrs::cp(reg.get(), 1)); self.ci.ret_reg = reg; } else { - self.ci.ret_reg = reg::Id::RET; + self.ci.ret_reg = rall::Id::RET; } if self.expr(body).is_some() { @@ -2208,7 +2176,7 @@ impl Codegen { self.ci.vars = vars; self.ci.finalize(); - self.ci.emit(jala(ZERO, RET_ADDR, 0)); + self.ci.emit(jala(reg::ZERO, reg::RET_ADDR, 0)); self.ci.regs.free(core::mem::take(&mut self.ci.ret_reg)); self.tys.ins.funcs[id as usize].code.append(&mut self.ci.code); self.tys.ins.funcs[id as usize].relocs = self.ci.relocs.drain(..).collect(); @@ -2273,7 +2241,7 @@ impl Codegen { } } - fn loc_to_reg(&mut self, loc: impl Into, size: Size) -> reg::Id { + fn loc_to_reg(&mut self, loc: impl Into, size: Size) -> rall::Id { match loc.into() { LocCow::Owned(Loc::Rt { derefed: false, mut reg, offset, stack }) => { debug_assert!(stack.is_none(), "TODO"); @@ -2711,10 +2679,7 @@ impl Codegen { } self.tys.dump_reachable(last_fn as _, &mut self.ct.code); - let entry = - &mut self.ct.code[self.tys.ins.funcs[last_fn].offset as usize] as *mut _ as _; - let prev_pc = core::mem::replace(&mut self.ct.vm.pc, hbvm::mem::Address::new(entry)) - - self.ct.code.as_ptr() as usize; + let prev_pc = self.ct.push_pc(self.tys.ins.funcs[last_fn].offset); #[cfg(debug_assertions)] { @@ -2731,7 +2696,7 @@ impl Codegen { } self.run_vm(); - self.ct.vm.pc = prev_pc + self.ct.code.as_ptr() as usize; + self.ct.pop_pc(prev_pc); let func = self.tys.ins.funcs.pop().unwrap(); self.ci.code = func.code; @@ -2815,7 +2780,7 @@ impl Codegen { &self.files[self.ci.file as usize] } - fn cow_reg(&mut self, rhs: reg::Id) -> reg::Id { + fn cow_reg(&mut self, rhs: rall::Id) -> rall::Id { if rhs.is_ref() { let reg = self.ci.regs.allocate(); self.ci.emit(cp(reg.get(), rhs.get())); diff --git a/lang/src/lib.rs b/lang/src/lib.rs index cab6d37..e2b0f26 100644 --- a/lang/src/lib.rs +++ b/lang/src/lib.rs @@ -37,7 +37,7 @@ use { parser::{CommentOr, Expr, ExprRef, FileId, Pos}, ty::ArrayLen, }, - alloc::{collections::BTreeMap, string::String, vec::Vec}, + alloc::{boxed::Box, collections::BTreeMap, string::String, vec::Vec}, core::{cell::Cell, ops::Range}, hashbrown::hash_map, hbbytecode as instrs, @@ -531,11 +531,11 @@ mod ty { } impl<'a> Display<'a> { - pub(super) fn new(tys: &'a super::Types, files: &'a [parser::Ast], ty: Id) -> Self { + pub fn new(tys: &'a super::Types, files: &'a [parser::Ast], ty: Id) -> Self { Self { tys, files, ty } } - fn rety(&self, ty: Id) -> Self { + pub fn rety(&self, ty: Id) -> Self { Self::new(self.tys, self.files, ty) } } @@ -1039,7 +1039,7 @@ impl Types { AbleOsExecutableHeader { magic_number: [0x15, 0x91, 0xD2], executable_version: 0, - code_length: (code_length - HEADER_SIZE) as _, + code_length: code_length.saturating_sub(HEADER_SIZE) as _, data_length: data_length as _, debug_length: 0, config_length: 0, @@ -1294,6 +1294,43 @@ impl Default for FnvHasher { } } +const VM_STACK_SIZE: usize = 1024 * 64; + +pub struct Comptime { + pub vm: hbvm::Vm, + stack: Box<[u8; VM_STACK_SIZE]>, + code: Vec, +} + +impl Comptime { + fn reset(&mut self) { + let ptr = unsafe { self.stack.as_mut_ptr().cast::().add(VM_STACK_SIZE) as u64 }; + self.vm.registers.fill(hbvm::value::Value(0)); + self.vm.write_reg(reg::STACK_PTR, ptr); + self.vm.pc = hbvm::mem::Address::new(self.code.as_ptr() as u64 + HEADER_SIZE as u64); + } + + fn push_pc(&mut self, offset: Offset) -> hbvm::mem::Address { + let entry = &mut self.code[offset as usize] as *mut _ as _; + core::mem::replace(&mut self.vm.pc, hbvm::mem::Address::new(entry)) + - self.code.as_ptr() as usize + } + + fn pop_pc(&mut self, prev_pc: hbvm::mem::Address) { + self.vm.pc = prev_pc + self.code.as_ptr() as usize; + } +} + +impl Default for Comptime { + fn default() -> Self { + let mut stack = Box::<[u8; VM_STACK_SIZE]>::new_uninit(); + 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() } + } +} + #[cfg(test)] pub fn run_test( name: &'static str, @@ -1455,7 +1492,7 @@ fn test_run_vm(out: &[u8], output: &mut String) { ) }; - vm.write_reg(codegen::STACK_PTR, unsafe { stack.as_mut_ptr().add(stack.len()) } as u64); + vm.write_reg(reg::STACK_PTR, unsafe { stack.as_mut_ptr().add(stack.len()) } as u64); let stat = loop { match vm.run() { diff --git a/lang/src/son.rs b/lang/src/son.rs index 8d329cb..d8f3c02 100644 --- a/lang/src/son.rs +++ b/lang/src/son.rs @@ -10,9 +10,9 @@ use { Expr, ExprRef, FileId, Pos, }, reg, task, - ty::{self, ArrayLen}, + ty::{self, ArrayLen, Tuple}, vc::{BitSet, Vc}, - Func, HashMap, Offset, OffsetIter, Reloc, Sig, SymKey, TypedReloc, Types, + Comptime, Func, Global, HashMap, Offset, OffsetIter, Reloc, Sig, SymKey, TypedReloc, Types, }, alloc::{string::String, vec::Vec}, core::{ @@ -73,6 +73,43 @@ impl Default for Nodes { } impl Nodes { + fn graphviz_low( + &self, + tys: &Types, + files: &[parser::Ast], + out: &mut String, + ) -> core::fmt::Result { + use core::fmt::Write; + + for (i, node) in self.iter() { + let color = if self.is_cfg(i) { "yellow" } else { "white" }; + writeln!( + out, + "node{i}[label=\"{} {}\" color={color}]", + node.kind, + ty::Display::new(tys, files, node.ty) + )?; + for (j, &o) in node.outputs.iter().enumerate() { + let color = if self.is_cfg(i) && self.is_cfg(o) { "red" } else { "lightgray" }; + let index = self[o].inputs.iter().position(|&inp| i == inp).unwrap(); + let style = if index == 0 && !self.is_cfg(o) { "style=dotted" } else { "" }; + writeln!( + out, + "node{o} -> node{i}[color={color} taillabel={index} headlabel={j} {style}]", + )?; + } + } + + Ok(()) + } + + #[allow(dead_code)] + fn graphviz(&self, tys: &Types, files: &[parser::Ast]) { + let out = &mut String::new(); + _ = self.graphviz_low(tys, files, out); + log::info!("{out}"); + } + fn gcm(&mut self) { self.visited.clear(self.values.len()); push_up(self); @@ -436,6 +473,7 @@ impl Nodes { Kind::Call { func } => { write!(out, "call: {func} {} ", self[node].depth) } + Kind::Global { global } => write!(out, "glob: {global:<5}"), Kind::Entry => write!(out, "ctrl: {:<5}", "entry"), Kind::Then => write!(out, "ctrl: {:<5}", "then"), Kind::Else => write!(out, "ctrl: {:<5}", "else"), @@ -808,6 +846,10 @@ pub enum Kind { BinOp { op: lexer::TokenKind, }, + // [ctrl] + Global { + global: ty::Global, + }, // [ctrl, ...args] Call { func: ty::Func, @@ -931,7 +973,6 @@ impl Scope { #[derive(Default)] struct ItemCtx { file: FileId, - id: ty::Id, ret: Option, task_base: usize, nodes: Nodes, @@ -946,7 +987,7 @@ struct ItemCtx { } impl ItemCtx { - fn init(&mut self, file: FileId, id: ty::Id, ret: Option, task_base: usize) { + 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); @@ -955,7 +996,6 @@ impl ItemCtx { debug_assert_eq!(self.code.len(), 0); self.file = file; - self.id = id; self.ret = ret; self.task_base = task_base; @@ -1109,6 +1149,14 @@ impl ItemCtx { }); self.emit(instrs::jal(reg::RET_ADDR, reg::ZERO, 0)); } + Kind::Global { global } => { + let reloc = Reloc::new(self.code.len(), 3, 4); + self.relocs.push(TypedReloc { + target: ty::Kind::Global(global).compress(), + reloc, + }); + self.emit(instrs::lra(atr(allocs[0]), 0, 0)); + } Kind::Stck => { let base = reg::STACK_PTR; let offset = func.nodes[nid].offset; @@ -1166,7 +1214,13 @@ impl ItemCtx { saved_regs.len() } - fn emit_body(&mut self, tys: &mut Types, sig: Sig) { + fn emit_body(&mut self, tys: &mut Types, files: &[parser::Ast], sig: Sig) { + self.nodes.graphviz(tys, files); + self.nodes.gcm(); + self.nodes.check_final_integrity(); + self.nodes.basic_blocks(); + self.nodes.graphviz(tys, files); + '_open_function: { self.emit(instrs::addi64(reg::STACK_PTR, reg::STACK_PTR, 0)); self.emit(instrs::st(reg::RET_ADDR, reg::STACK_PTR, 0, 0)); @@ -1236,10 +1290,6 @@ impl ItemCtx { } self.relocs.iter_mut().for_each(|r| r.reloc.offset -= stripped_prelude_size as u32); self.emit(instrs::jala(reg::ZERO, reg::RET_ADDR, 0)); - - let ty::Kind::Func(id) = self.id.expand() else { unreachable!() }; - tys.ins.funcs[id as usize].code.append(&mut self.code); - tys.ins.funcs[id as usize].relocs.append(&mut self.relocs); } } @@ -1273,11 +1323,10 @@ struct Pool { impl Pool { pub fn push_ci( &mut self, - target: &mut ItemCtx, file: FileId, - id: ty::Id, ret: Option, task_base: usize, + target: &mut ItemCtx, ) { if let Some(slot) = self.cis.get_mut(self.used_cis) { core::mem::swap(slot, target); @@ -1285,7 +1334,7 @@ impl Pool { self.cis.push(ItemCtx::default()); core::mem::swap(self.cis.last_mut().unwrap(), target); } - target.init(file, id, ret, task_base); + target.init(file, ret, task_base); self.used_cis += 1; } @@ -1363,47 +1412,11 @@ pub struct Codegen<'a> { pool: Pool, #[expect(dead_code)] ralloc: Regalloc, + ct: Comptime, errors: RefCell, } impl<'a> Codegen<'a> { - fn graphviz_low(&self, out: &mut String) -> core::fmt::Result { - use core::fmt::Write; - - for (i, node) in self.ci.nodes.iter() { - let color = if self.ci.nodes.is_cfg(i) { "yellow" } else { "white" }; - writeln!( - out, - "node{i}[label=\"{} {}\" color={color}]", - node.kind, - self.ty_display(node.ty) - )?; - for (j, &o) in node.outputs.iter().enumerate() { - let color = if self.ci.nodes.is_cfg(i) && self.ci.nodes.is_cfg(o) { - "red" - } else { - "lightgray" - }; - let index = self.ci.nodes[o].inputs.iter().position(|&inp| i == inp).unwrap(); - let style = - if index == 0 && !self.ci.nodes.is_cfg(o) { "style=dotted" } else { "" }; - writeln!( - out, - "node{o} -> node{i}[color={color} taillabel={index} headlabel={j} {style}]", - )?; - } - } - - Ok(()) - } - - #[allow(dead_code)] - fn graphviz(&self) { - let out = &mut String::new(); - _ = self.graphviz_low(out); - log::info!("{out}"); - } - fn store_mem(&mut self, region: Nid, value: Nid) -> Nid { if value == NEVER { return NEVER; @@ -1475,8 +1488,20 @@ impl<'a> Codegen<'a> { } Expr::Ident { id, pos, .. } => { let decl = self.find_or_declare(pos, self.ci.file, Ok(id)); - - todo!() + match decl { + ty::Kind::Global(g) => { + let gl = &self.tys.ins.globals[g as usize]; + Some( + Value::ptr(self.ci.nodes.new_node( + gl.ty, + Kind::Global { global: g }, + [VOID], + )) + .ty(gl.ty), + ) + } + _ => todo!("{decl:?}"), + } } Expr::Number { value, .. } => Some(self.ci.nodes.new_node_lit( ctx.ty.filter(|ty| ty.is_integer() || ty.is_pointer()).unwrap_or(ty::Id::INT), @@ -2260,7 +2285,7 @@ impl<'a> Codegen<'a> { let ast = &self.files[file as usize]; let expr = func.expr.get(ast).unwrap(); - self.pool.push_ci(&mut self.ci, file, ty::Kind::Func(id).compress(), Some(sig.ret), 0); + self.pool.push_ci(file, Some(sig.ret), 0, &mut self.ci); let Expr::BinOp { right: &Expr::Closure { body, args, .. }, .. } = expr else { unreachable!("{}", self.ast_display(expr)) @@ -2276,26 +2301,20 @@ impl<'a> Codegen<'a> { self.ci.scope.vars.push(Variable { id: arg.id, value, ty, ptr: false }); } - if self.expr(body).is_some() && self.tys.size_of(sig.ret) != 0 { + if self.expr(body).is_some() && sig.ret == ty::Id::VOID { self.report( body.pos(), "expected all paths in the fucntion to return \ - or the return type to be zero sized", + or the return type to be 'void'", ); } self.ci.finalize(); if self.errors.borrow().is_empty() { - self.graphviz(); - - self.ci.nodes.gcm(); - self.ci.nodes.check_final_integrity(); - self.ci.nodes.basic_blocks(); - - self.graphviz(); - - self.ci.emit_body(&mut self.tys, sig); + self.ci.emit_body(&mut self.tys, self.files, sig); + 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); } self.pool.pop_ci(&mut self.ci); @@ -2334,7 +2353,7 @@ impl<'a> Codegen<'a> { ), Err(name) => self.report(pos, fa!("idk indentifier: {name}")), } - return ty::Kind::Builtin(ty::NEVER); + return ty::Id::NEVER.expand(); }; let key = SymKey::Decl(file, ident); @@ -2398,8 +2417,81 @@ impl<'a> Codegen<'a> { op: TokenKind::Decl, right: right @ (Expr::Struct { .. } | Expr::Mod { .. }), } => self.ty(right).expand(), - Expr::BinOp { left: Expr::Ident { .. }, op: TokenKind::Decl, right } => { - todo!("{right:#?}"); + Expr::BinOp { left: &Expr::Ident { id: name, .. }, op: TokenKind::Decl, right } => { + let gid = self.tys.ins.globals.len() as ty::Global; + self.tys.ins.globals.push(Global { file, name, ..Default::default() }); + + let ty = ty::Kind::Global(gid); + self.pool.push_ci(file, None, self.tasks.len(), &mut self.ci); + + let ret = Expr::Return { pos: right.pos(), val: Some(right) }; + self.expr(&ret); + + self.ci.finalize(); + + let ret = self.ci.ret.expect("for return type to be infered"); + if self.errors.borrow().is_empty() { + self.ci.emit_body(&mut self.tys, self.files, Sig { args: Tuple::empty(), ret }); + self.ci.code.truncate(self.ci.code.len() - instrs::jala(0, 0, 0).0); + self.ci.emit(instrs::tx()); + + let func = Func { + file, + name, + expr: ExprRef::new(expr), + relocs: core::mem::take(&mut self.ci.relocs), + code: core::mem::take(&mut self.ci.code), + ..Default::default() + }; + self.pool.pop_ci(&mut self.ci); + self.complete_call_graph(); + + let mut mem = vec![0u8; self.tys.size_of(ret) as usize]; + + // 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); + + #[cfg(debug_assertions)] + { + let mut vc = String::new(); + if let Err(e) = self.tys.disasm(&self.ct.code, self.files, &mut vc, |_| {}) + { + panic!("{e} {}", vc); + } else { + log::trace!("{}", vc); + } + } + + self.ct.vm.write_reg(reg::RET, mem.as_mut_ptr() as u64); + let prev_pc = self.ct.push_pc(self.tys.ins.funcs[fuc as usize].offset); + loop { + match self.ct.vm.run().expect("TODO") { + hbvm::VmRunOk::End => break, + hbvm::VmRunOk::Timer => todo!(), + hbvm::VmRunOk::Ecall => todo!(), + hbvm::VmRunOk::Breakpoint => todo!(), + } + } + self.ct.pop_pc(prev_pc); + + match mem.len() { + 0 => unreachable!(), + len @ 1..=8 => mem + .copy_from_slice(&self.ct.vm.read_reg(reg::RET).0.to_ne_bytes()[..len]), + 9..=16 => todo!(), + _ => {} + } + + self.tys.ins.globals[gid as usize].data = mem; + } else { + self.pool.pop_ci(&mut self.ci); + } + self.tys.ins.globals[gid as usize].ty = ret; + + ty } e => unimplemented!("{e:#?}"), }; @@ -2755,14 +2847,6 @@ impl<'a> Function<'a> { let mut parama = self.tys.parama(fuc.ret); for (&(mut i), ti) in node.inputs[1..].iter().zip(fuc.args.range()) { let ty = self.tys.ins.args[ti]; - loop { - match self.nodes[i].kind { - Kind::Stre { .. } => i = self.nodes[i].inputs[2], - Kind::Load { .. } => i = self.nodes[i].inputs[1], - _ => break, - } - debug_assert_ne!(i, 0); - } match self.tys.size_of(ty) { 0 => continue, 1..=8 => { @@ -2773,6 +2857,14 @@ impl<'a> Function<'a> { } 9..=16 => todo!("pass in two register"), _ => { + loop { + match self.nodes[i].kind { + Kind::Stre { .. } => i = self.nodes[i].inputs[2], + Kind::Load { .. } => i = self.nodes[i].inputs[1], + _ => break, + } + debug_assert_ne!(i, 0); + } debug_assert!(i != 0); ops.push(regalloc2::Operand::reg_fixed_use( self.rg(i), @@ -2790,6 +2882,10 @@ impl<'a> Function<'a> { } } } + Kind::Global { .. } => { + let ops = vec![self.drg(nid)]; + self.add_instr(nid, ops); + } //Kind::Stck // if node.outputs.iter().all(|&n| { // matches!(self.nodes[n].kind, Kind::Stre | Kind::Load) @@ -3206,7 +3302,7 @@ mod tests { } let mut out = Vec::new(); - codegen.tys.assemble(&mut out); + codegen.tys.reassemble(&mut out); let err = codegen.tys.disasm(&out, codegen.files, output, |_| {}); if let Err(e) = err { diff --git a/lang/tests/son_tests_global_variables.txt b/lang/tests/son_tests_global_variables.txt index e69de29..c8a01e6 100644 --- a/lang/tests/son_tests_global_variables.txt +++ b/lang/tests/son_tests_global_variables.txt @@ -0,0 +1,9 @@ +main: + LRA r2, r0, :complex_global_var + LD r3, r2, 0a, 8h + ADDI64 r1, r3, 5d + ST r1, r2, 0a, 8h + JALA r0, r31, 0a +code size: 71 +ret: 55 +status: Ok(())