This commit is contained in:
mlokr 2024-09-19 17:15:03 +02:00
commit 31c501c643
No known key found for this signature in database
GPG key ID: DEA147DDEE644993
23 changed files with 1075 additions and 1481 deletions

283
Cargo.lock generated
View file

@ -1,283 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "ahash"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
dependencies = [
"cfg-if",
"once_cell",
"version_check",
"zerocopy",
]
[[package]]
name = "arbitrary"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110"
[[package]]
name = "bumpalo"
version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cranelift-bforest"
version = "0.113.0"
source = "git+https://github.com/jakubDoka/wasmtime.git#969c85a481985be2fa2d555cdb338454f77213c6"
dependencies = [
"cranelift-entity",
]
[[package]]
name = "cranelift-bitset"
version = "0.113.0"
source = "git+https://github.com/jakubDoka/wasmtime.git#969c85a481985be2fa2d555cdb338454f77213c6"
[[package]]
name = "cranelift-codegen"
version = "0.113.0"
source = "git+https://github.com/jakubDoka/wasmtime.git#969c85a481985be2fa2d555cdb338454f77213c6"
dependencies = [
"bumpalo",
"cranelift-bforest",
"cranelift-bitset",
"cranelift-codegen-meta",
"cranelift-codegen-shared",
"cranelift-control",
"cranelift-entity",
"cranelift-isle",
"hashbrown",
"log",
"regalloc2",
"rustc-hash",
"smallvec",
"target-lexicon",
]
[[package]]
name = "cranelift-codegen-meta"
version = "0.113.0"
source = "git+https://github.com/jakubDoka/wasmtime.git#969c85a481985be2fa2d555cdb338454f77213c6"
dependencies = [
"cranelift-codegen-shared",
]
[[package]]
name = "cranelift-codegen-shared"
version = "0.113.0"
source = "git+https://github.com/jakubDoka/wasmtime.git#969c85a481985be2fa2d555cdb338454f77213c6"
[[package]]
name = "cranelift-control"
version = "0.113.0"
source = "git+https://github.com/jakubDoka/wasmtime.git#969c85a481985be2fa2d555cdb338454f77213c6"
dependencies = [
"arbitrary",
]
[[package]]
name = "cranelift-entity"
version = "0.113.0"
source = "git+https://github.com/jakubDoka/wasmtime.git#969c85a481985be2fa2d555cdb338454f77213c6"
dependencies = [
"cranelift-bitset",
]
[[package]]
name = "cranelift-isle"
version = "0.113.0"
source = "git+https://github.com/jakubDoka/wasmtime.git#969c85a481985be2fa2d555cdb338454f77213c6"
[[package]]
name = "hashbrown"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
dependencies = [
"ahash",
]
[[package]]
name = "hbbytecode"
version = "0.1.0"
[[package]]
name = "hbcb"
version = "0.1.0"
dependencies = [
"cranelift-codegen",
"cranelift-codegen-meta",
"cranelift-control",
"cranelift-isle",
"log",
"regalloc2",
"smallvec",
"target-lexicon",
]
[[package]]
name = "hbjit"
version = "0.1.0"
[[package]]
name = "hblang"
version = "0.1.0"
dependencies = [
"hbvm",
]
[[package]]
name = "hbvm"
version = "0.1.0"
dependencies = [
"hbbytecode",
]
[[package]]
name = "hbxrt"
version = "0.1.0"
dependencies = [
"hbvm",
"memmap2",
]
[[package]]
name = "libc"
version = "0.2.158"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
[[package]]
name = "log"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "memmap2"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f"
dependencies = [
"libc",
]
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "proc-macro2"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
dependencies = [
"proc-macro2",
]
[[package]]
name = "regalloc2"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12908dbeb234370af84d0579b9f68258a0f67e201412dd9a2814e6f45b2fc0f0"
dependencies = [
"hashbrown",
"log",
"rustc-hash",
"slice-group-by",
"smallvec",
]
[[package]]
name = "rustc-hash"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152"
[[package]]
name = "slice-group-by"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7"
[[package]]
name = "smallvec"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "syn"
version = "2.0.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "target-lexicon"
version = "0.12.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
[[package]]
name = "unicode-ident"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "xtask"
version = "0.1.0"
[[package]]
name = "zerocopy"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]

View file

@ -9,3 +9,4 @@ path = "src/main.rs"
[dependencies] [dependencies]
hbvm = { path = "../hbvm", features = ["nightly"] } hbvm = { path = "../hbvm", features = ["nightly"] }
regalloc2 = { git = "https://github.com/jakubDoka/regalloc2" }

View file

