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
|
# assets
|
||||||
/depell/src/*.gz
|
/depell/src/*.gz
|
||||||
/depell/src/*.wasm
|
/depell/src/*.wasm
|
||||||
|
**/*-sv.rs
|
||||||
/bytecode/src/instrs.rs
|
/bytecode/src/instrs.rs
|
||||||
|
|
|
@ -6,7 +6,7 @@ use {
|
||||||
alloc::{string::String, vec::Vec},
|
alloc::{string::String, vec::Vec},
|
||||||
hblang::{
|
hblang::{
|
||||||
parser::FileId,
|
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 = {
|
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() {
|
if !ctx.parser.errors.borrow().is_empty() {
|
||||||
log::error!("{}", ctx.parser.errors.borrow());
|
log::error!("{}", ctx.parser.errors.borrow());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut c = Codegen::new(&files, &mut ctx);
|
let mut c = Codegen::new(&mut backend, &files, &mut ctx);
|
||||||
c.assemble_comptime()
|
c.assemble_comptime()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
parser::{self, Ast, Ctx, FileKind},
|
parser::{self, Ast, Ctx, FileKind},
|
||||||
son,
|
son::{self, hbvm::HbvmBackend},
|
||||||
},
|
},
|
||||||
alloc::{string::String, vec::Vec},
|
alloc::{string::String, vec::Vec},
|
||||||
core::{fmt::Write, num::NonZeroUsize, ops::Deref},
|
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();
|
let ast = parsed.ast.into_iter().next().unwrap();
|
||||||
write!(out, "{ast}").unwrap();
|
write!(out, "{ast}").unwrap();
|
||||||
} else {
|
} else {
|
||||||
|
let mut backend = HbvmBackend::default();
|
||||||
let mut ctx = crate::son::CodegenCtx::default();
|
let mut ctx = crate::son::CodegenCtx::default();
|
||||||
*ctx.parser.errors.get_mut() = parsed.errors;
|
*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.push_embeds(parsed.embeds);
|
||||||
codegen.generate(0);
|
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"));
|
return Err(std::io::Error::other("compilation faoled"));
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
codegen.assemble(out);
|
||||||
|
|
||||||
|
if options.dump_asm {
|
||||||
|
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::{
|
crate::{
|
||||||
lexer::TokenKind,
|
lexer::TokenKind,
|
||||||
parser,
|
parser,
|
||||||
son::{Codegen, CodegenCtx},
|
son::{hbvm::HbvmBackend, Codegen, CodegenCtx},
|
||||||
},
|
},
|
||||||
alloc::string::String,
|
alloc::string::String,
|
||||||
core::{fmt::Write, hash::BuildHasher, ops::Range},
|
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());
|
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);
|
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)]
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug)]
|
||||||
pub struct Ident(u32);
|
pub struct Ident(u32);
|
||||||
|
|
||||||
|
@ -567,6 +547,7 @@ mod ty {
|
||||||
};)*
|
};)*
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[expect(dead_code)]
|
||||||
impl Id {
|
impl Id {
|
||||||
$(pub const $name: Self = Kind::Builtin($name).compress();)*
|
$(pub const $name: Self = Kind::Builtin($name).compress();)*
|
||||||
}
|
}
|
||||||
|
@ -758,7 +739,7 @@ pub enum SymKey<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
struct Sig {
|
pub struct Sig {
|
||||||
args: ty::Tuple,
|
args: ty::Tuple,
|
||||||
ret: ty::Id,
|
ret: ty::Id,
|
||||||
}
|
}
|
||||||
|
@ -769,10 +750,7 @@ struct Func {
|
||||||
base: Option<ty::Func>,
|
base: Option<ty::Func>,
|
||||||
expr: ExprRef,
|
expr: ExprRef,
|
||||||
sig: Option<Sig>,
|
sig: Option<Sig>,
|
||||||
offset: Offset,
|
comp_state: [CompState; 2],
|
||||||
// TODO: change to indices into common vec
|
|
||||||
relocs: Vec<TypedReloc>,
|
|
||||||
code: Vec<u8>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Func {
|
impl Default for Func {
|
||||||
|
@ -783,13 +761,19 @@ impl Default for Func {
|
||||||
base: None,
|
base: None,
|
||||||
expr: Default::default(),
|
expr: Default::default(),
|
||||||
sig: None,
|
sig: None,
|
||||||
offset: u32::MAX,
|
comp_state: Default::default(),
|
||||||
relocs: Default::default(),
|
|
||||||
code: Default::default(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default, PartialEq, Eq)]
|
||||||
|
enum CompState {
|
||||||
|
#[default]
|
||||||
|
Dead,
|
||||||
|
Queued(usize),
|
||||||
|
Compiled,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
struct TypedReloc {
|
struct TypedReloc {
|
||||||
target: ty::Id,
|
target: ty::Id,
|
||||||
|
@ -801,7 +785,6 @@ struct Global {
|
||||||
file: FileId,
|
file: FileId,
|
||||||
name: Ident,
|
name: Ident,
|
||||||
ty: ty::Id,
|
ty: ty::Id,
|
||||||
offset: Offset,
|
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -809,7 +792,6 @@ impl Default for Global {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
ty: Default::default(),
|
ty: Default::default(),
|
||||||
offset: u32::MAX,
|
|
||||||
data: Default::default(),
|
data: Default::default(),
|
||||||
file: u32::MAX,
|
file: u32::MAX,
|
||||||
name: Default::default(),
|
name: Default::default(),
|
||||||
|
@ -947,9 +929,6 @@ impl IdentInterner {
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct TypesTmp {
|
struct TypesTmp {
|
||||||
fields: Vec<Field>,
|
fields: Vec<Field>,
|
||||||
frontier: Vec<ty::Id>,
|
|
||||||
globals: Vec<ty::Global>,
|
|
||||||
funcs: Vec<ty::Func>,
|
|
||||||
args: Vec<ty::Id>,
|
args: Vec<ty::Id>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -968,6 +947,7 @@ pub struct TypeIns {
|
||||||
struct FTask {
|
struct FTask {
|
||||||
file: FileId,
|
file: FileId,
|
||||||
id: ty::Func,
|
id: ty::Func,
|
||||||
|
ct: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct StringRef(ty::Global);
|
struct StringRef(ty::Global);
|
||||||
|
@ -982,7 +962,7 @@ impl ctx_map::CtxEntry for StringRef {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct Types {
|
pub struct Types {
|
||||||
syms: ctx_map::CtxMap<ty::Id>,
|
syms: ctx_map::CtxMap<ty::Id>,
|
||||||
names: IdentInterner,
|
names: IdentInterner,
|
||||||
strings: ctx_map::CtxMap<StringRef>,
|
strings: ctx_map::CtxMap<StringRef>,
|
||||||
|
@ -1222,12 +1202,6 @@ impl Types {
|
||||||
&self.ins.fields[self.struct_field_range(strct)]
|
&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) {
|
fn parama(&self, ret: impl Into<ty::Id>) -> (Option<PLoc>, ParamAlloc) {
|
||||||
let mut iter = ParamAlloc(1..12);
|
let mut iter = ParamAlloc(1..12);
|
||||||
let ret = iter.next(ret.into(), self);
|
let ret = iter.next(ret.into(), self);
|
||||||
|
@ -1395,9 +1369,6 @@ impl Types {
|
||||||
self.ins.slices.clear();
|
self.ins.slices.clear();
|
||||||
|
|
||||||
debug_assert_eq!(self.tmp.fields.len(), 0);
|
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.tmp.args.len(), 0);
|
||||||
|
|
||||||
debug_assert_eq!(self.tasks.len(), 0);
|
debug_assert_eq!(self.tasks.len(), 0);
|
||||||
|
|
368
lang/src/son.rs
368
lang/src/son.rs
|
@ -1,5 +1,8 @@
|
||||||
use {
|
use {
|
||||||
self::{hbvm::Comptime, strong_ref::StrongRef},
|
self::{
|
||||||
|
hbvm::{Comptime, HbvmBackend},
|
||||||
|
strong_ref::StrongRef,
|
||||||
|
},
|
||||||
crate::{
|
crate::{
|
||||||
ctx_map::CtxEntry,
|
ctx_map::CtxEntry,
|
||||||
debug,
|
debug,
|
||||||
|
@ -9,11 +12,10 @@ use {
|
||||||
idfl::{self},
|
idfl::{self},
|
||||||
CtorField, Expr, FileId, Pos,
|
CtorField, Expr, FileId, Pos,
|
||||||
},
|
},
|
||||||
task,
|
|
||||||
ty::{self, Arg, ArrayLen, Loc, Tuple},
|
ty::{self, Arg, ArrayLen, Loc, Tuple},
|
||||||
utils::{BitSet, Vc},
|
utils::{BitSet, Vc},
|
||||||
FTask, Func, Global, Ident, Offset, OffsetIter, OptLayout, Reloc, Sig, StringRef, SymKey,
|
CompState, FTask, Func, Global, Ident, Offset, OffsetIter, OptLayout, Sig, StringRef,
|
||||||
TypeParser, TypedReloc, Types,
|
SymKey, TypeParser, Types,
|
||||||
},
|
},
|
||||||
alloc::{string::String, vec::Vec},
|
alloc::{string::String, vec::Vec},
|
||||||
core::{
|
core::{
|
||||||
|
@ -41,6 +43,38 @@ pub mod hbvm;
|
||||||
type Nid = u16;
|
type Nid = u16;
|
||||||
type AClassId = i16;
|
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>;
|
type Lookup = crate::ctx_map::CtxMap<Nid>;
|
||||||
|
|
||||||
impl crate::ctx_map::CtxEntry for Nid {
|
impl crate::ctx_map::CtxEntry for Nid {
|
||||||
|
@ -71,23 +105,15 @@ macro_rules! inference {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct Nodes {
|
pub struct Nodes {
|
||||||
values: Vec<Result<Node, (Nid, debug::Trace)>>,
|
values: Vec<Result<Node, (Nid, debug::Trace)>>,
|
||||||
visited: BitSet,
|
|
||||||
free: Nid,
|
free: Nid,
|
||||||
lookup: Lookup,
|
lookup: Lookup,
|
||||||
complete: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Nodes {
|
impl Default for Nodes {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self { values: Default::default(), free: Nid::MAX, lookup: Default::default() }
|
||||||
values: Default::default(),
|
|
||||||
free: Nid::MAX,
|
|
||||||
lookup: Default::default(),
|
|
||||||
visited: Default::default(),
|
|
||||||
complete: false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,15 +209,15 @@ impl Nodes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_up_impl(&mut self, node: Nid) {
|
fn push_up_impl(&mut self, node: Nid, visited: &mut BitSet) {
|
||||||
if !self.visited.set(node) {
|
if !visited.set(node) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for i in 1..self[node].inputs.len() {
|
for i in 1..self[node].inputs.len() {
|
||||||
let inp = self[node].inputs[i];
|
let inp = self[node].inputs[i];
|
||||||
if !self[inp].kind.is_pinned() {
|
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);
|
self[deepest].outputs.push(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_rpo(&mut self, node: Nid, rpo: &mut Vec<Nid>) {
|
fn collect_rpo(&mut self, node: Nid, rpo: &mut Vec<Nid>, visited: &mut BitSet) {
|
||||||
if !self.is_cfg(node) || !self.visited.set(node) {
|
if !self.is_cfg(node) || !visited.set(node) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for i in 0..self[node].outputs.len() {
|
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);
|
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());
|
debug_assert!(rpo.is_empty());
|
||||||
self.collect_rpo(VOID, rpo);
|
self.collect_rpo(VOID, rpo, visited);
|
||||||
|
|
||||||
for &node in rpo.iter().rev() {
|
for &node in rpo.iter().rev() {
|
||||||
self.loop_depth(node);
|
self.loop_depth(node);
|
||||||
for i in 0..self[node].inputs.len() {
|
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) {
|
if matches!(self[node].kind, Kind::Loop | Kind::Region) {
|
||||||
for i in 0..self[node].outputs.len() {
|
for i in 0..self[node].outputs.len() {
|
||||||
let usage = self[node].outputs[i];
|
let usage = self[node].outputs[i];
|
||||||
if self[usage].kind == Kind::Phi {
|
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!(
|
debug_assert_eq!(
|
||||||
self.iter()
|
self.iter()
|
||||||
.map(|(n, _)| n)
|
.map(|(n, _)| n)
|
||||||
.filter(|&n| !self.visited.get(n)
|
.filter(|&n| !visited.get(n)
|
||||||
&& !matches!(self[n].kind, Kind::Arg | Kind::Mem | Kind::Loops))
|
&& !matches!(self[n].kind, Kind::Arg | Kind::Mem | Kind::Loops))
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
vec![],
|
vec![],
|
||||||
"{:?}",
|
"{:?}",
|
||||||
self.iter()
|
self.iter()
|
||||||
.filter(|&(n, nod)| !self.visited.get(n)
|
.filter(|&(n, nod)| !visited.get(n)
|
||||||
&& !matches!(nod.kind, Kind::Arg | Kind::Mem | Kind::Loops))
|
&& !matches!(nod.kind, Kind::Arg | Kind::Mem | Kind::Loops))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
);
|
);
|
||||||
|
@ -295,20 +321,20 @@ impl Nodes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_down(&mut self, node: Nid) {
|
fn push_down(&mut self, node: Nid, visited: &mut BitSet) {
|
||||||
if !self.visited.set(node) {
|
if !visited.set(node) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for usage in self[node].outputs.clone() {
|
for usage in self[node].outputs.clone() {
|
||||||
if self.is_forward_edge(usage, node) && self[node].kind == Kind::Stre {
|
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() {
|
for usage in self[node].outputs.clone() {
|
||||||
if self.is_forward_edge(usage, node) {
|
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(
|
fn graphviz_low(&self, disp: ty::Display, out: &mut String) -> core::fmt::Result {
|
||||||
&self,
|
|
||||||
tys: &Types,
|
|
||||||
files: &[parser::Ast],
|
|
||||||
out: &mut String,
|
|
||||||
) -> core::fmt::Result {
|
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
|
|
||||||
writeln!(out)?;
|
writeln!(out)?;
|
||||||
|
@ -518,7 +539,7 @@ impl Nodes {
|
||||||
out,
|
out,
|
||||||
" node{i}[label=\"{i} {} {} {}\" color={color}]",
|
" node{i}[label=\"{i} {} {} {}\" color={color}]",
|
||||||
node.kind,
|
node.kind,
|
||||||
ty::Display::new(tys, files, node.ty),
|
disp.rety(node.ty),
|
||||||
node.aclass,
|
node.aclass,
|
||||||
)?;
|
)?;
|
||||||
} else {
|
} else {
|
||||||
|
@ -545,17 +566,17 @@ impl Nodes {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn graphviz(&self, tys: &Types, files: &[parser::Ast]) {
|
fn graphviz(&self, disp: ty::Display) {
|
||||||
let out = &mut String::new();
|
let out = &mut String::new();
|
||||||
_ = self.graphviz_low(tys, files, out);
|
_ = self.graphviz_low(disp, out);
|
||||||
log::info!("{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"))]
|
#[cfg(all(debug_assertions, feature = "std"))]
|
||||||
{
|
{
|
||||||
let out = &mut String::new();
|
let out = &mut String::new();
|
||||||
_ = self.graphviz_low(_tys, _files, out);
|
_ = self.graphviz_low(disp, out);
|
||||||
if !std::process::Command::new("brave")
|
if !std::process::Command::new("brave")
|
||||||
.arg(format!("https://dreampuf.github.io/GraphvizOnline/#{out}"))
|
.arg(format!("https://dreampuf.github.io/GraphvizOnline/#{out}"))
|
||||||
.status()
|
.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.fix_loops();
|
||||||
self.visited.clear(self.values.len());
|
visited.clear(self.values.len());
|
||||||
self.push_up(rpo);
|
self.push_up(rpo, visited);
|
||||||
self.visited.clear(self.values.len());
|
visited.clear(self.values.len());
|
||||||
self.push_down(VOID);
|
self.push_down(VOID, visited);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear(&mut self) {
|
fn clear(&mut self) {
|
||||||
self.values.clear();
|
self.values.clear();
|
||||||
self.lookup.clear();
|
self.lookup.clear();
|
||||||
self.free = Nid::MAX;
|
self.free = Nid::MAX;
|
||||||
self.complete = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_node_nop(&mut self, ty: ty::Id, kind: Kind, inps: impl Into<Vc>) -> Nid {
|
fn new_node_nop(&mut self, ty: ty::Id, kind: Kind, inps: impl Into<Vc>) -> Nid {
|
||||||
let node =
|
let node = Node { inputs: inps.into(), kind, ty, ..Default::default() };
|
||||||
Node { ralloc_backref: u16::MAX, inputs: inps.into(), kind, ty, ..Default::default() };
|
|
||||||
|
|
||||||
if node.kind == Kind::Phi && node.ty != ty::Id::VOID {
|
if node.kind == Kind::Phi && node.ty != ty::Id::VOID {
|
||||||
debug_assert_ne!(
|
debug_assert_ne!(
|
||||||
|
@ -765,7 +784,7 @@ impl Nodes {
|
||||||
stack.iter().skip(prev_len).for_each(|&n| self.lock(n));
|
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 {
|
if self[region].aclass >= 0 {
|
||||||
(self[region].aclass as _, region)
|
(self[region].aclass as _, region)
|
||||||
} else {
|
} else {
|
||||||
|
@ -1336,9 +1355,6 @@ impl Nodes {
|
||||||
|
|
||||||
#[expect(clippy::format_in_format_args)]
|
#[expect(clippy::format_in_format_args)]
|
||||||
fn basic_blocks_instr(&mut self, out: &mut String, node: Nid) -> core::fmt::Result {
|
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 {
|
match self[node].kind {
|
||||||
Kind::Assert { .. } | Kind::Start => unreachable!("{} {out}", self[node].kind),
|
Kind::Assert { .. } | Kind::Start => unreachable!("{} {out}", self[node].kind),
|
||||||
Kind::End => return Ok(()),
|
Kind::End => return Ok(()),
|
||||||
|
@ -1382,9 +1398,14 @@ impl Nodes {
|
||||||
Ok(())
|
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();
|
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 {
|
match self[node].kind {
|
||||||
Kind::Start => {
|
Kind::Start => {
|
||||||
writeln!(out, "start: {}", self[node].depth.get())?;
|
writeln!(out, "start: {}", self[node].depth.get())?;
|
||||||
|
@ -1399,7 +1420,7 @@ impl Nodes {
|
||||||
}
|
}
|
||||||
Kind::End => break,
|
Kind::End => break,
|
||||||
Kind::If => {
|
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];
|
node = self[node].outputs[1];
|
||||||
}
|
}
|
||||||
Kind::Region => {
|
Kind::Region => {
|
||||||
|
@ -1480,8 +1501,8 @@ impl Nodes {
|
||||||
|
|
||||||
fn basic_blocks(&mut self) {
|
fn basic_blocks(&mut self) {
|
||||||
let mut out = String::new();
|
let mut out = String::new();
|
||||||
self.visited.clear(self.values.len());
|
let mut visited = BitSet::default();
|
||||||
self.basic_blocks_low(&mut out, VOID).unwrap();
|
self.basic_blocks_low(&mut out, VOID, &mut visited).unwrap();
|
||||||
log::info!("{out}");
|
log::info!("{out}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1489,7 +1510,7 @@ impl Nodes {
|
||||||
self[o].kind.is_cfg()
|
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) {
|
if !cfg!(debug_assertions) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1517,7 +1538,7 @@ impl Nodes {
|
||||||
}
|
}
|
||||||
|
|
||||||
if failed {
|
if failed {
|
||||||
self.graphviz_in_browser(tys, files);
|
self.graphviz_in_browser(disp);
|
||||||
panic!()
|
panic!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1743,8 +1764,6 @@ pub struct Node {
|
||||||
peep_triggers: Vc,
|
peep_triggers: Vc,
|
||||||
clobbers: BitSet,
|
clobbers: BitSet,
|
||||||
ty: ty::Id,
|
ty: ty::Id,
|
||||||
offset: Offset,
|
|
||||||
ralloc_backref: RallocBRef,
|
|
||||||
depth: Cell<IDomDepth>,
|
depth: Cell<IDomDepth>,
|
||||||
lock_rc: LockRc,
|
lock_rc: LockRc,
|
||||||
loop_depth: LoopDepth,
|
loop_depth: LoopDepth,
|
||||||
|
@ -1963,7 +1982,7 @@ impl Scope {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone)]
|
||||||
struct ItemCtx {
|
pub struct ItemCtx {
|
||||||
file: FileId,
|
file: FileId,
|
||||||
ret: Option<ty::Id>,
|
ret: Option<ty::Id>,
|
||||||
task_base: usize,
|
task_base: usize,
|
||||||
|
@ -1973,25 +1992,19 @@ struct ItemCtx {
|
||||||
inline_ret: Option<(Value, StrongRef, Scope)>,
|
inline_ret: Option<(Value, StrongRef, Scope)>,
|
||||||
nodes: Nodes,
|
nodes: Nodes,
|
||||||
ctrl: StrongRef,
|
ctrl: StrongRef,
|
||||||
call_count: u16,
|
|
||||||
loops: Vec<Loop>,
|
loops: Vec<Loop>,
|
||||||
scope: Scope,
|
scope: Scope,
|
||||||
ret_relocs: Vec<Reloc>,
|
|
||||||
relocs: Vec<TypedReloc>,
|
|
||||||
jump_relocs: Vec<(Nid, Reloc)>,
|
|
||||||
code: Vec<u8>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ItemCtx {
|
impl ItemCtx {
|
||||||
fn init(&mut self, file: FileId, ret: Option<ty::Id>, task_base: usize) {
|
fn init(&mut self, file: FileId, ret: Option<ty::Id>, task_base: usize) {
|
||||||
debug_assert_eq!(self.loops.len(), 0);
|
debug_assert_eq!(self.loops.len(), 0);
|
||||||
debug_assert_eq!(self.scope.vars.len(), 0);
|
debug_assert_eq!(self.scope.vars.len(), 0);
|
||||||
debug_assert_eq!(self.ret_relocs.len(), 0);
|
debug_assert_eq!(self.scope.aclasses.len(), 0);
|
||||||
debug_assert_eq!(self.relocs.len(), 0);
|
debug_assert!(self.inline_ret.is_none());
|
||||||
debug_assert_eq!(self.jump_relocs.len(), 0);
|
debug_assert_eq!(self.inline_depth, 0);
|
||||||
debug_assert_eq!(self.code.len(), 0);
|
debug_assert_eq!(self.inline_var_base, 0);
|
||||||
|
debug_assert_eq!(self.inline_aclass_base, 0);
|
||||||
self.call_count = 0;
|
|
||||||
|
|
||||||
self.file = file;
|
self.file = file;
|
||||||
self.ret = ret;
|
self.ret = ret;
|
||||||
|
@ -2043,21 +2056,21 @@ struct Ctx {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ctx {
|
impl Ctx {
|
||||||
pub fn with_ty(self, ty: ty::Id) -> Self {
|
fn with_ty(self, ty: ty::Id) -> Self {
|
||||||
Self { ty: Some(ty) }
|
Self { ty: Some(ty) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct Pool {
|
pub struct Pool {
|
||||||
cis: Vec<ItemCtx>,
|
cis: Vec<ItemCtx>,
|
||||||
used_cis: usize,
|
used_cis: usize,
|
||||||
ralloc: Regalloc,
|
|
||||||
nid_stack: Vec<Nid>,
|
nid_stack: Vec<Nid>,
|
||||||
|
nid_set: BitSet,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pool {
|
impl Pool {
|
||||||
pub fn push_ci(
|
fn push_ci(
|
||||||
&mut self,
|
&mut self,
|
||||||
file: FileId,
|
file: FileId,
|
||||||
ret: Option<ty::Id>,
|
ret: Option<ty::Id>,
|
||||||
|
@ -2074,7 +2087,7 @@ impl Pool {
|
||||||
self.used_cis += 1;
|
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;
|
self.used_cis -= 1;
|
||||||
mem::swap(&mut self.cis[self.used_cis], target);
|
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)]
|
#[derive(Default, Clone, Copy, PartialEq, Eq, Debug)]
|
||||||
struct Value {
|
struct Value {
|
||||||
ty: ty::Id,
|
ty: ty::Id,
|
||||||
|
@ -2140,20 +2126,20 @@ impl Value {
|
||||||
Some(Self { ty: ty::Id::NEVER, var: false, ptr: false, id: NEVER });
|
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 };
|
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() }
|
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() }
|
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() }
|
Self { id, ptr: true, ..Default::default() }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[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 }
|
Self { ty: ty.into(), ..self }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2164,6 +2150,7 @@ pub struct CodegenCtx {
|
||||||
tys: Types,
|
tys: Types,
|
||||||
pool: Pool,
|
pool: Pool,
|
||||||
ct: Comptime,
|
ct: Comptime,
|
||||||
|
ct_backend: HbvmBackend,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CodegenCtx {
|
impl CodegenCtx {
|
||||||
|
@ -2200,10 +2187,16 @@ pub struct Codegen<'a> {
|
||||||
ci: ItemCtx,
|
ci: ItemCtx,
|
||||||
pool: &'a mut Pool,
|
pool: &'a mut Pool,
|
||||||
ct: &'a mut Comptime,
|
ct: &'a mut Comptime,
|
||||||
|
ct_backend: &'a mut HbvmBackend,
|
||||||
|
backend: &'a mut dyn Backend,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Codegen<'a> {
|
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 {
|
Self {
|
||||||
files,
|
files,
|
||||||
errors: Errors(&ctx.parser.errors),
|
errors: Errors(&ctx.parser.errors),
|
||||||
|
@ -2211,9 +2204,46 @@ impl<'a> Codegen<'a> {
|
||||||
ci: Default::default(),
|
ci: Default::default(),
|
||||||
pool: &mut ctx.pool,
|
pool: &mut ctx.pool,
|
||||||
ct: &mut ctx.ct,
|
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 {
|
fn emit_and_eval(&mut self, file: FileId, ret: ty::Id, ret_loc: &mut [u8]) -> u64 {
|
||||||
let mut rets =
|
let mut rets =
|
||||||
self.ci.nodes[NEVER].inputs.iter().filter(|&&i| self.ci.nodes[i].kind == Kind::Return);
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.ci.emit_ct_body(self.tys, self.files, Sig { args: Tuple::empty(), ret }, self.pool);
|
let fuc = self.tys.ins.funcs.len() as ty::Func;
|
||||||
|
self.tys.ins.funcs.push(Func {
|
||||||
let func = Func {
|
|
||||||
file,
|
file,
|
||||||
relocs: mem::take(&mut self.ci.relocs),
|
sig: Some(Sig { args: Tuple::empty(), ret }),
|
||||||
code: mem::take(&mut self.ci.code),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
});
|
||||||
|
|
||||||
|
self.ct_backend.emit_ct_body(fuc, &mut self.ci.nodes, self.tys, self.files);
|
||||||
|
|
||||||
// TODO: return them back
|
// 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);
|
let entry =
|
||||||
self.dump_ct_asm();
|
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)]
|
#[cfg(debug_assertions)]
|
||||||
{
|
{
|
||||||
let mut vc = String::new();
|
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);
|
panic!("{e} {}", vc);
|
||||||
} else {
|
} else {
|
||||||
log::trace!("{}", vc);
|
log::trace!("{}", vc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push_embeds(&mut self, embeds: Vec<Vec<u8>>) {
|
self.ct.run(ret_loc, entry)
|
||||||
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 new_stack(&mut self, ty: ty::Id) -> Nid {
|
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!(region, VOID);
|
||||||
debug_assert_ne!({ self.ci.nodes[region].ty }, ty::Id::VOID, "{:?}", {
|
debug_assert_ne!({ self.ci.nodes[region].ty }, ty::Id::VOID, "{:?}", {
|
||||||
self.ci.nodes[region].lock_rc = Nid::MAX;
|
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!(
|
debug_assert!(
|
||||||
self.ci.nodes[region].kind != Kind::Load || self.ci.nodes[region].ty.is_pointer(),
|
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.file().path,
|
||||||
self.ty_display(self.ci.nodes[region].ty)
|
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)
|
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) {
|
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];
|
let fuc = &mut self.tys.ins.funcs[func as usize];
|
||||||
if fuc.offset == u32::MAX {
|
if fuc.comp_state[state_slot] == CompState::Dead {
|
||||||
fuc.offset = task::id(self.tys.tasks.len() as _);
|
fuc.comp_state[state_slot] = CompState::Queued(self.tys.tasks.len() as _);
|
||||||
self.tys.tasks.push(Some(FTask { file: fuc.file, id: func }));
|
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)))
|
alt_value.or(Some(Value::new(self.ci.ctrl.get()).ty(ty)))
|
||||||
}
|
}
|
||||||
Expr::Call { func, args, .. } => {
|
Expr::Call { func, args, .. } => {
|
||||||
self.ci.call_count += 1;
|
|
||||||
let ty = self.ty(func);
|
let ty = self.ty(func);
|
||||||
let ty::Kind::Func(mut fu) = ty.expand() else {
|
let ty::Kind::Func(mut fu) = ty.expand() else {
|
||||||
self.report(
|
self.report(
|
||||||
|
@ -4005,10 +3996,12 @@ impl<'a> Codegen<'a> {
|
||||||
self.errors.borrow().len() == prev_err_len
|
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];
|
let func = &mut self.tys.ins.funcs[id as usize];
|
||||||
debug_assert_eq!(func.file, file);
|
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 sig = func.sig.expect("to emmit only concrete functions");
|
||||||
let ast = &self.files[file as usize];
|
let ast = &self.files[file as usize];
|
||||||
let expr = func.expr.get(ast);
|
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));
|
self.ci.scope.vars.drain(..).for_each(|v| v.remove_ignore_arg(&mut self.ci.nodes));
|
||||||
|
|
||||||
if self.finalize(prev_err_len) {
|
if self.finalize(prev_err_len) {
|
||||||
self.ci.emit_body(self.tys, self.files, sig, self.pool);
|
let backend = if !cct { &mut *self.backend } else { &mut *self.ct_backend };
|
||||||
self.tys.ins.funcs[id as usize].code.append(&mut self.ci.code);
|
backend.emit_body(id, &mut self.ci.nodes, self.tys, self.files);
|
||||||
self.tys.ins.funcs[id as usize].relocs.append(&mut self.ci.relocs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.pool.pop_ci(&mut self.ci);
|
self.pool.pop_ci(&mut self.ci);
|
||||||
|
@ -4087,6 +4079,7 @@ impl<'a> Codegen<'a> {
|
||||||
use {AssertKind as AK, CondOptRes as CR};
|
use {AssertKind as AK, CondOptRes as CR};
|
||||||
|
|
||||||
self.ci.finalize(&mut self.pool.nid_stack, self.tys, self.files);
|
self.ci.finalize(&mut self.pool.nid_stack, self.tys, self.files);
|
||||||
|
|
||||||
let mut to_remove = vec![];
|
let mut to_remove = vec![];
|
||||||
for (id, node) in self.ci.nodes.iter() {
|
for (id, node) in self.ci.nodes.iter() {
|
||||||
let Kind::Assert { kind, pos } = node.kind else { continue };
|
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.nodes[n].outputs.iter().map(|&o| &self.ci.nodes[o]).collect::<Vec<_>>(),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
self.ci.unlock();
|
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
|
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 {
|
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);
|
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.pool.push_ci(file, Some(ret), self.tys.tasks.len(), &mut self.ci);
|
||||||
self.ci.scope.vars = scope;
|
self.ci.scope.vars = scope;
|
||||||
|
@ -4415,6 +4419,7 @@ impl TypeParser for Codegen<'_> {
|
||||||
self.pool.pop_ci(&mut self.ci);
|
self.pool.pop_ci(&mut self.ci);
|
||||||
self.ci.scope.vars = scope;
|
self.ci.scope.vars = scope;
|
||||||
|
|
||||||
|
self.ct.deactivate();
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4427,18 +4432,21 @@ impl TypeParser for Codegen<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_reuse(&mut self, existing: ty::Id) {
|
fn on_reuse(&mut self, existing: ty::Id) {
|
||||||
|
let state_slot = self.ct.active() as usize;
|
||||||
if let ty::Kind::Func(id) = existing.expand()
|
if let ty::Kind::Func(id) = existing.expand()
|
||||||
&& let func = &mut self.tys.ins.funcs[id as usize]
|
&& 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()
|
&& 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();
|
let task = self.tys.tasks[idx].take();
|
||||||
self.tys.tasks.push(task);
|
self.tys.tasks.push(task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_global(&mut self, file: FileId, name: Ident, expr: &Expr) -> ty::Id {
|
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;
|
let gid = self.tys.ins.globals.len() as ty::Global;
|
||||||
self.tys.ins.globals.push(Global { file, name, ..Default::default() });
|
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.pool.pop_ci(&mut self.ci);
|
||||||
self.tys.ins.globals[gid as usize].ty = ret;
|
self.tys.ins.globals[gid as usize].ty = ret;
|
||||||
|
|
||||||
|
self.ct.deactivate();
|
||||||
ty.compress()
|
ty.compress()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4475,7 +4484,7 @@ impl TypeParser for Codegen<'_> {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use {
|
use {
|
||||||
super::CodegenCtx,
|
super::{hbvm::HbvmBackend, CodegenCtx},
|
||||||
alloc::{string::String, vec::Vec},
|
alloc::{string::String, vec::Vec},
|
||||||
core::fmt::Write,
|
core::fmt::Write,
|
||||||
};
|
};
|
||||||
|
@ -4487,7 +4496,8 @@ mod tests {
|
||||||
|
|
||||||
let mut ctx = CodegenCtx::default();
|
let mut ctx = CodegenCtx::default();
|
||||||
let (ref files, embeds) = crate::test_parse_files(ident, input, &mut ctx.parser);
|
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.push_embeds(embeds);
|
||||||
|
|
||||||
codegen.generate(0);
|
codegen.generate(0);
|
||||||
|
@ -4501,9 +4511,9 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut out = Vec::new();
|
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 {
|
if let Err(e) = err {
|
||||||
writeln!(output, "!!! asm is invalid: {e}").unwrap();
|
writeln!(output, "!!! asm is invalid: {e}").unwrap();
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
use {
|
use {
|
||||||
super::{ItemCtx, Nid, Nodes, Pool, RallocBRef, Regalloc, ARG_START, NEVER, VOID},
|
super::{AssemblySpec, Backend, ItemCtx, Nid, Nodes, RallocBRef, ARG_START, NEVER, VOID},
|
||||||
crate::{
|
crate::{
|
||||||
lexer::TokenKind,
|
lexer::TokenKind,
|
||||||
parser, reg,
|
parser, reg,
|
||||||
son::{write_reloc, Kind, MEM},
|
son::{write_reloc, Kind, MEM},
|
||||||
task,
|
|
||||||
ty::{self, Arg, Loc},
|
ty::{self, Arg, Loc},
|
||||||
utils::{BitSet, Vc},
|
utils::{BitSet, Vc},
|
||||||
HashMap, Offset, PLoc, Reloc, Sig, Size, TypedReloc, Types,
|
HashMap, Offset, PLoc, Reloc, Sig, Size, TypedReloc, Types,
|
||||||
|
@ -14,139 +13,94 @@ use {
|
||||||
hbbytecode::{self as instrs, *},
|
hbbytecode::{self as instrs, *},
|
||||||
};
|
};
|
||||||
|
|
||||||
impl Types {
|
struct FuncDt {
|
||||||
pub fn assemble(&mut self, to: &mut Vec<u8>) {
|
offset: Offset,
|
||||||
to.extend([0u8; HEADER_SIZE]);
|
// TODO: change to indices into common vec
|
||||||
|
relocs: Vec<TypedReloc>,
|
||||||
|
code: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
binary_prelude(to);
|
impl Default for FuncDt {
|
||||||
let exe = self.dump_reachable(0, to);
|
fn default() -> Self {
|
||||||
Reloc::new(HEADER_SIZE, 3, 4).apply_jump(to, self.ins.funcs[0].offset, 0);
|
Self { offset: u32::MAX, relocs: Default::default(), code: Default::default() }
|
||||||
|
|
||||||
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 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])) {
|
fn emit(&mut self, instr: (usize, [u8; instrs::MAX_SIZE])) {
|
||||||
emit(&mut self.code, instr);
|
emit(&mut self.code, instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_body_code(
|
fn emit_body_code(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
nodes: &mut Nodes,
|
||||||
sig: Sig,
|
sig: Sig,
|
||||||
tys: &Types,
|
tys: &Types,
|
||||||
files: &[parser::Ast],
|
files: &[parser::Ast],
|
||||||
ralloc: &mut Regalloc,
|
) -> (usize, bool) {
|
||||||
) -> usize {
|
let mut ralloc = mem::take(&mut self.ralloc);
|
||||||
let mut nodes = mem::take(&mut self.nodes);
|
|
||||||
|
|
||||||
let fuc = Function::new(&mut nodes, tys, sig);
|
let fuc = Function::new(nodes, tys, sig);
|
||||||
log::info!("{:?}", fuc);
|
log::info!("{:?}", fuc);
|
||||||
if self.call_count != 0 {
|
if !fuc.tail {
|
||||||
mem::swap(
|
mem::swap(
|
||||||
&mut ralloc.env.preferred_regs_by_class,
|
&mut ralloc.env.preferred_regs_by_class,
|
||||||
&mut ralloc.env.non_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[vreg.vreg() as Nid].lock_rc = Nid::MAX;
|
||||||
fuc.nodes[fuc.instrs[inst.index()].nid].lock_rc = Nid::MAX - 1;
|
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}")
|
panic!("{err}")
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
if self.call_count != 0 {
|
if !fuc.tail {
|
||||||
mem::swap(
|
mem::swap(
|
||||||
&mut ralloc.env.preferred_regs_by_class,
|
&mut ralloc.env.preferred_regs_by_class,
|
||||||
&mut ralloc.env.non_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)
|
*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 (retl, mut parama) = tys.parama(sig.ret);
|
||||||
let mut typs = sig.args.args();
|
let mut typs = sig.args.args();
|
||||||
let mut args = fuc.nodes[VOID].outputs[ARG_START..].iter();
|
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(rg, size) if ty.loc(tys) == Loc::Stack => (rg, size),
|
||||||
PLoc::Reg(..) | PLoc::Ref(..) => continue,
|
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 {
|
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() {
|
for (i, block) in fuc.blocks.iter().enumerate() {
|
||||||
let blk = regalloc2::Block(i as _);
|
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) {
|
for instr_or_edit in ralloc.ctx.output.block_insts_and_edits(&fuc, blk) {
|
||||||
let inst = match instr_or_edit {
|
let inst = match instr_or_edit {
|
||||||
regalloc2::InstOrEdit::Inst(inst) => inst,
|
regalloc2::InstOrEdit::Inst(inst) => inst,
|
||||||
|
@ -223,6 +182,7 @@ impl ItemCtx {
|
||||||
};
|
};
|
||||||
let allocs = ralloc.ctx.output.inst_allocs(inst);
|
let allocs = ralloc.ctx.output.inst_allocs(inst);
|
||||||
let node = &fuc.nodes[nid];
|
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 mut extend = |base: ty::Id, dest: ty::Id, from: usize, to: usize| {
|
||||||
let (bsize, dsize) = (tys.size_of(base), tys.size_of(dest));
|
let (bsize, dsize) = (tys.size_of(base), tys.size_of(dest));
|
||||||
|
@ -270,7 +230,7 @@ impl ItemCtx {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Kind::Loop | Kind::Region => {
|
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);
|
let rel = Reloc::new(self.code.len(), 1, 4);
|
||||||
self.jump_relocs.push((nid, rel));
|
self.jump_relocs.push((nid, rel));
|
||||||
self.emit(instrs::jmp(0));
|
self.emit(instrs::jmp(0));
|
||||||
|
@ -418,7 +378,7 @@ impl ItemCtx {
|
||||||
fuc.nodes[*node.inputs.last().unwrap()].kind,
|
fuc.nodes[*node.inputs.last().unwrap()].kind,
|
||||||
Kind::Stck
|
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));
|
self.emit(instrs::st(r, reg::STACK_PTR, stck as _, size));
|
||||||
}
|
}
|
||||||
if let Some(PLoc::Reg(r, size)) = ret
|
if let Some(PLoc::Reg(r, size)) = ret
|
||||||
|
@ -428,7 +388,7 @@ impl ItemCtx {
|
||||||
fuc.nodes[*node.inputs.last().unwrap()].kind,
|
fuc.nodes[*node.inputs.last().unwrap()].kind,
|
||||||
Kind::Stck
|
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));
|
self.emit(instrs::st(r, reg::STACK_PTR, stck as _, size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -442,7 +402,7 @@ impl ItemCtx {
|
||||||
}
|
}
|
||||||
Kind::Stck => {
|
Kind::Stck => {
|
||||||
let base = reg::STACK_PTR;
|
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 _));
|
self.emit(instrs::addi64(atr(allocs[0]), base, offset as _));
|
||||||
}
|
}
|
||||||
Kind::Load => {
|
Kind::Load => {
|
||||||
|
@ -458,7 +418,9 @@ impl ItemCtx {
|
||||||
let size = tys.size_of(node.ty);
|
let size = tys.size_of(node.ty);
|
||||||
if node.ty.loc(tys) != Loc::Stack {
|
if node.ty.loc(tys) != Loc::Stack {
|
||||||
let (base, offset) = match fuc.nodes[region].kind {
|
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),
|
_ => (atr(allocs[1]), offset),
|
||||||
};
|
};
|
||||||
self.emit(instrs::ld(atr(allocs[0]), base, offset as _, size as _));
|
self.emit(instrs::ld(atr(allocs[0]), base, offset as _, size as _));
|
||||||
|
@ -480,7 +442,7 @@ impl ItemCtx {
|
||||||
let nd = &fuc.nodes[region];
|
let nd = &fuc.nodes[region];
|
||||||
let (base, offset, src) = match nd.kind {
|
let (base, offset, src) = match nd.kind {
|
||||||
Kind::Stck if node.ty.loc(tys) == Loc::Reg => {
|
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]),
|
_ => (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,
|
&mut self,
|
||||||
tys: &mut Types,
|
from: ty::Func,
|
||||||
files: &[parser::Ast],
|
types: &Types,
|
||||||
sig: Sig,
|
to: &mut Vec<u8>,
|
||||||
pool: &mut Pool,
|
) -> AssemblySpec {
|
||||||
) {
|
debug_assert!(self.asm.frontier.is_empty());
|
||||||
self.emit_body(tys, files, sig, pool);
|
debug_assert!(self.asm.funcs.is_empty());
|
||||||
self.code.truncate(self.code.len() - instrs::jala(0, 0, 0).0);
|
debug_assert!(self.asm.globals.is_empty());
|
||||||
self.emit(instrs::tx());
|
|
||||||
|
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!(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn emit_body(&mut self, tys: &mut Types, files: &[parser::Ast], sig: Sig, pool: &mut Pool) {
|
let init_len = to.len();
|
||||||
self.nodes.check_final_integrity(tys, files);
|
|
||||||
self.nodes.graphviz(tys, files);
|
for &func in &self.asm.funcs {
|
||||||
self.nodes.gcm(&mut pool.nid_stack);
|
let fuc = &mut self.funcs[func as usize];
|
||||||
self.nodes.basic_blocks();
|
fuc.offset = to.len() as _;
|
||||||
self.nodes.graphviz(tys, files);
|
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 _,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
debug_assert!(self.code.is_empty());
|
||||||
let tail = mem::take(&mut self.call_count) == 0;
|
|
||||||
|
|
||||||
'_open_function: {
|
self.offsets.clear();
|
||||||
self.emit(instrs::addi64(reg::STACK_PTR, reg::STACK_PTR, 0));
|
self.offsets.resize(nodes.values.len(), Offset::MAX);
|
||||||
self.emit(instrs::st(reg::RET_ADDR + tail as u8, reg::STACK_PTR, 0, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut stack_size = 0;
|
let mut stack_size = 0;
|
||||||
'_compute_stack: {
|
'_compute_stack: {
|
||||||
let mems = mem::take(&mut self.nodes[MEM].outputs);
|
let mems = mem::take(&mut nodes[MEM].outputs);
|
||||||
for &stck in mems.iter() {
|
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!(
|
debug_assert_matches!(
|
||||||
self.nodes[stck].kind,
|
nodes[stck].kind,
|
||||||
Kind::Phi | Kind::Return | Kind::Load | Kind::Call { .. } | Kind::Stre
|
Kind::Phi | Kind::Return | Kind::Load | Kind::Call { .. } | Kind::Stre
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
stack_size += tys.size_of(self.nodes[stck].ty);
|
stack_size += tys.size_of(nodes[stck].ty);
|
||||||
self.nodes[stck].offset = stack_size;
|
self.offsets[stck as usize] = stack_size;
|
||||||
}
|
}
|
||||||
for &stck in mems.iter() {
|
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;
|
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()
|
if let Some(last_ret) = self.ret_relocs.last()
|
||||||
&& last_ret.offset as usize == self.code.len() - 5
|
&& last_ret.offset as usize == self.code.len() - 5
|
||||||
&& self
|
&& self
|
||||||
.jump_relocs
|
.jump_relocs
|
||||||
.last()
|
.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.code.truncate(self.code.len() - 5);
|
||||||
self.ret_relocs.pop();
|
self.ret_relocs.pop();
|
||||||
|
@ -577,7 +674,7 @@ impl ItemCtx {
|
||||||
|
|
||||||
// FIXME: maybe do this incrementally
|
// FIXME: maybe do this incrementally
|
||||||
for (nd, rel) in self.jump_relocs.drain(..) {
|
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);
|
//debug_assert!(offset < self.code.len() as u32 - 1);
|
||||||
rel.apply_jump(&mut self.code, offset, 0);
|
rel.apply_jump(&mut self.code, offset, 0);
|
||||||
}
|
}
|
||||||
|
@ -592,17 +689,20 @@ impl ItemCtx {
|
||||||
let pushed = (saved as i64 + !tail as i64) * 8;
|
let pushed = (saved as i64 + !tail as i64) * 8;
|
||||||
let stack = stack_size as i64;
|
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) {
|
match (pushed, stack) {
|
||||||
(0, 0) => {
|
(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);
|
self.code.drain(0..stripped_prelude_size);
|
||||||
break '_close_function;
|
break '_close_function;
|
||||||
}
|
}
|
||||||
(0, stack) => {
|
(0, stack) => {
|
||||||
write_reloc(&mut self.code, 3, -stack, 8);
|
write_reloc(&mut self.code, 3, -stack, 8);
|
||||||
stripped_prelude_size = instrs::st(0, 0, 0, 0).0;
|
stripped_prelude_size = st_len;
|
||||||
let end = instrs::addi64(0, 0, 0).0 + instrs::st(0, 0, 0, 0).0;
|
let end = add_len + st_len;
|
||||||
self.code.drain(instrs::addi64(0, 0, 0).0..end);
|
self.code.drain(add_len..end);
|
||||||
self.emit(instrs::addi64(reg::STACK_PTR, reg::STACK_PTR, stack as _));
|
self.emit(instrs::addi64(reg::STACK_PTR, reg::STACK_PTR, stack as _));
|
||||||
break '_close_function;
|
break '_close_function;
|
||||||
}
|
}
|
||||||
|
@ -625,9 +725,22 @@ impl ItemCtx {
|
||||||
if sig.ret != ty::Id::NEVER {
|
if sig.ret != ty::Id::NEVER {
|
||||||
self.emit(instrs::jala(reg::ZERO, reg::RET_ADDR, 0));
|
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)]
|
#[derive(Debug)]
|
||||||
struct Block {
|
struct Block {
|
||||||
nid: Nid,
|
nid: Nid,
|
||||||
|
@ -648,6 +761,9 @@ pub struct Function<'a> {
|
||||||
sig: Sig,
|
sig: Sig,
|
||||||
nodes: &'a mut Nodes,
|
nodes: &'a mut Nodes,
|
||||||
tys: &'a Types,
|
tys: &'a Types,
|
||||||
|
tail: bool,
|
||||||
|
visited: BitSet,
|
||||||
|
backrefs: Vec<u16>,
|
||||||
blocks: Vec<Block>,
|
blocks: Vec<Block>,
|
||||||
instrs: Vec<Instr>,
|
instrs: Vec<Instr>,
|
||||||
}
|
}
|
||||||
|
@ -670,9 +786,17 @@ impl core::fmt::Debug for Function<'_> {
|
||||||
|
|
||||||
impl<'a> Function<'a> {
|
impl<'a> Function<'a> {
|
||||||
fn new(nodes: &'a mut Nodes, tys: &'a Types, sig: Sig) -> Self {
|
fn new(nodes: &'a mut Nodes, tys: &'a Types, sig: Sig) -> Self {
|
||||||
let mut s =
|
let mut s = Self {
|
||||||
Self { nodes, tys, sig, blocks: Default::default(), instrs: Default::default() };
|
tys,
|
||||||
s.nodes.visited.clear(s.nodes.values.len());
|
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.emit_node(VOID, VOID);
|
||||||
s.add_block(0);
|
s.add_block(0);
|
||||||
s.blocks.pop();
|
s.blocks.pop();
|
||||||
|
@ -726,7 +850,7 @@ impl<'a> Function<'a> {
|
||||||
|
|
||||||
fn emit_node(&mut self, nid: Nid, prev: Nid) {
|
fn emit_node(&mut self, nid: Nid, prev: Nid) {
|
||||||
if matches!(self.nodes[nid].kind, Kind::Region | Kind::Loop) {
|
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 node = self.nodes[nid].clone();
|
||||||
|
|
||||||
let idx = 1 + node.inputs.iter().position(|&i| i == prev).unwrap();
|
let idx = 1 + node.inputs.iter().position(|&i| i == prev).unwrap();
|
||||||
|
@ -742,7 +866,7 @@ impl<'a> Function<'a> {
|
||||||
|
|
||||||
self.add_instr(nid, vec![]);
|
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) => {
|
(Kind::Loop, false) => {
|
||||||
for i in node.inputs {
|
for i in node.inputs {
|
||||||
self.bridge(i, nid);
|
self.bridge(i, nid);
|
||||||
|
@ -752,7 +876,7 @@ impl<'a> Function<'a> {
|
||||||
(Kind::Region, true) => return,
|
(Kind::Region, true) => return,
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
} else if !self.nodes.visited.set(nid) {
|
} else if !self.visited.set(nid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -763,7 +887,7 @@ impl<'a> Function<'a> {
|
||||||
self.emit_node(node.outputs[0], VOID)
|
self.emit_node(node.outputs[0], VOID)
|
||||||
}
|
}
|
||||||
Kind::If => {
|
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 &[_, cond] = node.inputs.as_slice() else { unreachable!() };
|
||||||
let &[mut then, mut else_] = node.outputs.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);
|
self.emit_node(else_, nid);
|
||||||
}
|
}
|
||||||
Kind::Region | Kind::Loop => {
|
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 {
|
if node.kind == Kind::Region {
|
||||||
for i in node.inputs {
|
for i in node.inputs {
|
||||||
self.bridge(i, nid);
|
self.bridge(i, nid);
|
||||||
|
@ -800,7 +924,7 @@ impl<'a> Function<'a> {
|
||||||
}
|
}
|
||||||
block.push(self.rg(ph));
|
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);
|
self.reschedule_block(nid, &mut node.outputs);
|
||||||
for o in node.outputs.into_iter().rev() {
|
for o in node.outputs.into_iter().rev() {
|
||||||
self.emit_node(o, nid);
|
self.emit_node(o, nid);
|
||||||
|
@ -849,7 +973,7 @@ impl<'a> Function<'a> {
|
||||||
self.add_instr(nid, ops);
|
self.add_instr(nid, ops);
|
||||||
}
|
}
|
||||||
Kind::Entry => {
|
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 (ret, mut parama) = self.tys.parama(self.sig.ret);
|
||||||
let mut typs = self.sig.args.args();
|
let mut typs = self.sig.args.args();
|
||||||
|
@ -882,7 +1006,7 @@ impl<'a> Function<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Kind::Then | Kind::Else => {
|
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.bridge(prev, nid);
|
||||||
self.reschedule_block(nid, &mut node.outputs);
|
self.reschedule_block(nid, &mut node.outputs);
|
||||||
for o in node.outputs.into_iter().rev() {
|
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])];
|
let ops = vec![self.drg(nid), self.urg(node.inputs[1])];
|
||||||
self.add_instr(nid, ops);
|
self.add_instr(nid, ops);
|
||||||
}
|
}
|
||||||
Kind::Call { args, .. } => {
|
Kind::Call { args, func } => {
|
||||||
self.nodes[nid].ralloc_backref = self.nodes[prev].ralloc_backref;
|
self.tail &= func == ty::ECA;
|
||||||
|
self.backrefs[nid as usize] = self.backrefs[prev as usize];
|
||||||
let mut ops = vec![];
|
let mut ops = vec![];
|
||||||
|
|
||||||
let (ret, mut parama) = self.tys.parama(node.ty);
|
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) {
|
fn bridge(&mut self, pred: u16, succ: u16) {
|
||||||
if self.nodes[pred].ralloc_backref == u16::MAX
|
if self.backrefs[pred as usize] == u16::MAX || self.backrefs[succ as usize] == u16::MAX {
|
||||||
|| self.nodes[succ].ralloc_backref == u16::MAX
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.blocks[self.nodes[pred].ralloc_backref as usize]
|
self.blocks[self.backrefs[pred as usize] as usize]
|
||||||
.succs
|
.succs
|
||||||
.push(regalloc2::Block::new(self.nodes[succ].ralloc_backref as usize));
|
.push(regalloc2::Block::new(self.backrefs[succ as usize] as usize));
|
||||||
self.blocks[self.nodes[succ].ralloc_backref as usize]
|
self.blocks[self.backrefs[succ as usize] as usize]
|
||||||
.preds
|
.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) {
|
fn reschedule_block(&mut self, from: Nid, outputs: &mut Vc) {
|
||||||
|
@ -1245,7 +1368,7 @@ impl regalloc2::Function for Function<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TokenKind {
|
impl TokenKind {
|
||||||
pub fn cmp_against(self) -> Option<u64> {
|
fn cmp_against(self) -> Option<u64> {
|
||||||
Some(match self {
|
Some(match self {
|
||||||
TokenKind::Le | TokenKind::Gt => 1,
|
TokenKind::Le | TokenKind::Gt => 1,
|
||||||
TokenKind::Ne | TokenKind::Eq => 0,
|
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() {
|
if !ty.is_float() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
@ -1369,7 +1492,7 @@ impl TokenKind {
|
||||||
Some(ops[size.ilog2() as usize])
|
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;
|
let src_idx = src.simple_size().unwrap().ilog2() as usize - 2;
|
||||||
Some(match self {
|
Some(match self {
|
||||||
Self::Sub => instrs::neg,
|
Self::Sub => instrs::neg,
|
||||||
|
@ -1392,7 +1515,7 @@ fn emit(out: &mut Vec<u8>, (len, instr): EncodedInstr) {
|
||||||
out.extend_from_slice(&instr[..len]);
|
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::jal(reg::RET_ADDR, reg::ZERO, 0));
|
||||||
emit(to, instrs::tx());
|
emit(to, instrs::tx());
|
||||||
}
|
}
|
||||||
|
@ -1501,6 +1624,7 @@ pub struct Comptime {
|
||||||
pub vm: hbvm::Vm<LoggedMem, { 1024 * 10 }>,
|
pub vm: hbvm::Vm<LoggedMem, { 1024 * 10 }>,
|
||||||
stack: Box<[u8; VM_STACK_SIZE]>,
|
stack: Box<[u8; VM_STACK_SIZE]>,
|
||||||
pub code: Vec<u8>,
|
pub code: Vec<u8>,
|
||||||
|
depth: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Comptime {
|
impl Comptime {
|
||||||
|
@ -1544,6 +1668,19 @@ impl Comptime {
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
self.code.clear();
|
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 {
|
impl Default for Comptime {
|
||||||
|
@ -1552,7 +1689,7 @@ impl Default for Comptime {
|
||||||
let mut vm = hbvm::Vm::default();
|
let mut vm = hbvm::Vm::default();
|
||||||
let ptr = unsafe { stack.as_mut_ptr().cast::<u8>().add(VM_STACK_SIZE) as u64 };
|
let ptr = unsafe { stack.as_mut_ptr().cast::<u8>().add(VM_STACK_SIZE) as u64 };
|
||||||
vm.write_reg(reg::STACK_PTR, ptr);
|
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:
|
main:
|
||||||
ADDI64 r254, r254, -40d
|
ADDI64 r254, r254, -56d
|
||||||
ST r31, r254, 24a, 16h
|
ST r31, r254, 24a, 32h
|
||||||
LI64 r32, 1d
|
LI64 r32, 1d
|
||||||
ADDI64 r2, r254, 0d
|
ADDI64 r2, r254, 0d
|
||||||
ST r32, r254, 0a, 8h
|
ST r32, r254, 0a, 8h
|
||||||
LI64 r5, 2d
|
LI64 r33, 2d
|
||||||
ST r5, r254, 8a, 8h
|
ST r33, r254, 8a, 8h
|
||||||
LI64 r8, 4d
|
LI64 r34, 4d
|
||||||
ST r8, r254, 16a, 8h
|
ST r34, r254, 16a, 8h
|
||||||
JAL r31, r0, :pass
|
JAL r31, r0, :pass
|
||||||
ADD64 r1, r1, r32
|
ADD64 r1, r1, r32
|
||||||
LD r31, r254, 24a, 16h
|
LD r31, r254, 24a, 32h
|
||||||
ADDI64 r254, r254, 40d
|
ADDI64 r254, r254, 56d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
pass:
|
pass:
|
||||||
LD r4, r2, 8a, 8h
|
LD r4, r2, 8a, 8h
|
||||||
|
|
|
@ -6,8 +6,7 @@ main:
|
||||||
CP r32, r1
|
CP r32, r1
|
||||||
LRA r2, r0, :"fff\0"
|
LRA r2, r0, :"fff\0"
|
||||||
JAL r31, r0, :str_len
|
JAL r31, r0, :str_len
|
||||||
CP r10, r32
|
ADD64 r1, r1, r32
|
||||||
ADD64 r1, r1, r10
|
|
||||||
LD r31, r254, 0a, 16h
|
LD r31, r254, 0a, 16h
|
||||||
ADDI64 r254, r254, 16d
|
ADDI64 r254, r254, 16d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
|
@ -23,6 +22,6 @@ str_len:
|
||||||
ADDI64 r1, r1, 1d
|
ADDI64 r1, r1, 1d
|
||||||
JMP :2
|
JMP :2
|
||||||
1: JALA r0, r31, 0a
|
1: JALA r0, r31, 0a
|
||||||
code size: 219
|
code size: 216
|
||||||
ret: 16
|
ret: 16
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -2,18 +2,18 @@ cond:
|
||||||
LI64 r1, 0d
|
LI64 r1, 0d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -8d
|
ADDI64 r254, r254, -24d
|
||||||
ST r31, r254, 0a, 8h
|
ST r31, r254, 0a, 24h
|
||||||
JAL r31, r0, :cond
|
JAL r31, r0, :cond
|
||||||
LI64 r5, 0d
|
LI64 r32, 0d
|
||||||
CP r7, r5
|
CP r33, r32
|
||||||
JNE r1, r7, :0
|
JNE r1, r33, :0
|
||||||
CP r5, r7
|
CP r32, r33
|
||||||
CP r1, r5
|
CP r1, r32
|
||||||
JMP :1
|
JMP :1
|
||||||
0: LI64 r1, 2d
|
0: LI64 r1, 2d
|
||||||
1: LD r31, r254, 0a, 8h
|
1: LD r31, r254, 0a, 24h
|
||||||
ADDI64 r254, r254, 8d
|
ADDI64 r254, r254, 24d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 134
|
code size: 134
|
||||||
ret: 0
|
ret: 0
|
||||||
|
|
|
@ -30,50 +30,50 @@ infinite_loop:
|
||||||
ADDI64 r254, r254, 24d
|
ADDI64 r254, r254, 24d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -56d
|
ADDI64 r254, r254, -64d
|
||||||
ST r31, r254, 0a, 56h
|
ST r31, r254, 0a, 64h
|
||||||
LI64 r32, 0d
|
LI64 r32, 0d
|
||||||
CP r2, r32
|
CP r2, r32
|
||||||
JAL r31, r0, :multiple_breaks
|
JAL r31, r0, :multiple_breaks
|
||||||
CP r2, r1
|
CP r33, r1
|
||||||
LI64 r1, 3d
|
LI64 r1, 3d
|
||||||
JEQ r2, r1, :0
|
JEQ r33, r1, :0
|
||||||
LI64 r1, 1d
|
LI64 r1, 1d
|
||||||
JMP :1
|
JMP :1
|
||||||
0: CP r33, r1
|
0: CP r34, r1
|
||||||
LI64 r34, 4d
|
LI64 r35, 4d
|
||||||
CP r2, r34
|
CP r2, r35
|
||||||
JAL r31, r0, :multiple_breaks
|
JAL r31, r0, :multiple_breaks
|
||||||
CP r35, r34
|
CP r36, r35
|
||||||
LI64 r36, 10d
|
LI64 r37, 10d
|
||||||
JEQ r1, r36, :2
|
JEQ r1, r37, :2
|
||||||
LI64 r1, 2d
|
LI64 r1, 2d
|
||||||
JMP :1
|
JMP :1
|
||||||
2: CP r2, r32
|
2: CP r2, r32
|
||||||
JAL r31, r0, :state_change_in_break
|
JAL r31, r0, :state_change_in_break
|
||||||
JEQ r1, r32, :3
|
JEQ r1, r32, :3
|
||||||
CP r1, r33
|
CP r1, r34
|
||||||
JMP :1
|
JMP :1
|
||||||
3: CP r2, r35
|
3: CP r2, r36
|
||||||
JAL r31, r0, :state_change_in_break
|
JAL r31, r0, :state_change_in_break
|
||||||
JEQ r1, r36, :4
|
JEQ r1, r37, :4
|
||||||
CP r1, r35
|
CP r1, r36
|
||||||
JMP :1
|
JMP :1
|
||||||
4: CP r2, r36
|
4: CP r2, r37
|
||||||
JAL r31, r0, :continue_and_state_change
|
JAL r31, r0, :continue_and_state_change
|
||||||
JEQ r1, r36, :5
|
JEQ r1, r37, :5
|
||||||
LI64 r1, 5d
|
LI64 r1, 5d
|
||||||
JMP :1
|
JMP :1
|
||||||
5: CP r2, r33
|
5: CP r2, r34
|
||||||
JAL r31, r0, :continue_and_state_change
|
JAL r31, r0, :continue_and_state_change
|
||||||
JEQ r1, r32, :6
|
JEQ r1, r32, :6
|
||||||
LI64 r1, 6d
|
LI64 r1, 6d
|
||||||
JMP :1
|
JMP :1
|
||||||
6: CP r37, r32
|
6: CP r38, r32
|
||||||
JAL r31, r0, :infinite_loop
|
JAL r31, r0, :infinite_loop
|
||||||
CP r1, r37
|
CP r1, r38
|
||||||
1: LD r31, r254, 0a, 56h
|
1: LD r31, r254, 0a, 64h
|
||||||
ADDI64 r254, r254, 56d
|
ADDI64 r254, r254, 64d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
multiple_breaks:
|
multiple_breaks:
|
||||||
LI64 r6, 3d
|
LI64 r6, 3d
|
||||||
|
|
|
@ -6,42 +6,40 @@ check_platform:
|
||||||
ADDI64 r254, r254, 8d
|
ADDI64 r254, r254, 8d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -48d
|
ADDI64 r254, r254, -64d
|
||||||
ST r31, r254, 0a, 48h
|
ST r31, r254, 0a, 64h
|
||||||
JAL r31, r0, :check_platform
|
JAL r31, r0, :check_platform
|
||||||
LI64 r32, 0d
|
LI64 r32, 0d
|
||||||
LI64 r33, 30d
|
LI64 r33, 30d
|
||||||
LI64 r34, 100d
|
LI64 r34, 100d
|
||||||
CP r10, r32
|
|
||||||
CP r35, r32
|
CP r35, r32
|
||||||
CP r36, r32
|
CP r36, r32
|
||||||
5: JLTU r10, r33, :0
|
CP r37, r32
|
||||||
ADDI64 r35, r35, 1d
|
5: JLTU r35, r33, :0
|
||||||
|
ADDI64 r36, r36, 1d
|
||||||
CP r2, r32
|
CP r2, r32
|
||||||
CP r3, r35
|
CP r3, r36
|
||||||
CP r4, r33
|
CP r4, r33
|
||||||
JAL r31, r0, :set_pixel
|
JAL r31, r0, :set_pixel
|
||||||
CP r2, r36
|
JEQ r1, r37, :1
|
||||||
JEQ r1, r2, :1
|
|
||||||
CP r1, r32
|
CP r1, r32
|
||||||
JMP :2
|
JMP :2
|
||||||
1: CP r5, r32
|
1: CP r38, r32
|
||||||
CP r36, r2
|
JNE r36, r34, :3
|
||||||
JNE r35, r34, :3
|
CP r1, r37
|
||||||
CP r1, r36
|
|
||||||
JMP :2
|
JMP :2
|
||||||
3: CP r1, r36
|
3: CP r1, r37
|
||||||
CP r10, r5
|
CP r35, r38
|
||||||
JMP :4
|
JMP :4
|
||||||
0: CP r1, r36
|
0: CP r1, r37
|
||||||
CP r5, r32
|
CP r38, r32
|
||||||
ADDI64 r1, r1, 1d
|
ADDI64 r1, r1, 1d
|
||||||
ADDI64 r10, r10, 1d
|
ADDI64 r35, r35, 1d
|
||||||
4: CP r32, r5
|
4: CP r32, r38
|
||||||
CP r36, r1
|
CP r37, r1
|
||||||
JMP :5
|
JMP :5
|
||||||
2: LD r31, r254, 0a, 48h
|
2: LD r31, r254, 0a, 64h
|
||||||
ADDI64 r254, r254, 48d
|
ADDI64 r254, r254, 64d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
set_pixel:
|
set_pixel:
|
||||||
MUL64 r7, r3, r4
|
MUL64 r7, r3, r4
|
||||||
|
@ -50,6 +48,6 @@ set_pixel:
|
||||||
x86_fb_ptr:
|
x86_fb_ptr:
|
||||||
LI64 r1, 100d
|
LI64 r1, 100d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 336
|
code size: 330
|
||||||
ret: 3000
|
ret: 3000
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -12,11 +12,10 @@ main:
|
||||||
CP r32, r1
|
CP r32, r1
|
||||||
LI64 r2, 20d
|
LI64 r2, 20d
|
||||||
JAL r31, r0, :add_two
|
JAL r31, r0, :add_two
|
||||||
CP r10, r32
|
ADD64 r1, r1, r32
|
||||||
ADD64 r1, r1, r10
|
|
||||||
LD r31, r254, 0a, 16h
|
LD r31, r254, 0a, 16h
|
||||||
ADDI64 r254, r254, 16d
|
ADDI64 r254, r254, 16d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 155
|
code size: 152
|
||||||
ret: 33
|
ret: 33
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -5,8 +5,8 @@ add:
|
||||||
ADD32 r1, r2, r3
|
ADD32 r1, r2, r3
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -16d
|
ADDI64 r254, r254, -24d
|
||||||
ST r31, r254, 0a, 16h
|
ST r31, r254, 0a, 24h
|
||||||
LI32 r3, 2w
|
LI32 r3, 2w
|
||||||
CP r2, r3
|
CP r2, r3
|
||||||
JAL r31, r0, :add
|
JAL r31, r0, :add
|
||||||
|
@ -14,12 +14,11 @@ main:
|
||||||
LI64 r3, 3d
|
LI64 r3, 3d
|
||||||
LI64 r2, 1d
|
LI64 r2, 1d
|
||||||
JAL r31, r0, :add
|
JAL r31, r0, :add
|
||||||
CP r2, r32
|
ANDI r33, r32, 4294967295d
|
||||||
ANDI r11, r2, 4294967295d
|
SUB64 r1, r33, r1
|
||||||
SUB64 r1, r11, r1
|
LD r31, r254, 0a, 24h
|
||||||
LD r31, r254, 0a, 16h
|
ADDI64 r254, r254, 24d
|
||||||
ADDI64 r254, r254, 16d
|
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 161
|
code size: 158
|
||||||
ret: 0
|
ret: 0
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
deinit:
|
deinit:
|
||||||
ADDI64 r254, r254, -16d
|
ADDI64 r254, r254, -32d
|
||||||
ST r31, r254, 0a, 16h
|
ST r31, r254, 0a, 32h
|
||||||
CP r32, r2
|
CP r32, r2
|
||||||
LD r5, r2, 16a, 8h
|
LD r33, r2, 16a, 8h
|
||||||
LI64 r4, 8d
|
LI64 r4, 8d
|
||||||
MUL64 r3, r5, r4
|
MUL64 r3, r33, r4
|
||||||
CP r5, r32
|
CP r34, r32
|
||||||
LD r2, r5, 0a, 8h
|
LD r2, r34, 0a, 8h
|
||||||
JAL r31, r0, :free
|
JAL r31, r0, :free
|
||||||
CP r1, r32
|
CP r1, r32
|
||||||
JAL r31, r0, :new
|
JAL r31, r0, :new
|
||||||
LD r31, r254, 0a, 16h
|
LD r31, r254, 0a, 32h
|
||||||
ADDI64 r254, r254, 16d
|
ADDI64 r254, r254, 32d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
free:
|
free:
|
||||||
CP r10, r2
|
CP r10, r2
|
||||||
|
@ -23,21 +23,21 @@ free:
|
||||||
ECA
|
ECA
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -48d
|
ADDI64 r254, r254, -56d
|
||||||
ST r31, r254, 24a, 24h
|
ST r31, r254, 24a, 32h
|
||||||
ADDI64 r32, r254, 0d
|
ADDI64 r32, r254, 0d
|
||||||
CP r1, r32
|
CP r1, r32
|
||||||
JAL r31, r0, :new
|
JAL r31, r0, :new
|
||||||
LI64 r3, 69d
|
LI64 r3, 69d
|
||||||
CP r2, r32
|
CP r2, r32
|
||||||
JAL r31, r0, :push
|
JAL r31, r0, :push
|
||||||
LD r9, r254, 0a, 8h
|
LD r33, r254, 0a, 8h
|
||||||
LD r33, r9, 0a, 8h
|
LD r34, r33, 0a, 8h
|
||||||
CP r2, r32
|
CP r2, r32
|
||||||
JAL r31, r0, :deinit
|
JAL r31, r0, :deinit
|
||||||
CP r1, r33
|
CP r1, r34
|
||||||
LD r31, r254, 24a, 24h
|
LD r31, r254, 24a, 32h
|
||||||
ADDI64 r254, r254, 48d
|
ADDI64 r254, r254, 56d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
malloc:
|
malloc:
|
||||||
CP r9, r2
|
CP r9, r2
|
||||||
|
@ -58,69 +58,69 @@ new:
|
||||||
ADDI64 r254, r254, 24d
|
ADDI64 r254, r254, 24d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
push:
|
push:
|
||||||
ADDI64 r254, r254, -72d
|
ADDI64 r254, r254, -192d
|
||||||
ST r31, r254, 0a, 72h
|
ST r31, r254, 0a, 192h
|
||||||
CP r32, r3
|
CP r32, r3
|
||||||
LI64 r33, 1d
|
LI64 r33, 1d
|
||||||
LD r6, r2, 8a, 8h
|
LD r34, r2, 8a, 8h
|
||||||
LD r8, r2, 16a, 8h
|
LD r35, r2, 16a, 8h
|
||||||
CP r34, r2
|
CP r36, r2
|
||||||
JNE r8, r6, :0
|
JNE r35, r34, :0
|
||||||
LI64 r35, 0d
|
LI64 r37, 0d
|
||||||
JNE r8, r35, :1
|
JNE r35, r37, :1
|
||||||
CP r36, r33
|
CP r38, r33
|
||||||
JMP :2
|
JMP :2
|
||||||
1: MULI64 r36, r8, 2d
|
1: MULI64 r38, r35, 2d
|
||||||
2: LI64 r37, 8d
|
2: LI64 r39, 8d
|
||||||
MUL64 r2, r36, r37
|
MUL64 r2, r38, r39
|
||||||
CP r3, r37
|
CP r3, r39
|
||||||
JAL r31, r0, :malloc
|
JAL r31, r0, :malloc
|
||||||
CP r38, r1
|
CP r40, r1
|
||||||
CP r39, r34
|
CP r41, r36
|
||||||
ST r36, r39, 16a, 8h
|
ST r38, r41, 16a, 8h
|
||||||
LI64 r1, 0d
|
LI64 r1, 0d
|
||||||
CP r7, r38
|
CP r42, r40
|
||||||
JNE r7, r1, :3
|
JNE r42, r1, :3
|
||||||
JMP :4
|
JMP :4
|
||||||
3: CP r38, r7
|
3: CP r40, r42
|
||||||
LD r8, r39, 8a, 8h
|
LD r36, r41, 8a, 8h
|
||||||
MULI64 r10, r8, 8d
|
MULI64 r43, r36, 8d
|
||||||
LD r3, r39, 0a, 8h
|
LD r44, r41, 0a, 8h
|
||||||
ADD64 r7, r3, r10
|
ADD64 r45, r44, r43
|
||||||
CP r5, r38
|
CP r46, r40
|
||||||
9: LD r2, r39, 0a, 8h
|
9: LD r2, r41, 0a, 8h
|
||||||
LD r10, r39, 8a, 8h
|
LD r47, r41, 8a, 8h
|
||||||
JNE r7, r3, :5
|
JNE r45, r44, :5
|
||||||
JEQ r10, r35, :6
|
JEQ r47, r37, :6
|
||||||
CP r4, r37
|
CP r4, r39
|
||||||
MUL64 r3, r10, r4
|
MUL64 r3, r47, r4
|
||||||
JAL r31, r0, :free
|
JAL r31, r0, :free
|
||||||
CP r6, r38
|
CP r1, r40
|
||||||
JMP :7
|
JMP :7
|
||||||
6: CP r6, r38
|
6: CP r1, r40
|
||||||
7: ST r6, r39, 0a, 8h
|
7: ST r1, r41, 0a, 8h
|
||||||
JMP :8
|
JMP :8
|
||||||
5: CP r4, r37
|
5: CP r1, r40
|
||||||
CP r6, r38
|
CP r4, r39
|
||||||
ADDI64 r8, r5, 8d
|
ADDI64 r48, r46, 8d
|
||||||
ADDI64 r9, r3, 8d
|
ADDI64 r42, r44, 8d
|
||||||
LD r10, r3, 0a, 8h
|
LD r49, r44, 0a, 8h
|
||||||
ST r10, r5, 0a, 8h
|
ST r49, r46, 0a, 8h
|
||||||
CP r3, r9
|
CP r44, r42
|
||||||
CP r5, r8
|
CP r46, r48
|
||||||
JMP :9
|
JMP :9
|
||||||
0: CP r39, r34
|
0: CP r41, r36
|
||||||
8: LD r5, r39, 8a, 8h
|
8: LD r50, r41, 8a, 8h
|
||||||
MULI64 r7, r5, 8d
|
MULI64 r51, r50, 8d
|
||||||
LD r6, r39, 0a, 8h
|
LD r52, r41, 0a, 8h
|
||||||
ADD64 r1, r6, r7
|
ADD64 r1, r52, r51
|
||||||
CP r3, r32
|
CP r3, r32
|
||||||
ST r3, r1, 0a, 8h
|
ST r3, r1, 0a, 8h
|
||||||
LD r2, r39, 8a, 8h
|
LD r53, r41, 8a, 8h
|
||||||
ADD64 r3, r2, r33
|
ADD64 r54, r53, r33
|
||||||
ST r3, r39, 8a, 8h
|
ST r54, r41, 8a, 8h
|
||||||
4: LD r31, r254, 0a, 72h
|
4: LD r31, r254, 0a, 192h
|
||||||
ADDI64 r254, r254, 72d
|
ADDI64 r254, r254, 192d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 955
|
code size: 955
|
||||||
ret: 69
|
ret: 69
|
||||||
|
|
|
@ -4,15 +4,15 @@ clobber:
|
||||||
ST r3, r1, 0a, 8h
|
ST r3, r1, 0a, 8h
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -16d
|
ADDI64 r254, r254, -24d
|
||||||
ST r31, r254, 0a, 16h
|
ST r31, r254, 0a, 24h
|
||||||
LRA r32, r0, :var
|
LRA r32, r0, :var
|
||||||
LI64 r3, 2d
|
LI64 r33, 2d
|
||||||
ST r3, r32, 0a, 8h
|
ST r33, r32, 0a, 8h
|
||||||
JAL r31, r0, :clobber
|
JAL r31, r0, :clobber
|
||||||
LD r1, r32, 0a, 8h
|
LD r1, r32, 0a, 8h
|
||||||
LD r31, r254, 0a, 16h
|
LD r31, r254, 0a, 24h
|
||||||
ADDI64 r254, r254, 16d
|
ADDI64 r254, r254, 24d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 166
|
code size: 166
|
||||||
ret: 0
|
ret: 0
|
||||||
|
|
|
@ -1,22 +1,21 @@
|
||||||
fib:
|
fib:
|
||||||
ADDI64 r254, r254, -32d
|
ADDI64 r254, r254, -40d
|
||||||
ST r31, r254, 0a, 32h
|
ST r31, r254, 0a, 40h
|
||||||
LI64 r1, 1d
|
LI64 r1, 1d
|
||||||
LI64 r32, 2d
|
LI64 r32, 2d
|
||||||
JGTU r2, r32, :0
|
JGTU r2, r32, :0
|
||||||
JMP :1
|
JMP :1
|
||||||
0: CP r6, r2
|
0: CP r33, r2
|
||||||
SUB64 r2, r6, r1
|
SUB64 r2, r33, r1
|
||||||
CP r33, r6
|
CP r34, r33
|
||||||
JAL r31, r0, :fib
|
JAL r31, r0, :fib
|
||||||
CP r2, r33
|
CP r2, r34
|
||||||
CP r34, r1
|
CP r35, r1
|
||||||
SUB64 r2, r2, r32
|
SUB64 r2, r2, r32
|
||||||
JAL r31, r0, :fib
|
JAL r31, r0, :fib
|
||||||
CP r8, r34
|
ADD64 r1, r1, r35
|
||||||
ADD64 r1, r1, r8
|
1: LD r31, r254, 0a, 40h
|
||||||
1: LD r31, r254, 0a, 32h
|
ADDI64 r254, r254, 40d
|
||||||
ADDI64 r254, r254, 32d
|
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -8d
|
ADDI64 r254, r254, -8d
|
||||||
|
@ -26,6 +25,6 @@ main:
|
||||||
LD r31, r254, 0a, 8h
|
LD r31, r254, 0a, 8h
|
||||||
ADDI64 r254, r254, 8d
|
ADDI64 r254, r254, 8d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 214
|
code size: 211
|
||||||
ret: 55
|
ret: 55
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,22 +1,21 @@
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -16d
|
ADDI64 r254, r254, -32d
|
||||||
ST r31, r254, 0a, 16h
|
ST r31, r254, 0a, 32h
|
||||||
JAL r31, r0, :scalar_values
|
JAL r31, r0, :scalar_values
|
||||||
LI64 r3, 0d
|
LI64 r32, 0d
|
||||||
CP r8, r3
|
CP r33, r32
|
||||||
JEQ r1, r8, :0
|
JEQ r1, r33, :0
|
||||||
LI64 r1, 1d
|
LI64 r1, 1d
|
||||||
JMP :1
|
JMP :1
|
||||||
0: CP r32, r8
|
0: JAL r31, r0, :structs
|
||||||
JAL r31, r0, :structs
|
CP r34, r33
|
||||||
CP r3, r32
|
JEQ r1, r34, :2
|
||||||
JEQ r1, r3, :2
|
|
||||||
JAL r31, r0, :structs
|
JAL r31, r0, :structs
|
||||||
JMP :1
|
JMP :1
|
||||||
2: CP r1, r3
|
2: CP r1, r34
|
||||||
CP r32, r3
|
CP r33, r34
|
||||||
1: LD r31, r254, 0a, 16h
|
1: LD r31, r254, 0a, 32h
|
||||||
ADDI64 r254, r254, 16d
|
ADDI64 r254, r254, 32d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
scalar_values:
|
scalar_values:
|
||||||
LI64 r1, 0d
|
LI64 r1, 0d
|
||||||
|
@ -35,6 +34,6 @@ structs:
|
||||||
SUB64 r1, r1, r10
|
SUB64 r1, r1, r10
|
||||||
ADDI64 r254, r254, 32d
|
ADDI64 r254, r254, 32d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 310
|
code size: 307
|
||||||
ret: 0
|
ret: 0
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -1,32 +1,32 @@
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -66d
|
ADDI64 r254, r254, -106d
|
||||||
ST r31, r254, 58a, 8h
|
ST r31, r254, 58a, 48h
|
||||||
ADDI64 r3, r254, 33d
|
ADDI64 r32, r254, 33d
|
||||||
ADDI64 r2, r254, 34d
|
ADDI64 r2, r254, 34d
|
||||||
ADDI64 r6, r254, 1d
|
ADDI64 r6, r254, 1d
|
||||||
LI64 r9, 0d
|
LI64 r33, 0d
|
||||||
ADDI64 r4, r254, 17d
|
ADDI64 r4, r254, 17d
|
||||||
ST r3, r254, 34a, 8h
|
ST r32, r254, 34a, 8h
|
||||||
LI64 r10, 100d
|
LI64 r34, 100d
|
||||||
ADDI64 r7, r254, 0d
|
ADDI64 r7, r254, 0d
|
||||||
LI8 r5, 1b
|
LI8 r35, 1b
|
||||||
ST r9, r254, 1a, 8h
|
ST r33, r254, 1a, 8h
|
||||||
ST r9, r254, 17a, 8h
|
ST r33, r254, 17a, 8h
|
||||||
ST r10, r254, 42a, 8h
|
ST r34, r254, 42a, 8h
|
||||||
LI8 r3, 0b
|
LI8 r36, 0b
|
||||||
ST r5, r254, 0a, 1h
|
ST r35, r254, 0a, 1h
|
||||||
ST r9, r254, 9a, 8h
|
ST r33, r254, 9a, 8h
|
||||||
ST r9, r254, 25a, 8h
|
ST r33, r254, 25a, 8h
|
||||||
ST r10, r254, 50a, 8h
|
ST r34, r254, 50a, 8h
|
||||||
ST r3, r254, 33a, 1h
|
ST r36, r254, 33a, 1h
|
||||||
CP r3, r4
|
CP r3, r4
|
||||||
CP r5, r6
|
CP r5, r6
|
||||||
LD r3, r3, 0a, 16h
|
LD r3, r3, 0a, 16h
|
||||||
LD r5, r5, 0a, 16h
|
LD r5, r5, 0a, 16h
|
||||||
LD r7, r7, 0a, 1h
|
LD r7, r7, 0a, 1h
|
||||||
JAL r31, r0, :put_filled_rect
|
JAL r31, r0, :put_filled_rect
|
||||||
LD r31, r254, 58a, 8h
|
LD r31, r254, 58a, 48h
|
||||||
ADDI64 r254, r254, 66d
|
ADDI64 r254, r254, 106d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
put_filled_rect:
|
put_filled_rect:
|
||||||
ADDI64 r254, r254, -212d
|
ADDI64 r254, r254, -212d
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -24d
|
ADDI64 r254, r254, -32d
|
||||||
ST r31, r254, 16a, 8h
|
ST r31, r254, 16a, 16h
|
||||||
ADDI64 r3, r254, 0d
|
ADDI64 r3, r254, 0d
|
||||||
ADDI64 r2, r254, 8d
|
ADDI64 r2, r254, 8d
|
||||||
LI64 r4, 0d
|
LI64 r32, 0d
|
||||||
ST r4, r254, 0a, 8h
|
ST r32, r254, 0a, 8h
|
||||||
ST r4, r254, 8a, 8h
|
ST r32, r254, 8a, 8h
|
||||||
LI64 r4, 1024d
|
LI64 r4, 1024d
|
||||||
JAL r31, r0, :set
|
JAL r31, r0, :set
|
||||||
ANDI r1, r1, 4294967295d
|
ANDI r1, r1, 4294967295d
|
||||||
LD r31, r254, 16a, 8h
|
LD r31, r254, 16a, 16h
|
||||||
ADDI64 r254, r254, 24d
|
ADDI64 r254, r254, 32d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
set:
|
set:
|
||||||
CP r1, r4
|
CP r1, r4
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -16d
|
ADDI64 r254, r254, -32d
|
||||||
ST r31, r254, 0a, 16h
|
ST r31, r254, 0a, 32h
|
||||||
JAL r31, r0, :opaque
|
JAL r31, r0, :opaque
|
||||||
CP r32, r1
|
CP r32, r1
|
||||||
JAL r31, r0, :opaque
|
JAL r31, r0, :opaque
|
||||||
LI64 r6, 0d
|
LI64 r33, 0d
|
||||||
CP r1, r32
|
CP r1, r32
|
||||||
JNE r1, r6, :0
|
JNE r1, r33, :0
|
||||||
CP r32, r1
|
CP r32, r1
|
||||||
LI64 r1, 0d
|
LI64 r1, 0d
|
||||||
CP r3, r32
|
CP r34, r32
|
||||||
JMP :1
|
JMP :1
|
||||||
0: CP r3, r1
|
0: CP r34, r1
|
||||||
LD r1, r3, 0a, 8h
|
LD r1, r34, 0a, 8h
|
||||||
1: JEQ r3, r6, :2
|
1: JEQ r34, r33, :2
|
||||||
LD r1, r3, 0a, 8h
|
LD r1, r34, 0a, 8h
|
||||||
JMP :2
|
JMP :2
|
||||||
2: LD r31, r254, 0a, 16h
|
2: LD r31, r254, 0a, 32h
|
||||||
ADDI64 r254, r254, 16d
|
ADDI64 r254, r254, 32d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
opaque:
|
opaque:
|
||||||
LI64 r1, 0d
|
LI64 r1, 0d
|
||||||
|
|
|
@ -4,22 +4,22 @@ get_ptr:
|
||||||
ADDI64 r254, r254, 8d
|
ADDI64 r254, r254, 8d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -8d
|
ADDI64 r254, r254, -40d
|
||||||
ST r31, r254, 0a, 8h
|
ST r31, r254, 0a, 40h
|
||||||
JAL r31, r0, :get_ptr
|
JAL r31, r0, :get_ptr
|
||||||
LI64 r3, 0d
|
LI64 r32, 0d
|
||||||
JNE r1, r3, :0
|
JNE r1, r32, :0
|
||||||
LI64 r1, 0d
|
LI64 r1, 0d
|
||||||
JMP :1
|
JMP :1
|
||||||
0: LI64 r10, 10d
|
0: LI64 r33, 10d
|
||||||
CP r2, r1
|
CP r34, r1
|
||||||
2: LD r1, r2, 0a, 8h
|
2: LD r1, r34, 0a, 8h
|
||||||
JEQ r1, r10, :1
|
JEQ r1, r33, :1
|
||||||
ADDI64 r3, r1, 1d
|
ADDI64 r35, r1, 1d
|
||||||
ST r3, r2, 0a, 8h
|
ST r35, r34, 0a, 8h
|
||||||
JMP :2
|
JMP :2
|
||||||
1: LD r31, r254, 0a, 8h
|
1: LD r31, r254, 0a, 40h
|
||||||
ADDI64 r254, r254, 8d
|
ADDI64 r254, r254, 40d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 208
|
code size: 208
|
||||||
ret: 10
|
ret: 10
|
||||||
|
|
|
@ -2,77 +2,77 @@ decide:
|
||||||
LI8 r1, 1b
|
LI8 r1, 1b
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -136d
|
ADDI64 r254, r254, -224d
|
||||||
ST r31, r254, 80a, 56h
|
ST r31, r254, 80a, 144h
|
||||||
JAL r31, r0, :decide
|
JAL r31, r0, :decide
|
||||||
LI64 r4, 0d
|
LI64 r32, 0d
|
||||||
ADDI64 r2, r254, 72d
|
ADDI64 r2, r254, 72d
|
||||||
CP r32, r2
|
CP r33, r2
|
||||||
ANDI r1, r1, 255d
|
ANDI r1, r1, 255d
|
||||||
JNE r1, r0, :0
|
JNE r1, r0, :0
|
||||||
CP r33, r4
|
CP r34, r32
|
||||||
JMP :1
|
JMP :1
|
||||||
0: CP r33, r32
|
0: CP r34, r33
|
||||||
1: JNE r33, r4, :2
|
1: JNE r34, r32, :2
|
||||||
LI64 r1, 9001d
|
LI64 r1, 9001d
|
||||||
JMP :3
|
JMP :3
|
||||||
2: JAL r31, r0, :decide
|
2: JAL r31, r0, :decide
|
||||||
LI8 r34, 0b
|
LI8 r35, 0b
|
||||||
ANDI r1, r1, 255d
|
ANDI r1, r1, 255d
|
||||||
JNE r1, r0, :4
|
JNE r1, r0, :4
|
||||||
LI8 r8, 1b
|
LI8 r36, 1b
|
||||||
ST r8, r254, 56a, 1h
|
ST r36, r254, 56a, 1h
|
||||||
LD r9, r33, 0a, 8h
|
LD r36, r34, 0a, 8h
|
||||||
ST r9, r254, 64a, 8h
|
ST r36, r254, 64a, 8h
|
||||||
JMP :5
|
JMP :5
|
||||||
4: ST r34, r254, 56a, 1h
|
4: ST r35, r254, 56a, 1h
|
||||||
5: LD r6, r254, 56a, 1h
|
5: LD r37, r254, 56a, 1h
|
||||||
ANDI r6, r6, 255d
|
ANDI r37, r37, 255d
|
||||||
ANDI r34, r34, 255d
|
ANDI r35, r35, 255d
|
||||||
JEQ r6, r34, :6
|
JEQ r37, r35, :6
|
||||||
LI64 r1, 42d
|
LI64 r1, 42d
|
||||||
JMP :3
|
JMP :3
|
||||||
6: JAL r31, r0, :decide
|
6: JAL r31, r0, :decide
|
||||||
LI32 r2, 0w
|
LI32 r38, 0w
|
||||||
ANDI r1, r1, 255d
|
ANDI r1, r1, 255d
|
||||||
JNE r1, r0, :7
|
JNE r1, r0, :7
|
||||||
CP r35, r2
|
CP r39, r38
|
||||||
JMP :8
|
JMP :8
|
||||||
7: LI32 r35, 8388609w
|
7: LI32 r39, 8388609w
|
||||||
8: ANDI r35, r35, 4294967295d
|
8: ANDI r39, r39, 4294967295d
|
||||||
ANDI r2, r2, 4294967295d
|
ANDI r38, r38, 4294967295d
|
||||||
JNE r35, r2, :9
|
JNE r39, r38, :9
|
||||||
LI64 r1, 69d
|
LI64 r1, 69d
|
||||||
JMP :3
|
JMP :3
|
||||||
9: ADDI64 r3, r254, 40d
|
9: ADDI64 r3, r254, 40d
|
||||||
CP r36, r3
|
CP r40, r3
|
||||||
JAL r31, r0, :new_foo
|
JAL r31, r0, :new_foo
|
||||||
ST r1, r254, 40a, 16h
|
ST r1, r254, 40a, 16h
|
||||||
LI64 r37, 0d
|
LI64 r32, 0d
|
||||||
LD r7, r254, 40a, 8h
|
LD r41, r254, 40a, 8h
|
||||||
JNE r7, r37, :10
|
JNE r41, r32, :10
|
||||||
LI64 r1, 999d
|
LI64 r1, 999d
|
||||||
JMP :3
|
JMP :3
|
||||||
10: LRA r4, r0, :"foo\0"
|
10: LRA r4, r0, :"foo\0"
|
||||||
CP r3, r36
|
CP r3, r40
|
||||||
CP r2, r3
|
CP r2, r3
|
||||||
LD r2, r2, 0a, 16h
|
LD r2, r2, 0a, 16h
|
||||||
JAL r31, r0, :use_foo
|
JAL r31, r0, :use_foo
|
||||||
ADDI64 r6, r254, 0d
|
ADDI64 r42, r254, 0d
|
||||||
JAL r31, r0, :no_foo
|
JAL r31, r0, :no_foo
|
||||||
ST r1, r254, 0a, 16h
|
ST r1, r254, 0a, 16h
|
||||||
JAL r31, r0, :decide
|
JAL r31, r0, :decide
|
||||||
ANDI r1, r1, 255d
|
ANDI r1, r1, 255d
|
||||||
JNE r1, r0, :11
|
JNE r1, r0, :11
|
||||||
CP r2, r32
|
CP r2, r33
|
||||||
JMP :12
|
JMP :12
|
||||||
11: CP r2, r32
|
11: CP r2, r33
|
||||||
ST r2, r254, 0a, 8h
|
ST r2, r254, 0a, 8h
|
||||||
LI64 r12, 1d
|
LI64 r43, 1d
|
||||||
ST r12, r254, 8a, 8h
|
ST r43, r254, 8a, 8h
|
||||||
ST r12, r254, 72a, 8h
|
ST r43, r254, 72a, 8h
|
||||||
12: LD r6, r254, 0a, 8h
|
12: LD r44, r254, 0a, 8h
|
||||||
JNE r6, r37, :13
|
JNE r44, r32, :13
|
||||||
LI64 r1, 34d
|
LI64 r1, 34d
|
||||||
JMP :3
|
JMP :3
|
||||||
13: ADDI64 r1, r254, 16d
|
13: ADDI64 r1, r254, 16d
|
||||||
|
@ -81,19 +81,19 @@ main:
|
||||||
ANDI r1, r1, 255d
|
ANDI r1, r1, 255d
|
||||||
JNE r1, r0, :14
|
JNE r1, r0, :14
|
||||||
JMP :15
|
JMP :15
|
||||||
14: ST r34, r254, 16a, 1h
|
14: ST r35, r254, 16a, 1h
|
||||||
15: LD r10, r254, 16a, 1h
|
15: LD r45, r254, 16a, 1h
|
||||||
ANDI r10, r10, 255d
|
ANDI r45, r45, 255d
|
||||||
ANDI r34, r34, 255d
|
ANDI r35, r35, 255d
|
||||||
JEQ r10, r34, :16
|
JEQ r45, r35, :16
|
||||||
LI64 r1, 420d
|
LI64 r1, 420d
|
||||||
JMP :3
|
JMP :3
|
||||||
16: LD r4, r254, 0a, 8h
|
16: LD r46, r254, 0a, 8h
|
||||||
LD r6, r4, 0a, 8h
|
LD r47, r46, 0a, 8h
|
||||||
ANDI r8, r35, 65535d
|
ANDI r48, r39, 65535d
|
||||||
SUB64 r1, r8, r6
|
SUB64 r1, r48, r47
|
||||||
3: LD r31, r254, 80a, 56h
|
3: LD r31, r254, 80a, 144h
|
||||||
ADDI64 r254, r254, 136d
|
ADDI64 r254, r254, 224d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
new_bar:
|
new_bar:
|
||||||
ADDI64 r254, r254, -24d
|
ADDI64 r254, r254, -24d
|
||||||
|
|
|
@ -2,14 +2,14 @@ inb:
|
||||||
CP r1, r2
|
CP r1, r2
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -24d
|
ADDI64 r254, r254, -32d
|
||||||
ST r31, r254, 0a, 24h
|
ST r31, r254, 0a, 32h
|
||||||
LI64 r32, 0d
|
LI64 r32, 0d
|
||||||
LI64 r33, 100d
|
LI64 r33, 100d
|
||||||
4: CP r2, r33
|
4: CP r2, r33
|
||||||
JAL r31, r0, :inb
|
JAL r31, r0, :inb
|
||||||
ANDI r7, r1, 2d
|
ANDI r34, r1, 2d
|
||||||
JNE r7, r32, :0
|
JNE r34, r32, :0
|
||||||
LI64 r2, 96d
|
LI64 r2, 96d
|
||||||
CP r3, r32
|
CP r3, r32
|
||||||
JAL r31, r0, :outb
|
JAL r31, r0, :outb
|
||||||
|
@ -20,8 +20,8 @@ main:
|
||||||
JMP :2
|
JMP :2
|
||||||
1: JMP :3
|
1: JMP :3
|
||||||
0: JMP :4
|
0: JMP :4
|
||||||
2: LD r31, r254, 0a, 24h
|
2: LD r31, r254, 0a, 32h
|
||||||
ADDI64 r254, r254, 24d
|
ADDI64 r254, r254, 32d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
outb:
|
outb:
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -48d
|
ADDI64 r254, r254, -104d
|
||||||
ST r31, r254, 40a, 8h
|
ST r31, r254, 40a, 64h
|
||||||
LI64 r4, 4d
|
LI64 r32, 4d
|
||||||
ADDI64 r3, r254, 24d
|
ADDI64 r33, r254, 24d
|
||||||
ADDI64 r6, r254, 0d
|
ADDI64 r34, r254, 0d
|
||||||
ST r4, r254, 24a, 8h
|
ST r32, r254, 24a, 8h
|
||||||
LI64 r5, 1d
|
LI64 r35, 1d
|
||||||
ST r5, r254, 32a, 8h
|
ST r35, r254, 32a, 8h
|
||||||
ST r5, r254, 16a, 8h
|
ST r35, r254, 16a, 8h
|
||||||
BMC r3, r6, 16h
|
BMC r33, r34, 16h
|
||||||
JAL r31, r0, :opaque
|
JAL r31, r0, :opaque
|
||||||
ST r1, r254, 0a, 16h
|
ST r1, r254, 0a, 16h
|
||||||
LD r4, r254, 8a, 8h
|
LD r36, r254, 8a, 8h
|
||||||
LD r6, r254, 16a, 8h
|
LD r37, r254, 16a, 8h
|
||||||
ADD64 r8, r6, r4
|
ADD64 r38, r37, r36
|
||||||
LD r6, r254, 0a, 8h
|
LD r37, r254, 0a, 8h
|
||||||
SUB64 r1, r6, r8
|
SUB64 r1, r37, r38
|
||||||
LD r31, r254, 40a, 8h
|
LD r31, r254, 40a, 64h
|
||||||
ADDI64 r254, r254, 48d
|
ADDI64 r254, r254, 104d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
opaque:
|
opaque:
|
||||||
ADDI64 r254, r254, -16d
|
ADDI64 r254, r254, -16d
|
||||||
|
|
|
@ -3,17 +3,17 @@ clobber:
|
||||||
ST r3, r2, 0a, 8h
|
ST r3, r2, 0a, 8h
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -16d
|
ADDI64 r254, r254, -40d
|
||||||
ST r31, r254, 8a, 8h
|
ST r31, r254, 8a, 32h
|
||||||
ADDI64 r2, r254, 0d
|
ADDI64 r2, r254, 0d
|
||||||
LI64 r3, 2d
|
LI64 r32, 2d
|
||||||
ST r3, r254, 0a, 8h
|
ST r32, r254, 0a, 8h
|
||||||
JAL r31, r0, :clobber
|
JAL r31, r0, :clobber
|
||||||
LD r8, r254, 0a, 8h
|
LD r33, r254, 0a, 8h
|
||||||
LI64 r9, 4d
|
LI64 r34, 4d
|
||||||
SUB64 r1, r9, r8
|
SUB64 r1, r34, r33
|
||||||
LD r31, r254, 8a, 8h
|
LD r31, r254, 8a, 32h
|
||||||
ADDI64 r254, r254, 16d
|
ADDI64 r254, r254, 40d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 169
|
code size: 169
|
||||||
ret: 0
|
ret: 0
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
drop:
|
drop:
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -24d
|
ADDI64 r254, r254, -32d
|
||||||
ST r31, r254, 8a, 16h
|
ST r31, r254, 8a, 24h
|
||||||
ADDI64 r2, r254, 0d
|
ADDI64 r2, r254, 0d
|
||||||
LI64 r32, 1d
|
LI64 r32, 1d
|
||||||
ST r32, r254, 0a, 8h
|
ST r32, r254, 0a, 8h
|
||||||
JAL r31, r0, :modify
|
JAL r31, r0, :modify
|
||||||
CP r2, r32
|
CP r2, r32
|
||||||
JAL r31, r0, :drop
|
JAL r31, r0, :drop
|
||||||
LD r8, r254, 0a, 8h
|
LD r33, r254, 0a, 8h
|
||||||
ADDI64 r1, r8, -2d
|
ADDI64 r1, r33, -2d
|
||||||
LD r31, r254, 8a, 16h
|
LD r31, r254, 8a, 24h
|
||||||
ADDI64 r254, r254, 24d
|
ADDI64 r254, r254, 32d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
modify:
|
modify:
|
||||||
LI64 r3, 2d
|
LI64 r3, 2d
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
create_back_buffer:
|
create_back_buffer:
|
||||||
ADDI64 r254, r254, -48d
|
ADDI64 r254, r254, -56d
|
||||||
ST r31, r254, 0a, 48h
|
ST r31, r254, 0a, 56h
|
||||||
LI64 r32, 255d
|
LI64 r32, 255d
|
||||||
JGTS r2, r32, :0
|
JGTS r2, r32, :0
|
||||||
JAL r31, r0, :request_page
|
JAL r31, r0, :request_page
|
||||||
|
@ -9,23 +9,23 @@ create_back_buffer:
|
||||||
LI8 r34, 255b
|
LI8 r34, 255b
|
||||||
CP r2, r34
|
CP r2, r34
|
||||||
JAL r31, r0, :request_page
|
JAL r31, r0, :request_page
|
||||||
CP r35, r1
|
LI64 r35, 0d
|
||||||
LI64 r36, 0d
|
|
||||||
CP r2, r33
|
CP r2, r33
|
||||||
SUB64 r33, r2, r32
|
SUB64 r36, r2, r32
|
||||||
5: JGTS r33, r36, :2
|
5: JGTS r36, r35, :2
|
||||||
CP r1, r35
|
|
||||||
JMP :1
|
JMP :1
|
||||||
2: JLTS r33, r32, :3
|
2: CP r37, r1
|
||||||
|
JLTS r36, r32, :3
|
||||||
CP r2, r34
|
CP r2, r34
|
||||||
JAL r31, r0, :request_page
|
JAL r31, r0, :request_page
|
||||||
JMP :4
|
JMP :4
|
||||||
3: CP r2, r33
|
3: CP r2, r36
|
||||||
JAL r31, r0, :request_page
|
JAL r31, r0, :request_page
|
||||||
4: SUB64 r33, r33, r32
|
4: SUB64 r36, r36, r32
|
||||||
|
CP r1, r37
|
||||||
JMP :5
|
JMP :5
|
||||||
1: LD r31, r254, 0a, 48h
|
1: LD r31, r254, 0a, 56h
|
||||||
ADDI64 r254, r254, 48d
|
ADDI64 r254, r254, 56d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -8d
|
ADDI64 r254, r254, -8d
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -12d
|
ADDI64 r254, r254, -100d
|
||||||
ST r31, r254, 4a, 8h
|
ST r31, r254, 4a, 96h
|
||||||
ADDI64 r2, r254, 0d
|
ADDI64 r32, r254, 0d
|
||||||
JAL r31, r0, :random_color
|
JAL r31, r0, :random_color
|
||||||
ST r1, r254, 0a, 4h
|
ST r1, r254, 0a, 4h
|
||||||
LD r5, r254, 0a, 1h
|
LD r33, r254, 0a, 1h
|
||||||
LD r8, r254, 1a, 1h
|
LD r34, r254, 1a, 1h
|
||||||
LD r12, r254, 2a, 1h
|
LD r35, r254, 2a, 1h
|
||||||
ANDI r9, r5, 255d
|
ANDI r36, r33, 255d
|
||||||
ANDI r1, r8, 255d
|
ANDI r37, r34, 255d
|
||||||
LD r6, r254, 3a, 1h
|
LD r38, r254, 3a, 1h
|
||||||
ANDI r5, r12, 255d
|
ANDI r39, r35, 255d
|
||||||
ADD64 r4, r1, r9
|
ADD64 r40, r37, r36
|
||||||
ANDI r10, r6, 255d
|
ANDI r41, r38, 255d
|
||||||
ADD64 r9, r4, r5
|
ADD64 r42, r40, r39
|
||||||
ADD64 r1, r9, r10
|
ADD64 r1, r42, r41
|
||||||
LD r31, r254, 4a, 8h
|
LD r31, r254, 4a, 96h
|
||||||
ADDI64 r254, r254, 12d
|
ADDI64 r254, r254, 100d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
random_color:
|
random_color:
|
||||||
LRA r1, r0, :white
|
LRA r1, r0, :white
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -12d
|
ADDI64 r254, r254, -36d
|
||||||
ST r31, r254, 4a, 8h
|
ST r31, r254, 4a, 32h
|
||||||
LRA r1, r0, :white
|
LRA r32, r0, :white
|
||||||
ADDI64 r4, r254, 0d
|
ADDI64 r33, r254, 0d
|
||||||
LD r2, r1, 0a, 4h
|
LD r2, r32, 0a, 4h
|
||||||
JAL r31, r0, :u32_to_color
|
JAL r31, r0, :u32_to_color
|
||||||
ST r1, r254, 0a, 4h
|
ST r1, r254, 0a, 4h
|
||||||
LD r9, r254, 0a, 1h
|
LD r34, r254, 0a, 1h
|
||||||
ANDI r1, r9, 255d
|
ANDI r1, r34, 255d
|
||||||
LD r31, r254, 4a, 8h
|
LD r31, r254, 4a, 32h
|
||||||
ADDI64 r254, r254, 12d
|
ADDI64 r254, r254, 36d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
u32_to_color:
|
u32_to_color:
|
||||||
ADDI64 r254, r254, -12d
|
ADDI64 r254, r254, -20d
|
||||||
ST r31, r254, 4a, 8h
|
ST r31, r254, 4a, 16h
|
||||||
JAL r31, r0, :u32_to_u32
|
JAL r31, r0, :u32_to_u32
|
||||||
ADDI64 r5, r254, 0d
|
ADDI64 r32, r254, 0d
|
||||||
ST r1, r254, 0a, 4h
|
ST r1, r254, 0a, 4h
|
||||||
LD r1, r5, 0a, 4h
|
LD r1, r32, 0a, 4h
|
||||||
LD r31, r254, 4a, 8h
|
LD r31, r254, 4a, 16h
|
||||||
ADDI64 r254, r254, 12d
|
ADDI64 r254, r254, 20d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
u32_to_u32:
|
u32_to_u32:
|
||||||
CP r1, r2
|
CP r1, r2
|
||||||
|
|
|
@ -4,15 +4,14 @@ fib:
|
||||||
CP r32, r2
|
CP r32, r2
|
||||||
LI64 r33, 2d
|
LI64 r33, 2d
|
||||||
JLTU r2, r33, :0
|
JLTU r2, r33, :0
|
||||||
CP r6, r32
|
CP r34, r32
|
||||||
ADDI64 r2, r6, -1d
|
ADDI64 r2, r34, -1d
|
||||||
JAL r31, r0, :fib
|
JAL r31, r0, :fib
|
||||||
CP r2, r32
|
CP r2, r32
|
||||||
CP r34, r1
|
CP r34, r1
|
||||||
SUB64 r2, r2, r33
|
SUB64 r2, r2, r33
|
||||||
JAL r31, r0, :fib
|
JAL r31, r0, :fib
|
||||||
CP r6, r34
|
ADD64 r1, r1, r34
|
||||||
ADD64 r1, r1, r6
|
|
||||||
JMP :1
|
JMP :1
|
||||||
0: CP r1, r32
|
0: CP r1, r32
|
||||||
1: LD r31, r254, 0a, 32h
|
1: LD r31, r254, 0a, 32h
|
||||||
|
@ -41,11 +40,10 @@ main:
|
||||||
CP r2, r32
|
CP r2, r32
|
||||||
CP r33, r1
|
CP r33, r1
|
||||||
JAL r31, r0, :fib_iter
|
JAL r31, r0, :fib_iter
|
||||||
CP r9, r33
|
SUB64 r1, r33, r1
|
||||||
SUB64 r1, r9, r1
|
|
||||||
LD r31, r254, 0a, 24h
|
LD r31, r254, 0a, 24h
|
||||||
ADDI64 r254, r254, 24d
|
ADDI64 r254, r254, 24d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 306
|
code size: 300
|
||||||
ret: 0
|
ret: 0
|
||||||
status: Ok(())
|
status: Ok(())
|
||||||
|
|
|
@ -10,28 +10,28 @@ foo:
|
||||||
ADDI64 r254, r254, 16d
|
ADDI64 r254, r254, 16d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -56d
|
ADDI64 r254, r254, -128d
|
||||||
ST r31, r254, 48a, 8h
|
ST r31, r254, 48a, 80h
|
||||||
ADDI64 r2, r254, 32d
|
ADDI64 r32, r254, 32d
|
||||||
JAL r31, r0, :foo
|
JAL r31, r0, :foo
|
||||||
ST r1, r254, 32a, 16h
|
ST r1, r254, 32a, 16h
|
||||||
ADDI64 r7, r254, 16d
|
ADDI64 r33, r254, 16d
|
||||||
JAL r31, r0, :foo
|
JAL r31, r0, :foo
|
||||||
ST r1, r254, 16a, 16h
|
ST r1, r254, 16a, 16h
|
||||||
ADDI64 r2, r254, 0d
|
ADDI64 r34, r254, 0d
|
||||||
JAL r31, r0, :foo
|
JAL r31, r0, :foo
|
||||||
ST r1, r254, 0a, 16h
|
ST r1, r254, 0a, 16h
|
||||||
LD r1, r254, 24a, 4h
|
LD r35, r254, 24a, 4h
|
||||||
LD r7, r254, 12a, 4h
|
LD r36, r254, 12a, 4h
|
||||||
ANDI r4, r1, 4294967295d
|
ANDI r37, r35, 4294967295d
|
||||||
LD r1, r254, 32a, 8h
|
LD r35, r254, 32a, 8h
|
||||||
ANDI r11, r7, 4294967295d
|
ANDI r38, r36, 4294967295d
|
||||||
ADD64 r8, r1, r4
|
ADD64 r39, r35, r37
|
||||||
ADD64 r2, r8, r11
|
ADD64 r40, r39, r38
|
||||||
LI64 r3, 7d
|
LI64 r34, 7d
|
||||||
SUB64 r1, r3, r2
|
SUB64 r1, r34, r40
|
||||||
LD r31, r254, 48a, 8h
|
LD r31, r254, 48a, 80h
|
||||||
ADDI64 r254, r254, 56d
|
ADDI64 r254, r254, 128d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
code size: 355
|
code size: 355
|
||||||
ret: 0
|
ret: 0
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -56d
|
ADDI64 r254, r254, -72d
|
||||||
ST r31, r254, 32a, 24h
|
ST r31, r254, 32a, 40h
|
||||||
LI64 r2, 4d
|
LI64 r32, 4d
|
||||||
ADDI64 r4, r254, 16d
|
ADDI64 r4, r254, 16d
|
||||||
ST r2, r254, 16a, 8h
|
ST r32, r254, 16a, 8h
|
||||||
LI64 r32, 3d
|
LI64 r33, 3d
|
||||||
ST r32, r254, 24a, 8h
|
ST r33, r254, 24a, 8h
|
||||||
ADDI64 r33, r254, 0d
|
ADDI64 r34, r254, 0d
|
||||||
CP r3, r4
|
CP r3, r4
|
||||||
LD r3, r3, 0a, 16h
|
LD r3, r3, 0a, 16h
|
||||||
JAL r31, r0, :odher_pass
|
JAL r31, r0, :odher_pass
|
||||||
ST r1, r254, 0a, 16h
|
ST r1, r254, 0a, 16h
|
||||||
LD r2, r254, 8a, 8h
|
LD r35, r254, 8a, 8h
|
||||||
JNE r2, r32, :0
|
JNE r35, r33, :0
|
||||||
CP r2, r33
|
CP r2, r34
|
||||||
JAL r31, r0, :pass
|
JAL r31, r0, :pass
|
||||||
JMP :1
|
JMP :1
|
||||||
0: LI64 r1, 0d
|
0: LI64 r1, 0d
|
||||||
1: LD r31, r254, 32a, 24h
|
1: LD r31, r254, 32a, 40h
|
||||||
ADDI64 r254, r254, 56d
|
ADDI64 r254, r254, 72d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
odher_pass:
|
odher_pass:
|
||||||
ADDI64 r254, r254, -16d
|
ADDI64 r254, r254, -16d
|
||||||
|
|
|
@ -1,47 +1,47 @@
|
||||||
main:
|
main:
|
||||||
ADDI64 r254, r254, -24d
|
ADDI64 r254, r254, -56d
|
||||||
ST r31, r254, 16a, 8h
|
ST r31, r254, 16a, 40h
|
||||||
ADDI64 r3, r254, 0d
|
ADDI64 r32, r254, 0d
|
||||||
LI64 r4, 0d
|
LI64 r4, 0d
|
||||||
CP r3, r4
|
CP r3, r4
|
||||||
JAL r31, r0, :maina
|
JAL r31, r0, :maina
|
||||||
ST r1, r254, 0a, 16h
|
ST r1, r254, 0a, 16h
|
||||||
LD r8, r254, 12a, 1h
|
LD r33, r254, 12a, 1h
|
||||||
LD r9, r254, 3a, 1h
|
LD r34, r254, 3a, 1h
|
||||||
SUB8 r11, r9, r8
|
SUB8 r35, r34, r33
|
||||||
ANDI r1, r11, 255d
|
ANDI r1, r35, 255d
|
||||||
LD r31, r254, 16a, 8h
|
LD r31, r254, 16a, 40h
|
||||||
ADDI64 r254, r254, 24d
|
ADDI64 r254, r254, 56d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
maina:
|
maina:
|
||||||
ADDI64 r254, r254, -28d
|
ADDI64 r254, r254, -68d
|
||||||
ST r31, r254, 20a, 8h
|
ST r31, r254, 20a, 48h
|
||||||
ADDI64 r5, r254, 16d
|
ADDI64 r32, r254, 16d
|
||||||
JAL r31, r0, :small_struct
|
JAL r31, r0, :small_struct
|
||||||
ST r1, r254, 16a, 4h
|
ST r1, r254, 16a, 4h
|
||||||
LI8 r9, 0b
|
LI8 r33, 0b
|
||||||
ADDI64 r1, r254, 0d
|
ADDI64 r34, r254, 0d
|
||||||
ST r9, r254, 0a, 1h
|
ST r33, r254, 0a, 1h
|
||||||
ST r9, r254, 1a, 1h
|
ST r33, r254, 1a, 1h
|
||||||
ST r9, r254, 2a, 1h
|
ST r33, r254, 2a, 1h
|
||||||
LI8 r3, 3b
|
LI8 r35, 3b
|
||||||
ST r3, r254, 3a, 1h
|
ST r35, r254, 3a, 1h
|
||||||
LI8 r6, 1b
|
LI8 r36, 1b
|
||||||
ST r6, r254, 4a, 1h
|
ST r36, r254, 4a, 1h
|
||||||
ST r9, r254, 5a, 1h
|
ST r33, r254, 5a, 1h
|
||||||
ST r9, r254, 6a, 1h
|
ST r33, r254, 6a, 1h
|
||||||
ST r9, r254, 7a, 1h
|
ST r33, r254, 7a, 1h
|
||||||
ST r9, r254, 8a, 1h
|
ST r33, r254, 8a, 1h
|
||||||
ST r9, r254, 9a, 1h
|
ST r33, r254, 9a, 1h
|
||||||
ST r9, r254, 10a, 1h
|
ST r33, r254, 10a, 1h
|
||||||
ST r3, r254, 11a, 1h
|
ST r35, r254, 11a, 1h
|
||||||
ST r6, r254, 12a, 1h
|
ST r36, r254, 12a, 1h
|
||||||
ST r9, r254, 13a, 1h
|
ST r33, r254, 13a, 1h
|
||||||
ST r9, r254, 14a, 1h
|
ST r33, r254, 14a, 1h
|
||||||
ST r9, r254, 15a, 1h
|
ST r33, r254, 15a, 1h
|
||||||
LD r1, r1, 0a, 16h
|
LD r1, r34, 0a, 16h
|
||||||
LD r31, r254, 20a, 8h
|
LD r31, r254, 20a, 48h
|
||||||
ADDI64 r254, r254, 28d
|
ADDI64 r254, r254, 68d
|
||||||
JALA r0, r31, 0a
|
JALA r0, r31, 0a
|
||||||
small_struct:
|
small_struct:
|
||||||
ADDI64 r254, r254, -4d
|
ADDI64 r254, r254, -4d
|
||||||
|
|
Loading…
Reference in a new issue