making a Backend trait to separate the different backends we will have in the fucture
This commit is contained in:
parent
276d1bb0cf
commit
87cb77a553
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -9,4 +9,5 @@ db.sqlite-journal
|
|||
# assets
|
||||
/depell/src/*.gz
|
||||
/depell/src/*.wasm
|
||||
**/*-sv.rs
|
||||
/bytecode/src/instrs.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()
|
||||
};
|
||||
|
||||
|
|
|
@ -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<u8>) -> 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<u8>) -> std
|
|||
return Err(std::io::Error::other("compilation faoled"));
|
||||
}
|
||||
|
||||
codegen.assemble(out);
|
||||
|
||||
if options.dump_asm {
|
||||
codegen
|
||||
.disasm(unsafe { std::mem::transmute::<&mut Vec<u8>, &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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<u64>) {
|
|||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -219,26 +219,6 @@ mod ctx_map {
|
|||
}
|
||||
}
|
||||
|
||||
mod task {
|
||||
use super::Offset;
|
||||
|
||||
pub fn unpack(offset: Offset) -> Result<Offset, usize> {
|
||||
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<ty::Func>,
|
||||
expr: ExprRef,
|
||||
sig: Option<Sig>,
|
||||
offset: Offset,
|
||||
// TODO: change to indices into common vec
|
||||
relocs: Vec<TypedReloc>,
|
||||
code: Vec<u8>,
|
||||
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<u8>,
|
||||
}
|
||||
|
||||
|
@ -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<Field>,
|
||||
frontier: Vec<ty::Id>,
|
||||
globals: Vec<ty::Global>,
|
||||
funcs: Vec<ty::Func>,
|
||||
args: Vec<ty::Id>,
|
||||
}
|
||||
|
||||
|
@ -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<ty::Id>,
|
||||
names: IdentInterner,
|
||||
strings: ctx_map::CtxMap<StringRef>,
|
||||
|
@ -1222,12 +1202,6 @@ impl Types {
|
|||
&self.ins.fields[self.struct_field_range(strct)]
|
||||
}
|
||||
|
||||
fn reassemble(&mut self, buf: &mut Vec<u8>) {
|
||||
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<ty::Id>) -> (Option<PLoc>, 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);
|
||||
|
|
368
lang/src/son.rs
368
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<u8>,
|
||||
) -> 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<u8>) {
|
||||
self.assemble_reachable(from, types, to);
|
||||
}
|
||||
}
|
||||
|
||||
type Lookup = crate::ctx_map::CtxMap<Nid>;
|
||||
|
||||
impl crate::ctx_map::CtxEntry for Nid {
|
||||
|
@ -71,23 +105,15 @@ macro_rules! inference {
|
|||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Nodes {
|
||||
pub struct Nodes {
|
||||
values: Vec<Result<Node, (Nid, debug::Trace)>>,
|
||||
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<Nid>) {
|
||||
if !self.is_cfg(node) || !self.visited.set(node) {
|
||||
fn collect_rpo(&mut self, node: Nid, rpo: &mut Vec<Nid>, 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<Nid>) {
|
||||
fn push_up(&mut self, rpo: &mut Vec<Nid>, 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<_>>(),
|
||||
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::<Vec<_>>()
|
||||
);
|
||||
|
@ -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<Nid>) {
|
||||
fn gcm(&mut self, rpo: &mut Vec<Nid>, 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<Vc>) -> 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<IDomDepth>,
|
||||
lock_rc: LockRc,
|
||||
loop_depth: LoopDepth,
|
||||
|
@ -1963,7 +1982,7 @@ impl Scope {
|
|||
}
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
struct ItemCtx {
|
||||
pub struct ItemCtx {
|
||||
file: FileId,
|
||||
ret: Option<ty::Id>,
|
||||
task_base: usize,
|
||||
|
@ -1973,25 +1992,19 @@ struct ItemCtx {
|
|||
inline_ret: Option<(Value, StrongRef, Scope)>,
|
||||
nodes: Nodes,
|
||||
ctrl: StrongRef,
|
||||
call_count: u16,
|
||||
loops: Vec<Loop>,
|
||||
scope: Scope,
|
||||
ret_relocs: Vec<Reloc>,
|
||||
relocs: Vec<TypedReloc>,
|
||||
jump_relocs: Vec<(Nid, Reloc)>,
|
||||
code: Vec<u8>,
|
||||
}
|
||||
|
||||
impl ItemCtx {
|
||||
fn init(&mut self, file: FileId, ret: Option<ty::Id>, 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<ItemCtx>,
|
||||
used_cis: usize,
|
||||
ralloc: Regalloc,
|
||||
nid_stack: Vec<Nid>,
|
||||
nid_set: BitSet,
|
||||
}
|
||||
|
||||
impl Pool {
|
||||
pub fn push_ci(
|
||||
fn push_ci(
|
||||
&mut self,
|
||||
file: FileId,
|
||||
ret: Option<ty::Id>,
|
||||
|
@ -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<ty::Id>) -> Self {
|
||||
fn ty(self, ty: impl Into<ty::Id>) -> 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<u8>) {
|
||||
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<Vec<u8>>) {
|
||||
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<Vec<u8>>) {
|
||||
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<u8>) {
|
||||
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::<Vec<_>>(),
|
||||
);
|
||||
});
|
||||
|
||||
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;
|
||||
|
|
|
@ -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<u8>) {
|
||||
to.extend([0u8; HEADER_SIZE]);
|
||||
struct FuncDt {
|
||||
offset: Offset,
|
||||
// TODO: change to indices into common vec
|
||||
relocs: Vec<TypedReloc>,
|
||||
code: Vec<u8>,
|
||||
}
|
||||
|
||||
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::<AbleOsExecutableHeader>() = exe }
|
||||
}
|
||||
|
||||
pub fn dump_reachable(&mut self, from: ty::Func, to: &mut Vec<u8>) -> 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::<BTreeMap<_, _>>();
|
||||
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<ty::Id>,
|
||||
globals: Vec<ty::Global>,
|
||||
funcs: Vec<ty::Func>,
|
||||
}
|
||||
|
||||
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<FuncDt>,
|
||||
globals: Vec<GlobalDt>,
|
||||
asm: Assembler,
|
||||
ralloc: Regalloc,
|
||||
|
||||
ret_relocs: Vec<Reloc>,
|
||||
relocs: Vec<TypedReloc>,
|
||||
jump_relocs: Vec<(Nid, Reloc)>,
|
||||
code: Vec<u8>,
|
||||
offsets: Vec<Offset>,
|
||||
}
|
||||
|
||||
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<u8>) {
|
||||
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::<AbleOsExecutableHeader>() = 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<u8>,
|
||||
) -> 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::<BTreeMap<_, _>>();
|
||||
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<u16>,
|
||||
blocks: Vec<Block>,
|
||||
instrs: Vec<Instr>,
|
||||
}
|
||||
|
@ -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<u64> {
|
||||
fn cmp_against(self) -> Option<u64> {
|
||||
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<fn(u8, u8, u8) -> EncodedInstr> {
|
||||
fn float_cmp(self, ty: ty::Id) -> Option<fn(u8, u8, u8) -> 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<fn(u8, u8) -> EncodedInstr> {
|
||||
fn unop(&self, dst: ty::Id, src: ty::Id) -> Option<fn(u8, u8) -> 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<u8>, (len, instr): EncodedInstr) {
|
|||
out.extend_from_slice(&instr[..len]);
|
||||
}
|
||||
|
||||
pub fn binary_prelude(to: &mut Vec<u8>) {
|
||||
fn binary_prelude(to: &mut Vec<u8>) {
|
||||
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<LoggedMem, { 1024 * 10 }>,
|
||||
stack: Box<[u8; VM_STACK_SIZE]>,
|
||||
pub code: Vec<u8>,
|
||||
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::<u8>().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 }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(())
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(())
|
||||
|
|
|
@ -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(())
|
||||
|
|
|
@ -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(())
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(())
|
||||
|
|
|
@ -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(())
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(())
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue