Merge remote-tracking branch 'holey-bytes-main/trunk' into trunk

This commit is contained in:
peony 2024-11-07 21:32:24 +01:00
commit 5964857423
53 changed files with 3780 additions and 2201 deletions

1
.gitignore vendored
View file

@ -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

52
Cargo.lock generated
View file

@ -276,15 +276,15 @@ dependencies = [
[[package]] [[package]]
name = "bytes" name = "bytes"
version = "1.7.2" version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.1.30" version = "1.1.36"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" checksum = "baee610e9452a8f6f0a1b6194ec09ff9e2d85dea54432acdae41aa0761c95d70"
dependencies = [ dependencies = [
"jobserver", "jobserver",
"libc", "libc",
@ -721,9 +721,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]] [[package]]
name = "hyper" name = "hyper"
version = "1.4.1" version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-channel", "futures-channel",
@ -741,9 +741,9 @@ dependencies = [
[[package]] [[package]]
name = "hyper-util" name = "hyper-util"
version = "0.1.9" version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-util", "futures-util",
@ -979,18 +979,18 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]] [[package]]
name = "pin-project" name = "pin-project"
version = "1.1.6" version = "1.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf123a161dde1e524adf36f90bc5d8d3462824a9c43553ad07a8183161189ec" checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95"
dependencies = [ dependencies = [
"pin-project-internal", "pin-project-internal",
] ]
[[package]] [[package]]
name = "pin-project-internal" name = "pin-project-internal"
version = "1.1.6" version = "1.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8" checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -999,9 +999,9 @@ dependencies = [
[[package]] [[package]]
name = "pin-project-lite" name = "pin-project-lite"
version = "0.2.14" version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff"
[[package]] [[package]]
name = "pin-utils" name = "pin-utils"
@ -1073,9 +1073,9 @@ dependencies = [
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.11.0" version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
@ -1162,9 +1162,9 @@ dependencies = [
[[package]] [[package]]
name = "rustls" name = "rustls"
version = "0.23.14" version = "0.23.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" checksum = "eee87ff5d9b36712a58574e12e9f0ea80f915a5b0ac518d322b24a465617925e"
dependencies = [ dependencies = [
"aws-lc-rs", "aws-lc-rs",
"once_cell", "once_cell",
@ -1185,9 +1185,9 @@ dependencies = [
[[package]] [[package]]
name = "rustls-pki-types" name = "rustls-pki-types"
version = "1.9.0" version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b"
[[package]] [[package]]
name = "rustls-webpki" name = "rustls-webpki"
@ -1203,9 +1203,9 @@ dependencies = [
[[package]] [[package]]
name = "rustversion" name = "rustversion"
version = "1.0.17" version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248"
[[package]] [[package]]
name = "ryu" name = "ryu"
@ -1241,9 +1241,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.128" version = "1.0.132"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03"
dependencies = [ dependencies = [
"itoa", "itoa",
"memchr", "memchr",
@ -1366,9 +1366,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.40.0" version = "1.41.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33"
dependencies = [ dependencies = [
"backtrace", "backtrace",
"bytes", "bytes",

View file

@ -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},
}, },
}; };
@ -55,8 +55,9 @@ unsafe fn compile_and_run(mut fuel: usize) {
files files
}; };
let mut ctx = CodegenCtx::default();
let files = { let files = {
let mut ctx = hblang::parser::Ctx::default();
let paths = files.iter().map(|f| f.path).collect::<Vec<_>>(); let paths = files.iter().map(|f| f.path).collect::<Vec<_>>();
let mut loader = |path: &str, _: &str, kind| match kind { let mut loader = |path: &str, _: &str, kind| match kind {
hblang::parser::FileKind::Module => Ok(paths.binary_search(&path).unwrap() as FileId), hblang::parser::FileKind::Module => Ok(paths.binary_search(&path).unwrap() as FileId),
@ -69,7 +70,7 @@ unsafe fn compile_and_run(mut fuel: usize) {
f.path, f.path,
// since 'free' does nothing this is fine // since 'free' does nothing this is fine
String::from_raw_parts(f.code.as_mut_ptr(), f.code.len(), f.code.len()), String::from_raw_parts(f.code.as_mut_ptr(), f.code.len(), f.code.len()),
&mut ctx, &mut ctx.parser,
&mut loader, &mut loader,
) )
}) })
@ -77,9 +78,15 @@ unsafe fn compile_and_run(mut fuel: usize) {
}; };
let mut ct = { let mut ct = {
let mut ctx = CodegenCtx::default(); let mut backend = HbvmBackend::default();
let mut c = Codegen::new(&files, &mut ctx); Codegen::new(&mut backend, &files, &mut ctx).generate(root as FileId);
c.generate(root as FileId);
if !ctx.parser.errors.borrow().is_empty() {
log::error!("{}", ctx.parser.errors.borrow());
return;
}
let mut c = Codegen::new(&mut backend, &files, &mut ctx);
c.assemble_comptime() c.assemble_comptime()
}; };

47
f.txt
View file

@ -1,47 +0,0 @@
start: 0
46-c65535: +: [0, 38, 45] [47]
45-c65535: &: [0, 43, 44] [46]
44-c65535: cint: #255 [0] [45]
43-c65535: load: [0, 42, 23] [45]
42-c65535: +: [0, 22, 18] [43]
39-c65535: stre: [0, 0, 36, 37] [47]
39-c65535: stre: [0, 0, 36, 37] [47]
37-c65535: stre: [0, 35, 36, 3] [38, 39]
36-c65535: stck: [0, 3] [37, 38, 39]
35-c65535: load: [0, 24, 34] [37]
34-c65535: stre: [0, 31, 33, 30] [35, 47]
33-c65535: +: [0, 24, 32] [34]
32-c65535: cint: #16 [0] [33]
31-c65535: cint: #4 [0] [34]
30-c65535: stre: [0, 27, 29, 26] [34]
29-c65535: +: [0, 24, 28] [30]
28-c65535: cint: #8 [0] [29]
27-c65535: cint: #2 [0] [30]
26-c65535: stre: [0, 25, 24, 3] [30]
25-c65535: cint: #1 [0] [26]
24-c65535: stck: [0, 3] [26, 29, 33, 35]
23-c65535: stre: [0, 21, 22, 3] [43, 47]
22-c65535: stck: [0, 3] [23, 42]
21-c65535: load: [0, 6, 20] [23]
20-c65535: stre: [0, 17, 19, 14] [21, 47]
19-c65535: +: [0, 6, 18] [20]
18-c65535: cint: #3 [0] [19, 42]
17-c65535: cint: #1 [0] [20]
14-c65535: stre: [0, 5, 13, 11] [20]
13-c65535: +: [0, 6, 12] [14]
12-c65535: cint: #2 [0] [13]
11-c65535: stre: [0, 7, 10, 8] [14]
10-c65535: +: [0, 6, 9] [11]
9-c65535: cint: #1 [0] [10]
8-c65535: stre: [0, 7, 6, 3] [11]
7-c65535: cint: #0 [0] [8, 11]
6-c65535: stck: [0, 3] [8, 10, 13, 19, 21]
5-c65535: cint: #511 [0] [14]
4-c65535: loops: [0] []
3-c65535: mem: [0] [6, 8, 22, 23, 24, 26, 36, 37, 47]
2-c65535: ctrl: entry [0] [38]
b2: 0 0 [38]
38-c65535: call: 1 0 [2, 36, 37] [46, 47]
47-c65535: ret: [38, 46, 3, 20, 23, 34, 39] [1]

38
f1.txt
View file

@ -1,38 +0,0 @@
start: 0
34-c65535: stre: [0, 31, 51, 30] [39, 47, 38]
51-c65535: +: [0, 36, 32] [34]
32-c65535: cint: #16 [0] [51]
31-c65535: cint: #4 [0] [34]
30-c65535: stre: [0, 27, 50, 26] [34]
50-c65535: +: [0, 36, 28] [30]
28-c65535: cint: #8 [0] [50]
27-c65535: cint: #2 [0] [30]
26-c65535: stre: [0, 25, 36, 3] [30]
25-c65535: cint: #1 [0] [26, 46]
39-c65535: stre: [0, 0, 36, 34] [47]
36-c65535: stck: [0, 3] [51, 38, 39, 26, 50]
22-c65535: stck: [0, 3] [49, 42, 8, 48]
39-c65535: stre: [0, 0, 36, 34] [47]
20-c65535: stre: [0, 17, 42, 14] [47, 47]
46-c65535: +: [0, 38, 25] [47]
18-c65535: cint: #3 [0] [42]
17-c65535: cint: #1 [0] [20]
14-c65535: stre: [0, 5, 49, 11] [20]
49-c65535: +: [0, 22, 12] [14]
12-c65535: cint: #2 [0] [49]
11-c65535: stre: [0, 7, 48, 8] [14]
48-c65535: +: [0, 22, 9] [11]
9-c65535: cint: #1 [0] [48]
8-c65535: stre: [0, 7, 22, 3] [11]
7-c65535: cint: #0 [0] [8, 11]
42-c65535: +: [0, 22, 18] [20]
5-c65535: cint: #511 [0] [14]
4-c65535: loops: [0] []
3-c65535: mem: [0] [47, 8, 22, 26, 36]
2-c65535: ctrl: entry [0] [38]
b2: 0 0 [38]
38-c65535: call: 1 0 [2, 36, 34] [46, 47]
47-c65535: ret: [38, 46, 3, 20, 20, 34, 39] [1]

39
f2.txt
View file

@ -1,39 +0,0 @@
start: 0
42-c65535: +: [0, 22, 18] [43, 20]
36-c65535: stck: [0, 3] [51, 38, 39, 26, 50]
39-c65535: stre: [0, 0, 36, 34] [47]
34-c65535: stre: [0, 31, 51, 30] [39, 47, 38]
51-c65535: +: [0, 36, 32] [34]
32-c65535: cint: #16 [0] [51]
31-c65535: cint: #4 [0] [34]
30-c65535: stre: [0, 27, 50, 26] [34]
50-c65535: +: [0, 36, 28] [30]
28-c65535: cint: #8 [0] [50]
27-c65535: cint: #2 [0] [30]
26-c65535: stre: [0, 25, 36, 3] [30]
25-c65535: cint: #1 [0] [26]
39-c65535: stre: [0, 0, 36, 34] [47]
45-c65535: &: [0, 43, 44] [46]
22-c65535: stck: [0, 3] [49, 42, 8, 48]
44-c65535: cint: #255 [0] [45]
20-c65535: stre: [0, 17, 42, 14] [47, 47, 43]
46-c65535: +: [0, 38, 45] [47]
18-c65535: cint: #3 [0] [42]
17-c65535: cint: #1 [0] [20]
14-c65535: stre: [0, 5, 49, 11] [20]
49-c65535: +: [0, 22, 12] [14]
12-c65535: cint: #2 [0] [49]
11-c65535: stre: [0, 7, 48, 8] [14]
48-c65535: +: [0, 22, 9] [11]
9-c65535: cint: #1 [0] [48]
8-c65535: stre: [0, 7, 22, 3] [11]
7-c65535: cint: #0 [0] [8, 11]
43-c65535: load: [0, 42, 20] [45]
5-c65535: cint: #511 [0] [14]
4-c65535: loops: [0] []
3-c65535: mem: [0] [47, 8, 22, 26, 36]
2-c65535: ctrl: entry [0] [38]
b2: 0 0 [38]
38-c65535: call: 1 0 [2, 36, 34] [46, 47]
47-c65535: ret: [38, 46, 3, 20, 20, 34, 39] [1]

File diff suppressed because one or more lines are too long

View file

@ -346,6 +346,7 @@ impl<'a> Formatter<'a> {
self.fmt(val, f) self.fmt(val, f)
} }
Expr::Return { val: None, .. } => f.write_str("return"), Expr::Return { val: None, .. } => f.write_str("return"),
Expr::Wildcard { .. } => f.write_str("_"),
Expr::Ident { pos, is_ct, .. } => { Expr::Ident { pos, is_ct, .. } => {
if is_ct { if is_ct {
f.write_str("$")?; f.write_str("$")?;

View file

@ -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},
@ -81,16 +81,27 @@ pub fn run_compiler(root_file: &str, options: Options, out: &mut Vec<u8>) -> std
} }
if options.fmt { if options.fmt {
if !parsed.errors.is_empty() {
*out = parsed.errors.into_bytes();
return Err(std::io::Error::other("parsing fialed"));
}
for parsed in parsed.ast { for parsed in parsed.ast {
format_ast(parsed)?; format_ast(parsed)?;
} }
} else if options.fmt_stdout { } else if options.fmt_stdout {
if !parsed.errors.is_empty() {
*out = parsed.errors.into_bytes();
return Err(std::io::Error::other("parsing fialed"));
}
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 +111,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();
} }
} }

View file

@ -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);
} }
} }