@ -237,7 +237,7 @@ main := fn(): int {
size_of_Type_in_bytes := @sizeof(foo.Type) size_of_Type_in_bytes := @sizeof(foo.Type)
align_of_Type_in_bytes := @alignof(foo.Type) align_of_Type_in_bytes := @alignof(foo.Type)
hardcoded_pointer := @as(^u8, @bitcast(10)) hardcoded_pointer := @as(^u8, @bitcast(10))
ecall_that_returns_int := @eca(int, 1, foo.Type.(10, 20), 5, 6) ecall_that_returns_int := @as(int, @eca(1, foo.Type.(10, 20), 5, 6))
return @inline(foo.foo) return @inline(foo.foo)
} }
@ -356,6 +356,29 @@ main := fn(): int {
} }
``` ```
#### wide_ret
```hb
OemIdent := struct {
dos_version: [u8; 8],
dos_version_name: [u8; 8],
}
Stru := struct {
a: u16,
b: u16,
}
small_struct := fn(): Stru {
return .{a: 0, b: 0}
}
main := fn(major: int, minor: int): OemIdent {
small_struct()
ver := [u8].(0, 0, 0, 0, 0, 0, 0, 0)
return OemIdent.(ver, ver)
}
```
### Incomplete Examples ### Incomplete Examples
#### comptime_pointers #### comptime_pointers
@ -376,8 +399,8 @@ modify := fn($num: ^int): void {
MALLOC_SYS_CALL := 69 MALLOC_SYS_CALL := 69
FREE_SYS_CALL := 96 FREE_SYS_CALL := 96
malloc := fn(size: uint, align: uint): ^void return @eca(^void, MALLOC_SYS_CALL, size, align) malloc := fn(size: uint, align: uint): ^void return @eca(MALLOC_SYS_CALL, size, align)
free := fn(ptr: ^void, size: uint, align: uint): void return @eca(void, FREE_SYS_CALL, ptr, size, align) free := fn(ptr: ^void, size: uint, align: uint): void return @eca(FREE_SYS_CALL, ptr, size, align)
Vec := fn($Elem: type): type { Vec := fn($Elem: type): type {
return struct { return struct {
@ -750,7 +773,7 @@ screenidx := fn(orange: int): int {
// in module: random.hb // in module: random.hb
integer := fn(min: int, max: int): int { integer := fn(min: int, max: int): int {
rng := @eca(int, 3, 4) rng := @as(int, @eca(3, 4))
if min != 0 | max != 0 { if min != 0 | max != 0 {
return rng % (max - min + 1) + min return rng % (max - min + 1) + min
@ -781,7 +804,7 @@ main := fn(): void {
// in module: random.hb // in module: random.hb
integer_range := fn(min: uint, max: int): uint { integer_range := fn(min: uint, max: int): uint {
return @eca(uint, 3, 4) % (@bitcast(max) - min + 1) + min return @eca(3, 4) % (@bitcast(max) - min + 1) + min
} }
``` ```
@ -876,7 +899,7 @@ request_page := fn(page_count: u8): ^u8 {
msg := "\{00}\{01}xxxxxxxx\0" msg := "\{00}\{01}xxxxxxxx\0"
msg_page_count := msg + 1; msg_page_count := msg + 1;
*msg_page_count = page_count *msg_page_count = page_count
return @eca(^u8, 3, 2, msg, 12) return @eca(3, 2, msg, 12)
} }
create_back_buffer := fn(total_pages: int): ^u32 { create_back_buffer := fn(total_pages: int): ^u32 {

View file

@ -898,13 +898,21 @@ impl Codegen {
E::Directive { name: "TypeOf", args: [expr], .. } => { E::Directive { name: "TypeOf", args: [expr], .. } => {
Some(Value::ty(self.infer_type(expr))) Some(Value::ty(self.infer_type(expr)))
} }
E::Directive { name: "eca", args: [ret_ty, args @ ..], .. } => { E::Directive { name: "eca", args, pos } => {
let ty = self.ty(ret_ty); let Some(ty) = ctx.ty else {
self.report(
pos,
"type to return form eca is unknown, use `@as(<type>, @eca(...<expr>))`",
);
};
let mut parama = self.tys.parama(ty); let mut parama = self.tys.parama(ty);
let base = self.pool.arg_locs.len(); let base = self.pool.arg_locs.len();
for arg in args { for arg in args {
let arg = self.expr(arg)?; let arg = self.expr(arg)?;
if arg.ty == ty::Id::from(ty::TYPE) {
self.report(pos, "na na na nana, no passing types to ecas");
}
self.pass_arg(&arg, &mut parama); self.pass_arg(&arg, &mut parama);
self.pool.arg_locs.push(arg.loc); self.pool.arg_locs.push(arg.loc);
} }
@ -932,7 +940,7 @@ impl Codegen {
let Some(ty) = ctx.ty else { let Some(ty) = ctx.ty else {
self.report( self.report(
expr.pos(), expr.pos(),
"type to cast to is unknown, use `@as(<type>, <expr>)`", "type to cast to is unknown, use `@as(<type>, @intcast(<expr>))`",
); );
}; };
let mut val = self.expr(val)?; let mut val = self.expr(val)?;
@ -1086,7 +1094,7 @@ impl Codegen {
Some(Value::new(self.tys.make_ptr(ty::U8.into()), reg)) Some(Value::new(self.tys.make_ptr(ty::U8.into()), reg))
} }
E::Ctor { pos, ty, fields, .. } => { E::Ctor { pos, ty, fields, .. } => {
let (ty, loc) = self.prepare_struct_ctor(pos, ctx, ty, fields.len()); let (ty, loc) = self.prepare_struct_ctor(pos, &mut ctx, ty, fields.len());
let ty::Kind::Struct(stru) = ty.expand() else { let ty::Kind::Struct(stru) = ty.expand() else {
self.report( self.report(
@ -1103,10 +1111,16 @@ impl Codegen {
let value = self.expr_ctx(value, Ctx::default().with_loc(loc).with_ty(ty))?; let value = self.expr_ctx(value, Ctx::default().with_loc(loc).with_ty(ty))?;
self.ci.free_loc(value.loc); self.ci.free_loc(value.loc);
} }
return Some(Value { ty, loc });
if let Some(dst_loc) = ctx.loc {
self.store_typed(loc, &dst_loc, ty);
return Some(Value { ty, loc: dst_loc });
} else {
return Some(Value { ty, loc });
}
} }
E::Tupl { pos, ty, fields, .. } => { E::Tupl { pos, ty, fields, .. } => {
let (ty, loc) = self.prepare_struct_ctor(pos, ctx, ty, fields.len()); let (ty, loc) = self.prepare_struct_ctor(pos, &mut ctx, ty, fields.len());
match ty.expand() { match ty.expand() {
ty::Kind::Struct(stru) => { ty::Kind::Struct(stru) => {
@ -1141,7 +1155,12 @@ impl Codegen {
), ),
} }
return Some(Value { ty, loc }); if let Some(dst_loc) = ctx.loc {
self.store_typed(loc, &dst_loc, ty);
return Some(Value { ty, loc: dst_loc });
} else {
return Some(Value { ty, loc });
}
} }
E::Field { target, name: field } => { E::Field { target, name: field } => {
let checkpoint = self.ci.snap(); let checkpoint = self.ci.snap();
@ -1369,24 +1388,24 @@ impl Codegen {
tk => Some(Value::ty(tk.compress())), tk => Some(Value::ty(tk.compress())),
}, },
E::Return { pos, val, .. } => { E::Return { pos, val, .. } => {
let ty = if let Some(val) = val { let size = self.ci.ret.map_or(17, |ty| self.tys.size_of(ty));
let size = self.ci.ret.map_or(17, |ty| self.tys.size_of(ty)); let loc = match size {
let loc = match size { _ if self.ci.inline_ret_loc != Loc::default() => {
_ if self.ci.inline_ret_loc != Loc::default() => { Some(self.ci.inline_ret_loc.as_ref())
Some(self.ci.inline_ret_loc.as_ref()) }
} 0 => None,
0 => None, 1..=16 => Some(Loc::reg(1)),
1..=16 => Some(Loc::reg(1)), _ => Some(Loc::reg(self.ci.ret_reg.as_ref()).into_derefed()),
_ => Some(Loc::reg(self.ci.ret_reg.as_ref()).into_derefed()), };
}; let value = if let Some(val) = val {
self.expr_ctx(val, Ctx { ty: self.ci.ret, loc })?.ty self.expr_ctx(val, Ctx { ty: self.ci.ret, loc })?
} else { } else {
ty::VOID.into() Value::void()
}; };
match self.ci.ret { match self.ci.ret {
None => self.ci.ret = Some(ty), None => self.ci.ret = Some(value.ty),
Some(ret) => _ = self.assert_ty(pos, ty, ret, "return type"), Some(ret) => _ = self.assert_ty(pos, value.ty, ret, "return type"),
} }
self.ci.ret_relocs.push(Reloc::new(self.ci.code.len(), 1, 4)); self.ci.ret_relocs.push(Reloc::new(self.ci.code.len(), 1, 4));
@ -1891,7 +1910,7 @@ impl Codegen {
fn prepare_struct_ctor( fn prepare_struct_ctor(
&mut self, &mut self,
pos: Pos, pos: Pos,
ctx: Ctx, ctx: &mut Ctx,
ty: Option<&Expr>, ty: Option<&Expr>,
field_len: usize, field_len: usize,
) -> (ty::Id, Loc) { ) -> (ty::Id, Loc) {
@ -1927,8 +1946,11 @@ impl Codegen {
} }
let size = self.tys.size_of(ty); let size = self.tys.size_of(ty);
let loc = ctx.loc.unwrap_or_else(|| Loc::stack(self.ci.stack.allocate(size))); if ctx.loc.as_ref().map_or(true, |l| l.is_reg()) {
(ty, loc) (ty, Loc::stack(self.ci.stack.allocate(size)))
} else {
(ty, ctx.loc.take().unwrap_or_else(|| Loc::stack(self.ci.stack.allocate(size))))
}
} }
fn struct_op( fn struct_op(
@ -2278,6 +2300,25 @@ impl Codegen {
self.ci.emit(cp(dst.get(), src.get())); self.ci.emit(cp(dst.get(), src.get()));
} }
} }
//(lpat!(false, src, 0, None), lpat!(false, dst, off, None)) => {
// assert!(size <= 8);
// let off_rem = 8 * (off % 8);
// let freg = dst.get() + (off / 8) as u8;
// if size < 8 {
// let mask = !(((1u64 << (8 * size)) - 1) << off_rem);
// self.ci.emit(andi(freg, freg, mask));
// if off_rem == 0 {
// self.ci.emit(or(freg, freg, src.get()));
// } else {
// let tmp = self.ci.regs.allocate();
// self.ci.emit(slui64(tmp.get(), src.get(), off_rem as _));
// self.ci.emit(or(freg, freg, src.get()));
// self.ci.regs.free(tmp);
// }
// } else {
// self.ci.emit(cp(freg, src.get()));
// }
//}
(lpat!(true, src, soff, ref ssta), lpat!(false, dst, 0, None)) => { (lpat!(true, src, soff, ref ssta), lpat!(false, dst, 0, None)) => {
if size < 8 { if size < 8 {
self.ci.emit(cp(dst.get(), 0)); self.ci.emit(cp(dst.get(), 0));
@ -2740,5 +2781,6 @@ mod tests {
writing_into_string => README; writing_into_string => README;
request_page => README; request_page => README;
tests_ptr_to_ptr_copy => README; tests_ptr_to_ptr_copy => README;
wide_ret => README;
} }
} }

View file

@ -371,6 +371,10 @@ impl<'a> Lexer<'a> {
Self { pos, bytes: input.as_bytes() } Self { pos, bytes: input.as_bytes() }
} }
pub fn source(&self) -> &'a str {
unsafe { std::str::from_utf8_unchecked(self.bytes) }
}
pub fn slice(&self, tok: std::ops::Range<usize>) -> &'a str { pub fn slice(&self, tok: std::ops::Range<usize>) -> &'a str {
unsafe { std::str::from_utf8_unchecked(&self.bytes[tok]) } unsafe { std::str::from_utf8_unchecked(&self.bytes[tok]) }
} }
@ -511,10 +515,6 @@ impl<'a> Lexer<'a> {
false false
} }
} }
pub fn line_col(&self, pos: u32) -> (usize, usize) {
line_col(self.bytes, pos)
}
} }
pub fn line_col(bytes: &[u8], pos: u32) -> (usize, usize) { pub fn line_col(bytes: &[u8], pos: u32) -> (usize, usize) {

View file

@ -30,7 +30,7 @@ use {
parser::Ast, parser::Ast,
std::{ std::{
collections::{hash_map, BTreeMap, VecDeque}, collections::{hash_map, BTreeMap, VecDeque},
io::{self, Read}, io,
ops::Range, ops::Range,
path::{Path, PathBuf}, path::{Path, PathBuf},
rc::Rc, rc::Rc,
@ -601,6 +601,19 @@ impl ParamAlloc {
} }
} }
#[repr(packed)]
#[allow(dead_code)]
struct AbleOsExecutableHeader {
magic_number: [u8; 3],
executable_version: u32,
code_length: u64,
data_length: u64,
debug_length: u64,
config_length: u64,
metadata_length: u64,
}
#[derive(Default)] #[derive(Default)]
struct Types { struct Types {
syms: HashMap<SymKey, ty::Id>, syms: HashMap<SymKey, ty::Id>,
@ -613,15 +626,24 @@ struct Types {
arrays: Vec<Array>, arrays: Vec<Array>,
} }
const HEADER_SIZE: usize = std::mem::size_of::<AbleOsExecutableHeader>();
impl Types { impl Types {
fn assemble(&mut self, to: &mut Vec<u8>) { fn assemble(&mut self, to: &mut Vec<u8>) {
to.extend([0u8; HEADER_SIZE]);
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());
self.dump_reachable(0, to); let exe = self.dump_reachable(0, to);
Reloc::new(0, 3, 4).apply_jump(to, self.funcs[0].offset, 0); Reloc::new(HEADER_SIZE, 3, 4).apply_jump(to, self.funcs[0].offset, 0);
unsafe { *to.as_mut_ptr().cast::<AbleOsExecutableHeader>() = exe }
} }
fn dump_reachable(&mut self, from: ty::Func, to: &mut Vec<u8>) { fn dump_reachable(&mut self, from: ty::Func, to: &mut Vec<u8>) -> AbleOsExecutableHeader {
let mut used_funcs = vec![];
let mut used_globals = vec![];
let mut frontier = vec![ty::Kind::Func(from).compress()]; let mut frontier = vec![ty::Kind::Func(from).compress()];
while let Some(itm) = frontier.pop() { while let Some(itm) = frontier.pop() {
@ -631,8 +653,8 @@ impl Types {
if task::is_done(fuc.offset) { if task::is_done(fuc.offset) {
continue; continue;
} }
fuc.offset = to.len() as _; fuc.offset = 0;
to.extend(&fuc.code); used_funcs.push(func);
frontier.extend(fuc.relocs.iter().map(|r| r.target)); frontier.extend(fuc.relocs.iter().map(|r| r.target));
} }
ty::Kind::Global(glob) => { ty::Kind::Global(glob) => {
@ -640,18 +662,31 @@ impl Types {
if task::is_done(glb.offset) { if task::is_done(glb.offset) {
continue; continue;
} }
glb.offset = to.len() as _; glb.offset = 0;
to.extend(&glb.data); used_globals.push(glob);
} }
_ => unreachable!(), _ => unreachable!(),
} }
} }
for fuc in &self.funcs { for &func in &used_funcs {
if !task::is_done(fuc.offset) { let fuc = &mut self.funcs[func as usize];
continue; fuc.offset = to.len() as _;
} to.extend(&fuc.code);
}
let code_length = to.len();
for &global in &used_globals {
let global = &mut self.globals[global as usize];
global.offset = to.len() as _;
to.extend(&global.data);
}
let data_length = to.len() - code_length;
for func in used_funcs {
let fuc = &self.funcs[func as usize];
for rel in &fuc.relocs { for rel in &fuc.relocs {
let offset = match rel.target.expand() { let offset = match rel.target.expand() {
ty::Kind::Func(fun) => self.funcs[fun as usize].offset, ty::Kind::Func(fun) => self.funcs[fun as usize].offset,
@ -661,6 +696,16 @@ impl Types {
rel.reloc.apply_jump(to, offset, fuc.offset); rel.reloc.apply_jump(to, offset, fuc.offset);
} }
} }
AbleOsExecutableHeader {
magic_number: [0x15, 0x91, 0xD2],
executable_version: 0,
code_length: (code_length - HEADER_SIZE) as _,
data_length: data_length as _,
debug_length: 0,
config_length: 0,
metadata_length: 0,
}
} }
pub fn disasm( pub fn disasm(
@ -892,7 +937,10 @@ fn disasm(
*binary = prev; *binary = prev;
} }
'_dump: for (&off, &(name, len, kind)) in functions.iter() { let mut ordered = functions.iter().collect::<Vec<_>>();
ordered.sort_unstable_by_key(|(_, (name, _, _))| name);
'_dump: for (&off, &(name, len, kind)) in ordered {
if matches!(kind, DisasmItem::Global) { if matches!(kind, DisasmItem::Global) {
continue; continue;
} }
@ -1070,107 +1118,24 @@ impl<T> TaskQueueInner<T> {
} }
pub fn parse_from_fs(extra_threads: usize, root: &str) -> io::Result<Vec<Ast>> { pub fn parse_from_fs(extra_threads: usize, root: &str) -> io::Result<Vec<Ast>> {
const GIT_DEPS_DIR: &str = "git-deps"; fn resolve(path: &str, from: &str) -> Result<PathBuf, CantLoadFile> {
let path = match Path::new(from).parent() {
Some(parent) => PathBuf::from_iter([parent, Path::new(path)]),
None => PathBuf::from(path),
};
enum Chk<'a> { path.canonicalize().map_err(|source| CantLoadFile { path, source })
Branch(&'a str),
Rev(&'a str),
Tag(&'a str),
}
enum ImportPath<'a> {
Rel { path: &'a str },
Git { link: &'a str, path: &'a str, chk: Option<Chk<'a>> },
}
impl<'a> TryFrom<&'a str> for ImportPath<'a> {
type Error = ParseImportError;
fn try_from(value: &'a str) -> Result<Self, Self::Error> {
let (prefix, path) = value.split_once(':').unwrap_or(("", value));
match prefix {
"rel" | "" => Ok(Self::Rel { path }),
"git" => {
let (link, path) =
path.split_once(':').ok_or(ParseImportError::ExpectedPath)?;
let (link, params) = link.split_once('?').unwrap_or((link, ""));
let chk = params.split('&').filter_map(|s| s.split_once('=')).find_map(
|(key, value)| match key {
"branch" => Some(Chk::Branch(value)),
"rev" => Some(Chk::Rev(value)),
"tag" => Some(Chk::Tag(value)),
_ => None,
},
);
Ok(Self::Git { link, path, chk })
}
_ => Err(ParseImportError::InvalidPrefix),
}
}
}
fn preprocess_git(link: &str) -> &str {
let link = link.strip_prefix("https://").unwrap_or(link);
link.strip_suffix(".git").unwrap_or(link)
}
impl<'a> ImportPath<'a> {
fn resolve(&self, from: &str) -> Result<PathBuf, CantLoadFile> {
let path = match self {
Self::Rel { path } => match Path::new(from).parent() {
Some(parent) => PathBuf::from_iter([parent, Path::new(path)]),
None => PathBuf::from(path),
},
Self::Git { path, link, .. } => {
let link = preprocess_git(link);
PathBuf::from_iter([GIT_DEPS_DIR, link, path])
}
};
path.canonicalize().map_err(|source| CantLoadFile {
path,
from: PathBuf::from(from),
source,
})
}
}
#[derive(Debug)]
enum ParseImportError {
ExpectedPath,
InvalidPrefix,
}
impl std::fmt::Display for ParseImportError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self::ExpectedPath => "expected path".fmt(f),
Self::InvalidPrefix => "invalid prefix, expected one of rel, \
git or none followed by colon"
.fmt(f),
}
}
}
impl std::error::Error for ParseImportError {}
impl From<ParseImportError> for io::Error {
fn from(e: ParseImportError) -> Self {
io::Error::new(io::ErrorKind::InvalidInput, e)
}
} }
#[derive(Debug)] #[derive(Debug)]
struct CantLoadFile { struct CantLoadFile {
path: PathBuf, path: PathBuf,
from: PathBuf,
source: io::Error, source: io::Error,
} }
impl std::fmt::Display for CantLoadFile { impl std::fmt::Display for CantLoadFile {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "can't load file: {} (from: {})", self.path.display(), self.from.display(),) write!(f, "can't load file: {}", parser::display_rel_path(&self.path),)
} }
} }
@ -1186,37 +1151,22 @@ pub fn parse_from_fs(extra_threads: usize, root: &str) -> io::Result<Vec<Ast>> {
} }
} }
#[derive(Debug)] type Task = (u32, PathBuf);
struct InvalidFileData(std::str::Utf8Error);
impl std::fmt::Display for InvalidFileData {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "invalid file data")
}
}
impl std::error::Error for InvalidFileData {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
Some(&self.0)
}
}
impl From<InvalidFileData> for io::Error {
fn from(e: InvalidFileData) -> Self {
io::Error::new(io::ErrorKind::InvalidData, e)
}
}
type Task = (u32, PathBuf, Option<std::process::Command>);
let seen = Mutex::new(HashMap::<PathBuf, u32>::default()); let seen = Mutex::new(HashMap::<PathBuf, u32>::default());
let tasks = TaskQueue::<Task>::new(extra_threads + 1); let tasks = TaskQueue::<Task>::new(extra_threads + 1);
let ast = Mutex::new(Vec::<io::Result<Ast>>::new()); let ast = Mutex::new(Vec::<io::Result<Ast>>::new());
let loader = |path: &str, from: &str| { let loader = |path: &str, from: &str| {
let path = ImportPath::try_from(path)?; if path.starts_with("rel:") {
return Err(io::Error::new(
io::ErrorKind::Other,
"`rel:` prefix was removed and is now equivalent to no prefix (remove it)"
.to_string(),
));
}
let physiscal_path = path.resolve(from)?; let physiscal_path = resolve(path, from)?;
let id = { let id = {
let mut seen = seen.lock().unwrap(); let mut seen = seen.lock().unwrap();
@ -1232,63 +1182,30 @@ pub fn parse_from_fs(extra_threads: usize, root: &str) -> io::Result<Vec<Ast>> {
} }
}; };
let command = if !physiscal_path.exists() { if !physiscal_path.exists() {
let ImportPath::Git { link, chk, .. } = path else { return Err(io::Error::new(
return Err(io::Error::new( io::ErrorKind::NotFound,
io::ErrorKind::NotFound, format!("can't find file: {}", parser::display_rel_path(&physiscal_path)),
format!("can't find file: {}", physiscal_path.display()), ));
)); }
};
let root = PathBuf::from_iter([GIT_DEPS_DIR, preprocess_git(link)]); tasks.push((id, physiscal_path));
let mut command = std::process::Command::new("git");
command.args(["clone", "--depth", "1"]);
if let Some(chk) = chk {
command.args(match chk {
Chk::Branch(b) => ["--branch", b],
Chk::Tag(t) => ["--tag", t],
Chk::Rev(r) => ["--rev", r],
});
}
command.arg(link).arg(root);
Some(command)
} else {
None
};
tasks.push((id, physiscal_path, command));
Ok(id) Ok(id)
}; };
let execute_task = |(_, path, command): Task, buffer: &mut Vec<u8>| { let execute_task = |(_, path): Task| {
if let Some(mut command) = command {
let output = command.output()?;
if !output.status.success() {
let msg =
format!("git command failed: {}", String::from_utf8_lossy(&output.stderr));
return Err(io::Error::new(io::ErrorKind::Other, msg));
}
}
let path = path.to_str().ok_or_else(|| { let path = path.to_str().ok_or_else(|| {
io::Error::new( io::Error::new(
io::ErrorKind::InvalidData, io::ErrorKind::InvalidData,
format!("path contains invalid characters: {}", path.display()), format!("path contains invalid characters: {}", parser::display_rel_path(&path)),
) )
})?; })?;
let mut file = std::fs::File::open(path)?; Ok(Ast::new(path, std::fs::read_to_string(path)?, &loader))
file.read_to_end(buffer)?;
let src = std::str::from_utf8(buffer).map_err(InvalidFileData)?;
Ok(Ast::new(path, src.to_owned(), &loader))
}; };
let thread = || { let thread = || {
let mut buffer = Vec::new();
while let Some(task @ (indx, ..)) = tasks.pop() { while let Some(task @ (indx, ..)) = tasks.pop() {
let res = execute_task(task, &mut buffer); let res = execute_task(task);
buffer.clear();
let mut ast = ast.lock().unwrap(); let mut ast = ast.lock().unwrap();
let len = ast.len().max(indx as usize + 1); let len = ast.len().max(indx as usize + 1);
ast.resize_with(len, || Err(io::ErrorKind::InvalidData.into())); ast.resize_with(len, || Err(io::ErrorKind::InvalidData.into()));
@ -1298,7 +1215,7 @@ pub fn parse_from_fs(extra_threads: usize, root: &str) -> io::Result<Vec<Ast>> {
let path = Path::new(root).canonicalize()?; let path = Path::new(root).canonicalize()?;
seen.lock().unwrap().insert(path.clone(), 0); seen.lock().unwrap().insert(path.clone(), 0);
tasks.push((0, path, None)); tasks.push((0, path));
if extra_threads == 0 { if extra_threads == 0 {
thread(); thread();
@ -1467,7 +1384,7 @@ fn test_run_vm(out: &[u8], output: &mut String) {
let mut vm = unsafe { let mut vm = unsafe {
hbvm::Vm::<_, { 1024 * 100 }>::new( hbvm::Vm::<_, { 1024 * 100 }>::new(
LoggedMem::default(), LoggedMem::default(),
hbvm::mem::Address::new(out.as_ptr() as u64), hbvm::mem::Address::new(out.as_ptr() as u64).wrapping_add(HEADER_SIZE),
) )
}; };
@ -1506,7 +1423,7 @@ fn test_run_vm(out: &[u8], output: &mut String) {
} }
}; };
writeln!(output, "code size: {}", out.len()).unwrap(); writeln!(output, "code size: {}", out.len() - HEADER_SIZE).unwrap();
writeln!(output, "ret: {:?}", vm.read_reg(1).0).unwrap(); writeln!(output, "ret: {:?}", vm.read_reg(1).0).unwrap();
writeln!(output, "status: {:?}", stat).unwrap(); writeln!(output, "status: {:?}", stat).unwrap();
} }

View file

@ -5,8 +5,10 @@ use {
}, },
std::{ std::{
cell::{Cell, UnsafeCell}, cell::{Cell, UnsafeCell},
ffi::OsStr,
fmt, io, fmt, io,
ops::{Deref, Not}, ops::{Deref, Not},
path::PathBuf,
ptr::NonNull, ptr::NonNull,
sync::atomic::AtomicUsize, sync::atomic::AtomicUsize,
}, },
@ -95,20 +97,20 @@ impl<'a, 'b> Parser<'a, 'b> {
let f = self.collect_list(TokenKind::Semi, TokenKind::Eof, |s| s.expr_low(true)); let f = self.collect_list(TokenKind::Semi, TokenKind::Eof, |s| s.expr_low(true));
self.pop_scope(0); self.pop_scope(0);
let has_undeclared = !self.idents.is_empty(); let mut errors = String::new();
for id in self.idents.drain(..) { for id in self.idents.drain(..) {
let (line, col) = self.lexer.line_col(ident::pos(id.ident)); report_to(
eprintln!( self.lexer.source(),
"{}:{}:{} => undeclared identifier: {}",
self.path, self.path,
line, id.ident,
col, format_args!("undeclared identifier: {}", self.lexer.slice(ident::range(id.ident))),
self.lexer.slice(ident::range(id.ident)) &mut errors,
); );
} }
if has_undeclared { if !errors.is_empty() {
// TODO: we need error recovery // TODO: we need error recovery
eprintln!("{errors}");
unreachable!(); unreachable!();
} }
@ -193,7 +195,7 @@ impl<'a, 'b> Parser<'a, 'b> {
self.declare_rec(value, top_level) self.declare_rec(value, top_level)
} }
} }
_ => self.report_pos(expr.pos(), "cant declare this shit (yet)"), _ => self.report(expr.pos(), "cant declare this shit (yet)"),
} }
} }
@ -201,7 +203,7 @@ impl<'a, 'b> Parser<'a, 'b> {
if let Some(index) = index_to_check if let Some(index) = index_to_check
&& index != 0 && index != 0
{ {
self.report_pos( self.report(
pos, pos,
format_args!( format_args!(
"out of order declaration not allowed: {}", "out of order declaration not allowed: {}",
@ -212,7 +214,7 @@ impl<'a, 'b> Parser<'a, 'b> {
let index = self.idents.binary_search_by_key(&id, |s| s.ident).expect("fck up"); let index = self.idents.binary_search_by_key(&id, |s| s.ident).expect("fck up");
if std::mem::replace(&mut self.idents[index].declared, true) { if std::mem::replace(&mut self.idents[index].declared, true) {
self.report_pos( self.report(
pos, pos,
format_args!("redeclaration of identifier: {}", self.lexer.slice(ident::range(id))), format_args!("redeclaration of identifier: {}", self.lexer.slice(ident::range(id))),
) )
@ -276,7 +278,9 @@ impl<'a, 'b> Parser<'a, 'b> {
path: self.arena.alloc_str(path), path: self.arena.alloc_str(path),
id: match (self.loader)(path, self.path) { id: match (self.loader)(path, self.path) {
Ok(id) => id, Ok(id) => id,
Err(e) => self.report(format_args!("error loading dependency: {e:#}")), Err(e) => {
self.report(str.start, format_args!("error loading dependency: {e:#}"))
}
}, },
} }
} }
@ -408,7 +412,7 @@ impl<'a, 'b> Parser<'a, 'b> {
pos, pos,
value: match u64::from_str_radix(slice, radix as u32) { value: match u64::from_str_radix(slice, radix as u32) {
Ok(value) => value, Ok(value) => value,
Err(e) => self.report(format_args!("invalid number: {e}")), Err(e) => self.report(token.start, format_args!("invalid number: {e}")),
} as i64, } as i64,
radix, radix,
} }
@ -419,7 +423,7 @@ impl<'a, 'b> Parser<'a, 'b> {
expr expr
} }
T::Comment => Expr::Comment { pos, literal: self.move_str(token) }, T::Comment => Expr::Comment { pos, literal: self.move_str(token) },
tok => self.report(format_args!("unexpected token: {tok:?}")), tok => self.report(token.start, format_args!("unexpected token: {tok:?}")),
}; };
loop { loop {
@ -497,7 +501,10 @@ impl<'a, 'b> Parser<'a, 'b> {
if matches!(self.token.kind, TokenKind::Ident | TokenKind::CtIdent) { if matches!(self.token.kind, TokenKind::Ident | TokenKind::CtIdent) {
self.next() self.next()
} else { } else {
self.report(format_args!("expected identifier, found {:?}", self.token.kind)) self.report(
self.token.start,
format_args!("expected identifier, found {:?}", self.token.kind),
)
} }
} }
@ -552,20 +559,19 @@ impl<'a, 'b> Parser<'a, 'b> {
fn expect_advance(&mut self, kind: TokenKind) -> Token { fn expect_advance(&mut self, kind: TokenKind) -> Token {
if self.token.kind != kind { if self.token.kind != kind {
self.report(format_args!("expected {:?}, found {:?}", kind, self.token.kind)); self.report(
self.token.start,
format_args!("expected {:?}, found {:?}", kind, self.token.kind),
);
} }
self.next() self.next()
} }
#[track_caller] #[track_caller]
fn report(&self, msg: impl fmt::Display) -> ! { fn report(&self, pos: Pos, msg: impl fmt::Display) -> ! {
self.report_pos(self.token.start, msg) let mut str = String::new();
} report_to(self.lexer.source(), self.path, pos, msg, &mut str);
eprintln!("{str}");
#[track_caller]
fn report_pos(&self, pos: Pos, msg: impl fmt::Display) -> ! {
let (line, col) = self.lexer.line_col(pos);
eprintln!("{}:{}:{} => {}", self.path, line, col, msg);
unreachable!(); unreachable!();
} }
@ -1231,19 +1237,34 @@ impl AstInner<[Symbol]> {
} }
pub fn report_to(&self, pos: Pos, msg: impl fmt::Display, out: &mut impl fmt::Write) { pub fn report_to(&self, pos: Pos, msg: impl fmt::Display, out: &mut impl fmt::Write) {
let str = &self.file; report_to(&self.file, &self.path, pos, msg, out);
let (line, mut col) = lexer::line_col(str.as_bytes(), pos);
_ = writeln!(out, "{}:{}:{}: {}", self.path, line, col, msg);
let line = &str[str[..pos as usize].rfind('\n').map_or(0, |i| i + 1)
..str[pos as usize..].find('\n').unwrap_or(str.len()) + pos as usize];
col += line.matches('\t').count() * 3;
_ = writeln!(out, "{}", line.replace("\t", " "));
_ = writeln!(out, "{}^", " ".repeat(col - 1));
} }
} }
pub fn display_rel_path(path: &(impl AsRef<OsStr> + ?Sized)) -> std::path::Display {
static CWD: std::sync::LazyLock<PathBuf> =
std::sync::LazyLock::new(|| std::env::current_dir().unwrap_or_default());
std::path::Path::new(path).strip_prefix(&*CWD).unwrap_or(std::path::Path::new(path)).display()
}
pub fn report_to(
file: &str,
path: &str,
pos: Pos,
msg: impl fmt::Display,
out: &mut impl fmt::Write,
) {
let (line, mut col) = lexer::line_col(file.as_bytes(), pos);
_ = writeln!(out, "{}:{}:{}: {}", display_rel_path(path), line, col, msg);
let line = &file[file[..pos as usize].rfind('\n').map_or(0, |i| i + 1)
..file[pos as usize..].find('\n').unwrap_or(file.len()) + pos as usize];
col += line.matches('\t').count() * 3;
_ = writeln!(out, "{}", line.replace("\t", " "));
_ = writeln!(out, "{}^", " ".repeat(col - 1));
}
#[derive(PartialEq, Eq, Hash)] #[derive(PartialEq, Eq, Hash)]
pub struct Ast(NonNull<AstInner<[Symbol]>>); pub struct Ast(NonNull<AstInner<[Symbol]>>);

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,9 @@
foo:
ADDI64 r254, r254, -8d
ST r31, r254, 0a, 8h
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
JALA r0, r31, 0a
main: main:
ADDI64 r254, r254, -8d ADDI64 r254, r254, -8d
ST r31, r254, 0a, 8h ST r31, r254, 0a, 8h
@ -6,12 +12,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
foo:
ADDI64 r254, r254, -8d
ST r31, r254, 0a, 8h
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
JALA r0, r31, 0a
code size: 143 code size: 143
ret: 0 ret: 0
status: Ok(()) status: Ok(())

View file

@ -1,3 +1,19 @@
add_one:
ADDI64 r254, r254, -16d
ST r31, r254, 0a, 16h
CP r32, r2
ADDI64 r1, r32, 1d
LD r31, r254, 0a, 16h
ADDI64 r254, r254, 16d
JALA r0, r31, 0a
add_two:
ADDI64 r254, r254, -16d
ST r31, r254, 0a, 16h
CP r32, r2
ADDI64 r1, r32, 2d
LD r31, r254, 0a, 16h
ADDI64 r254, r254, 16d
JALA r0, r31, 0a
main: main:
ADDI64 r254, r254, -24d ADDI64 r254, r254, -24d
ST r31, r254, 0a, 24h ST r31, r254, 0a, 24h
@ -11,22 +27,6 @@ main:
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
add_two:
ADDI64 r254, r254, -16d
ST r31, r254, 0a, 16h
CP r32, r2
ADDI64 r1, r32, 2d
LD r31, r254, 0a, 16h
ADDI64 r254, r254, 16d
JALA r0, r31, 0a
add_one:
ADDI64 r254, r254, -16d
ST r31, r254, 0a, 16h
CP r32, r2
ADDI64 r1, r32, 1d
LD r31, r254, 0a, 16h
ADDI64 r254, r254, 16d
JALA r0, r31, 0a
code size: 257 code size: 257
ret: 33 ret: 33
status: Ok(()) status: Ok(())

View file

@ -1,20 +1,3 @@
main:
ADDI64 r254, r254, -32d
ST r31, r254, 0a, 32h
LI64 r2, 2d
LI64 r3, 2d
JAL r31, r0, :add
CP r32, r1
LI64 r2, 1d
LI64 r3, 3d
JAL r31, r0, :add
CP r33, r1
CP r34, r32
SXT32 r34, r34
SUB64 r1, r34, r33
LD r31, r254, 0a, 32h
ADDI64 r254, r254, 32d
JALA r0, r31, 0a
add: add:
ADDI64 r254, r254, -24d ADDI64 r254, r254, -24d
ST r31, r254, 0a, 24h ST r31, r254, 0a, 24h
@ -33,6 +16,23 @@ add:
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
main:
ADDI64 r254, r254, -32d
ST r31, r254, 0a, 32h
LI64 r2, 2d
LI64 r3, 2d
JAL r31, r0, :add
CP r32, r1
LI64 r2, 1d
LI64 r3, 3d
JAL r31, r0, :add
CP r33, r1
CP r34, r32
SXT32 r34, r34
SUB64 r1, r34, r33
LD r31, r254, 0a, 32h
ADDI64 r254, r254, 32d
JALA r0, r31, 0a
code size: 275 code size: 275
ret: 0 ret: 0
status: Ok(()) status: Ok(())

View file

@ -1,3 +1,33 @@
deinit:
ADDI64 r254, r254, -24d
ST r31, r254, 0a, 24h
CP r32, r2
LD r2, r32, 0a, 8h
LD r33, r32, 16a, 8h
MULI64 r33, r33, 8d
CP r3, r33
LI64 r4, 8d
JAL r31, r0, :free
CP r1, r32
JAL r31, r0, :new
LD r31, r254, 0a, 24h
ADDI64 r254, r254, 24d
JALA r0, r31, 0a
free:
ADDI64 r254, r254, -40d
ST r31, r254, 0a, 40h
CP r32, r2
CP r33, r3
CP r34, r4
LRA r35, r0, :FREE_SYS_CALL
LD r2, r35, 0a, 8h
CP r3, r32
CP r4, r33
CP r5, r34
ECA
LD r31, r254, 0a, 40h
ADDI64 r254, r254, 40d
JALA r0, r31, 0a
main: main:
ADDI64 r254, r254, -48d ADDI64 r254, r254, -48d
ST r31, r254, 24a, 24h ST r31, r254, 24a, 24h
@ -17,20 +47,18 @@ main:
LD r31, r254, 24a, 24h LD r31, r254, 24a, 24h
ADDI64 r254, r254, 48d ADDI64 r254, r254, 48d
JALA r0, r31, 0a JALA r0, r31, 0a
deinit: malloc:
ADDI64 r254, r254, -24d ADDI64 r254, r254, -32d
ST r31, r254, 0a, 24h ST r31, r254, 0a, 32h
CP r32, r2 CP r32, r2
LD r2, r32, 0a, 8h CP r33, r3
LD r33, r32, 16a, 8h LRA r34, r0, :MALLOC_SYS_CALL
MULI64 r33, r33, 8d LD r2, r34, 0a, 8h
CP r3, r33 CP r3, r32
LI64 r4, 8d CP r4, r33
JAL r31, r0, :free ECA
CP r1, r32 LD r31, r254, 0a, 32h
JAL r31, r0, :new ADDI64 r254, r254, 32d
LD r31, r254, 0a, 24h
ADDI64 r254, r254, 24d
JALA r0, r31, 0a JALA r0, r31, 0a
new: new:
ADDI64 r254, r254, -24d ADDI64 r254, r254, -24d
@ -45,21 +73,6 @@ new:
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
free:
ADDI64 r254, r254, -40d
ST r31, r254, 0a, 40h
CP r32, r2
CP r33, r3
CP r34, r4
LRA r35, r0, :FREE_SYS_CALL
LD r2, r35, 0a, 8h
CP r3, r32
CP r4, r33
CP r5, r34
ECA
LD r31, r254, 0a, 40h
ADDI64 r254, r254, 40d
JALA r0, r31, 0a
push: push:
ADDI64 r254, r254, -72d ADDI64 r254, r254, -72d
ST r31, r254, 0a, 72h ST r31, r254, 0a, 72h
@ -124,19 +137,6 @@ push:
4: LD r31, r254, 0a, 72h 4: LD r31, r254, 0a, 72h
ADDI64 r254, r254, 72d ADDI64 r254, r254, 72d
JALA r0, r31, 0a JALA r0, r31, 0a
malloc:
ADDI64 r254, r254, -32d
ST r31, r254, 0a, 32h
CP r32, r2
CP r33, r3
LRA r34, r0, :MALLOC_SYS_CALL
LD r2, r34, 0a, 8h
CP r3, r32
CP r4, r33
ECA
LD r31, r254, 0a, 32h
ADDI64 r254, r254, 32d
JALA r0, r31, 0a
code size: 1201 code size: 1201
ret: 69 ret: 69
status: Ok(()) status: Ok(())

View file

@ -1,11 +1,3 @@
main:
ADDI64 r254, r254, -8d
ST r31, r254, 0a, 8h
LI64 r2, 10d
JAL r31, r0, :fib
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
JALA r0, r31, 0a
fib: fib:
ADDI64 r254, r254, -24d ADDI64 r254, r254, -24d
ST r31, r254, 0a, 24h ST r31, r254, 0a, 24h
@ -27,6 +19,14 @@ fib:
1: LD r31, r254, 0a, 24h 1: LD r31, r254, 0a, 24h
ADDI64 r254, r254, 24d ADDI64 r254, r254, 24d
JALA r0, r31, 0a JALA r0, r31, 0a
main:
ADDI64 r254, r254, -8d
ST r31, r254, 0a, 8h
LI64 r2, 10d
JAL r31, r0, :fib
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
JALA r0, r31, 0a
code size: 231 code size: 231
ret: 55 ret: 55
status: Ok(()) status: Ok(())

View file

@ -1,45 +1,3 @@
main:
ADDI64 r254, r254, -64d
ST r31, r254, 48a, 16h
LI64 r32, 0d
ST r32, r254, 0a, 8h
LI64 r32, 0d
ST r32, r254, 8a, 8h
LD r2, r254, 0a, 16h
LI64 r32, 0d
ST r32, r254, 16a, 8h
LI64 r32, 0d
ST r32, r254, 24a, 8h
LD r4, r254, 16a, 16h
LI64 r32, 0d
ST r32, r254, 32a, 8h
LI64 r32, 0d
ST r32, r254, 40a, 8h
LD r6, r254, 32a, 16h
LI64 r8, 10d
JAL r31, r0, :line
LI64 r32, 0d
ST r32, r254, 0a, 8h
LI64 r32, 0d
ST r32, r254, 8a, 8h
LD r2, r254, 0a, 16h
LI64 r32, 0d
ST r32, r254, 16a, 8h
LI64 r32, 0d
ST r32, r254, 24a, 8h
LD r4, r254, 16a, 16h
LI64 r32, 0d
ST r32, r254, 32a, 8h
LI64 r32, 0d
ST r32, r254, 40a, 8h
LD r6, r254, 32a, 16h
LI64 r8, 10d
JAL r31, r0, :rect_line
JAL r31, r0, :example
LI64 r1, 0d
LD r31, r254, 48a, 16h
ADDI64 r254, r254, 64d
JALA r0, r31, 0a
example: example:
ADDI64 r254, r254, -48d ADDI64 r254, r254, -48d
ST r31, r254, 0a, 48h ST r31, r254, 0a, 48h
@ -103,6 +61,69 @@ integer:
1: LD r31, r254, 0a, 56h 1: LD r31, r254, 0a, 56h
ADDI64 r254, r254, 56d ADDI64 r254, r254, 56d
JALA r0, r31, 0a JALA r0, r31, 0a
line:
ADDI64 r254, r254, -80d
ST r31, r254, 48a, 32h
ST r2, r254, 16a, 16h
ST r4, r254, 0a, 16h
ST r6, r254, 32a, 16h
CP r32, r8
LI64 r33, 1d
JEQ r33, r0, :0
LD r33, r254, 16a, 8h
LD r34, r254, 0a, 8h
JGTS r33, r34, :1
JMP :1
1: JMP :2
0: LD r34, r254, 24a, 8h
LD r33, r254, 8a, 8h
JGTS r34, r33, :2
JMP :2
2: LD r31, r254, 48a, 32h
ADDI64 r254, r254, 80d
JALA r0, r31, 0a
main:
ADDI64 r254, r254, -64d
ST r31, r254, 48a, 16h
LI64 r32, 0d
ST r32, r254, 0a, 8h
LI64 r32, 0d
ST r32, r254, 8a, 8h
LD r2, r254, 0a, 16h
LI64 r32, 0d
ST r32, r254, 16a, 8h
LI64 r32, 0d
ST r32, r254, 24a, 8h
LD r4, r254, 16a, 16h
LI64 r32, 0d
ST r32, r254, 32a, 8h
LI64 r32, 0d
ST r32, r254, 40a, 8h
LD r6, r254, 32a, 16h
LI64 r8, 10d
JAL r31, r0, :line
LI64 r32, 0d
ST r32, r254, 0a, 8h
LI64 r32, 0d
ST r32, r254, 8a, 8h
LD r2, r254, 0a, 16h
LI64 r32, 0d
ST r32, r254, 16a, 8h
LI64 r32, 0d
ST r32, r254, 24a, 8h
LD r4, r254, 16a, 16h
LI64 r32, 0d
ST r32, r254, 32a, 8h
LI64 r32, 0d
ST r32, r254, 40a, 8h
LD r6, r254, 32a, 16h
LI64 r8, 10d
JAL r31, r0, :rect_line
JAL r31, r0, :example
LI64 r1, 0d
LD r31, r254, 48a, 16h
ADDI64 r254, r254, 64d
JALA r0, r31, 0a
rect_line: rect_line:
ADDI64 r254, r254, -112d ADDI64 r254, r254, -112d
ST r31, r254, 48a, 64h ST r31, r254, 48a, 64h
@ -135,27 +156,6 @@ rect_line:
1: LD r31, r254, 48a, 64h 1: LD r31, r254, 48a, 64h
ADDI64 r254, r254, 112d ADDI64 r254, r254, 112d
JALA r0, r31, 0a JALA r0, r31, 0a
line:
ADDI64 r254, r254, -80d
ST r31, r254, 48a, 32h
ST r2, r254, 16a, 16h
ST r4, r254, 0a, 16h
ST r6, r254, 32a, 16h
CP r32, r8
LI64 r33, 1d
JEQ r33, r0, :0
LD r33, r254, 16a, 8h
LD r34, r254, 0a, 8h
JGTS r33, r34, :1
JMP :1
1: JMP :2
0: LD r34, r254, 24a, 8h
LD r33, r254, 8a, 8h
JGTS r34, r33, :2
JMP :2
2: LD r31, r254, 48a, 32h
ADDI64 r254, r254, 80d
JALA r0, r31, 0a
code size: 1400 code size: 1400
ret: 0 ret: 0
status: Ok(()) status: Ok(())

View file

@ -1,13 +1,3 @@
main:
ADDI64 r254, r254, -16d
ST r31, r254, 0a, 16h
LI64 r2, 0d
LI64 r3, 1000d
JAL r31, r0, :integer_range
CP r32, r1
LD r31, r254, 0a, 16h
ADDI64 r254, r254, 16d
JALA r0, r31, 0a
integer_range: integer_range:
ADDI64 r254, r254, -32d ADDI64 r254, r254, -32d
ST r31, r254, 0a, 32h ST r31, r254, 0a, 32h
@ -24,6 +14,16 @@ integer_range:
LD r31, r254, 0a, 32h LD r31, r254, 0a, 32h
ADDI64 r254, r254, 32d ADDI64 r254, r254, 32d
JALA r0, r31, 0a JALA r0, r31, 0a
main:
ADDI64 r254, r254, -16d
ST r31, r254, 0a, 16h
LI64 r2, 0d
LI64 r3, 1000d
JAL r31, r0, :integer_range
CP r32, r1
LD r31, r254, 0a, 16h
ADDI64 r254, r254, 16d
JALA r0, r31, 0a
code size: 210 code size: 210
ret: 42 ret: 42
status: Ok(()) status: Ok(())

View file

@ -1,11 +1,3 @@
main:
ADDI64 r254, r254, -8d
ST r31, r254, 0a, 8h
LI64 r2, 10d
JAL r31, r0, :fib
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
JALA r0, r31, 0a
fib: fib:
ADDI64 r254, r254, -40d ADDI64 r254, r254, -40d
ST r31, r254, 0a, 40h ST r31, r254, 0a, 40h
@ -25,6 +17,14 @@ fib:
LD r31, r254, 0a, 40h LD r31, r254, 0a, 40h
ADDI64 r254, r254, 40d ADDI64 r254, r254, 40d
JALA r0, r31, 0a JALA r0, r31, 0a
main:
ADDI64 r254, r254, -8d
ST r31, r254, 0a, 8h
LI64 r2, 10d
JAL r31, r0, :fib
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
JALA r0, r31, 0a
code size: 218 code size: 218
ret: 55 ret: 55
status: Ok(()) status: Ok(())

View file

@ -1,3 +1,10 @@
drop:
ADDI64 r254, r254, -16d
ST r31, r254, 0a, 16h
CP r32, r2
LD r31, r254, 0a, 16h
ADDI64 r254, r254, 16d
JALA r0, r31, 0a
main: main:
ADDI64 r254, r254, -40d ADDI64 r254, r254, -40d
ST r31, r254, 8a, 32h ST r31, r254, 8a, 32h
@ -14,13 +21,6 @@ main:
LD r31, r254, 8a, 32h LD r31, r254, 8a, 32h
ADDI64 r254, r254, 40d ADDI64 r254, r254, 40d
JALA r0, r31, 0a JALA r0, r31, 0a
drop:
ADDI64 r254, r254, -16d
ST r31, r254, 0a, 16h
CP r32, r2
LD r31, r254, 0a, 16h
ADDI64 r254, r254, 16d
JALA r0, r31, 0a
modify: modify:
ADDI64 r254, r254, -24d ADDI64 r254, r254, -24d
ST r31, r254, 0a, 24h ST r31, r254, 0a, 24h

View file

@ -1,12 +1,3 @@
main:
ADDI64 r254, r254, -16d
ST r31, r254, 0a, 16h
LI64 r2, 400d
JAL r31, r0, :create_back_buffer
CP r32, r1
LD r31, r254, 0a, 16h
ADDI64 r254, r254, 16d
JALA r0, r31, 0a
create_back_buffer: create_back_buffer:
ADDI64 r254, r254, -32d ADDI64 r254, r254, -32d
ST r31, r254, 0a, 32h ST r31, r254, 0a, 32h
@ -38,6 +29,15 @@ create_back_buffer:
1: LD r31, r254, 0a, 32h 1: LD r31, r254, 0a, 32h
ADDI64 r254, r254, 32d ADDI64 r254, r254, 32d
JALA r0, r31, 0a JALA r0, r31, 0a
main:
ADDI64 r254, r254, -16d
ST r31, r254, 0a, 16h
LI64 r2, 400d
JAL r31, r0, :create_back_buffer
CP r32, r1
LD r31, r254, 0a, 16h
ADDI64 r254, r254, 16d
JALA r0, r31, 0a
request_page: request_page:
ADDI64 r254, r254, -32d ADDI64 r254, r254, -32d
ST r31, r254, 0a, 32h ST r31, r254, 0a, 32h

View file

@ -1,43 +1,3 @@
main:
ADDI64 r254, r254, -26d
ST r31, r254, 2a, 24h
LI64 r32, 10d
ST r32, r254, 0a, 1h
LI64 r32, 10d
ST r32, r254, 1a, 1h
CP r32, r0
LD r32, r254, 0a, 1h
CP r33, r0
LD r33, r254, 1a, 1h
CP r2, r32
JAL r31, r0, :fib
CP r32, r1
CP r2, r33
JAL r31, r0, :fib_iter
CP r33, r1
SUB64 r1, r32, r33
LD r31, r254, 2a, 24h
ADDI64 r254, r254, 26d
JALA r0, r31, 0a
fib_iter:
ADDI64 r254, r254, -40d
ST r31, r254, 0a, 40h
CP r32, r2
LI64 r33, 0d
LI64 r34, 1d
2: LI64 r35, 0d
JNE r32, r35, :0
JMP :1
0: CP r35, r33
ADD64 r35, r35, r34
CP r33, r34
CP r34, r35
ADDI64 r32, r32, -1d
JMP :2
1: CP r1, r33
LD r31, r254, 0a, 40h
ADDI64 r254, r254, 40d
JALA r0, r31, 0a
fib: fib:
ADDI64 r254, r254, -32d ADDI64 r254, r254, -32d
ST r31, r254, 0a, 32h ST r31, r254, 0a, 32h
@ -60,6 +20,46 @@ fib:
1: LD r31, r254, 0a, 32h 1: LD r31, r254, 0a, 32h
ADDI64 r254, r254, 32d ADDI64 r254, r254, 32d
JALA r0, r31, 0a JALA r0, r31, 0a
fib_iter:
ADDI64 r254, r254, -40d
ST r31, r254, 0a, 40h
CP r32, r2
LI64 r33, 0d
LI64 r34, 1d
2: LI64 r35, 0d
JNE r32, r35, :0
JMP :1
0: CP r35, r33
ADD64 r35, r35, r34
CP r33, r34
CP r34, r35
ADDI64 r32, r32, -1d
JMP :2
1: CP r1, r33
LD r31, r254, 0a, 40h
ADDI64 r254, r254, 40d
JALA r0, r31, 0a
main:
ADDI64 r254, r254, -26d
ST r31, r254, 2a, 24h
LI64 r32, 10d
ST r32, r254, 0a, 1h
LI64 r32, 10d
ST r32, r254, 1a, 1h
CP r32, r0
LD r32, r254, 0a, 1h
CP r33, r0
LD r33, r254, 1a, 1h
CP r2, r32
JAL r31, r0, :fib
CP r32, r1
CP r2, r33
JAL r31, r0, :fib_iter
CP r33, r1
SUB64 r1, r32, r33
LD r31, r254, 2a, 24h
ADDI64 r254, r254, 26d
JALA r0, r31, 0a
code size: 452 code size: 452
ret: 0 ret: 0
status: Ok(()) status: Ok(())

View file

@ -1,3 +1,16 @@
foo:
ADDI64 r254, r254, -32d
ST r31, r254, 16a, 16h
LI64 r32, 3d
ST r32, r254, 0a, 8h
LI64 r32, 2d
ST r32, r254, 8a, 4h
LI64 r32, 2d
ST r32, r254, 12a, 4h
LD r1, r254, 0a, 16h
LD r31, r254, 16a, 16h
ADDI64 r254, r254, 32d
JALA r0, r31, 0a
main: main:
ADDI64 r254, r254, -40d ADDI64 r254, r254, -40d
ST r31, r254, 16a, 24h ST r31, r254, 16a, 24h
@ -21,17 +34,6 @@ main:
LD r31, r254, 16a, 24h LD r31, r254, 16a, 24h
ADDI64 r254, r254, 40d ADDI64 r254, r254, 40d
JALA r0, r31, 0a JALA r0, r31, 0a
foo: code size: 341
ADDI64 r254, r254, -8d
ST r31, r254, 0a, 8h
LI64 r1, 3d
ANDI r2, r2, -4294967296d
ORI r2, r2, 2d
ANDI r2, r2, 4294967295d
ORI r2, r2, 8589934592d
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
JALA r0, r31, 0a
code size: 313
ret: 0 ret: 0
status: Ok(()) status: Ok(())

View file

@ -21,16 +21,6 @@ main:
1: LD r31, r254, 24a, 24h 1: LD r31, r254, 24a, 24h
ADDI64 r254, r254, 48d ADDI64 r254, r254, 48d
JALA r0, r31, 0a JALA r0, r31, 0a
pass:
ADDI64 r254, r254, -32d
ST r31, r254, 0a, 32h
CP r32, r2
LD r33, r32, 0a, 8h
LD r34, r32, 8a, 8h
SUB64 r1, r33, r34
LD r31, r254, 0a, 32h
ADDI64 r254, r254, 32d
JALA r0, r31, 0a
odher_pass: odher_pass:
ADDI64 r254, r254, -32d ADDI64 r254, r254, -32d
ST r31, r254, 0a, 32h ST r31, r254, 0a, 32h
@ -41,6 +31,16 @@ odher_pass:
LD r31, r254, 0a, 32h LD r31, r254, 0a, 32h
ADDI64 r254, r254, 32d ADDI64 r254, r254, 32d
JALA r0, r31, 0a JALA r0, r31, 0a
pass:
ADDI64 r254, r254, -32d
ST r31, r254, 0a, 32h
CP r32, r2
LD r33, r32, 0a, 8h
LD r34, r32, 8a, 8h
SUB64 r1, r33, r34
LD r31, r254, 0a, 32h
ADDI64 r254, r254, 32d
JALA r0, r31, 0a
code size: 394 code size: 394
ret: 3 ret: 3
status: Ok(()) status: Ok(())

View file

@ -0,0 +1,45 @@
main:
ADDI64 r254, r254, -48d
ST r31, r254, 16a, 32h
CP r32, r3
CP r33, r4
JAL r31, r0, :small_struct
CP r34, r1
LI64 r34, 0d
ST r34, r254, 8a, 1h
LI64 r34, 0d
ST r34, r254, 9a, 1h
LI64 r34, 0d
ST r34, r254, 10a, 1h
LI64 r34, 0d
ST r34, r254, 11a, 1h
LI64 r34, 0d
ST r34, r254, 12a, 1h
LI64 r34, 0d
ST r34, r254, 13a, 1h
LI64 r34, 0d
ST r34, r254, 14a, 1h
LI64 r34, 0d
ST r34, r254, 15a, 1h
LD r34, r254, 8a, 8h
ST r34, r254, 0a, 8h
ST r34, r254, 8a, 8h
LD r1, r254, 0a, 16h
LD r31, r254, 16a, 32h
ADDI64 r254, r254, 48d
JALA r0, r31, 0a
small_struct:
ADDI64 r254, r254, -20d
ST r31, r254, 4a, 16h
LI64 r32, 0d
ST r32, r254, 0a, 2h
LI64 r32, 0d
ST r32, r254, 2a, 2h
CP r1, r0
LD r1, r254, 0a, 4h
LD r31, r254, 4a, 16h
ADDI64 r254, r254, 20d
JALA r0, r31, 0a
code size: 440
ret: 0
status: Ok(())

View file

@ -1,3 +1,10 @@
inl:
ADDI64 r254, r254, -16d
ST r31, r254, 0a, 16h
LRA r32, r0, :"luhahah\0"
LD r31, r254, 0a, 16h
ADDI64 r254, r254, 16d
JALA r0, r31, 0a
main: main:
ADDI64 r254, r254, -8d ADDI64 r254, r254, -8d
ST r31, r254, 0a, 8h ST r31, r254, 0a, 8h
@ -6,13 +13,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
inl:
ADDI64 r254, r254, -16d
ST r31, r254, 0a, 16h
LRA r32, r0, :"luhahah\0"
LD r31, r254, 0a, 16h
ADDI64 r254, r254, 16d
JALA r0, r31, 0a
outl: outl:
ADDI64 r254, r254, -16d ADDI64 r254, r254, -16d
ST r31, r254, 0a, 16h ST r31, r254, 0a, 16h