View file

@ -148,6 +148,7 @@ pub enum TokenKind {
RBrack = b']', RBrack = b']',
Xor = b'^', Xor = b'^',
Tick = b'`', Tick = b'`',
Under = b'_',
// Unused = a-z // Unused = a-z
LBrace = b'{', LBrace = b'{',
Bor = b'|', Bor = b'|',
@ -308,6 +309,7 @@ gen_token_kind! {
Null = b"null", Null = b"null",
Idk = b"idk", Idk = b"idk",
Die = b"die", Die = b"die",
Under = b"_",
#[punkt] #[punkt]
Ctor = ".{", Ctor = ".{",
Tupl = ".(", Tupl = ".(",

View file

@ -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);

View file

@ -392,6 +392,7 @@ impl<'a, 'b> Parser<'a, 'b> {
let (id, is_first) = self.resolve_ident(token); let (id, is_first) = self.resolve_ident(token);
E::Ident { pos, is_ct: token.kind == T::CtIdent, id, is_first } E::Ident { pos, is_ct: token.kind == T::CtIdent, id, is_first }
} }
T::Under => E::Wildcard { pos },
T::If => E::If { T::If => E::If {
pos, pos,
cond: self.ptr_expr()?, cond: self.ptr_expr()?,
@ -800,6 +801,9 @@ generate_expr! {
pos: Pos, pos: Pos,
val: Option<&'a Self>, val: Option<&'a Self>,
}, },
Wildcard {
pos: Pos,
},
/// note: ':unicode:' is any utf-8 character except ascii /// note: ':unicode:' is any utf-8 character except ascii
/// `'[a-zA-Z_:unicode:][a-zA-Z0-9_:unicode:]*'` /// `'[a-zA-Z_:unicode:][a-zA-Z0-9_:unicode:]*'`
Ident { Ident {
@ -1163,14 +1167,16 @@ fn report_to(file: &str, path: &str, pos: Pos, msg: &dyn fmt::Display, out: &mut
let line = &file[file[..pos as usize].rfind('\n').map_or(0, |i| i + 1) let line = &file[file[..pos as usize].rfind('\n').map_or(0, |i| i + 1)
..file[pos as usize..].find('\n').map_or(file.len(), |i| i + pos as usize)]; ..file[pos as usize..].find('\n').map_or(file.len(), |i| i + pos as usize)];
col += line.matches('\t').count() * 3; col += line.chars().take_while(|c| c.is_whitespace()).filter(|&c| c == '\t').count() * 3;
let mut has_non_whitespace = false;
for char in line.chars() { for char in line.chars() {
if char == '\t' { if char == '\t' && !has_non_whitespace {
_ = out.write_str(" "); _ = out.write_str(" ");
} else { } else {
_ = out.write_char(char); _ = out.write_char(char);
} }
has_non_whitespace |= !char.is_whitespace();
} }
_ = out.write_char('\n'); _ = out.write_char('\n');
for _ in 0..col - 1 { for _ in 0..col - 1 {

View file

@ -1,150 +1,2 @@
use {crate::reg::Reg, alloc::vec::Vec, core::ops::Range};
type Nid = u16;
pub trait Ctx {
fn uses_of(&self, nid: Nid) -> impl Iterator<Item = Nid>;
fn params_of(&self, nid: Nid) -> impl Iterator<Item = Nid>;
fn args_of(&self, nid: Nid) -> impl Iterator<Item = Nid>;
fn dom_of(&self, nid: Nid) -> Nid;
}
pub struct Env<'a, C: Ctx> {
ctx: &'a C,
func: &'a Func,
res: &'a mut Res,
}
impl<'a, C: Ctx> Env<'a, C> {
pub fn new(ctx: &'a C, func: &'a Func, res: &'a mut Res) -> Self {
Self { ctx, func, res }
}
pub fn run(&mut self) {
self.res.reg_to_node.clear();
self.res.reg_to_node.resize(self.func.instrs.len(), 0);
let mut bundle = Bundle::new(self.func.instrs.len());
for &inst in &self.func.instrs {
for uinst in self.ctx.uses_of(inst) {
let mut cursor = self.ctx.dom_of(uinst);
while cursor != self.ctx.dom_of(inst) {
let mut range = self.func.blocks
[self.func.id_to_block[cursor as usize] as usize]
.range
.clone();
range.start = range.start.max(inst as usize);
range.end = range.end.min(uinst as usize);
bundle.add(range);
cursor = self.ctx.dom_of(cursor);
}
}
match self.res.bundles.iter_mut().enumerate().find(|(_, b)| !b.overlaps(&bundle)) {
Some((i, other)) => {
other.merge(&bundle);
bundle.clear();
self.res.reg_to_node[inst as usize] = i as Reg;
}
None => {
self.res.reg_to_node[inst as usize] = self.res.bundles.len() as Reg;
self.res.bundles.push(bundle);
bundle = Bundle::new(self.func.instrs.len());
}
}
}
}
}
pub struct Res {
bundles: Vec<Bundle>,
pub reg_to_node: Vec<Reg>,
}
pub struct Bundle {
//unit_range: Range<usize>,
//set: BitSet,
taken: Vec<bool>,
}
impl Bundle {
fn new(size: usize) -> Self {
Self { taken: vec![false; size] }
}
fn add(&mut self, range: Range<usize>) {
self.taken[range].fill(true);
}
fn overlaps(&self, other: &Self) -> bool {
self.taken.iter().zip(other.taken.iter()).any(|(a, b)| a & b)
}
fn merge(&mut self, other: &Self) {
debug_assert!(!self.overlaps(other));
self.taken.iter_mut().zip(other.taken.iter()).for_each(|(a, b)| *a = *b);
}
fn clear(&mut self) {
self.taken.fill(false);
}
//fn overlaps(&self, other: &Self) -> bool {
// if self.unit_range.start >= other.unit_range.end
// || self.unit_range.end <= other.unit_range.start
// {
// return false;
// }
// let [mut a, mut b] = [self, other];
// if a.unit_range.start > b.unit_range.start {
// mem::swap(&mut a, &mut b);
// }
// let [mut tmp_a, mut tmp_b] = [0; 2];
// let [units_a, units_b] = [a.set.units(&mut tmp_a), b.set.units(&mut tmp_b)];
// let len = a.unit_range.len().min(b.unit_range.len());
// let [units_a, units_b] =
// [&units_a[b.unit_range.start - a.unit_range.start..][..len], &units_b[..len]];
// units_a.iter().zip(units_b).any(|(&a, &b)| a & b != 0)
//}
//fn merge(mut self, mut other: Self) -> Self {
// debug_assert!(!self.overlaps(&other));
// if self.unit_range.start > other.unit_range.start {
// mem::swap(&mut self, &mut other);
// }
// let final_range = self.unit_range.start..self.unit_range.end.max(other.unit_range.end);
// self.set.reserve(final_range.len());
// let mut tmp = 0;
// let other_units = other.set.units(&mut tmp);
// match self.set.units_mut() {
// Ok(units) => {
// units[other.unit_range.start - self.unit_range.start..]
// .iter_mut()
// .zip(other_units)
// .for_each(|(a, b)| *a |= b);
// }
// Err(view) => view.add_mask(tmp),
// }
// self
//}
}
pub struct Func {
pub blocks: Vec<Block>,
pub instrs: Vec<Nid>,
pub id_to_instr: Vec<Nid>,
pub id_to_block: Vec<Nid>,
}
pub struct Block {
pub range: Range<usize>,
pub start_id: Nid,
pub eld_id: Nid,
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,903 @@
use {
super::{HbvmBackend, Nid, Nodes},
crate::{
lexer::TokenKind,
parser,
reg::{self, Reg},
son::{debug_assert_matches, Kind, ARG_START, MEM, VOID},
ty::{self, Arg, Loc},
utils::{BitSet, Vc},
Offset, PLoc, Reloc, Sig, TypedReloc, Types,
},
alloc::{borrow::ToOwned, vec::Vec},
core::{mem, ops::Range},
hbbytecode::{self as instrs},
};
impl HbvmBackend {
pub fn emit_body_code_my(
&mut self,
nodes: &mut Nodes,
sig: Sig,
tys: &Types,
files: &[parser::Ast],
) -> (usize, bool) {
let mut fuc = Function::new(nodes, tys, sig);
log::info!("{fuc:?}");
let mut res = mem::take(&mut self.ralloc_my);
Env::new(&fuc, &fuc.func, &mut res).run();
'_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 reg_offset = if fuc.tail { reg::RET + 12 } else { reg::RET_ADDR + 1 };
res.node_to_reg.iter_mut().filter(|r| **r != 0).for_each(|r| {
*r += reg_offset - 1;
if fuc.tail && *r >= reg::RET_ADDR {
*r += 1;
}
});
let atr = |allc: Nid| res.node_to_reg[allc as usize];
//for (id, node) in fuc.nodes.iter() {
// if node.kind == Kind::Phi {
// debug_assert_eq!(atr(node.inputs[1]), atr(node.inputs[2]));
// debug_assert_eq!(atr(id), atr(node.inputs[2]));
// }
//}
let (retl, mut parama) = tys.parama(sig.ret);
let mut typs = sig.args.args();
let mut args = fuc.nodes[VOID].outputs[ARG_START..].iter();
while let Some(aty) = typs.next(tys) {
let Arg::Value(ty) = aty else { continue };
let Some(loc) = parama.next(ty, tys) else { continue };
let &arg = args.next().unwrap();
let (rg, size) = match loc {
PLoc::WideReg(rg, size) => (rg, size),
PLoc::Reg(rg, size) if ty.loc(tys) == Loc::Stack => (rg, size),
PLoc::Reg(r, ..) | PLoc::Ref(r, ..) => {
self.emit(instrs::cp(atr(arg), r));
continue;
}
};
self.emit(instrs::st(rg, reg::STACK_PTR, self.offsets[arg as usize] as _, size));
if fuc.nodes[arg].lock_rc == 0 {
self.emit(instrs::addi64(rg, reg::STACK_PTR, self.offsets[arg as usize] as _));
}
self.emit(instrs::cp(atr(arg), rg));
}
for (i, block) in fuc.func.blocks.iter().enumerate() {
self.offsets[block.entry as usize] = self.code.len() as _;
for &nid in &fuc.func.instrs[block.range.clone()] {
if nid == VOID {
continue;
}
let node = &fuc.nodes[nid];
let extend = |base: ty::Id, dest: ty::Id, from: Nid, to: Nid| {
let (bsize, dsize) = (tys.size_of(base), tys.size_of(dest));
debug_assert!(bsize <= 8, "{}", ty::Display::new(tys, files, base));
debug_assert!(dsize <= 8, "{}", ty::Display::new(tys, files, dest));
if bsize == dsize {
return Default::default();
}
match (base.is_signed(), dest.is_signed()) {
(true, true) => {
let op = [instrs::sxt8, instrs::sxt16, instrs::sxt32]
[bsize.ilog2() as usize];
op(atr(to), atr(from))
}
_ => {
let mask = (1u64 << (bsize * 8)) - 1;
instrs::andi(atr(to), atr(from), mask)
}
}
};
match node.kind {
Kind::If => {
let &[_, cnd] = node.inputs.as_slice() else { unreachable!() };
if let Kind::BinOp { op } = fuc.nodes[cnd].kind
&& let Some((op, swapped)) =
op.cond_op(fuc.nodes[fuc.nodes[cnd].inputs[1]].ty)
{
let &[_, lhs, rhs] = fuc.nodes[cnd].inputs.as_slice() else {
unreachable!()
};
self.emit(extend(fuc.nodes[lhs].ty, fuc.nodes[lhs].ty.extend(), 0, 0));
self.emit(extend(fuc.nodes[rhs].ty, fuc.nodes[rhs].ty.extend(), 1, 1));
let rel = Reloc::new(self.code.len(), 3, 2);
self.jump_relocs.push((node.outputs[!swapped as usize], rel));
self.emit(op(atr(lhs), atr(rhs), 0));
} else {
self.emit(extend(fuc.nodes[cnd].ty, fuc.nodes[cnd].ty.extend(), 0, 0));
let rel = Reloc::new(self.code.len(), 3, 2);
self.jump_relocs.push((node.outputs[0], rel));
self.emit(instrs::jne(atr(cnd), reg::ZERO, 0));
}
}
Kind::Loop | Kind::Region => {
if (mem::replace(&mut fuc.backrefs[nid as usize], u16::MAX) != u16::MAX)
^ (node.kind == Kind::Loop)
{
let index = (node.kind == Kind::Loop) as usize + 1;
for &out in node.outputs.iter() {
if fuc.nodes[out].is_data_phi()
&& atr(out) != atr(fuc.nodes[out].inputs[index])
{
self.emit(instrs::cp(
atr(out),
atr(fuc.nodes[out].inputs[index]),
));
}
}
let rel = Reloc::new(self.code.len(), 1, 4);
self.jump_relocs.push((nid, rel));
self.emit(instrs::jmp(0));
} else {
let index = (node.kind != Kind::Loop) as usize + 1;
for &out in node.outputs.iter() {
if fuc.nodes[out].is_data_phi()
&& atr(out) != atr(fuc.nodes[out].inputs[index])
{
self.emit(instrs::cp(
atr(out),
atr(fuc.nodes[out].inputs[index]),
));
}
}
}
}
Kind::Return => {
let &[_, mut ret, ..] = node.inputs.as_slice() else { unreachable!() };
match retl {
None => {}
Some(PLoc::Reg(r, _)) if sig.ret.loc(tys) == Loc::Reg => {
self.emit(instrs::cp(r, atr(ret)));
}
Some(PLoc::Reg(r, size)) | Some(PLoc::WideReg(r, size)) => {
ret = match fuc.nodes[ret].kind {
Kind::Load { .. } => fuc.nodes[ret].inputs[1],
_ => ret,
};
self.emit(instrs::ld(r, atr(ret), 0, size))
}
Some(PLoc::Ref(_, size)) => {
ret = match fuc.nodes[ret].kind {
Kind::Load { .. } => fuc.nodes[ret].inputs[1],
_ => ret,
};
let [src, dst] = [atr(ret), atr(MEM)];
if let Ok(size) = u16::try_from(size) {
self.emit(instrs::bmc(src, dst, size));
} else {
for _ in 0..size / u16::MAX as u32 {
self.emit(instrs::bmc(src, dst, u16::MAX));
self.emit(instrs::addi64(src, src, u16::MAX as _));
self.emit(instrs::addi64(dst, dst, u16::MAX as _));
}
self.emit(instrs::bmc(src, dst, size as u16));
self.emit(instrs::addi64(src, src, size.wrapping_neg() as _));
self.emit(instrs::addi64(dst, dst, size.wrapping_neg() as _));
}
}
}
if i != fuc.func.blocks.len() - 1 {
let rel = Reloc::new(self.code.len(), 1, 4);
self.ret_relocs.push(rel);
self.emit(instrs::jmp(0));
}
}
Kind::Die => self.emit(instrs::un()),
Kind::CInt { value } if node.ty.is_float() => {
self.emit(match node.ty {
ty::Id::F32 => instrs::li32(
atr(nid),
(f64::from_bits(value as _) as f32).to_bits(),
),
ty::Id::F64 => instrs::li64(atr(nid), value as _),
_ => unreachable!(),
});
}
Kind::CInt { value } => self.emit(match tys.size_of(node.ty) {
1 => instrs::li8(atr(nid), value as _),
2 => instrs::li16(atr(nid), value as _),
4 => instrs::li32(atr(nid), value as _),
_ => instrs::li64(atr(nid), value as _),
}),
Kind::UnOp { op } => {
let op = op
.unop(node.ty, fuc.nodes[node.inputs[1]].ty)
.expect("TODO: unary operator not supported");
self.emit(op(atr(nid), atr(node.inputs[1])));
}
Kind::BinOp { .. } if node.lock_rc != 0 => {}
Kind::BinOp { op } => {
let &[.., lhs, rhs] = node.inputs.as_slice() else { unreachable!() };
if let Kind::CInt { value } = fuc.nodes[rhs].kind
&& fuc.nodes[rhs].lock_rc != 0
&& let Some(op) = op.imm_binop(node.ty)
{
self.emit(op(atr(nid), atr(lhs), value as _));
} else if let Some(op) =
op.binop(node.ty).or(op.float_cmp(fuc.nodes[lhs].ty))
{
self.emit(op(atr(nid), atr(lhs), atr(rhs)));
} else if let Some(against) = op.cmp_against() {
let op_ty = fuc.nodes[lhs].ty;
self.emit(extend(fuc.nodes[lhs].ty, fuc.nodes[lhs].ty.extend(), 0, 0));
self.emit(extend(fuc.nodes[rhs].ty, fuc.nodes[rhs].ty.extend(), 1, 1));
if op_ty.is_float() && matches!(op, TokenKind::Le | TokenKind::Ge) {
let opop = match op {
TokenKind::Le => TokenKind::Gt,
TokenKind::Ge => TokenKind::Lt,
_ => unreachable!(),
};
let op_fn = opop.float_cmp(op_ty).unwrap();
self.emit(op_fn(atr(nid), atr(lhs), atr(rhs)));
self.emit(instrs::not(atr(nid), atr(nid)));
} else if op_ty.is_integer() {
let op_fn =
if op_ty.is_signed() { instrs::cmps } else { instrs::cmpu };
self.emit(op_fn(atr(nid), atr(lhs), atr(rhs)));
self.emit(instrs::cmpui(atr(nid), atr(nid), against));
if matches!(op, TokenKind::Eq | TokenKind::Lt | TokenKind::Gt) {
self.emit(instrs::not(atr(nid), atr(nid)));
}
} else {
todo!("unhandled operator: {op}");
}
} else {
todo!("unhandled operator: {op}");
}
}
Kind::Call { args, func } => {
let (ret, mut parama) = tys.parama(node.ty);
let mut args = args.args();
let mut allocs = node.inputs[1..].iter();
while let Some(arg) = args.next(tys) {
let Arg::Value(ty) = arg else { continue };
let Some(loc) = parama.next(ty, tys) else { continue };
let mut arg = *allocs.next().unwrap();
let (rg, size) = match loc {
PLoc::Reg(rg, size) if ty.loc(tys) == Loc::Stack => (rg, size),
PLoc::WideReg(rg, size) => (rg, size),
PLoc::Ref(r, ..) => {
arg = match fuc.nodes[arg].kind {
Kind::Load { .. } => fuc.nodes[arg].inputs[1],
_ => arg,
};
self.emit(instrs::cp(r, atr(arg)));
continue;
}
PLoc::Reg(r, ..) => {
self.emit(instrs::cp(r, atr(arg)));
continue;
}
};
arg = match fuc.nodes[arg].kind {
Kind::Load { .. } => fuc.nodes[arg].inputs[1],
_ => arg,
};
self.emit(instrs::ld(rg, atr(arg), 0, size));
}
debug_assert!(
!matches!(ret, Some(PLoc::Ref(..))) || allocs.next().is_some()
);
if func == ty::ECA {
self.emit(instrs::eca());
} else {
self.relocs.push(TypedReloc {
target: ty::Kind::Func(func).compress(),
reloc: Reloc::new(self.code.len(), 3, 4),
});
self.emit(instrs::jal(reg::RET_ADDR, reg::ZERO, 0));
}
match ret {
Some(PLoc::WideReg(r, size)) => {
debug_assert_eq!(
fuc.nodes[*node.inputs.last().unwrap()].kind,
Kind::Stck
);
let stck = self.offsets[*node.inputs.last().unwrap() as usize];
self.emit(instrs::st(r, reg::STACK_PTR, stck as _, size));
}
Some(PLoc::Reg(r, size)) if node.ty.loc(tys) == Loc::Stack => {
debug_assert_eq!(
fuc.nodes[*node.inputs.last().unwrap()].kind,
Kind::Stck
);
let stck = self.offsets[*node.inputs.last().unwrap() as usize];
self.emit(instrs::st(r, reg::STACK_PTR, stck as _, size));
}
Some(PLoc::Reg(r, ..)) => self.emit(instrs::cp(atr(nid), r)),
None | Some(PLoc::Ref(..)) => {}
}
}
Kind::Global { global } => {
let reloc = Reloc::new(self.code.len(), 3, 4);
self.relocs.push(TypedReloc {
target: ty::Kind::Global(global).compress(),
reloc,
});
self.emit(instrs::lra(atr(nid), 0, 0));
}
Kind::Stck => {
let base = reg::STACK_PTR;
let offset = self.offsets[nid as usize];
self.emit(instrs::addi64(atr(nid), base, offset as _));
}
Kind::Load => {
let mut region = node.inputs[1];
let mut offset = 0;
if fuc.nodes[region].kind == (Kind::BinOp { op: TokenKind::Add })
&& let Kind::CInt { value } =
fuc.nodes[fuc.nodes[region].inputs[2]].kind
{
region = fuc.nodes[region].inputs[1];
offset = value as Offset;
}
let size = tys.size_of(node.ty);
if node.ty.loc(tys) != Loc::Stack {
let (base, offset) = match fuc.nodes[region].kind {
Kind::Stck => {
(reg::STACK_PTR, self.offsets[region as usize] + offset)
}
_ => (atr(region), offset),
};
self.emit(instrs::ld(atr(nid), base, offset as _, size as _));
}
}
Kind::Stre if node.inputs[1] == VOID => {}
Kind::Stre => {
let mut region = node.inputs[2];
let mut offset = 0;
let size = u16::try_from(tys.size_of(node.ty)).expect("TODO");
if fuc.nodes[region].kind == (Kind::BinOp { op: TokenKind::Add })
&& let Kind::CInt { value } =
fuc.nodes[fuc.nodes[region].inputs[2]].kind
&& node.ty.loc(tys) == Loc::Reg
{
region = fuc.nodes[region].inputs[1];
offset = value as Offset;
}
let nd = &fuc.nodes[region];
let value = node.inputs[1];
let (base, offset, src) = match nd.kind {
Kind::Stck if node.ty.loc(tys) == Loc::Reg => {
(reg::STACK_PTR, self.offsets[region as usize] + offset, value)
}
_ => (atr(region), offset, match fuc.nodes[value].kind {
Kind::Load { .. } => fuc.nodes[value].inputs[1],
_ => value,
}),
};
match node.ty.loc(tys) {
Loc::Reg => self.emit(instrs::st(atr(src), base, offset as _, size)),
Loc::Stack => {
debug_assert_eq!(offset, 0);
self.emit(instrs::bmc(atr(src), base, size))
}
}
}
Kind::Mem => self.emit(instrs::cp(atr(MEM), reg::RET)),
Kind::Arg => {}
e @ (Kind::Start
| Kind::Entry
| Kind::End
| Kind::Loops
| Kind::Then
| Kind::Else
| Kind::Phi
| Kind::Assert { .. }) => unreachable!("{e:?}"),
}
}
}
self.ralloc_my = res;
let bundle_count = self.ralloc_my.bundles.len() + (reg_offset as usize);
(
if fuc.tail {
bundle_count.saturating_sub(reg::RET_ADDR as _)
} else {
assert!(bundle_count < reg::STACK_PTR as usize, "TODO: spill memory");
self.ralloc_my.bundles.len()
},
fuc.tail,
)
}
}
pub struct Function<'a> {
sig: Sig,
tail: bool,
backrefs: Vec<u16>,
nodes: &'a mut Nodes,
tys: &'a Types,
visited: BitSet,
func: Func,
}
impl Function<'_> {
fn vreg_count(&self) -> usize {
self.nodes.values.len()
}
fn uses_of(&self, nid: Nid, buf: &mut Vec<Nid>) {
if self.nodes[nid].kind.is_cfg() && !matches!(self.nodes[nid].kind, Kind::Call { .. }) {
return;
}
self.nodes[nid]
.outputs
.iter()
.filter(|&&n| self.nodes.is_data_dep(nid, n))
.collect_into(buf);
}
fn phi_inputs_of(&self, nid: Nid, buf: &mut Vec<Nid>) {
match self.nodes[nid].kind {
Kind::Region => {
for &inp in self.nodes[nid].outputs.as_slice() {
if self.nodes[inp].is_data_phi() {
buf.extend(&self.nodes[inp].inputs[1..]);
buf.push(inp);
}
}
}
Kind::Loop => {
for &inp in self.nodes[nid].outputs.as_slice() {
if self.nodes[inp].is_data_phi() {
buf.push(self.nodes[inp].inputs[1]);
buf.push(inp);
buf.push(self.nodes[inp].inputs[2]);
}
}
}
_ => {}
}
}
fn instr_of(&self, nid: Nid) -> Option<Nid> {
if self.nodes[nid].kind == Kind::Phi || self.nodes[nid].lock_rc != 0 {
return None;
}
debug_assert_ne!(self.backrefs[nid as usize], Nid::MAX, "{:?}", self.nodes[nid]);
Some(self.backrefs[nid as usize])
}
fn block_of(&self, nid: Nid) -> Nid {
debug_assert!(self.nodes[nid].kind.starts_basic_block());
self.backrefs[nid as usize]
}
fn idom_of(&self, mut nid: Nid) -> Nid {
while !self.nodes[nid].kind.starts_basic_block() {
nid = self.nodes.idom(nid);
}
nid
}
fn use_block(&self, inst: Nid, uinst: Nid) -> Nid {
let mut block = self.nodes.use_block(inst, uinst);
while !self.nodes[block].kind.starts_basic_block() {
block = self.nodes.idom(block);
}
block
}
}
impl core::fmt::Debug for Function<'_> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
for block in &self.func.blocks {
writeln!(f, "{:?}", self.nodes[block.entry].kind)?;
for &instr in &self.func.instrs[block.range.clone()] {
writeln!(f, "{:?}", self.nodes[instr].kind)?;
}
}
Ok(())
}
}
impl<'a> Function<'a> {
fn new(nodes: &'a mut Nodes, tys: &'a Types, sig: Sig) -> Self {
let mut s = Self {
backrefs: vec![u16::MAX; nodes.values.len()],
tail: true,
nodes,
tys,
sig,
visited: Default::default(),
func: Default::default(),
};
s.visited.clear(s.nodes.values.len());
s.emit_node(VOID);
s
}
fn add_block(&mut self, entry: Nid) {
self.func
.blocks
.push(Block { range: self.func.instrs.len()..self.func.instrs.len(), entry });
self.backrefs[entry as usize] = self.func.blocks.len() as u16 - 1;
}
fn close_block(&mut self, exit: Nid) {
if !matches!(self.nodes[exit].kind, Kind::Loop | Kind::Region) {
self.add_instr(exit);
} else {
self.func.instrs.push(exit);
}
let prev = self.func.blocks.last_mut().unwrap();
prev.range.end = self.func.instrs.len();
}
fn add_instr(&mut self, nid: Nid) {
debug_assert_ne!(self.nodes[nid].kind, Kind::Loop);
self.backrefs[nid as usize] = self.func.instrs.len() as u16;
self.func.instrs.push(nid);
}
fn emit_node(&mut self, nid: Nid) {
if matches!(self.nodes[nid].kind, Kind::Region | Kind::Loop) {
match (self.nodes[nid].kind, self.visited.set(nid)) {
(Kind::Loop, false) | (Kind::Region, true) => {
self.close_block(nid);
return;
}
_ => {}
}
} else if !self.visited.set(nid) {
return;
}
if self.nodes.is_never_used(nid, self.tys) {
self.nodes.lock(nid);
return;
}
let mut node = self.nodes[nid].clone();
match node.kind {
Kind::Start => {
debug_assert_matches!(self.nodes[node.outputs[0]].kind, Kind::Entry);
self.add_block(VOID);
self.emit_node(node.outputs[0])
}
Kind::If => {
let &[_, cond] = node.inputs.as_slice() else { unreachable!() };
let &[mut then, mut else_] = node.outputs.as_slice() else { unreachable!() };
if let Kind::BinOp { op } = self.nodes[cond].kind
&& let Some((_, swapped)) = op.cond_op(node.ty)
&& swapped
{
mem::swap(&mut then, &mut else_);
}
self.close_block(nid);
self.emit_node(then);
self.emit_node(else_);
}
Kind::Region | Kind::Loop => {
self.close_block(nid);
self.add_block(nid);
self.reschedule_block(nid, &mut node.outputs);
for o in node.outputs.into_iter().rev() {
self.emit_node(o);
}
}
Kind::Return | Kind::Die => {
self.close_block(nid);
self.emit_node(node.outputs[0]);
}
Kind::Entry => {
let (ret, mut parama) = self.tys.parama(self.sig.ret);
let mut typs = self.sig.args.args();
#[expect(clippy::unnecessary_to_owned)]
let mut args = self.nodes[VOID].outputs[ARG_START..].to_owned().into_iter();
while let Some(ty) = typs.next_value(self.tys) {
let arg = args.next().unwrap();
debug_assert_eq!(self.nodes[arg].kind, Kind::Arg);
match parama.next(ty, self.tys) {
None => {}
Some(_) => self.add_instr(arg),
}
}
if let Some(PLoc::Ref(..)) = ret {
self.add_instr(MEM);
}
self.reschedule_block(nid, &mut node.outputs);
for o in node.outputs.into_iter().rev() {
self.emit_node(o);
}
}
Kind::Then | Kind::Else => {
self.add_block(nid);
self.reschedule_block(nid, &mut node.outputs);
for o in node.outputs.into_iter().rev() {
self.emit_node(o);
}
}
Kind::Call { func, .. } => {
self.tail &= func == ty::ECA;
self.add_instr(nid);
self.reschedule_block(nid, &mut node.outputs);
for o in node.outputs.into_iter().rev() {
if self.nodes[o].inputs[0] == nid
|| (matches!(self.nodes[o].kind, Kind::Loop | Kind::Region)
&& self.nodes[o].inputs[1] == nid)
{
self.emit_node(o);
}
}
}
Kind::CInt { .. }
| Kind::BinOp { .. }
| Kind::UnOp { .. }
| Kind::Global { .. }
| Kind::Load { .. }
| Kind::Stre
| Kind::Stck => self.add_instr(nid),
Kind::End | Kind::Phi | Kind::Arg | Kind::Mem | Kind::Loops => {}
Kind::Assert { .. } => unreachable!(),
}
}
fn reschedule_block(&mut self, from: Nid, outputs: &mut Vc) {
let from = Some(&from);
let mut buf = Vec::with_capacity(outputs.len());
let mut seen = BitSet::default();
seen.clear(self.nodes.values.len());
for &o in outputs.iter() {
if !self.nodes.is_cfg(o) {
continue;
}
seen.set(o);
let mut cursor = buf.len();
buf.push(o);
while let Some(&n) = buf.get(cursor) {
for &i in &self.nodes[n].inputs[1..] {
if from == self.nodes[i].inputs.first()
&& self.nodes[i]
.outputs
.iter()
.all(|&o| self.nodes[o].inputs.first() != from || seen.get(o))
&& seen.set(i)
{
buf.push(i);
}
}
cursor += 1;
}
}
for &o in outputs.iter() {
if !seen.set(o) {
continue;
}
let mut cursor = buf.len();
buf.push(o);
while let Some(&n) = buf.get(cursor) {
for &i in &self.nodes[n].inputs[1..] {
if from == self.nodes[i].inputs.first()
&& self.nodes[i]
.outputs
.iter()
.all(|&o| self.nodes[o].inputs.first() != from || seen.get(o))
&& seen.set(i)
{
buf.push(i);
}
}
cursor += 1;
}
}
debug_assert!(
outputs.len() == buf.len() || outputs.len() == buf.len() + 1,
"{:?} {:?}",
outputs,
buf
);
if buf.len() + 1 == outputs.len() {
outputs.remove(outputs.len() - 1);
}
outputs.copy_from_slice(&buf);
}
}
pub struct Env<'a> {
ctx: &'a Function<'a>,
func: &'a Func,
res: &'a mut Res,
}
impl<'a> Env<'a> {
pub fn new(ctx: &'a Function<'a>, func: &'a Func, res: &'a mut Res) -> Self {
Self { ctx, func, res }
}
pub fn run(&mut self) {
self.res.bundles.clear();
self.res.node_to_reg.clear();
self.res.node_to_reg.resize(self.ctx.vreg_count(), 0);
debug_assert!(self.res.dfs_buf.is_empty());
debug_assert!(self.res.use_buf.is_empty());
debug_assert!(self.res.phi_input_buf.is_empty());
let mut bundle = Bundle::new(self.func.instrs.len());
let mut visited = BitSet::with_capacity(self.ctx.nodes.values.len());
let mut use_buf = mem::take(&mut self.res.use_buf);
let mut phi_input_buf = mem::take(&mut self.res.phi_input_buf);
for block in &self.func.blocks {
self.ctx.phi_inputs_of(block.entry, &mut phi_input_buf);
for param in phi_input_buf.drain(..) {
if !visited.set(param) {
continue;
}
self.append_bundle(param, &mut bundle, &mut use_buf);
}
}
self.res.phi_input_buf = phi_input_buf;
for &inst in &self.func.instrs {
if visited.get(inst) || inst == 0 {
continue;
}
self.append_bundle(inst, &mut bundle, &mut use_buf);
}
self.res.use_buf = use_buf;
}
fn append_bundle(&mut self, inst: Nid, bundle: &mut Bundle, use_buf: &mut Vec<Nid>) {
let mut dom = self.ctx.idom_of(inst);
if self.ctx.nodes[dom].kind == Kind::Loop && self.ctx.nodes[inst].kind == Kind::Phi {
dom = self.ctx.nodes.idom(dom);
dom = self.ctx.idom_of(dom);
}
self.ctx.uses_of(inst, use_buf);
for uinst in use_buf.drain(..) {
let cursor = self.ctx.use_block(inst, uinst);
self.reverse_cfg_dfs(cursor, dom, |_, n, b| {
let mut range = b.range.clone();
range.start =
range.start.max(self.ctx.instr_of(inst).map_or(0, |n| n + 1) as usize);
range.end = range.end.min(
self.ctx
.instr_of(uinst)
.filter(|_| self.ctx.nodes.loop_depth(dom) == self.ctx.nodes.loop_depth(n))
.map_or(Nid::MAX, |n| n + 1) as usize,
);
bundle.add(range);
});
}
match self.res.bundles.iter_mut().enumerate().find(|(_, b)| !b.overlaps(bundle)) {
Some((i, other)) => {
other.merge(bundle);
bundle.clear();
self.res.node_to_reg[inst as usize] = i as Reg + 1;
}
None => {
self.res.bundles.push(mem::replace(bundle, Bundle::new(self.func.instrs.len())));
self.res.node_to_reg[inst as usize] = self.res.bundles.len() as Reg;
}
}
}
fn reverse_cfg_dfs(
&mut self,
from: Nid,
until: Nid,
mut each: impl FnMut(&mut Self, Nid, &Block),
) {
debug_assert!(self.res.dfs_buf.is_empty());
self.res.dfs_buf.push(from);
self.res.dfs_seem.clear(self.ctx.nodes.values.len());
while let Some(nid) = self.res.dfs_buf.pop() {
each(self, nid, &self.func.blocks[self.ctx.block_of(nid) as usize]);
if nid == until {
continue;
}
match self.ctx.nodes[nid].kind {
Kind::Then | Kind::Else | Kind::Region | Kind::Loop => {
for &n in self.ctx.nodes[nid].inputs.iter() {
let d = self.ctx.idom_of(n);
if self.res.dfs_seem.set(d) {
self.res.dfs_buf.push(d);
}
}
}
Kind::Start => {}
_ => unreachable!(),
}
}
}
}
#[derive(Default)]
pub struct Res {
pub bundles: Vec<Bundle>,
pub node_to_reg: Vec<Reg>,
use_buf: Vec<Nid>,
phi_input_buf: Vec<Nid>,
dfs_buf: Vec<Nid>,
dfs_seem: BitSet,
}
pub struct Bundle {
taken: Vec<bool>,
}
impl Bundle {
fn new(size: usize) -> Self {
Self { taken: vec![false; size] }
}
fn add(&mut self, range: Range<usize>) {
self.taken[range].fill(true);
}
fn overlaps(&self, other: &Self) -> bool {
self.taken.iter().zip(other.taken.iter()).any(|(a, b)| a & b)
}
fn merge(&mut self, other: &Self) {
debug_assert!(!self.overlaps(other));
self.taken.iter_mut().zip(other.taken.iter()).for_each(|(a, b)| *a |= *b);
}
fn clear(&mut self) {
self.taken.fill(false);
}
}
#[derive(Default)]
pub struct Func {
pub blocks: Vec<Block>,
pub instrs: Vec<Nid>,
}
pub struct Block {
pub range: Range<usize>,
pub entry: Nid,
}

File diff suppressed because it is too large Load diff

View file

@ -62,6 +62,12 @@ impl BitSet {
const INLINE_ELEMS: usize = Self::UNIT - 1; const INLINE_ELEMS: usize = Self::UNIT - 1;
const UNIT: usize = core::mem::size_of::<usize>() * 8; const UNIT: usize = core::mem::size_of::<usize>() * 8;
pub fn with_capacity(len: usize) -> Self {
let mut s = Self::default();
s.reserve(len);
s
}
fn is_inline(&self) -> bool { fn is_inline(&self) -> bool {
unsafe { self.inline & Self::FLAG != 0 } unsafe { self.inline & Self::FLAG != 0 }
} }

View file

@ -0,0 +1,44 @@
main:
ADDI64 r254, r254, -24d
ST r31, r254, 0a, 24h
LI32 r32, 1148846080w
CP r2, r32
JAL r31, r0, :sin
FMUL32 r33, r1, r32
FTI32 r1, r33, 1b
LD r31, r254, 0a, 24h
ADDI64 r254, r254, 24d
JALA r0, r31, 0a
sin:
LI32 r4, 1124073472w
LI32 r5, 1078530011w
FMUL32 r7, r2, r4
FDIV32 r9, r7, r5
FTI32 r11, r9, 1b
ANDI r10, r11, 255d
ITF64 r5, r11
MULI64 r4, r10, 4d
LRA r3, r0, :SIN_TABLE
LI32 r7, 1086918619w
FC64T32 r9, r5, 1b
ADDI64 r5, r11, 64d
ADD64 r8, r3, r4
LI32 r1, 1132462080w
FMUL32 r6, r9, r7
ANDI r7, r5, 255d
LI32 r5, 1056964608w
LD r4, r8, 0a, 4h
FDIV32 r8, r6, r1
MULI64 r6, r7, 4d
FMUL32 r10, r4, r5
FSUB32 r11, r2, r8
ADD64 r9, r3, r6
FMUL32 r2, r11, r10
LD r12, r9, 0a, 4h
FSUB32 r5, r12, r2
FMUL32 r7, r5, r11
FADD32 r1, r4, r7
JALA r0, r31, 0a
code size: 1303
ret: 826
status: Ok(())

View file

@ -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

View file

@ -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(())

View file

@ -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

View file

@ -8,12 +8,13 @@ main:
LI64 r6, 6d LI64 r6, 6d
LI64 r5, 5d LI64 r5, 5d
LI64 r2, 1d LI64 r2, 1d
LD r3, r4, 0a, 16h CP r3, r4
LD r3, r3, 0a, 16h
ECA ECA
LI64 r1, 0d LI64 r1, 0d
ADDI64 r254, r254, 16d ADDI64 r254, r254, 16d
JALA r0, r31, 0a JALA r0, r31, 0a
ev: Ecall ev: Ecall
code size: 152 code size: 155
ret: 0 ret: 0
status: Ok(()) status: Ok(())

View file

@ -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

View file

@ -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(())

View file

@ -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(())

View file

@ -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(())

View file

@ -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
ST r36, r39, 16a, 8h
LI64 r1, 0d LI64 r1, 0d
CP r7, r38 CP r41, r40
JNE r7, r1, :3 JNE r41, r1, :3
JMP :4 JMP :4
3: CP r38, r7 3: CP r40, r41
LD r8, r39, 8a, 8h CP r42, r36
MULI64 r10, r8, 8d ST r38, r42, 16a, 8h
LD r3, r39, 0a, 8h LD r36, r42, 8a, 8h
ADD64 r7, r3, r10 MULI64 r43, r36, 8d
CP r5, r38 LD r44, r42, 0a, 8h
9: LD r2, r39, 0a, 8h ADD64 r45, r44, r43
LD r10, r39, 8a, 8h CP r46, r40
JNE r7, r3, :5 9: LD r2, r42, 0a, 8h
JEQ r10, r35, :6 LD r47, r42, 8a, 8h
CP r4, r37 JNE r45, r44, :5
MUL64 r3, r10, r4 JEQ r47, r37, :6
CP r4, r39
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, r42, 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 r41, r46, 8d
ADDI64 r9, r3, 8d ADDI64 r48, 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, r48
CP r5, r8 CP r46, r41
JMP :9 JMP :9
0: CP r39, r34 0: CP r42, r36
8: LD r5, r39, 8a, 8h 8: LD r50, r42, 8a, 8h
MULI64 r7, r5, 8d MULI64 r51, r50, 8d
LD r6, r39, 0a, 8h LD r52, r42, 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, r42, 8a, 8h
ADD64 r3, r2, r33 ADD64 r54, r53, r33
ST r3, r39, 8a, 8h ST r54, r42, 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

View file

@ -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

View file

@ -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(())

View file

@ -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
@ -24,17 +23,17 @@ scalar_values:
structs: structs:
ADDI64 r254, r254, -32d ADDI64 r254, r254, -32d
LI64 r1, 5d LI64 r1, 5d
ST r1, r254, 0a, 8h ST r1, r254, 16a, 8h
ST r1, r254, 8a, 8h ST r1, r254, 24a, 8h
LD r5, r254, 0a, 8h LD r5, r254, 16a, 8h
ADDI64 r7, r5, 15d ADDI64 r7, r5, 15d
ST r7, r254, 16a, 8h ST r7, r254, 0a, 8h
LI64 r10, 20d LI64 r10, 20d
ST r10, r254, 24a, 8h ST r10, r254, 8a, 8h
LD r1, r254, 16a, 8h LD r1, r254, 0a, 8h
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(())

View file

@ -0,0 +1,109 @@
main:
ADDI64 r254, r254, -106d
ST r31, r254, 58a, 48h
ADDI64 r32, r254, 33d
ADDI64 r2, r254, 34d
ADDI64 r6, r254, 1d
LI64 r33, 0d
ADDI64 r4, r254, 17d
ST r32, r254, 34a, 8h
LI64 r34, 100d
ADDI64 r7, r254, 0d
LI8 r35, 1b
ST r33, r254, 1a, 8h
ST r33, r254, 17a, 8h
ST r34, r254, 42a, 8h
LI8 r36, 0b
ST r35, r254, 0a, 1h
ST r33, r254, 9a, 8h
ST r33, r254, 25a, 8h
ST r34, r254, 50a, 8h
ST r36, r254, 33a, 1h
CP r3, r4
CP r5, r6
LD r3, r3, 0a, 16h
LD r5, r5, 0a, 16h
LD r7, r7, 0a, 1h
JAL r31, r0, :put_filled_rect
LD r31, r254, 58a, 48h
ADDI64 r254, r254, 106d
JALA r0, r31, 0a
put_filled_rect:
ADDI64 r254, r254, -212d
ST r32, r254, 108a, 104h
ST r3, r254, 92a, 16h
ADDI64 r3, r254, 92d
ST r5, r254, 76a, 16h
ADDI64 r5, r254, 76d
ST r7, r254, 75a, 1h
ADDI64 r7, r254, 75d
LI64 r8, 25d
LI64 r32, 2d
LI64 r6, 8d
ADDI64 r33, r254, 25d
ADDI64 r34, r254, 50d
LI8 r35, 5b
ST r35, r254, 25a, 1h
LD r36, r5, 0a, 8h
ST r36, r254, 26a, 4h
LI64 r37, 1d
ST r37, r254, 30a, 4h
ST r7, r254, 34a, 8h
ST r35, r254, 50a, 1h
ST r36, r254, 51a, 4h
ST r37, r254, 55a, 4h
ST r7, r254, 59a, 8h
CP r38, r7
LD r7, r3, 8a, 8h
LD r39, r5, 8a, 8h
ADD64 r11, r39, r7
SUB64 r4, r11, r37
LD r40, r2, 8a, 8h
MUL64 r5, r40, r4
LD r9, r2, 0a, 8h
ADD64 r10, r9, r5
LD r2, r3, 0a, 8h
ADD64 r41, r2, r10
MUL64 r3, r40, r7
ADD64 r4, r9, r3
ADD64 r42, r2, r4
3: JGTU r39, r37, :0
JNE r39, r37, :1
ADDI64 r4, r254, 0d
ST r35, r254, 0a, 1h
ST r36, r254, 1a, 4h
ST r37, r254, 5a, 4h
ST r38, r254, 9a, 8h
ST r42, r254, 17a, 8h
CP r2, r6
CP r3, r32
CP r5, r8
ECA
JMP :1
1: JMP :2
0: CP r3, r32
CP r43, r6
CP r44, r8
ST r42, r254, 67a, 8h
CP r2, r43
CP r4, r34
CP r5, r44
ECA
ST r41, r254, 42a, 8h
CP r2, r43
CP r3, r32
CP r4, r33
CP r5, r44
ECA
ADD64 r42, r40, r42
SUB64 r41, r41, r40
SUB64 r39, r39, r32
CP r6, r43
CP r8, r44
JMP :3
2: LD r32, r254, 108a, 104h
ADDI64 r254, r254, 212d
JALA r0, r31, 0a
code size: 917
ret: 0
status: Ok(())

View file

@ -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

View file

@ -0,0 +1,27 @@
main:
ADDI64 r254, r254, -32d
ST r31, r254, 0a, 32h
JAL r31, r0, :opaque
CP r32, r1
JAL r31, r0, :opaque
LI64 r33, 0d
CP r1, r32
JNE r1, r33, :0
CP r32, r1
LI64 r1, 0d
CP r34, r32
JMP :1
0: CP r34, r1
LD r1, r34, 0a, 8h
1: JEQ r34, r33, :2
LD r1, r34, 0a, 8h
JMP :2
2: LD r31, r254, 0a, 32h
ADDI64 r254, r254, 32d
JALA r0, r31, 0a
opaque:
LI64 r1, 0d
JALA r0, r31, 0a
code size: 183
ret: 0
status: Ok(())

View file

@ -0,0 +1,6 @@
test.hb:4:17: unwrap is not needed since the value is (provably) never null, remove it, or replace with '@as(<expr_ty>, <opt_expr>)'
ptr := @unwrap(always_nn)
^
test.hb:6:16: unwrap is incorrect since the value is (provably) always null, make sure your logic is correct
ptr = @unwrap(always_n)
^

View file

@ -1,6 +1,26 @@
test.hb:15:4: can't prove the value is not 'null', use '@unwrap(<opt>)' if you believe compiler is stupid, or explicitly check for null and handle it ('if <opt> == null { /* handle */ } else { /* use opt */ }') get_ptr:
*ptr += 1 ADDI64 r254, r254, -8d
^ ADDI64 r1, r254, 0d
test.hb:15:4: can't prove the value is not 'null', use '@unwrap(<opt>)' if you believe compiler is stupid, or explicitly check for null and handle it ('if <opt> == null { /* handle */ } else { /* use opt */ }') ADDI64 r254, r254, 8d
*ptr += 1 JALA r0, r31, 0a
^ main:
ADDI64 r254, r254, -40d
ST r31, r254, 0a, 40h
JAL r31, r0, :get_ptr
LI64 r32, 0d
JNE r1, r32, :0
LI64 r1, 0d
JMP :1
0: LI64 r33, 10d
CP r34, r1
2: LD r1, r34, 0a, 8h
JEQ r1, r33, :1
ADDI64 r35, r1, 1d
ST r35, r34, 0a, 8h
JMP :2
1: LD r31, r254, 0a, 40h
ADDI64 r254, r254, 40d
JALA r0, r31, 0a
code size: 208
ret: 10
status: Ok(())

View file

@ -0,0 +1,65 @@
main:
ADDI64 r254, r254, -122d
ST r31, r254, 26a, 96h
JAL r31, r0, :returner_fn
CP r32, r1
ADDI64 r1, r254, 2d
JAL r31, r0, :returner_bn
ADDI64 r33, r254, 0d
JAL r31, r0, :returner_cn
ST r1, r254, 0a, 2h
LI8 r34, 0b
LI8 r35, 0b
LD r36, r254, 2a, 1h
CP r1, r32
ANDI r37, r37, 255d
ANDI r1, r1, 255d
CMPU r37, r1, r34
CMPUI r37, r37, 0d
ANDI r38, r38, 255d
ANDI r36, r36, 255d
CMPU r38, r36, r35
CMPUI r38, r38, 0d
LD r39, r254, 0a, 1h
AND r40, r38, r37
ANDI r41, r41, 255d
ANDI r39, r39, 255d
CMPU r41, r39, r35
CMPUI r41, r41, 0d
AND r42, r41, r40
ANDI r42, r42, 255d
JNE r42, r0, :0
LI64 r1, 0d
JMP :1
0: LI64 r1, 1d
1: LD r31, r254, 26a, 96h
ADDI64 r254, r254, 122d
JALA r0, r31, 0a
returner_bn:
ADDI64 r254, r254, -24d
LI8 r6, 1b
ADDI64 r5, r254, 0d
ST r6, r254, 0a, 1h
LI64 r6, 0d
ST r6, r254, 8a, 8h
ST r6, r254, 16a, 8h
BMC r5, r1, 24h
ADDI64 r254, r254, 24d
JALA r0, r31, 0a
returner_cn:
ADDI64 r254, r254, -2d
LI8 r4, 1b
ADDI64 r3, r254, 0d
ST r4, r254, 0a, 1h
LI8 r4, 0b
ST r4, r254, 1a, 1h
LD r1, r3, 0a, 2h
ADDI64 r254, r254, 2d
JALA r0, r31, 0a
returner_fn:
LD r1, r254, 0a, 0h
ORI r1, r1, 128d
JALA r0, r31, 0a
code size: 546
ret: 1
status: Ok(())

View file

@ -2,86 +2,134 @@ 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 r32, r254, 72d ADDI64 r2, r254, 72d
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
LI8 r35, 1b
ANDI r1, r1, 255d ANDI r1, r1, 255d
JNE r1, r0, :4 JNE r1, r0, :4
ST r35, r254, 56a, 1h LI8 r36, 1b
LD r9, r33, 0a, 8h ST r36, r254, 56a, 1h
ST r9, r254, 64a, 8h LD r36, r34, 0a, 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 r36, r2 CP r39, r38
JMP :8 JMP :8
7: LI32 r36, 8388609w 7: LI32 r39, 2147483649w
8: ANDI r36, r36, 4294967295d 8: ANDI r39, r39, 4294967295d
ANDI r2, r2, 4294967295d ANDI r38, r38, 4294967295d
JNE r36, r2, :9 JNE r39, r38, :9
LI64 r1, 69d LI64 r1, 69d
JMP :3 JMP :3
9: JAL r31, r0, :decide 9: ADDI64 r3, r254, 40d
LI64 r3, 0d CP r40, r3
LI64 r37, 1d JAL r31, r0, :new_foo
ST r1, r254, 40a, 16h
LI64 r32, 0d
LD r41, r254, 40a, 8h
JNE r41, r32, :10
LI64 r1, 999d
JMP :3
10: LRA r4, r0, :"foo\0"
CP r3, r40
CP r2, r3
LD r2, r2, 0a, 16h
JAL r31, r0, :use_foo
ADDI64 r42, r254, 0d
JAL r31, r0, :no_foo
ST r1, r254, 0a, 16h
JAL r31, r0, :decide
ANDI r1, r1, 255d ANDI r1, r1, 255d
JNE r1, r0, :10 JNE r1, r0, :11
ST r3, r254, 16a, 8h CP r2, r33
JMP :11 JMP :12
10: ST r32, r254, 16a, 8h 11: CP r2, r33
ST r37, r254, 24a, 8h ST r2, r254, 0a, 8h
ST r37, r254, 72a, 8h LI64 r43, 1d
11: LD r2, r254, 16a, 8h ST r43, r254, 8a, 8h
JNE r2, r3, :12 ST r43, r254, 72a, 8h
12: LD r44, r254, 0a, 8h
JNE r44, r32, :13
LI64 r1, 34d LI64 r1, 34d
JMP :3 JMP :3
12: JAL r31, r0, :decide 13: ADDI64 r1, r254, 16d
ADDI64 r10, r254, 32d JAL r31, r0, :new_bar
JAL r31, r0, :decide
ANDI r1, r1, 255d ANDI r1, r1, 255d
JNE r1, r0, :13 JNE r1, r0, :14
ADDI64 r11, r254, 0d JMP :15
ST r32, r254, 0a, 8h 14: ST r35, r254, 16a, 1h
ST r37, r254, 8a, 8h 15: LD r45, r254, 16a, 1h
ST r35, r254, 32a, 1h ANDI r45, r45, 255d
ADDI64 r12, r10, 8d ANDI r35, r35, 255d
BMC r11, r12, 16h JEQ r45, r35, :16
JMP :14
13: ST r34, r254, 32a, 1h
14: LD r11, r254, 32a, 1h
ANDI r11, r11, 255d
ANDI r34, r34, 255d
JEQ r11, r34, :15
LI64 r1, 420d LI64 r1, 420d
JMP :3 JMP :3
15: LD r5, r254, 16a, 8h 16: LD r46, r254, 0a, 8h
LD r7, r5, 0a, 8h LD r47, r46, 0a, 8h
ANDI r9, r36, 65535d ANDI r48, r39, 65535d
SUB64 r1, r9, r7 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
code size: 729 new_bar:
ADDI64 r254, r254, -24d
LI8 r8, 1b
ADDI64 r7, r254, 0d
ST r8, r254, 0a, 1h
ST r2, r254, 8a, 8h
LI64 r9, 1d
ST r9, r254, 16a, 8h
BMC r7, r1, 24h
ADDI64 r254, r254, 24d
JALA r0, r31, 0a
new_foo:
ADDI64 r254, r254, -24d
ADDI64 r3, r254, 0d
ADDI64 r2, r254, 8d
ST r3, r254, 8a, 8h
LI64 r5, 0d
ST r5, r254, 16a, 8h
LD r1, r2, 0a, 16h
ADDI64 r254, r254, 24d
JALA r0, r31, 0a
no_foo:
ADDI64 r254, r254, -16d
ADDI64 r1, r254, 0d
LI64 r3, 0d
ST r3, r254, 0a, 8h
LD r1, r1, 0a, 16h
ADDI64 r254, r254, 16d
JALA r0, r31, 0a
use_foo:
ADDI64 r254, r254, -16d
ST r2, r254, 0a, 16h
ADDI64 r2, r254, 0d
ADDI64 r254, r254, 16d
JALA r0, r31, 0a
code size: 1143
ret: 0 ret: 0
status: Ok(()) status: Ok(())

View file

@ -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

View file

@ -0,0 +1,22 @@
main:
ADDI64 r254, r254, -16d
ADDI64 r3, r254, 0d
LI64 r6, 0d
CP r3, r6
CP r4, r6
CP r5, r6
ECA
ST r1, r254, 0a, 16h
LI8 r8, 0b
LD r9, r254, 0a, 1h
ANDI r9, r9, 255d
ANDI r8, r8, 255d
JNE r9, r8, :0
UN
0: LD r1, r254, 8a, 8h
ADDI64 r254, r254, 16d
JALA r0, r31, 0a
unknown ecall: 0
code size: 142
ret: 0
status: Err(Unreachable)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -1,3 +1,6 @@
test.hb:3:16: type 'int' cannot be uninitialized, use a zero value instead ('null' in case of pointers) main:
a := @as(int, idk) LI64 r1, 0d
^ JALA r0, r31, 0a
code size: 29
ret: 0
status: Ok(())

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,31 @@
get_format:
ADDI64 r254, r254, -16d
LI8 r5, 1b
ADDI64 r4, r254, 0d
LRA r3, r0, :BMP
ST r5, r254, 0a, 1h
LD r6, r3, 0a, 8h
ST r6, r254, 8a, 8h
LD r1, r4, 0a, 16h
ADDI64 r254, r254, 16d
JALA r0, r31, 0a
main:
ADDI64 r254, r254, -48d
ST r31, r254, 16a, 32h
ADDI64 r32, r254, 0d
JAL r31, r0, :get_format
ST r1, r254, 0a, 16h
LI8 r33, 0b
LD r34, r254, 0a, 1h
ANDI r34, r34, 255d
ANDI r33, r33, 255d
JNE r34, r33, :0
LI64 r1, 1d
JMP :1
0: LD r1, r254, 8a, 8h
1: LD r31, r254, 16a, 32h
ADDI64 r254, r254, 48d
JALA r0, r31, 0a
code size: 283
ret: 0
status: Ok(())

View file

@ -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

View file

@ -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(())

View file

@ -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

View file

@ -1,23 +1,24 @@
main: main:
ADDI64 r254, r254, -56d ADDI64 r254, r254, -72d
ST r31, r254, 32a, 24h ST r31, r254, 32a, 40h
LI64 r3, 4d LI64 r32, 4d
ADDI64 r2, r254, 16d ADDI64 r4, r254, 16d
ST r3, 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
LD r3, r2, 0a, 16h CP r3, r4
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
@ -29,6 +30,6 @@ odher_pass:
pass: pass:
LD r1, r2, 0a, 8h LD r1, r2, 0a, 8h
JALA r0, r31, 0a JALA r0, r31, 0a
code size: 305 code size: 308
ret: 4 ret: 4
status: Ok(()) status: Ok(())

View file

@ -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