Compare commits

...

106 commits

Author SHA1 Message Date
Jakub Doka 87cb77a553
making a Backend trait to separate the different backends we will have in the fucture 2024-11-05 14:52:30 +01:00
Jakub Doka 276d1bb0cf
fixing tab indentation in error messages and depell not displaying errors 2024-11-05 09:41:57 +01:00
Jakub Doka 5cce904135
fixing struct null check on function arguments 2024-11-04 19:57:15 +01:00
Jakub Doka 3338d50672
nasty bug with rescheduled load 2024-11-04 19:18:37 +01:00
Jakub Doka 2e36f32ae0
fixing very sneaky bug 2024-11-04 12:38:47 +01:00
Jakub Doka e8f1d2af8c
allowing 0 idk 2024-11-03 22:54:05 +01:00
Jakub Doka 999b25df8b
adding '_ = <expr>' syntax 2024-11-03 22:27:37 +01:00
Jakub Doka 61250c906a
comparison of non null types to null are now errors 2024-11-03 21:31:46 +01:00
Jakub Doka 44fc9c3e2e
deferring all null checks after the peepholes 2024-11-03 21:13:24 +01:00
Jakub Doka 798000c756
little correction 2024-11-03 10:23:17 +01:00
Jakub Doka 9de631234d
adding unreachable 2024-11-03 10:15:03 +01:00
Jakub Doka 843fbddf3b
loops in inlined functions now work better 2024-11-03 08:59:42 +01:00
Jakub Doka 38a00cbaa0
some start for homemade regalloc 2024-10-31 14:56:55 +01:00
Jakub Doka 4664240e08
eliminating even more todos 2024-10-31 11:10:05 +01:00
Jakub Doka 728d563cea
eliminating more todos 2024-10-31 11:03:58 +01:00
Jakub Doka 56984f08ff
eliminating more todos 2024-10-31 10:56:59 +01:00
Jakub Doka 3f9f99ff65
adding optional values 2024-10-31 10:36:18 +01:00
Jakub Doka 9ed3c7ab9e
saving 2024-10-30 20:20:03 +01:00
Jakub Doka acacd10ee9
microoptimizing bitset 2024-10-30 18:42:25 +01:00
Jakub Doka f6f661cee3
finally struct operators fold into constant 2024-10-30 14:10:46 +01:00
Jakub Doka 4bfb5f192e
fixing the matrix 2024-10-30 13:45:19 +01:00
Jakub Doka ea628c1278
saving 2024-10-29 20:38:33 +01:00
Jakub Doka 7448339605
removing return value temporary optimization sadly 2024-10-29 17:03:00 +01:00
Jakub Doka da7cd5926c
unifiing annoying clobber logic 2024-10-29 15:15:30 +01:00
Jakub Doka 9cf7933251
clobber global loads across functions 2024-10-29 15:04:07 +01:00
Jakub Doka 24b9f9e78b
adding floating point conversions 2024-10-29 14:24:31 +01:00
Jakub Doka 80558ea7e6
adding floating point arithmetic 2024-10-29 13:36:12 +01:00
Jakub Doka 348d9014e3
adding a lot better load elimination 2024-10-29 10:31:52 +01:00
Jakub Doka 30bd6103a6
cleaning up some code 2024-10-29 10:01:37 +01:00
Jakub Doka 97eb985a02
removing specific opts from a fucntion and adding them to the general peepholes 2024-10-29 09:04:49 +01:00
Jakub Doka 7ef1adf7e2
saving 2024-10-28 23:38:57 +01:00
Jakub Doka be828b8c54
properly handling cases when stack is referenced by dofferent part of the memory 2024-10-28 18:53:36 +01:00
Jakub Doka b4b3bae104
fixing storing struct pointer bug 2024-10-28 18:39:42 +01:00
Jakub Doka 33d78fbc52
missing scoping 2024-10-28 17:22:18 +01:00
Jakub Doka be2d38a6d2
making the aliasing analisys bit smarter 2024-10-28 17:19:41 +01:00
Jakub Doka bbd7e12af4
saving this to make sure 2024-10-28 16:18:53 +01:00
Jakub Doka 37db783699
making stack peeps compatible with parallel alias classes 2024-10-28 12:39:26 +01:00
Jakub Doka 948710dc27
fixing an infeence bug 2024-10-28 12:36:46 +01:00
Jakub Doka f0a588fcff
updating test 2024-10-28 11:04:47 +01:00
Jakub Doka 9c32f260a1
cleanup 2024-10-27 21:34:03 +01:00
Jakub Doka 047e1ed15c
adding null 2024-10-27 19:55:11 +01:00
Jakub Doka 2c2f0c048b
cleaning up tests 2024-10-27 19:13:25 +01:00
Jakub Doka 3c12c0e288
removing codegen test outputs 2024-10-27 19:08:22 +01:00
Jakub Doka ca8497550a
updating commandline help 2024-10-27 19:02:13 +01:00
Jakub Doka 849e842336
dont write to the file if the contents did not differ from formatted 2024-10-27 18:56:29 +01:00
Jakub Doka 5c82623db9
removing stuff 2024-10-27 18:37:18 +01:00
Jakub Doka e8a8fa3eb1
simplifiing upcasts, hwich conincidentally allowed more optimizations 2024-10-27 18:21:33 +01:00
Jakub Doka 5926f69e6c
fixing missing upcast 2024-10-27 18:04:50 +01:00
Jakub Doka 83d3fb4919
adding array reformatting rule 2024-10-27 16:07:46 +01:00
Jakub Doka b429534d23
moving hbvm related code into one file 2024-10-27 14:29:14 +01:00
Jakub Doka b187af64a8
removing old compiler 2024-10-27 13:57:00 +01:00
Jakub Doka ce7bb001da
handling infinite loops properly 2024-10-27 11:32:34 +01:00
Jakub Doka 9c90adbfe8
removing idk for scalar values (antipattern) 2024-10-27 00:02:59 +02:00
Jakub Doka db62434736
fixing infinite loop when fetching cycles 2024-10-26 23:24:45 +02:00
Jakub Doka 3d721812f0
adding better dead code elimination 2024-10-26 20:29:31 +02:00
Jakub Doka 5b23a0661b
fixing peep_iter related bugs 2024-10-26 15:18:00 +02:00
Jakub Doka 7c919cd453
fixing nonexistent identifier file mismatch 2024-10-26 14:06:08 +02:00
Jakub Doka bb61526d3e
eliminating more useless stack moves related to return values 2024-10-26 13:43:36 +02:00
Jakub Doka 45e1c6743a
eliminating more useless operations 2024-10-26 12:48:57 +02:00
Jakub Doka 39588579a8
using more typesafe locking 2024-10-26 12:09:53 +02:00
Jakub Doka 9095af6d84
appliing late peepholes 2024-10-26 10:45:50 +02:00
Jakub Doka b62413046d
cleanup 2024-10-26 10:25:42 +02:00
Jakub Doka af4d965b8c
fixed fmt error reporting 2024-10-26 09:53:14 +02:00
Jakub Doka 855da58e06
fixed a binor uga buga 2024-10-26 01:07:35 +02:00
Jakub Doka 2fc24f0f58
ups 2024-10-26 00:37:39 +02:00
Jakub Doka 8016b1fad5
adding rescheduling 2024-10-26 00:34:22 +02:00
Jakub Doka 46f9903562
adding error log when compiler crashes 2024-10-25 23:05:43 +02:00
Jakub Doka 517850f283
fixing undescriptive error or not enough arguments 2024-10-25 22:59:01 +02:00
Jakub Doka faa8dd2e6f
adding pointer checks on ecas 2024-10-25 16:33:56 +02:00
Jakub Doka d23d010917
fixing eror message 2024-10-25 16:08:20 +02:00
Jakub Doka b1da36ecde
fixing upcasting signed to unsigned 2024-10-25 15:45:00 +02:00
Jakub Doka e62aab9b4b
adding better binaro operator errors positions 2024-10-25 15:40:23 +02:00
Jakub Doka 423361a80e
forgottend typecheck on a struct 2024-10-25 15:31:49 +02:00
Jakub Doka 62a7c61cdc
properly selecting li instructions for integer sizes 2024-10-25 15:29:17 +02:00
Jakub Doka 2bab16d3ce
making never type cause less errors 2024-10-25 15:14:32 +02:00
Jakub Doka c88daa4800
adding better negative number inference 2024-10-25 15:07:39 +02:00
Jakub Doka 6988d8893f
changing uint to be the default 2024-10-25 14:51:33 +02:00
Jakub Doka 64e228450f
little cleanup and fixing error recovery 2024-10-25 11:29:54 +02:00
Jakub Doka 897e121eeb
fixing stack alloc overoptimization 2024-10-24 19:57:36 +02:00
Jakub Doka 648bd24d0d
forgot to mul by 8 2024-10-24 16:26:28 +02:00
Jakub Doka aefa7e6405
forgot 2024-10-24 15:49:41 +02:00
Jakub Doka 026f6141e6
forgot 2024-10-24 15:45:16 +02:00
Jakub Doka cb88edea1f
fixing overoptimization of load -> store 2024-10-24 15:39:38 +02:00
Jakub Doka 127e8dcb38
fixing @as misbehaving 2024-10-24 14:10:07 +02:00
Jakub Doka 9c43dafcf5
fixing @as misbehaving 2024-10-24 14:08:17 +02:00
Jakub Doka e65dbcfcbe
fixing bitcasts 2024-10-24 13:58:58 +02:00
Jakub Doka e0d4955bd5
fixing small struct return 2024-10-24 13:25:30 +02:00
Jakub Doka 78ebc3292c
removing useless clobbers 2024-10-24 12:28:18 +02:00
Jakub Doka 0c2db878f0
adding the stack optimizations 2024-10-24 10:21:10 +02:00
Jakub Doka cb9d7f7d1e
okay now it works 2024-10-24 09:43:07 +02:00
Jakub Doka 41b70bec43
should work better 2024-10-23 12:26:07 +02:00
Jakub Doka f013e90936
better somehow 2024-10-22 22:57:40 +02:00
Jakub Doka 6977cb218c
seems to be compiling 2024-10-22 16:54:32 +02:00
Jakub Doka 3f30735eaa
seems to be compiling 2024-10-22 16:53:48 +02:00
Jakub Doka 58f4837ae0
eliminating important todo 2024-10-22 16:03:23 +02:00
Jakub Doka b95bddac7b
ups 2024-10-22 12:57:49 +02:00
Jakub Doka 7d53706e71
adding --optimize flag to the compiler 2024-10-22 12:50:54 +02:00
Jakub Doka 4d699fcbf1
strinc operatos seem to work now 2024-10-22 12:40:41 +02:00
Jakub Doka 5aa6150c70
now the generic types work too 2024-10-22 10:17:16 +02:00
Jakub Doka b0a85f44c9
fixing some bugs and making the generic types work, well not quite 2024-10-22 10:08:50 +02:00
Jakub Doka 2aa5ba9abc
generic functions work now 2024-10-22 07:20:08 +02:00
Jakub Doka 35d34dca54
sweeping trought more tests 2024-10-21 19:57:55 +02:00
Jakub Doka bc817c4ea2
implementing directives 2024-10-21 18:57:23 +02:00
Jakub Doka 0298b32e38
sniping a peephole 2024-10-21 17:29:11 +02:00
Jakub Doka 73c9ccef6a
simplifing code patterns and sixing argument passing 2024-10-21 17:04:29 +02:00
Jakub Doka ad4aed9c98
fixing loop bugs and some optimization edgecases 2024-10-21 15:12:37 +02:00
112 changed files with 8291 additions and 7816 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

3
Cargo.lock generated
View file

@ -594,6 +594,9 @@ name = "hashbrown"
version = "0.15.0" version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb"
dependencies = [
"allocator-api2",
]
[[package]] [[package]]
name = "hashlink" name = "hashlink"

View file

@ -24,7 +24,7 @@ hbjit = { path = "jit" }
[profile.release] [profile.release]
lto = true lto = true
#debug = true #debug = true
#strip = true strip = true
codegen-units = 1 codegen-units = 1
panic = "abort" panic = "abort"
@ -32,7 +32,7 @@ panic = "abort"
rustflags = ["-Zfmt-debug=none", "-Zlocation-detail=none"] rustflags = ["-Zfmt-debug=none", "-Zlocation-detail=none"]
inherits = "release" inherits = "release"
opt-level = "z" opt-level = "z"
strip = true strip = "debuginfo"
lto = true lto = true
codegen-units = 1 codegen-units = 1
panic = "abort" panic = "abort"
@ -42,3 +42,9 @@ inherits = "dev"
opt-level = "z" opt-level = "z"
strip = "debuginfo" strip = "debuginfo"
panic = "abort" panic = "abort"
[profile.fuzz]
inherits = "dev"
debug = true
opt-level = 3
panic = "abort"

View file

@ -14,7 +14,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
} }
fn gen_instrs(generated: &mut String) -> Result<(), Box<dyn std::error::Error>> { fn gen_instrs(generated: &mut String) -> Result<(), Box<dyn std::error::Error>> {
writeln!(generated, "#![allow(dead_code)] #![allow(clippy::upper_case_acronyms)]")?; writeln!(generated, "#![expect(dead_code)]")?;
writeln!(generated, "use crate::*;")?; writeln!(generated, "use crate::*;")?;
'_opcode_structs: { '_opcode_structs: {

View file

@ -89,7 +89,6 @@ pub enum DisasmError<'a> {
InstructionOutOfBounds(&'a str), InstructionOutOfBounds(&'a str),
FmtFailed(core::fmt::Error), FmtFailed(core::fmt::Error),
HasOutOfBoundsJumps, HasOutOfBoundsJumps,
HasDirectInstructionCycles,
} }
#[cfg(feature = "disasm")] #[cfg(feature = "disasm")]
@ -113,9 +112,6 @@ impl core::fmt::Display for DisasmError<'_> {
"the code contained jumps that dont got neither to a \ "the code contained jumps that dont got neither to a \
valid symbol or local insturction" valid symbol or local insturction"
), ),
DisasmError::HasDirectInstructionCycles => {
writeln!(f, "found instruction that jumps to itself")
}
} }
} }
} }
@ -145,7 +141,6 @@ pub fn disasm<'a>(
let mut labels = BTreeMap::<u32, u32>::default(); let mut labels = BTreeMap::<u32, u32>::default();
let mut buf = Vec::<instrs::Oper>::new(); let mut buf = Vec::<instrs::Oper>::new();
let mut has_cycle = false;
let mut has_oob = false; let mut has_oob = false;
'_offset_pass: for (&off, &(name, len, kind)) in functions.iter() { '_offset_pass: for (&off, &(name, len, kind)) in functions.iter() {
@ -174,8 +169,6 @@ pub fn disasm<'a>(
_ => continue, _ => continue,
}; };
has_cycle |= rel == 0;
let global_offset: u32 = (offset + rel).try_into().unwrap(); let global_offset: u32 = (offset + rel).try_into().unwrap();
if functions.get(&global_offset).is_some() { if functions.get(&global_offset).is_some() {
continue; continue;
@ -287,9 +280,5 @@ pub fn disasm<'a>(
return Err(DisasmError::HasOutOfBoundsJumps); return Err(DisasmError::HasOutOfBoundsJumps);
} }
if has_cycle {
return Err(DisasmError::HasDirectInstructionCycles);
}
Ok(()) Ok(())
} }

View file

@ -665,7 +665,6 @@ mod db {
($vis:vis struct $name:ident { ($vis:vis struct $name:ident {
$($qname:ident: $code:expr,)* $($qname:ident: $code:expr,)*
}) => { }) => {
#[allow(dead_code)]
$vis struct $name<'a> { $vis struct $name<'a> {
$($vis $qname: rusqlite::Statement<'a>,)* $($vis $qname: rusqlite::Statement<'a>,)*
} }
@ -694,7 +693,7 @@ mod db {
fetch_deps: " fetch_deps: "
WITH RECURSIVE roots(name, author, code) AS ( WITH RECURSIVE roots(name, author, code) AS (
SELECT name, author, code FROM post WHERE name = ? AND author = ? SELECT name, author, code FROM post WHERE name = ? AND author = ?
UNION ALL UNION
SELECT post.name, post.author, post.code FROM SELECT post.name, post.author, post.code FROM
post JOIN import ON post.name = import.to_name post JOIN import ON post.name = import.to_name
AND post.author = import.to_author AND post.author = import.to_author

View file

@ -19,7 +19,7 @@ unsafe extern "C" fn fmt() {
let code = core::str::from_raw_parts(core::ptr::addr_of!(INPUT).cast(), INPUT_LEN); let code = core::str::from_raw_parts(core::ptr::addr_of!(INPUT).cast(), INPUT_LEN);
let arena = parser::Arena::with_capacity(code.len() * parser::SOURCE_TO_AST_FACTOR); let arena = parser::Arena::with_capacity(code.len() * parser::SOURCE_TO_AST_FACTOR);
let mut ctx = parser::ParserCtx::default(); let mut ctx = parser::Ctx::default();
let exprs = parser::Parser::parse(&mut ctx, code, "source.hb", &mut parser::no_loader, &arena); let exprs = parser::Parser::parse(&mut ctx, code, "source.hb", &mut parser::no_loader, &arena);
let mut f = wasm_rt::Write(&mut OUTPUT[..]); let mut f = wasm_rt::Write(&mut OUTPUT[..]);

View file

@ -4,7 +4,10 @@
use { use {
alloc::{string::String, vec::Vec}, alloc::{string::String, vec::Vec},
hblang::{codegen::Codegen, parser::FileId}, hblang::{
parser::FileId,
son::{hbvm::HbvmBackend, Codegen, CodegenCtx},
},
}; };
extern crate alloc; extern crate alloc;
@ -52,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::ParserCtx::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),
@ -66,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,
) )
}) })
@ -74,9 +78,15 @@ unsafe fn compile_and_run(mut fuel: usize) {
}; };
let mut ct = { let mut ct = {
let mut c = Codegen::default(); let mut backend = HbvmBackend::default();
c.files = files; 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()
}; };

View file

@ -104,7 +104,7 @@ pub struct ArenaAllocator<const SIZE: usize> {
} }
impl<const SIZE: usize> ArenaAllocator<SIZE> { impl<const SIZE: usize> ArenaAllocator<SIZE> {
#[allow(clippy::new_without_default)] #[expect(clippy::new_without_default)]
pub const fn new() -> Self { pub const fn new() -> Self {
ArenaAllocator { ArenaAllocator {
arena: UnsafeCell::new([0; SIZE]), arena: UnsafeCell::new([0; SIZE]),
@ -112,7 +112,7 @@ impl<const SIZE: usize> ArenaAllocator<SIZE> {
} }
} }
#[allow(clippy::missing_safety_doc)] #[expect(clippy::missing_safety_doc)]
pub unsafe fn reset(&self) { pub unsafe fn reset(&self) {
(*self.head.get()) = self.arena.get().cast::<u8>().add(SIZE); (*self.head.get()) = self.arena.get().cast::<u8>().add(SIZE);
} }

View file

@ -7,8 +7,12 @@ edition = "2021"
name = "hbc" name = "hbc"
path = "src/main.rs" path = "src/main.rs"
[[bin]]
name = "fuzz"
path = "src/fuzz_main.rs"
[dependencies] [dependencies]
hashbrown = { version = "0.15.0", default-features = false, features = ["raw-entry"] } hashbrown = { version = "0.15.0", default-features = false, features = ["raw-entry", "allocator-api2"] }
hbbytecode = { workspace = true, features = ["disasm"] } hbbytecode = { workspace = true, features = ["disasm"] }
hbvm = { workspace = true, features = ["nightly"] } hbvm = { workspace = true, features = ["nightly"] }
log = "0.4.22" log = "0.4.22"
@ -16,11 +20,9 @@ log = "0.4.22"
[dependencies.regalloc2] [dependencies.regalloc2]
git = "https://github.com/jakubDoka/regalloc2" git = "https://github.com/jakubDoka/regalloc2"
branch = "reuse-allocations" branch = "reuse-allocations"
optional = true default-features = false
features = ["trace-log"]
[features] [features]
default = ["std", "opts"] default = ["std", "regalloc2/trace-log"]
std = [] std = []
opts = ["regalloc2"]
no_log = ["log/max_level_off"] no_log = ["log/max_level_off"]

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
--fmt - format all source files --fmt - format all imported source files
--fmt-stdout - dont write the formatted file but print it --fmt-stdout - dont write the formatted file but print it
--dump-asm - output assembly instead of raw code, (the assembly is more for debugging the compiler) --dump-asm - output assembly instead of raw code, (the assembly is more for debugging the compiler)
--threads <1...> - number of threads compiler can use [default: 1] --threads <1...> - number of extra threads compiler can use [default: 0]

File diff suppressed because it is too large Load diff

View file

@ -1,10 +1,9 @@
use { use {
crate::{ crate::{
ident,
lexer::{self, Lexer, TokenKind}, lexer::{self, Lexer, TokenKind},
parser::{self, CommentOr, CtorField, Expr, Poser, Radix, StructField}, parser::{self, CommentOr, CtorField, Expr, Poser, Radix, StructField},
}, },
core::fmt, core::fmt::{self},
}; };
pub fn display_radix(radix: Radix, mut value: u64, buf: &mut [u8; 64]) -> &str { pub fn display_radix(radix: Radix, mut value: u64, buf: &mut [u8; 64]) -> &str {
@ -256,7 +255,7 @@ impl<'a> Formatter<'a> {
fields, fields,
|s: &mut Self, CtorField { name, value, .. }: &_, f| { |s: &mut Self, CtorField { name, value, .. }: &_, f| {
f.write_str(name)?; f.write_str(name)?;
if !matches!(value, &Expr::Ident { id, .. } if *name == &self.source[ident::range(id)]) { if !matches!(value, &Expr::Ident { id, .. } if *name == &self.source[id.range()]) {
f.write_str(": ")?; f.write_str(": ")?;
s.fmt(value, f)?; s.fmt(value, f)?;
} }
@ -264,6 +263,20 @@ impl<'a> Formatter<'a> {
}, },
) )
} }
Expr::Tupl {
pos,
ty: Some(&Expr::Slice { pos: spos, size: Some(&Expr::Number { value, .. }), item }),
fields,
trailing_comma,
} if value as usize == fields.len() => self.fmt(
&Expr::Tupl {
pos,
ty: Some(&Expr::Slice { pos: spos, size: None, item }),
fields,
trailing_comma,
},
f,
),
Expr::Tupl { ty, fields, trailing_comma, .. } => { Expr::Tupl { ty, fields, trailing_comma, .. } => {
if let Some(ty) = ty { if let Some(ty) = ty {
self.fmt_paren(ty, f, unary)?; self.fmt_paren(ty, f, unary)?;
@ -333,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("$")?;
@ -353,12 +367,18 @@ impl<'a> Formatter<'a> {
let mut buf = [0u8; 64]; let mut buf = [0u8; 64];
f.write_str(display_radix(radix, value as u64, &mut buf)) f.write_str(display_radix(radix, value as u64, &mut buf))
} }
Expr::Float { pos, .. } => {
f.write_str(&self.source[Lexer::restore(self.source, pos).eat().range()])
}
Expr::Bool { value, .. } => f.write_str(if value { "true" } else { "false" }), Expr::Bool { value, .. } => f.write_str(if value { "true" } else { "false" }),
Expr::Idk { .. } => f.write_str("idk"), Expr::Idk { .. } => f.write_str("idk"),
Expr::Die { .. } => f.write_str("die"),
Expr::Null { .. } => f.write_str("null"),
Expr::BinOp { Expr::BinOp {
left, left,
op: TokenKind::Assign, op: TokenKind::Assign,
right: &Expr::BinOp { left: lleft, op, right }, right: &Expr::BinOp { left: lleft, op, right, .. },
..
} if left.pos() == lleft.pos() => { } if left.pos() == lleft.pos() => {
self.fmt(left, f)?; self.fmt(left, f)?;
f.write_str(" ")?; f.write_str(" ")?;
@ -366,7 +386,7 @@ impl<'a> Formatter<'a> {
f.write_str("= ")?; f.write_str("= ")?;
self.fmt(right, f) self.fmt(right, f)
} }
Expr::BinOp { right, op, left } => { Expr::BinOp { right, op, left, .. } => {
let prec_miss_left = |e: &Expr| { let prec_miss_left = |e: &Expr| {
matches!( matches!(
e, Expr::BinOp { op: lop, .. } if op.precedence() > lop.precedence() e, Expr::BinOp { op: lop, .. } if op.precedence() > lop.precedence()
@ -450,7 +470,7 @@ pub fn fmt_file(exprs: &[Expr], file: &str, f: &mut impl fmt::Write) -> fmt::Res
#[cfg(test)] #[cfg(test)]
pub mod test { pub mod test {
use { use {
crate::parser::{self, ParserCtx}, crate::parser::{self, Ctx},
alloc::borrow::ToOwned, alloc::borrow::ToOwned,
std::{fmt::Write, string::String}, std::{fmt::Write, string::String},
}; };
@ -460,8 +480,8 @@ pub mod test {
let len = crate::fmt::minify(&mut minned); let len = crate::fmt::minify(&mut minned);
minned.truncate(len); minned.truncate(len);
let ast = let mut ctx = Ctx::default();
parser::Ast::new(ident, minned, &mut ParserCtx::default(), &mut parser::no_loader); let ast = parser::Ast::new(ident, minned, &mut ctx, &mut parser::no_loader);
//log::error!( //log::error!(
// "{} / {} = {} | {} / {} = {}", // "{} / {} = {} | {} / {} = {}",
// ast.mem.size(), // ast.mem.size(),

View file

@ -1,10 +1,10 @@
use { use {
crate::{ crate::{
codegen, parser::{self, Ast, Ctx, FileKind},
parser::{self, Ast, FileKind, ParserCtx}, son::{self, hbvm::HbvmBackend},
}, },
alloc::{string::String, vec::Vec}, alloc::{string::String, vec::Vec},
core::{fmt::Write, num::NonZeroUsize}, core::{fmt::Write, num::NonZeroUsize, ops::Deref},
hashbrown::hash_map, hashbrown::hash_map,
std::{ std::{
collections::VecDeque, collections::VecDeque,
@ -74,7 +74,9 @@ pub fn run_compiler(root_file: &str, options: Options, out: &mut Vec<u8>) -> std
fn format_ast(ast: parser::Ast) -> std::io::Result<()> { fn format_ast(ast: parser::Ast) -> std::io::Result<()> {
let mut output = String::new(); let mut output = String::new();
write!(output, "{ast}").unwrap(); write!(output, "{ast}").unwrap();
std::fs::write(&*ast.path, output)?; if ast.file.deref().trim() != output.as_str().trim() {
std::fs::write(&*ast.path, output)?;
}
Ok(()) Ok(())
} }
@ -86,17 +88,25 @@ pub fn run_compiler(root_file: &str, options: Options, out: &mut Vec<u8>) -> std
let ast = parsed.ast.into_iter().next().unwrap(); let ast = parsed.ast.into_iter().next().unwrap();
write!(out, "{ast}").unwrap(); write!(out, "{ast}").unwrap();
} else { } else {
let mut codegen = codegen::Codegen::default(); let mut backend = HbvmBackend::default();
codegen.files = parsed.ast; let mut ctx = crate::son::CodegenCtx::default();
codegen.push_embeds(parsed.embeds); *ctx.parser.errors.get_mut() = parsed.errors;
let mut codegen = son::Codegen::new(&mut backend, &parsed.ast, &mut ctx);
codegen.push_embeds(parsed.embeds);
codegen.generate(0); codegen.generate(0);
if !codegen.errors.borrow().is_empty() {
log::error!("{}", codegen.errors.borrow());
return Err(std::io::Error::other("compilation faoled"));
}
codegen.assemble(out);
if options.dump_asm { if options.dump_asm {
codegen let mut disasm = String::new();
.disasm(unsafe { std::mem::transmute::<&mut Vec<u8>, &mut String>(out) }) codegen.disasm(&mut disasm, out).map_err(|e| io::Error::other(e.to_string()))?;
.map_err(|e| io::Error::other(e.to_string()))?; *out = disasm.into_bytes();
} else {
codegen.assemble(out);
} }
} }
@ -191,6 +201,7 @@ impl<T> TaskQueueInner<T> {
pub struct Loaded { pub struct Loaded {
ast: Vec<Ast>, ast: Vec<Ast>,
embeds: Vec<Vec<u8>>, embeds: Vec<Vec<u8>>,
errors: String,
} }
pub fn parse_from_fs(extra_threads: usize, root: &str) -> io::Result<Loaded> { pub fn parse_from_fs(extra_threads: usize, root: &str) -> io::Result<Loaded> {
@ -312,7 +323,7 @@ pub fn parse_from_fs(extra_threads: usize, root: &str) -> io::Result<Loaded> {
}; };
let thread = || { let thread = || {
let mut ctx = ParserCtx::default(); let mut ctx = Ctx::default();
let mut tmp = PathBuf::new(); let mut tmp = PathBuf::new();
while let Some(task @ (indx, ..)) = tasks.pop() { while let Some(task @ (indx, ..)) = tasks.pop() {
let res = execute_task(&mut ctx, task, &mut tmp); let res = execute_task(&mut ctx, task, &mut tmp);
@ -321,6 +332,7 @@ pub fn parse_from_fs(extra_threads: usize, root: &str) -> io::Result<Loaded> {
ast.resize_with(len, || Err(io::ErrorKind::InvalidData.into())); ast.resize_with(len, || Err(io::ErrorKind::InvalidData.into()));
ast[indx as usize] = res; ast[indx as usize] = res;
} }
ctx.errors.into_inner()
}; };
let path = Path::new(root).canonicalize().map_err(|e| { let path = Path::new(root).canonicalize().map_err(|e| {
@ -329,15 +341,23 @@ pub fn parse_from_fs(extra_threads: usize, root: &str) -> io::Result<Loaded> {
seen_modules.lock().unwrap().insert(path.clone(), 0); seen_modules.lock().unwrap().insert(path.clone(), 0);
tasks.push((0, path)); tasks.push((0, path));
if extra_threads == 0 { let errors = if extra_threads == 0 {
thread(); thread()
} else { } else {
std::thread::scope(|s| (0..extra_threads + 1).for_each(|_| _ = s.spawn(thread))); std::thread::scope(|s| {
} (0..extra_threads + 1)
.map(|_| s.spawn(thread))
.collect::<Vec<_>>()
.into_iter()
.map(|t| t.join().unwrap())
.collect::<String>()
})
};
Ok(Loaded { Ok(Loaded {
ast: ast.into_inner().unwrap().into_iter().collect::<io::Result<Vec<_>>>()?, ast: ast.into_inner().unwrap().into_iter().collect::<io::Result<Vec<_>>>()?,
embeds: embeds.into_inner().unwrap(), embeds: embeds.into_inner().unwrap(),
errors,
}) })
} }

140
lang/src/fuzz.rs Normal file
View file

@ -0,0 +1,140 @@
use {
crate::{
lexer::TokenKind,
parser,
son::{hbvm::HbvmBackend, Codegen, CodegenCtx},
},
alloc::string::String,
core::{fmt::Write, hash::BuildHasher, ops::Range},
};
#[derive(Default)]
struct Rand(pub u64);
impl Rand {
pub fn next(&mut self) -> u64 {
self.0 = crate::FnvBuildHasher::default().hash_one(self.0);
self.0
}
pub fn range(&mut self, min: u64, max: u64) -> u64 {
self.next() % (max - min) + min
}
fn bool(&mut self) -> bool {
self.next() % 2 == 0
}
}
#[derive(Default)]
struct FuncGen {
rand: Rand,
buf: String,
vars: u64,
}
impl FuncGen {
fn gen(&mut self, seed: u64) -> &str {
self.rand = Rand(seed);
self.buf.clear();
self.buf.push_str("main := fn(): void ");
self.block().unwrap();
&self.buf
}
fn block(&mut self) -> core::fmt::Result {
let prev_vars = self.vars;
self.buf.push('{');
for _ in 0..self.rand.range(1, 10) {
self.stmt()?;
}
self.buf.push('}');
self.vars = prev_vars;
Ok(())
}
fn stmt(&mut self) -> core::fmt::Result {
match self.rand.range(0, 100) {
0..4 => _ = self.block(),
4..10 => {
write!(self.buf, "var{} := ", self.vars)?;
self.expr()?;
self.vars += 1;
}
10..20 if self.vars != 0 => {
write!(self.buf, "var{} = ", self.rand.range(0, self.vars))?;
self.expr()?;
}
20..23 => {
self.buf.push_str("if ");
self.expr()?;
self.block()?;
if self.rand.bool() {
self.buf.push_str(" else ");
self.block()?;
}
}
_ => {
self.buf.push_str("return ");
self.expr()?;
}
}
self.buf.push(';');
Ok(())
}
fn expr(&mut self) -> core::fmt::Result {
match self.rand.range(0, 100) {
0..80 => {
write!(self.buf, "{}", self.rand.next())
}
80..90 if self.vars != 0 => {
write!(self.buf, "var{}", self.rand.range(0, self.vars))
}
80..100 => {
self.expr()?;
let ops = [
TokenKind::Add,
TokenKind::Sub,
TokenKind::Mul,
TokenKind::Div,
TokenKind::Shl,
TokenKind::Eq,
TokenKind::Ne,
TokenKind::Lt,
TokenKind::Gt,
TokenKind::Le,
TokenKind::Ge,
TokenKind::Band,
TokenKind::Bor,
TokenKind::Xor,
TokenKind::Mod,
TokenKind::Shr,
];
let op = ops[self.rand.range(0, ops.len() as u64) as usize];
write!(self.buf, " {op} ")?;
self.expr()
}
_ => unreachable!(),
}
}
}
pub fn fuzz(seed_range: Range<u64>) {
let mut gen = FuncGen::default();
let mut ctx = CodegenCtx::default();
for i in seed_range {
ctx.clear();
let src = gen.gen(i);
let parsed = parser::Ast::new("fuzz", src, &mut ctx.parser, &mut parser::no_loader);
assert!(ctx.parser.errors.get_mut().is_empty());
let mut backend = HbvmBackend::default();
let mut cdg = Codegen::new(&mut backend, core::slice::from_ref(&parsed), &mut ctx);
cdg.generate(0);
}
}

3
lang/src/fuzz_main.rs Normal file
View file

@ -0,0 +1,3 @@
fn main() {
hblang::fuzz::fuzz(0..1000000);
}

View file

@ -1,5 +1,3 @@
use crate::EncodedInstr;
const fn ascii_mask(chars: &[u8]) -> u128 { const fn ascii_mask(chars: &[u8]) -> u128 {
let mut eq = 0; let mut eq = 0;
let mut i = 0; let mut i = 0;
@ -51,6 +49,8 @@ macro_rules! gen_token_kind {
} }
impl $name { impl $name {
pub const OPS: &[Self] = &[$($(Self::$op),*),*];
pub fn name(&self) -> &str { pub fn name(&self) -> &str {
let sf = unsafe { &*(self as *const _ as *const u8) } ; let sf = unsafe { &*(self as *const _ as *const u8) } ;
match *self { match *self {
@ -116,6 +116,7 @@ pub enum TokenKind {
Ident, Ident,
Number, Number,
Float,
Eof, Eof,
Ct, Ct,
@ -131,7 +132,9 @@ pub enum TokenKind {
Packed, Packed,
True, True,
False, False,
Null,
Idk, Idk,
Die,
Ctor, Ctor,
Tupl, Tupl,
@ -145,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'|',
@ -176,87 +180,6 @@ impl core::fmt::Debug for TokenKind {
} }
impl TokenKind { impl TokenKind {
#[allow(clippy::type_complexity)]
pub fn cond_op(self, signed: bool) -> Option<(fn(u8, u8, i16) -> EncodedInstr, bool)> {
use crate::instrs;
Some((
match self {
Self::Le if signed => instrs::jgts,
Self::Le => instrs::jgtu,
Self::Lt if signed => instrs::jlts,
Self::Lt => instrs::jltu,
Self::Ge if signed => instrs::jlts,
Self::Ge => instrs::jltu,
Self::Gt if signed => instrs::jgts,
Self::Gt => instrs::jgtu,
Self::Eq => instrs::jne,
Self::Ne => instrs::jeq,
_ => return None,
},
matches!(self, Self::Lt | TokenKind::Gt),
))
}
pub fn binop(self, signed: bool, size: u32) -> Option<fn(u8, u8, u8) -> EncodedInstr> {
use crate::instrs::*;
macro_rules! div { ($($op:ident),*) => {[$(|a, b, c| $op(a, 0, b, c)),*]}; }
macro_rules! rem { ($($op:ident),*) => {[$(|a, b, c| $op(0, a, b, c)),*]}; }
let ops = match self {
Self::Add => [add8, add16, add32, add64],
Self::Sub => [sub8, sub16, sub32, sub64],
Self::Mul => [mul8, mul16, mul32, mul64],
Self::Div if signed => div!(dirs8, dirs16, dirs32, dirs64),
Self::Div => div!(diru8, diru16, diru32, diru64),
Self::Mod if signed => rem!(dirs8, dirs16, dirs32, dirs64),
Self::Mod => rem!(diru8, diru16, diru32, diru64),
Self::Band => return Some(and),
Self::Bor => return Some(or),
Self::Xor => return Some(xor),
Self::Shl => [slu8, slu16, slu32, slu64],
Self::Shr if signed => [srs8, srs16, srs32, srs64],
Self::Shr => [sru8, sru16, sru32, sru64],
_ => return None,
};
Some(ops[size.ilog2() as usize])
}
#[allow(clippy::type_complexity)]
pub fn imm_binop(self, signed: bool, size: u32) -> Option<fn(u8, u8, u64) -> EncodedInstr> {
use crate::instrs::*;
macro_rules! def_op {
($name:ident |$a:ident, $b:ident, $c:ident| $($tt:tt)*) => {
macro_rules! $name {
($$($$op:ident),*) => {
[$$(
|$a, $b, $c: u64| $$op($($tt)*),
)*]
}
}
};
}
def_op!(basic_op | a, b, c | a, b, c as _);
def_op!(sub_op | a, b, c | a, b, c.wrapping_neg() as _);
let ops = match self {
Self::Add => basic_op!(addi8, addi16, addi32, addi64),
Self::Sub => sub_op!(addi8, addi16, addi32, addi64),
Self::Mul => basic_op!(muli8, muli16, muli32, muli64),
Self::Band => return Some(andi),
Self::Bor => return Some(ori),
Self::Xor => return Some(xori),
Self::Shr if signed => basic_op!(srui8, srui16, srui32, srui64),
Self::Shr => basic_op!(srui8, srui16, srui32, srui64),
Self::Shl => basic_op!(slui8, slui16, slui32, slui64),
_ => return None,
};
Some(ops[size.ilog2() as usize])
}
pub fn ass_op(self) -> Option<Self> { pub fn ass_op(self) -> Option<Self> {
let id = (self as u8).saturating_sub(128); let id = (self as u8).saturating_sub(128);
if ascii_mask(b"|+-*/%^&79") & (1u128 << id) == 0 { if ascii_mask(b"|+-*/%^&79") & (1u128 << id) == 0 {
@ -270,17 +193,62 @@ impl TokenKind {
matches!(self, S::Eq | S::Ne | S::Bor | S::Xor | S::Band | S::Add | S::Mul) matches!(self, S::Eq | S::Ne | S::Bor | S::Xor | S::Band | S::Add | S::Mul)
} }
pub fn apply_binop(self, a: i64, b: i64) -> i64 { pub fn is_supported_float_op(self) -> bool {
matches!(
self,
Self::Add
| Self::Sub
| Self::Mul
| Self::Div
| Self::Eq
| Self::Ne
| Self::Le
| Self::Ge
| Self::Lt
| Self::Gt
)
}
pub fn apply_binop(self, a: i64, b: i64, float: bool) -> i64 {
if float {
debug_assert!(self.is_supported_float_op());
let [a, b] = [f64::from_bits(a as _), f64::from_bits(b as _)];
let res = match self {
Self::Add => a + b,
Self::Sub => a - b,
Self::Mul => a * b,
Self::Div => a / b,
Self::Eq => return (a == b) as i64,
Self::Ne => return (a != b) as i64,
Self::Lt => return (a < b) as i64,
Self::Gt => return (a > b) as i64,
Self::Le => return (a >= b) as i64,
Self::Ge => return (a <= b) as i64,
_ => todo!("floating point op: {self}"),
};
return res.to_bits() as _;
}
match self { match self {
Self::Add => a.wrapping_add(b), Self::Add => a.wrapping_add(b),
Self::Sub => a.wrapping_sub(b), Self::Sub => a.wrapping_sub(b),
Self::Mul => a.wrapping_mul(b), Self::Mul => a.wrapping_mul(b),
Self::Div if b == 0 => 0,
Self::Div => a.wrapping_div(b), Self::Div => a.wrapping_div(b),
Self::Shl => a.wrapping_shl(b as _), Self::Shl => a.wrapping_shl(b as _),
Self::Eq => (a == b) as i64, Self::Eq => (a == b) as i64,
Self::Ne => (a != b) as i64, Self::Ne => (a != b) as i64,
Self::Lt => (a < b) as i64,
Self::Gt => (a > b) as i64,
Self::Le => (a >= b) as i64,
Self::Ge => (a <= b) as i64,
Self::Band => a & b, Self::Band => a & b,
Self::Shr => a >> b, Self::Bor => a | b,
Self::Xor => a ^ b,
Self::Mod if b == 0 => 0,
Self::Mod => a.wrapping_rem(b),
Self::Shr => a.wrapping_shr(b as _),
s => todo!("{s}"), s => todo!("{s}"),
} }
} }
@ -291,19 +259,30 @@ impl TokenKind {
&& self.precedence() != Self::Eof.precedence() && self.precedence() != Self::Eof.precedence()
} }
pub fn unop(&self) -> Option<fn(u8, u8) -> EncodedInstr> { pub fn apply_unop(&self, value: i64, float: bool) -> i64 {
Some(match self {
Self::Sub => crate::instrs::neg,
_ => return None,
})
}
pub fn apply_unop(&self, value: i64) -> i64 {
match self { match self {
Self::Sub if float => (-f64::from_bits(value as _)).to_bits() as _,
Self::Sub => value.wrapping_neg(), Self::Sub => value.wrapping_neg(),
Self::Float if float => value,
Self::Float => (value as f64).to_bits() as _,
Self::Number => {
debug_assert!(float);
f64::from_bits(value as _).to_bits() as _
}
s => todo!("{s}"), s => todo!("{s}"),
} }
} }
pub fn closing(&self) -> Option<TokenKind> {
Some(match self {
Self::Ctor => Self::RBrace,
Self::Tupl => Self::RParen,
Self::LParen => Self::RParen,
Self::LBrack => Self::RBrack,
Self::LBrace => Self::RBrace,
_ => return None,
})
}
} }
gen_token_kind! { gen_token_kind! {
@ -312,6 +291,7 @@ gen_token_kind! {
CtIdent, CtIdent,
Ident, Ident,
Number, Number,
Float,
Eof, Eof,
Directive, Directive,
#[keywords] #[keywords]
@ -326,7 +306,10 @@ gen_token_kind! {
Packed = b"packed", Packed = b"packed",
True = b"true", True = b"true",
False = b"false", False = b"false",
Idk = b"idk", Null = b"null",
Idk = b"idk",
Die = b"die",
Under = b"_",
#[punkt] #[punkt]
Ctor = ".{", Ctor = ".{",
Tupl = ".(", Tupl = ".(",
@ -475,7 +458,15 @@ impl<'a> Lexer<'a> {
while let Some(b'0'..=b'9') = self.peek() { while let Some(b'0'..=b'9') = self.peek() {
self.advance(); self.advance();
} }
T::Number
if self.advance_if(b'.') {
while let Some(b'0'..=b'9') = self.peek() {
self.advance();
}
T::Float
} else {
T::Number
}
} }
b'a'..=b'z' | b'A'..=b'Z' | b'_' | 127.. => { b'a'..=b'z' | b'A'..=b'Z' | b'_' | 127.. => {
advance_ident(self); advance_ident(self);

File diff suppressed because it is too large Load diff

View file

@ -3,7 +3,7 @@ fn main() -> std::io::Result<()> {
use std::io::Write; use std::io::Write;
log::set_logger(&hblang::Logger).unwrap(); log::set_logger(&hblang::Logger).unwrap();
log::set_max_level(log::LevelFilter::Error); log::set_max_level(log::LevelFilter::Info);
let args = std::env::args().collect::<Vec<_>>(); let args = std::env::args().collect::<Vec<_>>();
let args = args.iter().map(String::as_str).collect::<Vec<_>>(); let args = args.iter().map(String::as_str).collect::<Vec<_>>();

View file

@ -1,13 +1,13 @@
use { use {
crate::{ crate::{
fmt::Formatter, fmt::Formatter,
ident::{self, Ident},
lexer::{self, Lexer, Token, TokenKind}, lexer::{self, Lexer, Token, TokenKind},
Ident,
}, },
alloc::{boxed::Box, string::String, vec::Vec}, alloc::{boxed::Box, string::String, vec::Vec},
core::{ core::{
alloc::Layout, alloc::Layout,
cell::UnsafeCell, cell::{RefCell, UnsafeCell},
fmt::{self}, fmt::{self},
intrinsics::unlikely, intrinsics::unlikely,
marker::PhantomData, marker::PhantomData,
@ -19,7 +19,6 @@ use {
pub type Pos = u32; pub type Pos = u32;
pub type IdentFlags = u32; pub type IdentFlags = u32;
pub type Symbols = Vec<Symbol>;
pub type FileId = u32; pub type FileId = u32;
pub type IdentIndex = u16; pub type IdentIndex = u16;
pub type LoaderError = String; pub type LoaderError = String;
@ -31,6 +30,20 @@ pub enum FileKind {
Embed, Embed,
} }
trait Trans {
fn trans(self) -> Self;
}
impl<T> Trans for Option<Option<T>> {
fn trans(self) -> Self {
match self {
Some(None) => None,
Some(Some(v)) => Some(Some(v)),
None => Some(None),
}
}
}
pub const SOURCE_TO_AST_FACTOR: usize = 7 * (core::mem::size_of::<usize>() / 4) + 1; pub const SOURCE_TO_AST_FACTOR: usize = 7 * (core::mem::size_of::<usize>() / 4) + 1;
pub mod idfl { pub mod idfl {
@ -73,7 +86,7 @@ pub struct Parser<'a, 'b> {
loader: Loader<'b>, loader: Loader<'b>,
lexer: Lexer<'a>, lexer: Lexer<'a>,
arena: &'a Arena, arena: &'a Arena,
ctx: &'b mut ParserCtx, ctx: &'b mut Ctx,
token: Token, token: Token,
ns_bound: usize, ns_bound: usize,
trailing_sep: bool, trailing_sep: bool,
@ -82,7 +95,7 @@ pub struct Parser<'a, 'b> {
impl<'a, 'b> Parser<'a, 'b> { impl<'a, 'b> Parser<'a, 'b> {
pub fn parse( pub fn parse(
ctx: &'b mut ParserCtx, ctx: &'b mut Ctx,
input: &'a str, input: &'a str,
path: &'b str, path: &'b str,
loader: Loader<'b>, loader: Loader<'b>,
@ -110,23 +123,14 @@ impl<'a, 'b> Parser<'a, 'b> {
if !self.ctx.idents.is_empty() { if !self.ctx.idents.is_empty() {
// TODO: we need error recovery // TODO: we need error recovery
log::error!("{}", { let mut idents = core::mem::take(&mut self.ctx.idents);
let mut errors = String::new(); for id in idents.drain(..) {
for id in self.ctx.idents.drain(..) { self.report(
report_to( id.ident.pos(),
self.lexer.source(), format_args!("undeclared identifier: {}", self.lexer.slice(id.ident.range())),
self.path, );
ident::pos(id.ident), }
&format_args!( self.ctx.idents = idents;
"undeclared identifier: {}",
self.lexer.slice(ident::range(id.ident))
),
&mut errors,
);
}
errors
});
unreachable!();
} }
f f
@ -136,53 +140,56 @@ impl<'a, 'b> Parser<'a, 'b> {
core::mem::replace(&mut self.token, self.lexer.eat()) core::mem::replace(&mut self.token, self.lexer.eat())
} }
fn ptr_expr(&mut self) -> &'a Expr<'a> { fn ptr_expr(&mut self) -> Option<&'a Expr<'a>> {
self.arena.alloc(self.expr()) Some(self.arena.alloc(self.expr()?))
} }
fn expr_low(&mut self, top_level: bool) -> Expr<'a> { fn expr_low(&mut self, top_level: bool) -> Option<Expr<'a>> {
let left = self.unit_expr(); let left = self.unit_expr()?;
self.bin_expr(left, 0, top_level) self.bin_expr(left, 0, top_level)
} }
fn expr(&mut self) -> Expr<'a> { fn expr(&mut self) -> Option<Expr<'a>> {
self.expr_low(false) self.expr_low(false)
} }
fn bin_expr(&mut self, mut fold: Expr<'a>, min_prec: u8, top_level: bool) -> Expr<'a> { fn bin_expr(&mut self, mut fold: Expr<'a>, min_prec: u8, top_level: bool) -> Option<Expr<'a>> {
loop { loop {
let Some(prec) = self.token.kind.precedence() else { let Some(prec) = self.token.kind.precedence() else { break };
break;
};
if prec <= min_prec { if prec <= min_prec {
break; break;
} }
let op = self.next().kind; let Token { kind: op, start: pos, .. } = self.next();
if op == TokenKind::Decl { if op == TokenKind::Decl {
self.declare_rec(&fold, top_level); self.declare_rec(&fold, top_level);
} }
let right = self.unit_expr(); let right = self.unit_expr()?;
let right = self.bin_expr(right, prec, false); let right = self.bin_expr(right, prec, false)?;
let right = self.arena.alloc(right); let right = self.arena.alloc(right);
let left = self.arena.alloc(fold); let left = self.arena.alloc(fold);
if let Some(op) = op.ass_op() { if let Some(op) = op.ass_op() {
self.flag_idents(*left, idfl::MUTABLE); self.flag_idents(*left, idfl::MUTABLE);
let right = Expr::BinOp { left: self.arena.alloc(fold), op, right }; let right = Expr::BinOp { left: self.arena.alloc(fold), pos, op, right };
fold = Expr::BinOp { left, op: TokenKind::Assign, right: self.arena.alloc(right) }; fold = Expr::BinOp {
left,
pos,
op: TokenKind::Assign,
right: self.arena.alloc(right),
};
} else { } else {
fold = Expr::BinOp { left, right, op }; fold = Expr::BinOp { left, right, pos, op };
if op == TokenKind::Assign { if op == TokenKind::Assign {
self.flag_idents(*left, idfl::MUTABLE); self.flag_idents(*left, idfl::MUTABLE);
} }
} }
} }
fold Some(fold)
} }
fn declare_rec(&mut self, expr: &Expr, top_level: bool) { fn declare_rec(&mut self, expr: &Expr, top_level: bool) {
@ -195,7 +202,7 @@ impl<'a, 'b> Parser<'a, 'b> {
self.declare_rec(value, top_level) self.declare_rec(value, top_level)
} }
} }
_ => self.report(expr.pos(), "cant declare this shit (yet)"), _ => _ = self.report(expr.pos(), "cant declare this shit (yet)"),
} }
} }
@ -205,19 +212,21 @@ impl<'a, 'b> Parser<'a, 'b> {
pos, pos,
format_args!( format_args!(
"out of order declaration not allowed: {}", "out of order declaration not allowed: {}",
self.lexer.slice(ident::range(id)) self.lexer.slice(id.range())
), ),
); );
} }
let Ok(index) = self.ctx.idents.binary_search_by_key(&id, |s| s.ident) else { let Ok(index) = self.ctx.idents.binary_search_by_key(&id, |s| s.ident) else {
self.report(pos, "the identifier is rezerved for a builtin (proably)"); self.report(pos, "the identifier is rezerved for a builtin (proably)");
return;
}; };
if core::mem::replace(&mut self.ctx.idents[index].declared, true) { if core::mem::replace(&mut self.ctx.idents[index].declared, true) {
self.report( self.report(
pos, pos,
format_args!("redeclaration of identifier: {}", self.lexer.slice(ident::range(id))), format_args!("redeclaration of identifier: {}", self.lexer.slice(id.range())),
) );
return;
} }
self.ctx.idents[index].ordered = ordered; self.ctx.idents[index].ordered = ordered;
@ -228,7 +237,7 @@ impl<'a, 'b> Parser<'a, 'b> {
let name = self.lexer.slice(token.range()); let name = self.lexer.slice(token.range());
if let Some(builtin) = crate::ty::from_str(name) { if let Some(builtin) = crate::ty::from_str(name) {
return (builtin, false); return (Ident::builtin(builtin), false);
} }
let (i, id, bl) = match self let (i, id, bl) = match self
@ -236,15 +245,20 @@ impl<'a, 'b> Parser<'a, 'b> {
.idents .idents
.iter_mut() .iter_mut()
.enumerate() .enumerate()
.rfind(|(_, elem)| self.lexer.slice(ident::range(elem.ident)) == name) .rfind(|(_, elem)| self.lexer.slice(elem.ident.range()) == name)
{ {
Some((i, elem)) => (i, elem, false), Some((i, elem)) => (i, elem, false),
None => { None => {
let Some(id) = ident::new(token.start, name.len() as _) else { let ident = match Ident::new(token.start, name.len() as _) {
self.report(token.start, "identifier can at most have 64 characters"); None => {
self.report(token.start, "identifier can at most have 64 characters");
Ident::new(token.start, 63).unwrap()
}
Some(id) => id,
}; };
self.ctx.idents.push(ScopeIdent { self.ctx.idents.push(ScopeIdent {
ident: id, ident,
declared: false, declared: false,
ordered: false, ordered: false,
flags: 0, flags: 0,
@ -266,18 +280,18 @@ impl<'a, 'b> Parser<'a, 'b> {
self.lexer.slice(range.range()) self.lexer.slice(range.range())
} }
fn unit_expr(&mut self) -> Expr<'a> { fn unit_expr(&mut self) -> Option<Expr<'a>> {
use {Expr as E, TokenKind as T}; use {Expr as E, TokenKind as T};
let frame = self.ctx.idents.len(); let frame = self.ctx.idents.len();
let token @ Token { start: pos, .. } = self.next(); let token @ Token { start: pos, .. } = self.next();
let prev_boundary = self.ns_bound; let prev_boundary = self.ns_bound;
let prev_captured = self.ctx.captured.len(); let prev_captured = self.ctx.captured.len();
let mut expr = match token.kind { let mut expr = match token.kind {
T::Ct => E::Ct { pos, value: self.ptr_expr() }, T::Ct => E::Ct { pos, value: self.ptr_expr()? },
T::Directive if self.lexer.slice(token.range()) == "use" => { T::Directive if self.lexer.slice(token.range()) == "use" => {
self.expect_advance(TokenKind::LParen); self.expect_advance(TokenKind::LParen)?;
let str = self.expect_advance(TokenKind::DQuote); let str = self.expect_advance(TokenKind::DQuote)?;
self.expect_advance(TokenKind::RParen); self.expect_advance(TokenKind::RParen)?;
let path = self.lexer.slice(str.range()); let path = self.lexer.slice(str.range());
let path = &path[1..path.len() - 1]; let path = &path[1..path.len() - 1];
@ -287,15 +301,15 @@ impl<'a, 'b> Parser<'a, 'b> {
id: match (self.loader)(path, self.path, FileKind::Module) { id: match (self.loader)(path, self.path, FileKind::Module) {
Ok(id) => id, Ok(id) => id,
Err(e) => { Err(e) => {
self.report(str.start, format_args!("error loading dependency: {e:#}")) self.report(str.start, format_args!("error loading dependency: {e:#}"))?
} }
}, },
} }
} }
T::Directive if self.lexer.slice(token.range()) == "embed" => { T::Directive if self.lexer.slice(token.range()) == "embed" => {
self.expect_advance(TokenKind::LParen); self.expect_advance(TokenKind::LParen)?;
let str = self.expect_advance(TokenKind::DQuote); let str = self.expect_advance(TokenKind::DQuote)?;
self.expect_advance(TokenKind::RParen); self.expect_advance(TokenKind::RParen)?;
let path = self.lexer.slice(str.range()); let path = self.lexer.slice(str.range());
let path = &path[1..path.len() - 1]; let path = &path[1..path.len() - 1];
@ -304,8 +318,10 @@ impl<'a, 'b> Parser<'a, 'b> {
path, path,
id: match (self.loader)(path, self.path, FileKind::Embed) { id: match (self.loader)(path, self.path, FileKind::Embed) {
Ok(id) => id, Ok(id) => id,
Err(e) => self Err(e) => self.report(
.report(str.start, format_args!("error loading embedded file: {e:#}")), str.start,
format_args!("error loading embedded file: {e:#}"),
)?,
}, },
} }
} }
@ -313,17 +329,19 @@ impl<'a, 'b> Parser<'a, 'b> {
pos: pos - 1, // need to undo the directive shift pos: pos - 1, // need to undo the directive shift
name: self.tok_str(token), name: self.tok_str(token),
args: { args: {
self.expect_advance(T::LParen); self.expect_advance(T::LParen)?;
self.collect_list(T::Comma, T::RParen, Self::expr) self.collect_list(T::Comma, T::RParen, Self::expr)
}, },
}, },
T::True => E::Bool { pos, value: true }, T::True => E::Bool { pos, value: true },
T::False => E::Bool { pos, value: false }, T::False => E::Bool { pos, value: false },
T::Null => E::Null { pos },
T::Idk => E::Idk { pos }, T::Idk => E::Idk { pos },
T::Die => E::Die { pos },
T::DQuote => E::String { pos, literal: self.tok_str(token) }, T::DQuote => E::String { pos, literal: self.tok_str(token) },
T::Packed => { T::Packed => {
self.packed = true; self.packed = true;
let expr = self.unit_expr(); let expr = self.unit_expr()?;
if self.packed { if self.packed {
self.report( self.report(
expr.pos(), expr.pos(),
@ -337,20 +355,20 @@ impl<'a, 'b> Parser<'a, 'b> {
packed: core::mem::take(&mut self.packed), packed: core::mem::take(&mut self.packed),
fields: { fields: {
self.ns_bound = self.ctx.idents.len(); self.ns_bound = self.ctx.idents.len();
self.expect_advance(T::LBrace); self.expect_advance(T::LBrace)?;
self.collect_list(T::Comma, T::RBrace, |s| { self.collect_list(T::Comma, T::RBrace, |s| {
let tok = s.token; let tok = s.token;
if s.advance_if(T::Comment) { Some(if s.advance_if(T::Comment) {
CommentOr::Comment { literal: s.tok_str(tok), pos: tok.start } CommentOr::Comment { literal: s.tok_str(tok), pos: tok.start }
} else { } else {
let name = s.expect_advance(T::Ident); let name = s.expect_advance(T::Ident)?;
s.expect_advance(T::Colon); s.expect_advance(T::Colon)?;
CommentOr::Or(StructField { CommentOr::Or(StructField {
pos: name.start, pos: name.start,
name: s.tok_str(name), name: s.tok_str(name),
ty: s.expr(), ty: s.expr()?,
}) })
} })
}) })
}, },
captured: { captured: {
@ -374,13 +392,14 @@ 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()?,
then: self.ptr_expr(), then: self.ptr_expr()?,
else_: self.advance_if(T::Else).then(|| self.ptr_expr()), else_: self.advance_if(T::Else).then(|| self.ptr_expr()).trans()?,
}, },
T::Loop => E::Loop { pos, body: self.ptr_expr() }, T::Loop => E::Loop { pos, body: self.ptr_expr()? },
T::Break => E::Break { pos }, T::Break => E::Break { pos },
T::Continue => E::Continue { pos }, T::Continue => E::Continue { pos },
T::Return => E::Return { T::Return => E::Return {
@ -389,47 +408,48 @@ impl<'a, 'b> Parser<'a, 'b> {
self.token.kind, self.token.kind,
T::Semi | T::RBrace | T::RBrack | T::RParen | T::Comma T::Semi | T::RBrace | T::RBrack | T::RParen | T::Comma
)) ))
.then(|| self.ptr_expr()), .then(|| self.ptr_expr())
.trans()?,
}, },
T::Fn => E::Closure { T::Fn => E::Closure {
pos, pos,
args: { args: {
self.expect_advance(T::LParen); self.expect_advance(T::LParen)?;
self.collect_list(T::Comma, T::RParen, |s| { self.collect_list(T::Comma, T::RParen, |s| {
let name = s.advance_ident(); let name = s.advance_ident()?;
let (id, _) = s.resolve_ident(name); let (id, _) = s.resolve_ident(name);
s.declare(name.start, id, true, true); s.declare(name.start, id, true, true);
s.expect_advance(T::Colon); s.expect_advance(T::Colon)?;
Arg { Some(Arg {
pos: name.start, pos: name.start,
name: s.tok_str(name), name: s.tok_str(name),
is_ct: name.kind == T::CtIdent, is_ct: name.kind == T::CtIdent,
id, id,
ty: s.expr(), ty: s.expr()?,
} })
}) })
}, },
ret: { ret: {
self.expect_advance(T::Colon); self.expect_advance(T::Colon)?;
self.ptr_expr() self.ptr_expr()?
}, },
body: self.ptr_expr(), body: self.ptr_expr()?,
}, },
T::Ctor => self.ctor(pos, None), T::Ctor => self.ctor(pos, None),
T::Tupl => self.tupl(pos, None), T::Tupl => self.tupl(pos, None),
T::LBrack => E::Slice { T::LBrack => E::Slice {
item: self.ptr_unit_expr(), item: self.ptr_unit_expr()?,
size: self.advance_if(T::Semi).then(|| self.ptr_expr()), size: self.advance_if(T::Semi).then(|| self.ptr_expr()).trans()?,
pos: { pos: {
self.expect_advance(T::RBrack); self.expect_advance(T::RBrack)?;
pos pos
}, },
}, },
T::Band | T::Mul | T::Xor | T::Sub => E::UnOp { T::Band | T::Mul | T::Xor | T::Sub | T::Que => E::UnOp {
pos, pos,
op: token.kind, op: token.kind,
val: { val: {
let expr = self.ptr_unit_expr(); let expr = self.ptr_unit_expr()?;
if token.kind == T::Band { if token.kind == T::Band {
self.flag_idents(*expr, idfl::REFERENCED); self.flag_idents(*expr, idfl::REFERENCED);
} }
@ -449,18 +469,26 @@ 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(token.start, format_args!("invalid number: {e}")), Err(e) => self.report(token.start, format_args!("invalid number: {e}"))?,
} as i64, } as i64,
radix, radix,
} }
} }
T::Float => E::Float {
pos,
value: match <f64 as core::str::FromStr>::from_str(self.lexer.slice(token.range()))
{
Ok(f) => f.to_bits(),
Err(e) => self.report(token.start, format_args!("invalid float: {e}"))?,
},
},
T::LParen => { T::LParen => {
let expr = self.expr(); let expr = self.expr()?;
self.expect_advance(T::RParen); self.expect_advance(T::RParen)?;
expr expr
} }
T::Comment => Expr::Comment { pos, literal: self.tok_str(token) }, T::Comment => Expr::Comment { pos, literal: self.tok_str(token) },
tok => self.report(token.start, format_args!("unexpected token: {tok}")), tok => self.report(token.start, format_args!("unexpected token: {tok}"))?,
}; };
loop { loop {
@ -480,8 +508,8 @@ impl<'a, 'b> Parser<'a, 'b> {
T::LBrack => E::Index { T::LBrack => E::Index {
base: self.arena.alloc(expr), base: self.arena.alloc(expr),
index: { index: {
let index = self.expr(); let index = self.expr()?;
self.expect_advance(T::RBrack); self.expect_advance(T::RBrack)?;
self.arena.alloc(index) self.arena.alloc(index)
}, },
}, },
@ -489,7 +517,7 @@ impl<'a, 'b> Parser<'a, 'b> {
target: self.arena.alloc(expr), target: self.arena.alloc(expr),
pos: token.start, pos: token.start,
name: { name: {
let token = self.expect_advance(T::Ident); let token = self.expect_advance(T::Ident)?;
self.tok_str(token) self.tok_str(token)
}, },
}, },
@ -501,7 +529,7 @@ impl<'a, 'b> Parser<'a, 'b> {
self.pop_scope(frame); self.pop_scope(frame);
} }
expr Some(expr)
} }
fn tupl(&mut self, pos: Pos, ty: Option<Expr<'a>>) -> Expr<'a> { fn tupl(&mut self, pos: Pos, ty: Option<Expr<'a>>) -> Expr<'a> {
@ -518,31 +546,29 @@ impl<'a, 'b> Parser<'a, 'b> {
pos, pos,
ty: ty.map(|ty| self.arena.alloc(ty)), ty: ty.map(|ty| self.arena.alloc(ty)),
fields: self.collect_list(TokenKind::Comma, TokenKind::RBrace, |s| { fields: self.collect_list(TokenKind::Comma, TokenKind::RBrace, |s| {
let name_tok = s.advance_ident(); let name_tok = s.advance_ident()?;
let name = s.tok_str(name_tok); let name = s.tok_str(name_tok);
CtorField { Some(CtorField {
pos: name_tok.start, pos: name_tok.start,
name, name,
value: if s.advance_if(TokenKind::Colon) { value: if s.advance_if(TokenKind::Colon) {
s.expr() s.expr()?
} else { } else {
let (id, is_first) = s.resolve_ident(name_tok); let (id, is_first) = s.resolve_ident(name_tok);
Expr::Ident { pos: name_tok.start, is_ct: false, id, is_first } Expr::Ident { pos: name_tok.start, is_ct: false, id, is_first }
}, },
} })
}), }),
trailing_comma: core::mem::take(&mut self.trailing_sep), trailing_comma: core::mem::take(&mut self.trailing_sep),
} }
} }
fn advance_ident(&mut self) -> Token { fn advance_ident(&mut self) -> Option<Token> {
if matches!(self.token.kind, TokenKind::Ident | TokenKind::CtIdent) { let next = self.next();
self.next() if matches!(next.kind, TokenKind::Ident | TokenKind::CtIdent) {
Some(next)
} else { } else {
self.report( self.report(self.token.start, format_args!("expected identifier, found {}", next.kind))?
self.token.start,
format_args!("expected identifier, found {}", self.token.kind),
)
} }
} }
@ -562,20 +588,49 @@ impl<'a, 'b> Parser<'a, 'b> {
.collect_into(&mut self.ctx.symbols); .collect_into(&mut self.ctx.symbols);
} }
fn ptr_unit_expr(&mut self) -> &'a Expr<'a> { fn ptr_unit_expr(&mut self) -> Option<&'a Expr<'a>> {
self.arena.alloc(self.unit_expr()) Some(self.arena.alloc(self.unit_expr()?))
} }
fn collect_list<T: Copy>( fn collect_list<T: Copy>(
&mut self, &mut self,
delim: TokenKind, delim: TokenKind,
end: TokenKind, end: TokenKind,
mut f: impl FnMut(&mut Self) -> T, mut f: impl FnMut(&mut Self) -> Option<T>,
) -> &'a [T] { ) -> &'a [T] {
let mut trailing_sep = false; let mut trailing_sep = false;
let mut view = self.ctx.stack.view(); let mut view = self.ctx.stack.view();
while !self.advance_if(end) { 'o: while !self.advance_if(end) {
let val = f(self); let val = match f(self) {
Some(val) => val,
None => {
let mut paren = None::<TokenKind>;
let mut depth = 0;
loop {
let tok = self.next();
if tok.kind == TokenKind::Eof {
break 'o;
}
if let Some(par) = paren {
if par == tok.kind {
depth += 1;
} else if tok.kind.closing() == par.closing() {
depth -= 1;
if depth == 0 {
paren = None;
}
}
} else if tok.kind == delim {
continue 'o;
} else if tok.kind == end {
break 'o;
} else if tok.kind.closing().is_some() && paren.is_none() {
paren = Some(tok.kind);
depth = 1;
}
}
}
};
trailing_sep = self.advance_if(delim); trailing_sep = self.advance_if(delim);
unsafe { self.ctx.stack.push(&mut view, val) }; unsafe { self.ctx.stack.push(&mut view, val) };
} }
@ -592,20 +647,28 @@ impl<'a, 'b> Parser<'a, 'b> {
} }
} }
fn expect_advance(&mut self, kind: TokenKind) -> Token { #[must_use]
if self.token.kind != kind { fn expect_advance(&mut self, kind: TokenKind) -> Option<Token> {
self.report( let next = self.next();
self.token.start, if next.kind != kind {
format_args!("expected {}, found {}", kind, self.token.kind), self.report(next.start, format_args!("expected {}, found {}", kind, next.kind))?
); } else {
Some(next)
} }
self.next()
} }
#[track_caller] #[track_caller]
fn report(&self, pos: Pos, msg: impl fmt::Display) -> ! { fn report(&mut self, pos: Pos, msg: impl fmt::Display) -> Option<!> {
log::error!("{}", Report::new(self.lexer.source(), self.path, pos, msg)); if log::log_enabled!(log::Level::Error) {
unreachable!(); use core::fmt::Write;
writeln!(
self.ctx.errors.get_mut(),
"{}",
Report::new(self.lexer.source(), self.path, pos, msg)
)
.unwrap();
}
None
} }
fn flag_idents(&mut self, e: Expr<'a>, flags: IdentFlags) { fn flag_idents(&mut self, e: Expr<'a>, flags: IdentFlags) {
@ -668,7 +731,7 @@ macro_rules! generate_expr {
} }
pub fn pos(&self) -> Pos { pub fn pos(&self) -> Pos {
#[allow(unused_variables)] #[expect(unused_variables)]
match self { match self {
$(Self::$variant { $($field),* } => generate_expr!(@first $(($field),)*).posi(),)* $(Self::$variant { $($field),* } => generate_expr!(@first $(($field),)*).posi(),)*
} }
@ -738,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 {
@ -758,10 +824,16 @@ generate_expr! {
value: i64, value: i64,
radix: Radix, radix: Radix,
}, },
/// `'[0-9]+.[0-9]*'`
Float {
pos: Pos,
value: u64,
},
/// node: precedence defined in `OP` applies /// node: precedence defined in `OP` applies
/// `Expr OP Expr` /// `Expr OP Expr`
BinOp { BinOp {
left: &'a Self, left: &'a Self,
pos: Pos,
op: TokenKind, op: TokenKind,
right: &'a Self, right: &'a Self,
}, },
@ -828,10 +900,18 @@ generate_expr! {
pos: Pos, pos: Pos,
value: bool, value: bool,
}, },
/// `'null'`
Null {
pos: Pos,
},
/// `'idk'` /// `'idk'`
Idk { Idk {
pos: Pos, pos: Pos,
}, },
/// `'die'`
Die {
pos: Pos,
},
/// `'@' Ident List('(', ',', ')', Expr)` /// `'@' Ident List('(', ',', ')', Expr)`
Directive { Directive {
pos: Pos, pos: Pos,
@ -856,7 +936,7 @@ generate_expr! {
impl Expr<'_> { impl Expr<'_> {
pub fn declares(&self, iden: Result<Ident, &str>, source: &str) -> Option<Ident> { pub fn declares(&self, iden: Result<Ident, &str>, source: &str) -> Option<Ident> {
match *self { match *self {
Self::Ident { id, .. } if iden == Ok(id) || iden == Err(&source[ident::range(id)]) => { Self::Ident { id, .. } if iden == Ok(id) || iden == Err(&source[id.range()]) => {
Some(id) Some(id)
} }
Self::Ctor { fields, .. } => fields.iter().find_map(|f| f.value.declares(iden, source)), Self::Ctor { fields, .. } => fields.iter().find_map(|f| f.value.declares(iden, source)),
@ -982,13 +1062,25 @@ impl core::fmt::Display for Display<'_> {
} }
#[derive(Default)] #[derive(Default)]
pub struct ParserCtx { pub struct Ctx {
symbols: Symbols, pub errors: RefCell<String>,
symbols: Vec<Symbol>,
stack: StackAlloc, stack: StackAlloc,
idents: Vec<ScopeIdent>, idents: Vec<ScopeIdent>,
captured: Vec<Ident>, captured: Vec<Ident>,
} }
impl Ctx {
pub fn clear(&mut self) {
self.errors.get_mut().clear();
debug_assert_eq!(self.symbols.len(), 0);
debug_assert_eq!(self.stack.len, 0);
debug_assert_eq!(self.idents.len(), 0);
debug_assert_eq!(self.captured.len(), 0);
}
}
#[repr(C)] #[repr(C)]
pub struct AstInner<T: ?Sized> { pub struct AstInner<T: ?Sized> {
ref_count: AtomicUsize, ref_count: AtomicUsize,
@ -1008,12 +1100,12 @@ impl AstInner<[Symbol]> {
.0 .0
} }
fn new(file: Box<str>, path: &str, ctx: &mut ParserCtx, loader: Loader) -> NonNull<Self> { fn new(file: Box<str>, path: Box<str>, ctx: &mut Ctx, loader: Loader) -> NonNull<Self> {
let arena = Arena::with_capacity( let arena = Arena::with_capacity(
SOURCE_TO_AST_FACTOR * file.bytes().filter(|b| !b.is_ascii_whitespace()).count(), SOURCE_TO_AST_FACTOR * file.bytes().filter(|b| !b.is_ascii_whitespace()).count(),
); );
let exprs = let exprs =
unsafe { core::mem::transmute(Parser::parse(ctx, &file, path, loader, &arena)) }; unsafe { core::mem::transmute(Parser::parse(ctx, &file, &path, loader, &arena)) };
crate::quad_sort(&mut ctx.symbols, |a, b| a.name.cmp(&b.name)); crate::quad_sort(&mut ctx.symbols, |a, b| a.name.cmp(&b.name));
@ -1027,13 +1119,14 @@ impl AstInner<[Symbol]> {
ref_count: AtomicUsize::new(1), ref_count: AtomicUsize::new(1),
mem: arena.chunk.into_inner(), mem: arena.chunk.into_inner(),
exprs, exprs,
path: path.into(), path,
file, file,
symbols: (), symbols: (),
}); });
core::ptr::addr_of_mut!((*inner).symbols) core::ptr::addr_of_mut!((*inner).symbols)
.as_mut_ptr() .as_mut_ptr()
.copy_from_nonoverlapping(ctx.symbols.as_ptr(), ctx.symbols.len()); .copy_from_nonoverlapping(ctx.symbols.as_ptr(), ctx.symbols.len());
ctx.symbols.clear();
NonNull::new_unchecked(inner) NonNull::new_unchecked(inner)
} }
@ -1074,18 +1167,35 @@ 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;
_ = writeln!(out, "{}", line.replace("\t", " ")); let mut has_non_whitespace = false;
_ = writeln!(out, "{}^", " ".repeat(col - 1)); for char in line.chars() {
if char == '\t' && !has_non_whitespace {
_ = out.write_str(" ");
} else {
_ = out.write_char(char);
}
has_non_whitespace |= !char.is_whitespace();
}
_ = out.write_char('\n');
for _ in 0..col - 1 {
_ = out.write_str(" ");
}
_ = out.write_str("^\n");
} }
#[derive(PartialEq, Eq, Hash)] #[derive(PartialEq, Eq, Hash)]
pub struct Ast(NonNull<AstInner<[Symbol]>>); pub struct Ast(NonNull<AstInner<[Symbol]>>);
impl Ast { impl Ast {
pub fn new(path: &str, content: String, ctx: &mut ParserCtx, loader: Loader) -> Self { pub fn new(
Self(AstInner::new(content.into(), path, ctx, loader)) path: impl Into<Box<str>>,
content: impl Into<Box<str>>,
ctx: &mut Ctx,
loader: Loader,
) -> Self {
Self(AstInner::new(content.into(), path.into(), ctx, loader))
} }
pub fn exprs(&self) -> &[Expr] { pub fn exprs(&self) -> &[Expr] {
@ -1106,13 +1216,13 @@ impl Ast {
} }
pub fn ident_str(&self, ident: Ident) -> &str { pub fn ident_str(&self, ident: Ident) -> &str {
&self.file[ident::range(ident)] &self.file[ident.range()]
} }
} }
impl Default for Ast { impl Default for Ast {
fn default() -> Self { fn default() -> Self {
Self(AstInner::new("".into(), "", &mut ParserCtx::default(), &mut no_loader)) Self(AstInner::new("".into(), "".into(), &mut Ctx::default(), &mut no_loader))
} }
} }
@ -1125,12 +1235,12 @@ impl ExprRef {
Self(NonNull::from(expr).cast()) Self(NonNull::from(expr).cast())
} }
pub fn get<'a>(&self, from: &'a Ast) -> Option<&'a Expr<'a>> { pub fn get<'a>(&self, from: &'a Ast) -> &'a Expr<'a> {
from.mem.contains(self.0.as_ptr() as _).then_some(())?; assert!(from.mem.contains(self.0.as_ptr() as _));
// SAFETY: the pointer is or was a valid reference in the past, if it points within one of // SAFETY: the pointer is or was a valid reference in the past, if it points within one of
// arenas regions, it muts be walid, since arena does not give invalid pointers to its // arenas regions, it muts be walid, since arena does not give invalid pointers to its
// allocations // allocations
Some(unsafe { { self.0 }.as_ref() }) unsafe { { self.0 }.as_ref() }
} }
pub fn dangling() -> Self { pub fn dangling() -> Self {
@ -1321,6 +1431,15 @@ impl Arena {
chunk.alloc(layout).unwrap() chunk.alloc(layout).unwrap()
} }
pub fn clear(&mut self) {
let size = self.chunk.get_mut().size();
if self.chunk.get_mut().next().is_some() {
self.chunk = ArenaChunk::new(size + 1024, Default::default()).into();
} else {
self.chunk.get_mut().reset();
}
}
} }
pub struct ArenaChunk { pub struct ArenaChunk {
@ -1379,6 +1498,10 @@ impl ArenaChunk {
pub fn size(&self) -> usize { pub fn size(&self) -> usize {
self.base as usize + self.size - self.end as usize + self.next().map_or(0, Self::size) self.base as usize + self.size - self.end as usize + self.next().map_or(0, Self::size)
} }
fn reset(&mut self) {
self.end = unsafe { self.base.add(self.size) };
}
} }
impl Drop for ArenaChunk { impl Drop for ArenaChunk {

150
lang/src/regalloc.rs Normal file
View file

@ -0,0 +1,150 @@
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

1763
lang/src/son/hbvm.rs Normal file

File diff suppressed because it is too large Load diff

528
lang/src/utils.rs Normal file
View file

@ -0,0 +1,528 @@
#![expect(dead_code)]
use {
alloc::alloc,
core::{
alloc::Layout,
fmt::Debug,
hint::unreachable_unchecked,
mem::MaybeUninit,
ops::{Deref, DerefMut, Not},
ptr::Unique,
},
};
type Nid = u16;
pub union BitSet {
inline: usize,
alloced: Unique<AllocedBitSet>,
}
impl Debug for BitSet {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_list().entries(self.iter()).finish()
}
}
impl Clone for BitSet {
fn clone(&self) -> Self {
if self.is_inline() {
Self { inline: unsafe { self.inline } }
} else {
let (data, _) = self.data_and_len();
let (layout, _) = Self::layout(data.len());
unsafe {
let ptr = alloc::alloc(layout);
ptr.copy_from_nonoverlapping(self.alloced.as_ptr() as _, layout.size());
Self { alloced: Unique::new_unchecked(ptr as _) }
}
}
}
}
impl Drop for BitSet {
fn drop(&mut self) {
if !self.is_inline() {
unsafe {
let cap = self.alloced.as_ref().cap;
alloc::dealloc(self.alloced.as_ptr() as _, Self::layout(cap).0);
}
}
}
}
impl Default for BitSet {
fn default() -> Self {
Self { inline: Self::FLAG }
}
}
impl BitSet {
const FLAG: usize = 1 << (Self::UNIT - 1);
const INLINE_ELEMS: usize = Self::UNIT - 1;
const UNIT: usize = core::mem::size_of::<usize>() * 8;
fn is_inline(&self) -> bool {
unsafe { self.inline & Self::FLAG != 0 }
}
fn data_and_len(&self) -> (&[usize], usize) {
unsafe {
if self.is_inline() {
(core::slice::from_ref(&self.inline), Self::INLINE_ELEMS)
} else {
let small_vec = self.alloced.as_ref();
(
core::slice::from_raw_parts(
&small_vec.data as *const _ as *const usize,
small_vec.cap,
),
small_vec.cap * core::mem::size_of::<usize>() * 8,
)
}
}
}
fn data_mut_and_len(&mut self) -> (&mut [usize], usize) {
unsafe {
if self.is_inline() {
(core::slice::from_mut(&mut self.inline), INLINE_ELEMS)
} else {
let small_vec = self.alloced.as_mut();
(
core::slice::from_raw_parts_mut(
&mut small_vec.data as *mut _ as *mut usize,
small_vec.cap,
),
small_vec.cap * Self::UNIT,
)
}
}
}
fn indexes(index: usize) -> (usize, usize) {
(index / Self::UNIT, index % Self::UNIT)
}
pub fn get(&self, index: Nid) -> bool {
let index = index as usize;
let (data, len) = self.data_and_len();
if index >= len {
return false;
}
let (elem, bit) = Self::indexes(index);
(unsafe { *data.get_unchecked(elem) }) & (1 << bit) != 0
}
pub fn set(&mut self, index: Nid) -> bool {
let index = index as usize;
let (mut data, len) = self.data_mut_and_len();
if core::intrinsics::unlikely(index >= len) {
self.grow(index.next_power_of_two().max(4 * Self::UNIT));
(data, _) = self.data_mut_and_len();
}
let (elem, bit) = Self::indexes(index);
let elem = unsafe { data.get_unchecked_mut(elem) };
let prev = *elem;
*elem |= 1 << bit;
*elem != prev
}
fn grow(&mut self, size: usize) {
debug_assert!(size.is_power_of_two());
let slot_count = size / Self::UNIT;
let (layout, off) = Self::layout(slot_count);
let (ptr, prev_len) = unsafe {
if self.is_inline() {
let ptr = alloc::alloc(layout);
*ptr.add(off).cast::<usize>() = self.inline & !Self::FLAG;
(ptr, 1)
} else {
let prev_len = self.alloced.as_ref().cap;
let (prev_layout, _) = Self::layout(prev_len);
(alloc::realloc(self.alloced.as_ptr() as _, prev_layout, layout.size()), prev_len)
}
};
unsafe {
MaybeUninit::fill(
core::slice::from_raw_parts_mut(
ptr.add(off).cast::<MaybeUninit<usize>>().add(prev_len),
slot_count - prev_len,
),
0,
);
*ptr.cast::<usize>() = slot_count;
core::ptr::write(self, Self { alloced: Unique::new_unchecked(ptr as _) });
}
}
fn layout(slot_count: usize) -> (core::alloc::Layout, usize) {
unsafe {
core::alloc::Layout::new::<AllocedBitSet>()
.extend(Layout::array::<usize>(slot_count).unwrap_unchecked())
.unwrap_unchecked()
}
}
pub fn iter(&self) -> BitSetIter {
if self.is_inline() {
BitSetIter { index: 0, current: unsafe { self.inline & !Self::FLAG }, remining: &[] }
} else {
let &[current, ref remining @ ..] = self.data_and_len().0 else {
unsafe { unreachable_unchecked() }
};
BitSetIter { index: 0, current, remining }
}
}
pub fn clear(&mut self, len: usize) {
self.reserve(len);
if self.is_inline() {
unsafe { self.inline &= Self::FLAG };
} else {
self.data_mut_and_len().0.fill(0);
}
}
pub fn units<'a>(&'a self, slot: &'a mut usize) -> &'a [usize] {
if self.is_inline() {
*slot = unsafe { self.inline } & !Self::FLAG;
core::slice::from_ref(slot)
} else {
self.data_and_len().0
}
}
pub fn reserve(&mut self, len: usize) {
if len > self.data_and_len().1 {
self.grow(len.next_power_of_two().max(4 * Self::UNIT));
}
}
pub fn units_mut(&mut self) -> Result<&mut [usize], &mut InlineBitSetView> {
if self.is_inline() {
Err(unsafe {
core::mem::transmute::<&mut usize, &mut InlineBitSetView>(&mut self.inline)
})
} else {
Ok(self.data_mut_and_len().0)
}
}
}
pub struct InlineBitSetView(usize);
impl InlineBitSetView {
pub(crate) fn add_mask(&mut self, tmp: usize) {
debug_assert!(tmp & BitSet::FLAG == 0);
self.0 |= tmp;
}
}
pub struct BitSetIter<'a> {
index: usize,
current: usize,
remining: &'a [usize],
}
impl Iterator for BitSetIter<'_> {
type Item = usize;
fn next(&mut self) -> Option<Self::Item> {
while self.current == 0 {
self.current = *self.remining.take_first()?;
self.index += 1;
}
let sub_idx = self.current.trailing_zeros() as usize;
self.current &= self.current - 1;
Some(self.index * BitSet::UNIT + sub_idx)
}
}
struct AllocedBitSet {
cap: usize,
data: [usize; 0],
}
#[cfg(test)]
#[test]
fn test_small_bit_set() {
use std::vec::Vec;
let mut sv = BitSet::default();
sv.set(10);
debug_assert!(sv.get(10));
sv.set(100);
debug_assert!(sv.get(100));
sv.set(10000);
debug_assert!(sv.get(10000));
debug_assert_eq!(sv.iter().collect::<Vec<_>>(), &[10, 100, 10000]);
sv.clear(10000);
debug_assert_eq!(sv.iter().collect::<Vec<_>>(), &[]);
}
pub union Vc {
inline: InlineVc,
alloced: AllocedVc,
}
impl Default for Vc {
fn default() -> Self {
Vc { inline: InlineVc { elems: MaybeUninit::uninit(), cap: Default::default() } }
}
}
impl Debug for Vc {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.as_slice().fmt(f)
}
}
impl FromIterator<Nid> for Vc {
fn from_iter<T: IntoIterator<Item = Nid>>(iter: T) -> Self {
let mut slf = Self::default();
for i in iter {
slf.push(i);
}
slf
}
}
const INLINE_ELEMS: usize = VC_SIZE / 2 - 1;
const VC_SIZE: usize = 16;
impl Vc {
fn is_inline(&self) -> bool {
unsafe { self.inline.cap <= INLINE_ELEMS as Nid }
}
fn layout(&self) -> Option<core::alloc::Layout> {
unsafe {
self.is_inline().not().then(|| {
core::alloc::Layout::array::<Nid>(self.alloced.cap as _).unwrap_unchecked()
})
}
}
pub fn len(&self) -> usize {
unsafe {
if self.is_inline() {
self.inline.cap as _
} else {
self.alloced.len as _
}
}
}
fn len_mut(&mut self) -> &mut Nid {
unsafe {
if self.is_inline() {
&mut self.inline.cap
} else {
&mut self.alloced.len
}
}
}
fn as_ptr(&self) -> *const Nid {
unsafe {
match self.is_inline() {
true => self.inline.elems.as_ptr().cast(),
false => self.alloced.base.as_ptr(),
}
}
}
fn as_mut_ptr(&mut self) -> *mut Nid {
unsafe {
match self.is_inline() {
true => self.inline.elems.as_mut_ptr().cast(),
false => self.alloced.base.as_ptr(),
}
}
}
pub fn as_slice(&self) -> &[Nid] {
unsafe { core::slice::from_raw_parts(self.as_ptr(), self.len()) }
}
fn as_slice_mut(&mut self) -> &mut [Nid] {
unsafe { core::slice::from_raw_parts_mut(self.as_mut_ptr(), self.len()) }
}
pub fn push(&mut self, value: Nid) {
if let Some(layout) = self.layout()
&& unsafe { self.alloced.len == self.alloced.cap }
{
unsafe {
self.alloced.cap *= 2;
self.alloced.base = Unique::new_unchecked(
alloc::realloc(
self.alloced.base.as_ptr().cast(),
layout,
self.alloced.cap as usize * core::mem::size_of::<Nid>(),
)
.cast(),
);
}
} else if self.len() == INLINE_ELEMS {
unsafe {
let mut allcd =
Self::alloc((self.inline.cap + 1).next_power_of_two() as _, self.len());
core::ptr::copy_nonoverlapping(self.as_ptr(), allcd.as_mut_ptr(), self.len());
*self = allcd;
}
}
unsafe {
*self.len_mut() += 1;
self.as_mut_ptr().add(self.len() - 1).write(value);
}
}
unsafe fn alloc(cap: usize, len: usize) -> Self {
debug_assert!(cap > INLINE_ELEMS);
let layout = unsafe { core::alloc::Layout::array::<Nid>(cap).unwrap_unchecked() };
let alloc = unsafe { alloc::alloc(layout) };
unsafe {
Vc {
alloced: AllocedVc {
base: Unique::new_unchecked(alloc.cast()),
len: len as _,
cap: cap as _,
},
}
}
}
pub fn swap_remove(&mut self, index: usize) {
let len = self.len() - 1;
self.as_slice_mut().swap(index, len);
*self.len_mut() -= 1;
}
pub fn remove(&mut self, index: usize) {
self.as_slice_mut().copy_within(index + 1.., index);
*self.len_mut() -= 1;
}
}
impl Drop for Vc {
fn drop(&mut self) {
if let Some(layout) = self.layout() {
unsafe {
alloc::dealloc(self.alloced.base.as_ptr().cast(), layout);
}
}
}
}
impl Clone for Vc {
fn clone(&self) -> Self {
self.as_slice().into()
}
}
impl IntoIterator for Vc {
type IntoIter = VcIntoIter;
type Item = Nid;
fn into_iter(self) -> Self::IntoIter {
VcIntoIter { start: 0, end: self.len(), vc: self }
}
}
pub struct VcIntoIter {
start: usize,
end: usize,
vc: Vc,
}
impl Iterator for VcIntoIter {
type Item = Nid;
fn next(&mut self) -> Option<Self::Item> {
if self.start == self.end {
return None;
}
let ret = unsafe { core::ptr::read(self.vc.as_slice().get_unchecked(self.start)) };
self.start += 1;
Some(ret)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.end - self.start;
(len, Some(len))
}
}
impl DoubleEndedIterator for VcIntoIter {
fn next_back(&mut self) -> Option<Self::Item> {
if self.start == self.end {
return None;
}
self.end -= 1;
Some(unsafe { core::ptr::read(self.vc.as_slice().get_unchecked(self.end)) })
}
}
impl ExactSizeIterator for VcIntoIter {}
impl<const SIZE: usize> From<[Nid; SIZE]> for Vc {
fn from(value: [Nid; SIZE]) -> Self {
value.as_slice().into()
}
}
impl<'a> From<&'a [Nid]> for Vc {
fn from(value: &'a [Nid]) -> Self {
if value.len() <= INLINE_ELEMS {
let mut dflt = Self::default();
unsafe {
core::ptr::copy_nonoverlapping(value.as_ptr(), dflt.as_mut_ptr(), value.len())
};
dflt.inline.cap = value.len() as _;
dflt
} else {
let mut allcd = unsafe { Self::alloc(value.len(), value.len()) };
unsafe {
core::ptr::copy_nonoverlapping(value.as_ptr(), allcd.as_mut_ptr(), value.len())
};
allcd
}
}
}
impl Deref for Vc {
type Target = [Nid];
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
impl DerefMut for Vc {
fn deref_mut(&mut self) -> &mut Self::Target {
self.as_slice_mut()
}
}
#[derive(Clone, Copy)]
#[repr(C)]
struct InlineVc {
cap: Nid,
elems: MaybeUninit<[Nid; INLINE_ELEMS]>,
}
#[derive(Clone, Copy)]
#[repr(C)]
struct AllocedVc {
cap: Nid,
len: Nid,
base: Unique<Nid>,
}

View file

@ -1,292 +0,0 @@
use {
alloc::vec::Vec,
core::{
fmt::Debug,
mem::MaybeUninit,
ops::{Deref, DerefMut, Not},
ptr::Unique,
},
};
type Nid = u16;
const VC_SIZE: usize = 16;
const INLINE_ELEMS: usize = VC_SIZE / 2 - 1;
pub union Vc {
inline: InlineVc,
alloced: AllocedVc,
}
impl Default for Vc {
fn default() -> Self {
Vc { inline: InlineVc { elems: MaybeUninit::uninit(), cap: Default::default() } }
}
}
impl Debug for Vc {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.as_slice().fmt(f)
}
}
impl Vc {
fn is_inline(&self) -> bool {
unsafe { self.inline.cap <= INLINE_ELEMS as Nid }
}
fn layout(&self) -> Option<core::alloc::Layout> {
unsafe {
self.is_inline().not().then(|| {
core::alloc::Layout::array::<Nid>(self.alloced.cap as _).unwrap_unchecked()
})
}
}
pub fn len(&self) -> usize {
unsafe {
if self.is_inline() {
self.inline.cap as _
} else {
self.alloced.len as _
}
}
}
fn len_mut(&mut self) -> &mut Nid {
unsafe {
if self.is_inline() {
&mut self.inline.cap
} else {
&mut self.alloced.len
}
}
}
fn as_ptr(&self) -> *const Nid {
unsafe {
match self.is_inline() {
true => self.inline.elems.as_ptr().cast(),
false => self.alloced.base.as_ptr(),
}
}
}
fn as_mut_ptr(&mut self) -> *mut Nid {
unsafe {
match self.is_inline() {
true => self.inline.elems.as_mut_ptr().cast(),
false => self.alloced.base.as_ptr(),
}
}
}
pub fn as_slice(&self) -> &[Nid] {
unsafe { core::slice::from_raw_parts(self.as_ptr(), self.len()) }
}
fn as_slice_mut(&mut self) -> &mut [Nid] {
unsafe { core::slice::from_raw_parts_mut(self.as_mut_ptr(), self.len()) }
}
pub fn push(&mut self, value: Nid) {
if let Some(layout) = self.layout()
&& unsafe { self.alloced.len == self.alloced.cap }
{
unsafe {
self.alloced.cap *= 2;
self.alloced.base = Unique::new_unchecked(
alloc::alloc::realloc(
self.alloced.base.as_ptr().cast(),
layout,
self.alloced.cap as usize * core::mem::size_of::<Nid>(),
)
.cast(),
);
}
} else if self.len() == INLINE_ELEMS {
unsafe {
let mut allcd =
Self::alloc((self.inline.cap + 1).next_power_of_two() as _, self.len());
core::ptr::copy_nonoverlapping(self.as_ptr(), allcd.as_mut_ptr(), self.len());
*self = allcd;
}
}
unsafe {
*self.len_mut() += 1;
self.as_mut_ptr().add(self.len() - 1).write(value);
}
}
unsafe fn alloc(cap: usize, len: usize) -> Self {
debug_assert!(cap > INLINE_ELEMS);
let layout = unsafe { core::alloc::Layout::array::<Nid>(cap).unwrap_unchecked() };
let alloc = unsafe { alloc::alloc::alloc(layout) };
unsafe {
Vc {
alloced: AllocedVc {
base: Unique::new_unchecked(alloc.cast()),
len: len as _,
cap: cap as _,
},
}
}
}
pub fn swap_remove(&mut self, index: usize) {
let len = self.len() - 1;
self.as_slice_mut().swap(index, len);
*self.len_mut() -= 1;
}
pub fn remove(&mut self, index: usize) {
self.as_slice_mut().copy_within(index + 1.., index);
*self.len_mut() -= 1;
}
}
impl Drop for Vc {
fn drop(&mut self) {
if let Some(layout) = self.layout() {
unsafe {
alloc::alloc::dealloc(self.alloced.base.as_ptr().cast(), layout);
}
}
}
}
impl Clone for Vc {
fn clone(&self) -> Self {
self.as_slice().into()
}
}
impl IntoIterator for Vc {
type IntoIter = VcIntoIter;
type Item = Nid;
fn into_iter(self) -> Self::IntoIter {
VcIntoIter { start: 0, end: self.len(), vc: self }
}
}
pub struct VcIntoIter {
start: usize,
end: usize,
vc: Vc,
}
impl Iterator for VcIntoIter {
type Item = Nid;
fn next(&mut self) -> Option<Self::Item> {
if self.start == self.end {
return None;
}
let ret = unsafe { core::ptr::read(self.vc.as_slice().get_unchecked(self.start)) };
self.start += 1;
Some(ret)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.end - self.start;
(len, Some(len))
}
}
impl DoubleEndedIterator for VcIntoIter {
fn next_back(&mut self) -> Option<Self::Item> {
if self.start == self.end {
return None;
}
self.end -= 1;
Some(unsafe { core::ptr::read(self.vc.as_slice().get_unchecked(self.end)) })
}
}
impl ExactSizeIterator for VcIntoIter {}
impl<const SIZE: usize> From<[Nid; SIZE]> for Vc {
fn from(value: [Nid; SIZE]) -> Self {
value.as_slice().into()
}
}
impl<'a> From<&'a [Nid]> for Vc {
fn from(value: &'a [Nid]) -> Self {
if value.len() <= INLINE_ELEMS {
let mut dflt = Self::default();
unsafe {
core::ptr::copy_nonoverlapping(value.as_ptr(), dflt.as_mut_ptr(), value.len())
};
dflt.inline.cap = value.len() as _;
dflt
} else {
let mut allcd = unsafe { Self::alloc(value.len(), value.len()) };
unsafe {
core::ptr::copy_nonoverlapping(value.as_ptr(), allcd.as_mut_ptr(), value.len())
};
allcd
}
}
}
impl Deref for Vc {
type Target = [Nid];
fn deref(&self) -> &Self::Target {
if self.as_slice().iter().position(|&i| i == 1) == Some(2) {
log::info!("foo {}", std::backtrace::Backtrace::capture());
}
self.as_slice()
}
}
impl DerefMut for Vc {
fn deref_mut(&mut self) -> &mut Self::Target {
self.as_slice_mut()
}
}
#[derive(Clone, Copy)]
#[repr(C)]
struct InlineVc {
cap: Nid,
elems: MaybeUninit<[Nid; INLINE_ELEMS]>,
}
#[derive(Clone, Copy)]
#[repr(C)]
struct AllocedVc {
cap: Nid,
len: Nid,
base: Unique<Nid>,
}
#[derive(Default)]
pub struct BitSet {
data: Vec<usize>,
}
impl BitSet {
const ELEM_SIZE: usize = core::mem::size_of::<usize>() * 8;
pub fn clear(&mut self, bit_size: usize) {
let new_len = bit_size.div_ceil(Self::ELEM_SIZE);
self.data.clear();
self.data.resize(new_len, 0);
}
#[track_caller]
pub fn set(&mut self, idx: Nid) -> bool {
let idx = idx as usize;
let data_idx = idx / Self::ELEM_SIZE;
let sub_idx = idx % Self::ELEM_SIZE;
let prev = self.data[data_idx] & (1 << sub_idx);
self.data[data_idx] |= 1 << sub_idx;
prev == 0
}
}

View file

@ -1,28 +0,0 @@
main:
ADDI64 r254, r254, -32d
ST r31, r254, 0a, 32h
LI64 r32, 10d
LI64 r33, 20d
LI64 r34, 2d
DIRS64 r33, r0, r33, r34
SUB64 r32, r32, r33
LI64 r33, 4d
LI64 r34, 2d
ADDI64 r34, r34, 2d
MUL64 r33, r33, r34
ADD64 r32, r32, r33
LI64 r33, 4d
MULI64 r33, r33, 4d
SUB64 r32, r32, r33
LI64 r33, 1d
SLUI64 r33, r33, 0b
ADD64 r32, r32, r33
LI64 r33, 1d
NEG r33, r33
ADD64 r1, r32, r33
LD r31, r254, 0a, 32h
ADDI64 r254, r254, 32d
JALA r0, r31, 0a
code size: 205
ret: 0
status: Ok(())

View file

@ -1,67 +0,0 @@
main:
ADDI64 r254, r254, -76d
ST r31, r254, 28a, 48h
LI64 r32, 511d
LI64 r33, 0d
ST r33, r254, 0a, 1h
LI64 r33, 0d
ST r33, r254, 1a, 1h
CP r33, r32
ANDI r33, r33, 255d
ST r33, r254, 2a, 1h
CP r33, r32
SRUI16 r33, r33, 8b
ANDI r33, r33, 255d
ST r33, r254, 3a, 1h
ADDI64 r33, r254, 0d
LI64 r34, 1d
ST r34, r254, 4a, 8h
LI64 r34, 2d
ST r34, r254, 12a, 8h
LI64 r34, 4d
ST r34, r254, 20a, 8h
ADDI64 r34, r254, 4d
CP r2, r34
JAL r31, r0, :pass
CP r34, r1
ADDI64 r35, r254, 0d
LI64 r36, 3d
ADD64 r35, r35, r36
CP r36, r0
LD r36, r35, 0a, 1h
SXT8 r36, r36
ADD64 r1, r34, r36
LD r31, r254, 28a, 48h
ADDI64 r254, r254, 76d
JALA r0, r31, 0a
pass:
ADDI64 r254, r254, -48d
ST r31, r254, 0a, 48h
CP r32, r2
CP r33, r32
LI64 r34, 0d
MULI64 r34, r34, 8d
ADD64 r33, r33, r34
LD r34, r33, 0a, 8h
CP r33, r32
LI64 r35, 1d
MULI64 r35, r35, 8d
ADD64 r33, r33, r35
LD r35, r33, 0a, 8h
ADD64 r34, r34, r35
CP r33, r32
CP r35, r32
LI64 r36, 1d
MULI64 r36, r36, 8d
ADD64 r35, r35, r36
LD r36, r35, 0a, 8h
MULI64 r36, r36, 8d
ADD64 r33, r33, r36
LD r36, r33, 0a, 8h
ADD64 r1, r34, r36
LD r31, r254, 0a, 48h
ADDI64 r254, r254, 48d
JALA r0, r31, 0a
code size: 557
ret: 8
status: Ok(())

View file

@ -1,36 +0,0 @@
main:
ADDI64 r254, r254, -40d
ST r31, r254, 0a, 40h
LRA r32, r0, :"abඞ\n\r\t56789\0"
CP r2, r32
JAL r31, r0, :str_len
CP r33, r1
LRA r34, r0, :"fff\0"
CP r2, r34
JAL r31, r0, :str_len
CP r35, r1
ADD64 r1, r35, r33
LD r31, r254, 0a, 40h
ADDI64 r254, r254, 40d
JALA r0, r31, 0a
str_len:
ADDI64 r254, r254, -48d
ST r31, r254, 0a, 48h
CP r32, r2
LI64 r33, 0d
2: CP r34, r32
CP r35, r0
LD r35, r34, 0a, 1h
LI64 r36, 0d
JNE r35, r36, :0
JMP :1
0: ADDI64 r33, r33, 1d
ADDI64 r32, r32, 1d
JMP :2
1: CP r1, r33
LD r31, r254, 0a, 48h
ADDI64 r254, r254, 48d
JALA r0, r31, 0a
code size: 270
ret: 16
status: Ok(())

View file

@ -1,17 +0,0 @@
foo:
ADDI64 r254, r254, -8d
ST r31, r254, 0a, 8h
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
JALA r0, r31, 0a
main:
ADDI64 r254, r254, -8d
ST r31, r254, 0a, 8h
JAL r31, r0, :foo
LI64 r1, 0d
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
JALA r0, r31, 0a
code size: 143
ret: 0
status: Ok(())

View file

@ -1,11 +0,0 @@
main:
ADDI64 r254, r254, -16d
ST r31, r254, 0a, 16h
LRA r32, r0, :a
LD r1, r32, 0a, 8h
LD r31, r254, 0a, 16h
ADDI64 r254, r254, 16d
JALA r0, r31, 0a
code size: 95
ret: 50
status: Ok(())

View file

@ -1,11 +0,0 @@
main:
ADDI64 r254, r254, -16d
ST r31, r254, 0a, 16h
LRA r32, r0, :a
LD r1, r32, 0a, 8h
LD r31, r254, 0a, 16h
ADDI64 r254, r254, 16d
JALA r0, r31, 0a
code size: 218
ret: 50
status: Ok(())

View file

@ -1,57 +0,0 @@
main:
ADDI64 r254, r254, -52d
ST r31, r254, 12a, 40h
LI64 r32, 255d
ST r32, r254, 0a, 1h
LI64 r32, 0d
ST r32, r254, 1a, 1h
LI64 r32, 0d
ST r32, r254, 2a, 1h
LI64 r32, 255d
ST r32, r254, 3a, 1h
LI64 r32, 0d
ST r32, r254, 4a, 4h
LI64 r32, 2d
ST r32, r254, 8a, 4h
LI64 r32, 1d
ADDI64 r33, r254, 4d
CP r34, r32
MULI64 r34, r34, 4d
ADD64 r33, r33, r34
CP r34, r0
LD r34, r33, 0a, 4h
LI64 r35, 2d
JEQ r34, r35, :0
LI64 r1, 0d
JMP :1
0: ADDI64 r35, r254, 8d
ADDI64 r35, r35, -4d
CP r34, r0
LD r34, r35, 0a, 4h
LI64 r33, 0d
JEQ r34, r33, :2
LI64 r1, 64d
JMP :1
2: CP r33, r0
LD r33, r254, 4a, 4h
CP r34, r0
LD r34, r254, 8a, 4h
ADD32 r33, r33, r34
CP r34, r0
LD r34, r254, 0a, 1h
ADD32 r33, r33, r34
CP r34, r0
LD r34, r254, 1a, 1h
ADD32 r33, r33, r34
CP r34, r0
LD r34, r254, 2a, 1h
ADD32 r33, r33, r34
CP r34, r0
LD r34, r254, 3a, 1h
ADD32 r1, r33, r34
1: LD r31, r254, 12a, 40h
ADDI64 r254, r254, 52d
JALA r0, r31, 0a
code size: 474
ret: 512
status: Ok(())

View file

@ -1,30 +0,0 @@
main:
ADDI64 r254, r254, -96d
ST r31, r254, 16a, 80h
LI64 r32, 10d
LI64 r33, 30d
LI64 r34, 40d
CP r35, r34
LI64 r36, 16d
LI64 r37, 8d
LI64 r38, 10d
LI64 r2, 1d
LI64 r39, 10d
ST r39, r254, 0a, 8h
LI64 r39, 20d
ST r39, r254, 8a, 8h
LD r3, r254, 0a, 16h
LI64 r5, 5d
LI64 r6, 6d
ECA
CP r39, r1
LRA r40, r0, :arbitrary text
LI64 r1, 0d
LD r31, r254, 16a, 80h
ADDI64 r254, r254, 96d
JALA r0, r31, 0a
ev: Ecall
code size: 255
ret: 0
status: Ok(())

View file

@ -1,74 +0,0 @@
main:
ADDI64 r254, r254, -80d
ST r31, r254, 0a, 80h
JAL r31, r0, :check_platform
CP r32, r1
LI64 r33, 100d
LI64 r34, 30d
LI64 r35, 0d
LI64 r36, 0d
4: CP r37, r35
CP r38, r34
ADDI64 r38, r38, 1d
CMPS r37, r37, r38
CMPUI r37, r37, 1d
JEQ r37, r0, :0
CP r2, r35
CP r3, r36
CP r4, r33
JAL r31, r0, :set_pixel
CP r37, r1
CP r38, r35
ADDI64 r38, r38, 1d
CP r35, r38
JMP :1
0: CP r2, r35
CP r3, r36
CP r4, r33
JAL r31, r0, :set_pixel
CP r38, r1
LI64 r35, 0d
CP r39, r36
ADDI64 r39, r39, 1d
CP r36, r39
1: CP r39, r36
CP r40, r33
CMPS r39, r39, r40
CMPUI r39, r39, 0d
NOT r39, r39
JEQ r39, r0, :2
JMP :3
2: JMP :4
3: LI64 r1, 0d
LD r31, r254, 0a, 80h
ADDI64 r254, r254, 80d
JALA r0, r31, 0a
set_pixel:
ADDI64 r254, r254, -32d
ST r31, r254, 0a, 32h
CP r32, r2
CP r33, r3
CP r34, r4
MUL64 r33, r33, r34
ADD64 r33, r33, r32
LI64 r1, 0d
LD r31, r254, 0a, 32h
ADDI64 r254, r254, 32d
JALA r0, r31, 0a
check_platform:
ADDI64 r254, r254, -8d
ST r31, r254, 0a, 8h
JAL r31, r0, :x86_fb_ptr
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
JALA r0, r31, 0a
x86_fb_ptr:
ADDI64 r254, r254, -8d
ST r31, r254, 0a, 8h
LI64 r1, 100d
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
JALA r0, r31, 0a
code size: 511
ret: 0
status: Ok(())

View file

@ -1,32 +0,0 @@
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:
ADDI64 r254, r254, -24d
ST r31, r254, 0a, 24h
LI64 r2, 10d
JAL r31, r0, :add_one
CP r32, r1
LI64 r2, 20d
JAL r31, r0, :add_two
CP r33, r1
ADD64 r1, r32, r33
LD r31, r254, 0a, 24h
ADDI64 r254, r254, 24d
JALA r0, r31, 0a
code size: 257
ret: 33
status: Ok(())

View file

@ -1,38 +0,0 @@
add:
ADDI64 r254, r254, -24d
ST r31, r254, 0a, 24h
CP r32, r2
CP r33, r3
ADD64 r1, r32, r33
LD r31, r254, 0a, 24h
ADDI64 r254, r254, 24d
JALA r0, r31, 0a
add:
ADDI64 r254, r254, -24d
ST r31, r254, 0a, 24h
CP r32, r2
CP r33, r3
ADD32 r1, r32, r33
LD r31, r254, 0a, 24h
ADDI64 r254, r254, 24d
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
ret: 0
status: Ok(())

View file

@ -1,144 +0,0 @@
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 r33, r32
CP r1, r33
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:
ADDI64 r254, r254, -48d
ST r31, r254, 24a, 24h
ADDI64 r1, r254, 0d
JAL r31, r0, :new
ADDI64 r32, r254, 0d
CP r2, r32
LI64 r3, 69d
JAL r31, r0, :push
CP r32, r1
LD r32, r254, 0a, 8h
LD r33, r32, 0a, 8h
ADDI64 r32, r254, 0d
CP r2, r32
JAL r31, r0, :deinit
CP r1, r33
LD r31, r254, 24a, 24h
ADDI64 r254, r254, 48d
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
new:
ADDI64 r254, r254, -24d
ST r31, r254, 0a, 24h
CP r32, r1
LI64 r33, 0d
ST r33, r32, 0a, 8h
LI64 r33, 0d
ST r33, r32, 8a, 8h
LI64 r33, 0d
ST r33, r32, 16a, 8h
LD r31, r254, 0a, 24h
ADDI64 r254, r254, 24d
JALA r0, r31, 0a
push:
ADDI64 r254, r254, -80d
ST r31, r254, 0a, 80h
CP r32, r2
CP r33, r3
LD r34, r32, 8a, 8h
LD r35, r32, 16a, 8h
JNE r34, r35, :0
LD r35, r32, 16a, 8h
LI64 r34, 0d
JNE r35, r34, :1
LI64 r34, 1d
ST r34, r32, 16a, 8h
JMP :2
1: LD r34, r32, 16a, 8h
MULI64 r34, r34, 2d
ST r34, r32, 16a, 8h
2: LD r34, r32, 16a, 8h
MULI64 r34, r34, 8d
CP r2, r34
LI64 r3, 8d
JAL r31, r0, :malloc
CP r34, r1
LI64 r35, 0d
JNE r34, r35, :3
LI64 r1, 0d
JMP :4
3: LD r35, r32, 0a, 8h
CP r36, r34
LD r37, r32, 0a, 8h
LD r38, r32, 8a, 8h
MULI64 r38, r38, 8d
ADD64 r37, r37, r38
7: JNE r35, r37, :5
JMP :6
5: CP r38, r36
CP r39, r35
LD r40, r39, 0a, 8h
ST r40, r38, 0a, 8h
ADDI64 r35, r35, 8d
ADDI64 r36, r36, 8d
JMP :7
6: LD r38, r32, 8a, 8h
LI64 r39, 0d
JEQ r38, r39, :8
LD r2, r32, 0a, 8h
LD r39, r32, 8a, 8h
MULI64 r39, r39, 8d
CP r3, r39
LI64 r4, 8d
JAL r31, r0, :free
8: ST r34, r32, 0a, 8h
0: LD r39, r32, 0a, 8h
LD r38, r32, 8a, 8h
MULI64 r38, r38, 8d
ADD64 r39, r39, r38
CP r38, r39
ST r33, r38, 0a, 8h
LD r38, r32, 8a, 8h
ADDI64 r38, r38, 1d
ST r38, r32, 8a, 8h
CP r1, r39
4: LD r31, r254, 0a, 80h
ADDI64 r254, r254, 80d
JALA r0, r31, 0a
code size: 1225
ret: 69
status: Ok(())

View file

@ -1,16 +0,0 @@
main:
ADDI64 r254, r254, -32d
ST r31, r254, 0a, 32h
LRA r32, r0, :complex_global_var
LRA r33, r0, :complex_global_var
LD r34, r33, 0a, 8h
ADDI64 r34, r34, 5d
ST r34, r32, 0a, 8h
LRA r32, r0, :complex_global_var
LD r1, r32, 0a, 8h
LD r31, r254, 0a, 32h
ADDI64 r254, r254, 32d
JALA r0, r31, 0a
code size: 146
ret: 55
status: Ok(())

View file

@ -1,31 +0,0 @@
main:
ADDI64 r254, r254, -56d
ST r31, r254, 0a, 56h
LI64 r32, 255d
LI64 r33, 255d
LI64 r34, 255d
LI64 r35, 255d
CP r36, r32
CMPS r36, r36, r33
CMPUI r36, r36, 0d
NOT r36, r36
CP r37, r34
CMPS r37, r37, r33
CMPUI r37, r37, 0d
NOT r37, r37
AND r36, r36, r37
CP r37, r35
CMPS r37, r37, r33
CMPUI r37, r37, 0d
NOT r37, r37
AND r36, r36, r37
JEQ r36, r0, :0
LI64 r1, 0d
JMP :1
0: LI64 r1, 1d
1: LD r31, r254, 0a, 56h
ADDI64 r254, r254, 56d
JALA r0, r31, 0a
code size: 208
ret: 0
status: Ok(())

View file

@ -1,25 +0,0 @@
main:
ADDI64 r254, r254, -160d
ST r31, r254, 128a, 32h
LI64 r32, 0d
2: LI64 r33, 128d
JLTS r32, r33, :0
JMP :1
0: ADDI64 r33, r254, 0d
CP r34, r32
ADD64 r33, r33, r34
LI64 r34, 69d
ST r34, r33, 0a, 1h
ADDI64 r32, r32, 1d
JMP :2
1: ADDI64 r33, r254, 0d
LI64 r34, 42d
ADD64 r33, r33, r34
CP r1, r0
LD r1, r33, 0a, 1h
LD r31, r254, 128a, 32h
ADDI64 r254, r254, 160d
JALA r0, r31, 0a
code size: 195
ret: 69
status: Ok(())

View file

@ -1,33 +0,0 @@
fib:
ADDI64 r254, r254, -32d
ST r31, r254, 0a, 32h
CP r32, r2
LI64 r33, 2d
JGTS r32, r33, :0
LI64 r1, 1d
JMP :1
0: CP r33, r32
ADDI64 r33, r33, -1d
CP r2, r33
JAL r31, r0, :fib
CP r33, r1
CP r34, r32
ADDI64 r34, r34, -2d
CP r2, r34
JAL r31, r0, :fib
CP r34, r1
ADD64 r1, r33, r34
1: LD r31, r254, 0a, 32h
ADDI64 r254, r254, 32d
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: 234
ret: 55
status: Ok(())

View file

@ -1,13 +0,0 @@
main:
ADDI64 r254, r254, -24d
ST r31, r254, 0a, 24h
LI64 r33, 1d
ADDI64 r33, r33, 2d
ADDI64 r32, r33, 3d
ADDI64 r1, r32, -6d
LD r31, r254, 0a, 24h
ADDI64 r254, r254, 24d
JALA r0, r31, 0a
code size: 110
ret: 0
status: Ok(())

View file

@ -1,162 +0,0 @@
example:
ADDI64 r254, r254, -48d
ST r31, r254, 0a, 48h
LI64 r2, 3d
LI64 r3, 4d
ECA
CP r33, r1
LI64 r34, 0d
LI64 r35, 0d
CMPS r34, r34, r35
CMPUI r34, r34, 0d
LI64 r35, 1024d
LI64 r36, 0d
CMPS r35, r35, r36
CMPUI r35, r35, 0d
OR r34, r34, r35
JEQ r34, r0, :0
CP r34, r33
LI64 r35, 1024d
ADDI64 r35, r35, 0d
ADDI64 r35, r35, 1d
DIRS64 r0, r34, r34, r35
ADDI64 r32, r34, 0d
JMP :1
0: CP r32, r33
1: LI64 r2, 0d
LI64 r3, 768d
JAL r31, r0, :integer
CP r33, r1
CP r34, r32
JMP :2
2: LD r31, r254, 0a, 48h
ADDI64 r254, r254, 48d
JALA r0, r31, 0a
integer:
ADDI64 r254, r254, -56d
ST r31, r254, 0a, 56h
CP r32, r2
CP r33, r3
LI64 r2, 3d
LI64 r3, 4d
ECA
CP r34, r1
CP r35, r32
LI64 r36, 0d
CMPS r35, r35, r36
CMPUI r35, r35, 0d
CP r36, r33
LI64 r37, 0d
CMPS r36, r36, r37
CMPUI r36, r36, 0d
OR r35, r35, r36
JEQ r35, r0, :0
CP r35, r34
CP r36, r33
SUB64 r36, r36, r32
ADDI64 r36, r36, 1d
DIRS64 r0, r35, r35, r36
ADD64 r1, r35, r32
JMP :1
0: CP r1, r34
1: LD r31, r254, 0a, 56h
ADDI64 r254, r254, 56d
JALA r0, r31, 0a
line:
ADDI64 r254, r254, -80d
ST r31, r254, 48a, 32h
ST r2, r254, 0a, 16h
ST r4, r254, 16a, 16h
ST r6, r254, 32a, 16h
CP r32, r8
LI64 r33, 1d
JEQ r33, r0, :0
LD r33, r254, 0a, 8h
LD r34, r254, 16a, 8h
JGTS r33, r34, :1
JMP :1
1: JMP :2
0: LD r34, r254, 8a, 8h
LD r33, r254, 24a, 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, -112d
ST r31, r254, 96a, 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, 48a, 8h
LI64 r32, 0d
ST r32, r254, 56a, 8h
LD r2, r254, 48a, 16h
LI64 r32, 0d
ST r32, r254, 64a, 8h
LI64 r32, 0d
ST r32, r254, 72a, 8h
LD r4, r254, 64a, 16h
LI64 r32, 0d
ST r32, r254, 80a, 8h
LI64 r32, 0d
ST r32, r254, 88a, 8h
LD r6, r254, 80a, 16h
LI64 r8, 10d
JAL r31, r0, :rect_line
JAL r31, r0, :example
LI64 r1, 0d
LD r31, r254, 96a, 16h
ADDI64 r254, r254, 112d
JALA r0, r31, 0a
rect_line:
ADDI64 r254, r254, -112d
ST r31, r254, 48a, 64h
ST r2, r254, 0a, 16h
ST r4, r254, 16a, 16h
ST r6, r254, 32a, 16h
CP r32, r8
LI64 r33, 0d
LI64 r34, 0d
LI64 r35, 0d
5: JNE r33, r32, :0
JMP :1
0: LD r34, r254, 8a, 8h
LD r35, r254, 0a, 8h
4: LD r36, r254, 8a, 8h
LD r37, r254, 16a, 8h
ADD64 r36, r36, r37
JNE r34, r36, :2
JMP :3
2: LI64 r36, 1d
LI64 r37, 10d
ADD64 r36, r36, r37
LI64 r37, 1d
LI64 r38, 2d
ADD64 r36, r37, r38
ADDI64 r34, r34, 1d
JMP :4
3: ADDI64 r33, r33, 1d
JMP :5
1: LD r31, r254, 48a, 64h
ADDI64 r254, r254, 112d
JALA r0, r31, 0a
code size: 1403
ret: 0
status: Ok(())

View file

@ -1,18 +0,0 @@
main:
ADDI64 r254, r254, -32d
ST r31, r254, 0a, 32h
LI64 r32, 10d
NEG r32, r32
CP r33, r32
LI64 r34, 8d
ADDI64 r34, r34, -1d
SRS64 r33, r33, r34
CP r34, r32
XOR r34, r34, r33
SUB64 r1, r34, r33
LD r31, r254, 0a, 32h
ADDI64 r254, r254, 32d
JALA r0, r31, 0a
code size: 119
ret: 10
status: Ok(())

View file

@ -1,30 +0,0 @@
integer_range:
ADDI64 r254, r254, -40d
ST r31, r254, 0a, 40h
CP r32, r2
CP r33, r3
LI64 r2, 3d
LI64 r3, 4d
ECA
CP r34, r1
CP r35, r33
SUB64 r35, r35, r32
ADDI64 r35, r35, 1d
DIRU64 r0, r34, r34, r35
ADD64 r1, r34, r32
LD r31, r254, 0a, 40h
ADDI64 r254, r254, 40d
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: 213
ret: 42
status: Ok(())

View file

@ -1,30 +0,0 @@
fib:
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, -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
ret: 55
status: Ok(())

View file

@ -1,47 +0,0 @@
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:
ADDI64 r254, r254, -48d
ST r31, r254, 8a, 40h
LI64 r32, 1d
ST r32, r254, 0a, 8h
ADDI64 r32, r254, 0d
LI64 r33, 1000d
CP r34, r32
CP r35, r33
MULI64 r35, r35, 8d
ADD64 r34, r34, r35
ADDI64 r32, r34, -16d
CP r34, r33
ADDI64 r34, r34, -2d
CP r35, r34
MULI64 r35, r35, 8d
SUB64 r32, r32, r35
CP r2, r32
JAL r31, r0, :modify
LD r2, r254, 0a, 8h
JAL r31, r0, :drop
CP r34, r32
LD r35, r34, 0a, 8h
ADDI64 r1, r35, -2d
LD r31, r254, 8a, 40h
ADDI64 r254, r254, 48d
JALA r0, r31, 0a
modify:
ADDI64 r254, r254, -32d
ST r31, r254, 0a, 32h
CP r32, r2
CP r33, r32
LI64 r34, 2d
ST r34, r33, 0a, 8h
LD r31, r254, 0a, 32h
ADDI64 r254, r254, 32d
JALA r0, r31, 0a
code size: 382
ret: 0
status: Ok(())

View file

@ -1,61 +0,0 @@
create_back_buffer:
ADDI64 r254, r254, -40d
ST r31, r254, 0a, 40h
CP r32, r2
LI64 r33, 255d
JGTS r32, r33, :0
CP r2, r32
JAL r31, r0, :request_page
JMP :1
0: LI64 r2, 255d
JAL r31, r0, :request_page
CP r33, r1
CP r34, r32
ADDI64 r34, r34, -255d
6: LI64 r35, 0d
JGTS r34, r35, :2
JMP :3
2: LI64 r35, 255d
JLTS r34, r35, :4
LI64 r2, 255d
JAL r31, r0, :request_page
CP r35, r1
JMP :5
4: CP r2, r34
JAL r31, r0, :request_page
CP r35, r1
5: ADDI64 r34, r34, -255d
JMP :6
3: CP r1, r33
1: LD r31, r254, 0a, 40h
ADDI64 r254, r254, 40d
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:
ADDI64 r254, r254, -40d
ST r31, r254, 0a, 40h
CP r32, r2
LRA r33, r0, :"\0\u{1}xxxxxxxx\0"
CP r34, r33
ADDI64 r34, r34, 1d
CP r35, r34
ST r32, r35, 0a, 1h
LI64 r2, 3d
LI64 r3, 2d
CP r4, r33
LI64 r5, 12d
ECA
LD r31, r254, 0a, 40h
ADDI64 r254, r254, 40d
JALA r0, r31, 0a
code size: 449
ret: 42
status: Ok(())

View file

@ -1,36 +0,0 @@
main:
ADDI64 r254, r254, -8d
ST r31, r254, 0a, 8h
LI64 r2, 1d
JAL r31, r0, :sqrt
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
JALA r0, r31, 0a
sqrt:
ADDI64 r254, r254, -56d
ST r31, r254, 0a, 56h
CP r32, r2
LI64 r33, 0d
LI64 r34, 0d
LI64 r35, 32768d
LI64 r36, 15d
3: LI64 r37, 0d
JNE r35, r37, :0
JMP :1
0: ADDI64 r36, r36, -1d
CP r37, r34
SLUI64 r37, r37, 1b
ADD64 r33, r35, r37
SLU64 r33, r33, r36
JLTS r32, r33, :2
ADD64 r34, r34, r35
SUB64 r32, r32, r33
2: SRUI64 r35, r35, 1b
JMP :3
1: CP r1, r34
LD r31, r254, 0a, 56h
ADDI64 r254, r254, 56d
JALA r0, r31, 0a
code size: 257
ret: 1
status: Ok(())

View file

@ -1,130 +0,0 @@
main:
ADDI64 r254, r254, -160d
ST r31, r254, 136a, 24h
LI64 r32, 0d
ST r32, r254, 0a, 1h
LI64 r32, 0d
ST r32, r254, 1a, 1h
LI64 r32, 0d
ST r32, r254, 2a, 1h
LI64 r32, 0d
ST r32, r254, 3a, 1h
LI64 r32, 1d
ST r32, r254, 4a, 1h
LI64 r32, 1d
ST r32, r254, 5a, 1h
LI64 r32, 1d
ST r32, r254, 6a, 1h
LI64 r32, 1d
ST r32, r254, 7a, 1h
CP r32, r0
LD r32, r254, 0a, 1h
CP r33, r0
LD r33, r254, 4a, 1h
ADD8 r32, r32, r33
ST r32, r254, 0a, 1h
CP r32, r0
LD r32, r254, 1a, 1h
CP r33, r0
LD r33, r254, 5a, 1h
ADD8 r32, r32, r33
ST r32, r254, 1a, 1h
CP r32, r0
LD r32, r254, 2a, 1h
CP r33, r0
LD r33, r254, 6a, 1h
ADD8 r32, r32, r33
ST r32, r254, 2a, 1h
CP r32, r0
LD r32, r254, 3a, 1h
CP r33, r0
LD r33, r254, 7a, 1h
ADD8 r32, r32, r33
ST r32, r254, 3a, 1h
CP r32, r0
LD r32, r254, 2a, 1h
CP r33, r0
LD r33, r254, 1a, 1h
ADD8 r32, r32, r33
CP r33, r0
LD r33, r254, 0a, 1h
ADD8 r32, r32, r33
CP r33, r0
LD r33, r254, 3a, 1h
ADD8 r32, r32, r33
LI64 r33, 4d
JEQ r32, r33, :0
LI64 r1, 1008d
JMP :1
0: LI64 r33, 1d
ST r33, r254, 8a, 8h
LI64 r33, 2d
ST r33, r254, 16a, 8h
LI64 r33, 3d
ST r33, r254, 24a, 8h
LI64 r33, 4d
ST r33, r254, 32a, 8h
LD r33, r254, 8a, 8h
LD r32, r254, 24a, 8h
ADD64 r33, r33, r32
ST r33, r254, 40a, 8h
LD r33, r254, 16a, 8h
LD r32, r254, 32a, 8h
ADD64 r33, r33, r32
ST r33, r254, 48a, 8h
LD r33, r254, 24a, 8h
LD r32, r254, 8a, 8h
SUB64 r33, r33, r32
ST r33, r254, 56a, 8h
LD r33, r254, 32a, 8h
LD r32, r254, 16a, 8h
SUB64 r33, r33, r32
ST r33, r254, 64a, 8h
LI64 r33, 0d
ST r33, r254, 72a, 8h
LI64 r33, 0d
ST r33, r254, 80a, 8h
LD r33, r254, 72a, 8h
LD r32, r254, 24a, 8h
SUB64 r33, r33, r32
ST r33, r254, 88a, 8h
LD r33, r254, 80a, 8h
LD r32, r254, 32a, 8h
SUB64 r33, r33, r32
ST r33, r254, 96a, 8h
ADDI64 r33, r254, 8d
ADDI64 r32, r254, 104d
BMC r33, r32, 16h
LD r32, r254, 88a, 8h
LD r33, r254, 40a, 8h
ADD64 r32, r32, r33
ST r32, r254, 88a, 8h
LD r32, r254, 96a, 8h
LD r33, r254, 48a, 8h
ADD64 r32, r32, r33
ST r32, r254, 96a, 8h
LD r32, r254, 104a, 8h
LD r33, r254, 56a, 8h
ADD64 r32, r32, r33
ST r32, r254, 104a, 8h
LD r32, r254, 112a, 8h
LD r33, r254, 64a, 8h
ADD64 r32, r32, r33
ST r32, r254, 112a, 8h
LD r32, r254, 88a, 8h
LD r33, r254, 104a, 8h
ADD64 r32, r32, r33
ST r32, r254, 120a, 8h
LD r32, r254, 96a, 8h
LD r33, r254, 112a, 8h
ADD64 r32, r32, r33
ST r32, r254, 128a, 8h
LD r32, r254, 120a, 8h
LD r33, r254, 128a, 8h
ADD64 r1, r32, r33
1: LD r31, r254, 136a, 24h
ADDI64 r254, r254, 160d
JALA r0, r31, 0a
code size: 1264
ret: 10
status: Ok(())

View file

@ -1,64 +0,0 @@
fib:
ADDI64 r254, r254, -32d
ST r31, r254, 0a, 32h
CP r32, r2
LI64 r33, 2d
JLTS r32, r33, :0
CP r33, r32
ADDI64 r33, r33, -1d
CP r2, r33
JAL r31, r0, :fib
CP r33, r1
CP r34, r32
ADDI64 r34, r34, -2d
CP r2, r34
JAL r31, r0, :fib
CP r34, r1
ADD64 r1, r33, r34
JMP :1
0: CP r1, r32
1: LD r31, r254, 0a, 32h
ADDI64 r254, r254, 32d
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, -34d
ST r31, r254, 2a, 32h
LI64 r32, 10d
ST r32, r254, 0a, 1h
LI64 r32, 10d
ST r32, r254, 1a, 1h
CP r32, r0
LD r32, r254, 1a, 1h
CP r2, r0
LD r2, r254, 0a, 1h
JAL r31, r0, :fib
CP r33, r1
CP r2, r32
JAL r31, r0, :fib_iter
CP r34, r1
SUB64 r1, r33, r34
LD r31, r254, 2a, 32h
ADDI64 r254, r254, 34d
JALA r0, r31, 0a
code size: 449
ret: 0
status: Ok(())

View file

@ -1,39 +0,0 @@
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:
ADDI64 r254, r254, -72d
ST r31, r254, 48a, 24h
LI64 r32, 7d
JAL r31, r0, :foo
ST r1, r254, 0a, 16h
LD r33, r254, 0a, 8h
SUB64 r32, r32, r33
JAL r31, r0, :foo
ST r1, r254, 16a, 16h
CP r33, r0
LD r33, r254, 24a, 4h
SXT32 r33, r33
SUB64 r32, r32, r33
JAL r31, r0, :foo
ST r1, r254, 32a, 16h
CP r33, r0
LD r33, r254, 44a, 4h
SXT32 r33, r33
SUB64 r1, r32, r33
LD r31, r254, 48a, 24h
ADDI64 r254, r254, 72d
JALA r0, r31, 0a
code size: 341
ret: 0
status: Ok(())

View file

@ -1,52 +0,0 @@
main:
ADDI64 r254, r254, -72d
ST r31, r254, 48a, 24h
LI64 r32, 3d
LI64 r33, 3d
JEQ r32, r33, :0
LI64 r1, 9001d
JMP :1
0: LI64 r33, 4d
ST r33, r254, 0a, 8h
LI64 r33, 1d
ST r33, r254, 8a, 8h
LI64 r33, 3d
ST r33, r254, 16a, 8h
ADDI64 r2, r254, 0d
ADDI64 r1, r254, 24d
JAL r31, r0, :odher_pass
LD r33, r254, 40a, 8h
LI64 r32, 3d
JNE r33, r32, :2
ADDI64 r32, r254, 24d
CP r2, r32
JAL r31, r0, :pass
JMP :1
2: LI64 r1, 0d
1: LD r31, r254, 48a, 24h
ADDI64 r254, r254, 72d
JALA r0, r31, 0a
odher_pass:
ADDI64 r254, r254, -40d
ST r31, r254, 0a, 40h
CP r32, r2
CP r33, r1
CP r34, r32
CP r35, r33
BMC r34, r35, 24h
LD r31, r254, 0a, 40h
ADDI64 r254, r254, 40d
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: 437
ret: 3
status: Ok(())

View file

@ -1,38 +0,0 @@
main:
ADDI64 r254, r254, -10272d
ST r31, r254, 10240a, 32h
LI64 r32, 0d
2: LI64 r33, 1024d
JLTS r32, r33, :0
JMP :1
0: ADDI64 r33, r254, 0d
CP r34, r32
ADD64 r33, r33, r34
LI64 r34, 64d
ST r34, r33, 0a, 1h
ADDI64 r32, r32, 1d
JMP :2
1: LI64 r32, 1d
5: LI64 r33, 10d
JLTS r32, r33, :3
JMP :4
3: ADDI64 r33, r254, 0d
CP r34, r32
MULI64 r34, r34, 1024d
ADD64 r33, r33, r34
ADDI64 r34, r254, 0d
BMC r34, r33, 1024h
ADDI64 r32, r32, 1d
JMP :5
4: LI64 r33, 1024d
MULI64 r33, r33, 2d
ADDI64 r34, r254, 0d
ADD64 r34, r34, r33
CP r1, r0
LD r1, r34, 0a, 1h
LD r31, r254, 10240a, 32h
ADDI64 r254, r254, 10272d
JALA r0, r31, 0a
code size: 297
ret: 64
status: Ok(())

View file

@ -1,13 +0,0 @@
main:
ADDI64 r254, r254, -24d
ST r31, r254, 0a, 24h
LI64 r32, 1d
LI64 r33, 2d
ADDI64 r32, r32, 1d
SUB64 r1, r32, r33
LD r31, r254, 0a, 24h
ADDI64 r254, r254, 24d
JALA r0, r31, 0a
code size: 102
ret: 0
status: Ok(())

View file

@ -1,46 +0,0 @@
main:
ADDI64 r254, r254, -56d
ST r31, r254, 24a, 32h
CP r32, r3
CP r33, r4
JAL r31, r0, :small_struct
CP r34, r1
LI64 r34, 0d
ST r34, r254, 0a, 1h
LI64 r34, 0d
ST r34, r254, 1a, 1h
LI64 r34, 0d
ST r34, r254, 2a, 1h
LI64 r34, 0d
ST r34, r254, 3a, 1h
LI64 r34, 0d
ST r34, r254, 4a, 1h
LI64 r34, 0d
ST r34, r254, 5a, 1h
LI64 r34, 0d
ST r34, r254, 6a, 1h
LI64 r34, 0d
ST r34, r254, 7a, 1h
LD r34, r254, 0a, 8h
ST r34, r254, 8a, 8h
LD r34, r254, 0a, 8h
ST r34, r254, 16a, 8h
LD r1, r254, 8a, 16h
LD r31, r254, 24a, 32h
ADDI64 r254, r254, 56d
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: 453
ret: 0
status: Ok(())

View file

@ -1,26 +0,0 @@
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:
ADDI64 r254, r254, -8d
ST r31, r254, 0a, 8h
JAL r31, r0, :outl
JAL r31, r0, :inl
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
JALA r0, r31, 0a
outl:
ADDI64 r254, r254, -24d
ST r31, r254, 0a, 24h
LRA r32, r0, :"whahaha\0"
LI64 r33, 0d
LD r31, r254, 0a, 24h
ADDI64 r254, r254, 24d
JALA r0, r31, 0a
code size: 239
ret: 0
status: Ok(())

View file

@ -0,0 +1,6 @@
main:
LI64 r1, 0d
JALA r0, r31, 0a
code size: 29
ret: 0
status: Ok(())

View file

@ -1,37 +1,27 @@
main: main:
ADDI64 r254, r254, -108d ADDI64 r254, r254, -56d
ST r31, r254, 28a, 80h ST r31, r254, 24a, 32h
LI64 r32, 4d LI64 r32, 1d
LI64 r33, 1d
LI64 r34, 2d
LI64 r35, 3d
LI64 r36, 1d
LI64 r37, 0d
ADDI64 r2, r254, 0d ADDI64 r2, r254, 0d
ADDI64 r38, r254, 24d ST r32, r254, 0a, 8h
ST r37, r254, 24a, 1h LI64 r33, 2d
ST r37, r254, 25a, 1h ST r33, r254, 8a, 8h
ST r35, r254, 26a, 1h LI64 r34, 4d
ST r33, r254, 27a, 1h ST r34, r254, 16a, 8h
ST r36, r254, 0a, 8h
ST r34, r254, 8a, 8h
ST r32, r254, 16a, 8h
JAL r31, r0, :pass JAL r31, r0, :pass
LD r39, r254, 27a, 1h ADD64 r1, r1, r32
ANDI r40, r39, 255d LD r31, r254, 24a, 32h
ADD64 r1, r1, r40 ADDI64 r254, r254, 56d
LD r31, r254, 28a, 80h
ADDI64 r254, r254, 108d
JALA r0, r31, 0a JALA r0, r31, 0a
pass: pass:
LD r3, r2, 8a, 8h LD r4, r2, 8a, 8h
MULI64 r8, r3, 8d MULI64 r7, r4, 8d
ADD64 r10, r8, r2 LD r5, r2, 0a, 8h
LD r8, r10, 0a, 8h ADD64 r10, r7, r2
LD r9, r2, 0a, 8h ADD64 r9, r4, r5
ADD64 r11, r3, r9 LD r1, r10, 0a, 8h
ADD64 r1, r8, r11 ADD64 r1, r1, r9
JALA r0, r31, 0a JALA r0, r31, 0a
code size: 348 code size: 231
ret: 8 ret: 8
status: Ok(()) status: Ok(())

View file

@ -0,0 +1,7 @@
main:
LRA r1, r0, :SIN_TABLE
LD r1, r1, 80a, 8h
JALA r0, r31, 0a
code size: 767
ret: 1736
status: Ok(())

View file

@ -11,7 +11,7 @@ main:
ADDI64 r254, r254, 16d ADDI64 r254, r254, 16d
JALA r0, r31, 0a JALA r0, r31, 0a
str_len: str_len:
LI64 r6, 0d LI8 r6, 0b
LI64 r1, 0d LI64 r1, 0d
2: LD r8, r2, 0a, 1h 2: LD r8, r2, 0a, 1h
ANDI r8, r8, 255d ANDI r8, r8, 255d
@ -22,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: 223 code size: 216
ret: 16 ret: 16
status: Ok(()) status: Ok(())

View file

@ -2,8 +2,8 @@ cond:
LI64 r1, 0d LI64 r1, 0d
JALA r0, r31, 0a JALA r0, r31, 0a
main: main:
ADDI64 r254, r254, -32d ADDI64 r254, r254, -24d
ST r31, r254, 8a, 24h ST r31, r254, 0a, 24h
JAL r31, r0, :cond JAL r31, r0, :cond
LI64 r32, 0d LI64 r32, 0d
CP r33, r32 CP r33, r32
@ -12,11 +12,9 @@ main:
CP r1, r32 CP r1, r32
JMP :1 JMP :1
0: LI64 r1, 2d 0: LI64 r1, 2d
1: ADDI64 r33, r254, 0d 1: LD r31, r254, 0a, 24h
ST r1, r254, 0a, 8h ADDI64 r254, r254, 24d
LD r31, r254, 8a, 24h
ADDI64 r254, r254, 32d
JALA r0, r31, 0a JALA r0, r31, 0a
code size: 158 code size: 134
ret: 0 ret: 0
status: Ok(()) status: Ok(())

View file

@ -0,0 +1,6 @@
main:
LI64 r1, 0d
JALA r0, r31, 0a
code size: 29
ret: 0
status: Ok(())

View file

@ -0,0 +1,5 @@
main:
UN
code size: 9
ret: 0
status: Err(Unreachable)

View file

@ -1,54 +1,30 @@
main: main:
ADDI64 r254, r254, -24d ADDI64 r254, r254, -12d
LI64 r9, 2d LI8 r1, 255b
LI64 r8, 0d ST r1, r254, 0a, 1h
LI64 r6, 0d LI8 r4, 0b
LI64 r7, 255d ST r4, r254, 1a, 1h
ADDI64 r10, r254, 0d ST r4, r254, 2a, 1h
ADDI64 r10, r254, 8d ST r1, r254, 3a, 1h
ST r7, r254, 8a, 1h LI32 r9, 0w
ST r6, r254, 9a, 1h
ST r6, r254, 10a, 1h
ST r7, r254, 11a, 1h
LD r3, r254, 8a, 4h
ADDI64 r12, r254, 12d
ST r3, r254, 12a, 4h
ST r8, r254, 0a, 4h
ST r9, r254, 4a, 4h ST r9, r254, 4a, 4h
LD r1, r254, 0a, 8h LI32 r12, 2w
ST r1, r254, 16a, 8h ST r12, r254, 8a, 4h
LD r3, r254, 20a, 4h LD r3, r254, 8a, 4h
ANDI r3, r3, 4294967295d ANDI r3, r3, 4294967295d
ANDI r9, r9, 4294967295d ANDI r12, r12, 4294967295d
JEQ r3, r9, :0 JEQ r3, r12, :0
LI64 r1, 0d LI64 r1, 0d
JMP :1 JMP :1
0: ADDI64 r10, r12, 8d 0: LD r10, r254, 4a, 4h
ADDI64 r10, r10, -4d ANDI r10, r10, 4294967295d
LD r1, r10, 0a, 4h ANDI r9, r9, 4294967295d
ANDI r1, r1, 4294967295d JEQ r10, r9, :2
ANDI r8, r8, 4294967295d
JEQ r1, r8, :2
LI64 r1, 64d LI64 r1, 64d
JMP :1 JMP :1
2: LD r7, r254, 15a, 1h 2: LI64 r1, 512d
ANDI r9, r7, 255d 1: ADDI64 r254, r254, 12d
LD r6, r254, 14a, 1h
ANDI r8, r6, 255d
LD r5, r254, 13a, 1h
ANDI r7, r5, 255d
LD r3, r254, 12a, 1h
ANDI r6, r3, 255d
LD r4, r254, 20a, 4h
LD r5, r254, 16a, 4h
ADD32 r10, r4, r5
ADD32 r11, r10, r6
ADD32 r3, r11, r7
ADD32 r7, r3, r8
ADD32 r11, r7, r9
ANDI r1, r11, 4294967295d
1: ADDI64 r254, r254, 24d
JALA r0, r31, 0a JALA r0, r31, 0a
code size: 529 code size: 257
ret: 512 ret: 512
status: Ok(()) status: Ok(())

View file

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

View file

@ -15,55 +15,65 @@ continue_and_state_change:
4: ADDI64 r2, r2, 1d 4: ADDI64 r2, r2, 1d
3: JMP :6 3: JMP :6
5: JALA r0, r31, 0a 5: JALA r0, r31, 0a
infinite_loop:
ADDI64 r254, r254, -24d
ST r31, r254, 0a, 24h
LI64 r32, 1d
LI64 r33, 0d
CP r1, r33
1: JNE r1, r32, :0
JMP :0
0: CP r2, r33
JAL r31, r0, :continue_and_state_change
JMP :1
LD r31, r254, 0a, 24h
ADDI64 r254, r254, 24d
JALA r0, r31, 0a
main: main:
ADDI64 r254, r254, -80d ADDI64 r254, r254, -64d
ST r31, r254, 0a, 80h 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 r33, r32 CP r33, r1
CP r34, r1
LI64 r1, 3d LI64 r1, 3d
JEQ r34, r1, :0 JEQ r33, r1, :0
LI64 r1, 1d LI64 r1, 1d
JMP :1 JMP :1
0: CP r35, r1 0: CP r34, r1
LI64 r36, 4d LI64 r35, 4d
CP r2, r36 CP r2, r35
JAL r31, r0, :multiple_breaks JAL r31, r0, :multiple_breaks
CP r37, r36 CP r36, r35
LI64 r38, 10d LI64 r37, 10d
JEQ r1, r38, :2 JEQ r1, r37, :2
LI64 r1, 2d LI64 r1, 2d
JMP :1 JMP :1
2: CP r2, r33 2: CP r2, r32
JAL r31, r0, :state_change_in_break JAL r31, r0, :state_change_in_break
CP r39, r1 JEQ r1, r32, :3
CP r1, r33 CP r1, r34
JEQ r39, r1, :3
CP r1, r35
JMP :1 JMP :1
3: CP r33, r1 3: CP r2, r36
CP r2, r37
JAL r31, r0, :state_change_in_break JAL r31, r0, :state_change_in_break
JEQ r1, r38, :4 JEQ r1, r37, :4
CP r1, r37 CP r1, r36
JMP :1 JMP :1
4: CP r2, r38 4: CP r2, r37
JAL r31, r0, :continue_and_state_change JAL r31, r0, :continue_and_state_change
JEQ r1, r38, :5 JEQ r1, r37, :5
LI64 r1, 5d LI64 r1, 5d
JMP :1 JMP :1
5: CP r2, r35 5: CP r2, r34
JAL r31, r0, :continue_and_state_change JAL r31, r0, :continue_and_state_change
CP r40, r1 JEQ r1, r32, :6
CP r1, r33
JEQ r40, r1, :6
LI64 r1, 6d LI64 r1, 6d
JMP :1 JMP :1
6: CP r1, r33 6: CP r38, r32
1: LD r31, r254, 0a, 80h JAL r31, r0, :infinite_loop
ADDI64 r254, r254, 80d CP r1, r38
1: LD r31, r254, 0a, 64h
ADDI64 r254, r254, 64d
JALA r0, r31, 0a JALA r0, r31, 0a
multiple_breaks: multiple_breaks:
LI64 r6, 3d LI64 r6, 3d
@ -89,6 +99,7 @@ state_change_in_break:
2: ADDI64 r2, r2, 1d 2: ADDI64 r2, r2, 1d
JMP :4 JMP :4
3: JALA r0, r31, 0a 3: JALA r0, r31, 0a
code size: 569 timed out
ret: 0 code size: 668
ret: 10
status: Ok(()) status: Ok(())

View file

@ -0,0 +1,6 @@
main:
LI32 r1, 3212836864w
JALA r0, r31, 0a
code size: 25
ret: 3212836864
status: Ok(())

View file

@ -0,0 +1,24 @@
add:
ADD64 r1, r2, r3
JALA r0, r31, 0a
add:
ADD32 r1, r2, r3
JALA r0, r31, 0a
main:
ADDI64 r254, r254, -24d
ST r31, r254, 0a, 24h
LI32 r3, 2w
CP r2, r3
JAL r31, r0, :add
CP r32, r1
LI64 r3, 3d
LI64 r2, 1d
JAL r31, r0, :add
ANDI r33, r32, 4294967295d
SUB64 r1, r33, r1
LD r31, r254, 0a, 24h
ADDI64 r254, r254, 24d
JALA r0, r31, 0a
code size: 158
ret: 0
status: Ok(())

View file

@ -0,0 +1,127 @@
deinit:
ADDI64 r254, r254, -32d
ST r31, r254, 0a, 32h
CP r32, r2
LD r33, r2, 16a, 8h
LI64 r4, 8d
MUL64 r3, r33, r4
CP r34, r32
LD r2, r34, 0a, 8h
JAL r31, r0, :free
CP r1, r32
JAL r31, r0, :new
LD r31, r254, 0a, 32h
ADDI64 r254, r254, 32d
JALA r0, r31, 0a
free:
CP r10, r2
LRA r7, r0, :FREE_SYS_CALL
LD r2, r7, 0a, 8h
CP r5, r4
CP r4, r3
CP r3, r10
ECA
JALA r0, r31, 0a
main:
ADDI64 r254, r254, -56d
ST r31, r254, 24a, 32h
ADDI64 r32, r254, 0d
CP r1, r32
JAL r31, r0, :new
LI64 r3, 69d
CP r2, r32
JAL r31, r0, :push
LD r33, r254, 0a, 8h
LD r34, r33, 0a, 8h
CP r2, r32
JAL r31, r0, :deinit
CP r1, r34
LD r31, r254, 24a, 32h
ADDI64 r254, r254, 56d
JALA r0, r31, 0a
malloc:
CP r9, r2
LRA r5, r0, :MALLOC_SYS_CALL
LD r2, r5, 0a, 8h
CP r4, r3
CP r3, r9
ECA
JALA r0, r31, 0a
new:
ADDI64 r254, r254, -24d
LI64 r4, 0d
ADDI64 r5, r254, 0d
ST r4, r254, 0a, 8h
ST r4, r254, 8a, 8h
ST r4, r254, 16a, 8h
BMC r5, r1, 24h
ADDI64 r254, r254, 24d
JALA r0, r31, 0a
push:
ADDI64 r254, r254, -192d
ST r31, r254, 0a, 192h
CP r32, r3
LI64 r33, 1d
LD r34, r2, 8a, 8h
LD r35, r2, 16a, 8h
CP r36, r2
JNE r35, r34, :0
LI64 r37, 0d
JNE r35, r37, :1
CP r38, r33
JMP :2
1: MULI64 r38, r35, 2d
2: LI64 r39, 8d
MUL64 r2, r38, r39
CP r3, r39
JAL r31, r0, :malloc
CP r40, r1
CP r41, r36
ST r38, r41, 16a, 8h
LI64 r1, 0d
CP r42, r40
JNE r42, r1, :3
JMP :4
3: CP r40, r42
LD r36, r41, 8a, 8h
MULI64 r43, r36, 8d
LD r44, r41, 0a, 8h
ADD64 r45, r44, r43
CP r46, r40
9: LD r2, r41, 0a, 8h
LD r47, r41, 8a, 8h
JNE r45, r44, :5
JEQ r47, r37, :6
CP r4, r39
MUL64 r3, r47, r4
JAL r31, r0, :free
CP r1, r40
JMP :7
6: CP r1, r40
7: ST r1, r41, 0a, 8h
JMP :8
5: CP r1, r40
CP r4, r39
ADDI64 r48, r46, 8d
ADDI64 r42, r44, 8d
LD r49, r44, 0a, 8h
ST r49, r46, 0a, 8h
CP r44, r42
CP r46, r48
JMP :9
0: CP r41, r36
8: LD r50, r41, 8a, 8h
MULI64 r51, r50, 8d
LD r52, r41, 0a, 8h
ADD64 r1, r52, r51
CP r3, r32
ST r3, r1, 0a, 8h
LD r53, r41, 8a, 8h
ADD64 r54, r53, r33
ST r54, r41, 8a, 8h
4: LD r31, r254, 0a, 192h
ADDI64 r254, r254, 192d
JALA r0, r31, 0a
code size: 955
ret: 69
status: Ok(())

View file

@ -0,0 +1,19 @@
clobber:
LRA r1, r0, :var
LI64 r3, 0d
ST r3, r1, 0a, 8h
JALA r0, r31, 0a
main:
ADDI64 r254, r254, -24d
ST r31, r254, 0a, 24h
LRA r32, r0, :var
LI64 r33, 2d
ST r33, r32, 0a, 8h
JAL r31, r0, :clobber
LD r1, r32, 0a, 8h
LD r31, r254, 0a, 24h
ADDI64 r254, r254, 24d
JALA r0, r31, 0a
code size: 166
ret: 0
status: Ok(())

View file

@ -1,20 +1,20 @@
main: main:
ADDI64 r254, r254, -128d ADDI64 r254, r254, -128d
LI64 r6, 69d LI8 r5, 69b
LI64 r5, 128d LI64 r6, 128d
LI64 r7, 0d LI64 r7, 0d
ADDI64 r4, r254, 0d ADDI64 r4, r254, 0d
2: JLTU r7, r5, :0 2: LD r12, r254, 42a, 1h
LD r2, r254, 42a, 1h JLTU r7, r6, :0
ANDI r1, r2, 255d ANDI r1, r12, 255d
JMP :1 JMP :1
0: ADDI64 r8, r7, 1d 0: ADDI64 r3, r7, 1d
ADD64 r3, r7, r4 ADD64 r7, r4, r7
ST r6, r3, 0a, 1h ST r5, r7, 0a, 1h
CP r7, r8 CP r7, r3
JMP :2 JMP :2
1: ADDI64 r254, r254, 128d 1: ADDI64 r254, r254, 128d
JALA r0, r31, 0a JALA r0, r31, 0a
code size: 152 code size: 145
ret: 69 ret: 69
status: Ok(()) status: Ok(())

View file

@ -0,0 +1,9 @@
main:
LI64 r2, 0d
0: ADDI64 r2, r2, 1d
JMP :0
JALA r0, r31, 0a
timed out
code size: 45
ret: 0
status: Ok(())

View file

@ -0,0 +1,18 @@
main:
LI64 r7, 6d
LRA r3, r0, :gb
LI64 r6, 0d
LD r8, r3, 0a, 8h
CMPU r9, r8, r6
CMPUI r9, r9, 0d
ORI r11, r9, 0d
ANDI r11, r11, 255d
JNE r11, r0, :0
CP r4, r7
JMP :1
0: LI64 r4, 1d
1: SUB64 r1, r4, r7
JALA r0, r31, 0a
code size: 131
ret: 0
status: Ok(())

View file

@ -0,0 +1,39 @@
main:
ADDI64 r254, r254, -32d
ST r31, r254, 0a, 32h
JAL r31, r0, :scalar_values
LI64 r32, 0d
CP r33, r32
JEQ r1, r33, :0
LI64 r1, 1d
JMP :1
0: JAL r31, r0, :structs
CP r34, r33
JEQ r1, r34, :2
JAL r31, r0, :structs
JMP :1
2: CP r1, r34
CP r33, r34
1: LD r31, r254, 0a, 32h
ADDI64 r254, r254, 32d
JALA r0, r31, 0a
scalar_values:
LI64 r1, 0d
JALA r0, r31, 0a
structs:
ADDI64 r254, r254, -32d
LI64 r1, 5d
ST r1, r254, 16a, 8h
ST r1, r254, 24a, 8h
LD r5, r254, 16a, 8h
ADDI64 r7, r5, 15d
ST r7, r254, 0a, 8h
LI64 r10, 20d
ST r10, r254, 8a, 8h
LD r1, r254, 0a, 8h
SUB64 r1, r1, r10
ADDI64 r254, r254, 32d
JALA r0, r31, 0a
code size: 307
ret: 0
status: Ok(())

View file

@ -0,0 +1,6 @@
main:
LI64 r1, 10d
JALA r0, r31, 0a
code size: 29
ret: 10
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

@ -0,0 +1,20 @@
main:
ADDI64 r254, r254, -32d
ST r31, r254, 16a, 16h
ADDI64 r3, r254, 0d
ADDI64 r2, r254, 8d
LI64 r32, 0d
ST r32, r254, 0a, 8h
ST r32, r254, 8a, 8h
LI64 r4, 1024d
JAL r31, r0, :set
ANDI r1, r1, 4294967295d
LD r31, r254, 16a, 16h
ADDI64 r254, r254, 32d
JALA r0, r31, 0a
set:
CP r1, r4
JALA r0, r31, 0a
code size: 167
ret: 1024
status: Ok(())

View file

@ -0,0 +1,29 @@
integer_range:
ADDI64 r254, r254, -16d
ST r32, r254, 0a, 16h
CP r32, r2
CP r33, r3
LI64 r3, 4d
LI64 r2, 3d
ECA
CP r2, r32
CP r3, r33
SUB64 r11, r3, r2
ADDI64 r3, r11, 1d
DIRU64 r0, r3, r1, r3
ADD64 r1, r3, r2
LD r32, r254, 0a, 16h
ADDI64 r254, r254, 16d
JALA r0, r31, 0a
main:
ADDI64 r254, r254, -8d
ST r31, r254, 0a, 8h
LI64 r3, 1000d
LI64 r2, 0d
JAL r31, r0, :integer_range
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
JALA r0, r31, 0a
code size: 210
ret: 42
status: Ok(())

View file

@ -1,17 +1,16 @@
main: main:
ADDI64 r254, r254, -8d ADDI64 r254, r254, -8d
LI64 r4, 0d LI64 r3, 0d
LI64 r2, 10d LI64 r2, 10d
ADDI64 r5, r254, 0d
ST r2, r254, 0a, 8h ST r2, r254, 0a, 8h
2: LD r1, r254, 0a, 8h 2: LD r1, r254, 0a, 8h
JNE r1, r4, :0 JNE r1, r3, :0
JMP :1 JMP :1
0: ADDI64 r1, r1, -1d 0: ADDI64 r11, r1, -1d
ST r1, r254, 0a, 8h ST r11, r254, 0a, 8h
JMP :2 JMP :2
1: ADDI64 r254, r254, 8d 1: ADDI64 r254, r254, 8d
JALA r0, r31, 0a JALA r0, r31, 0a
code size: 137 code size: 126
ret: 0 ret: 0
status: Ok(()) status: Ok(())

View file

@ -5,8 +5,9 @@ fib:
CP r10, r4 CP r10, r4
2: JNE r2, r5, :0 2: JNE r2, r5, :0
JMP :1 JMP :1
0: ADD64 r3, r10, r1 0: ADD64 r1, r10, r1
SUB64 r2, r2, r4 SUB64 r2, r2, r4
CP r3, r1
CP r1, r10 CP r1, r10
CP r10, r3 CP r10, r3
JMP :2 JMP :2
@ -19,6 +20,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: 150 code size: 153
ret: 55 ret: 55
status: Ok(()) status: Ok(())

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

@ -0,0 +1,7 @@
foo.hb:4:1: redeclaration of identifier: foo
foo := fn(): void {
^
foo.hb:7:23: undefined indentifier: mian
main := @use("bar.hb").mian
^

View file

@ -0,0 +1,26 @@
get_ptr:
ADDI64 r254, r254, -8d
ADDI64 r1, r254, 0d
ADDI64 r254, r254, 8d
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,130 @@
decide:
LI8 r1, 1b
JALA r0, r31, 0a
main:
ADDI64 r254, r254, -224d
ST r31, r254, 80a, 144h
JAL r31, r0, :decide
LI64 r32, 0d
ADDI64 r2, r254, 72d
CP r33, r2
ANDI r1, r1, 255d
JNE r1, r0, :0
CP r34, r32
JMP :1
0: CP r34, r33
1: JNE r34, r32, :2
LI64 r1, 9001d
JMP :3
2: JAL r31, r0, :decide
LI8 r35, 0b
ANDI r1, r1, 255d
JNE r1, r0, :4
LI8 r36, 1b
ST r36, r254, 56a, 1h
LD r36, r34, 0a, 8h
ST r36, r254, 64a, 8h
JMP :5
4: ST r35, r254, 56a, 1h
5: LD r37, r254, 56a, 1h
ANDI r37, r37, 255d
ANDI r35, r35, 255d
JEQ r37, r35, :6
LI64 r1, 42d
JMP :3
6: JAL r31, r0, :decide
LI32 r38, 0w
ANDI r1, r1, 255d
JNE r1, r0, :7
CP r39, r38
JMP :8
7: LI32 r39, 8388609w
8: ANDI r39, r39, 4294967295d
ANDI r38, r38, 4294967295d
JNE r39, r38, :9
LI64 r1, 69d
JMP :3
9: ADDI64 r3, r254, 40d
CP r40, r3
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
JNE r1, r0, :11
CP r2, r33
JMP :12
11: CP r2, r33
ST r2, r254, 0a, 8h
LI64 r43, 1d
ST r43, r254, 8a, 8h
ST r43, r254, 72a, 8h
12: LD r44, r254, 0a, 8h
JNE r44, r32, :13
LI64 r1, 34d
JMP :3
13: ADDI64 r1, r254, 16d
JAL r31, r0, :new_bar
JAL r31, r0, :decide
ANDI r1, r1, 255d
JNE r1, r0, :14
JMP :15
14: ST r35, r254, 16a, 1h
15: LD r45, r254, 16a, 1h
ANDI r45, r45, 255d
ANDI r35, r35, 255d
JEQ r45, r35, :16
LI64 r1, 420d
JMP :3
16: LD r46, r254, 0a, 8h
LD r47, r46, 0a, 8h
ANDI r48, r39, 65535d
SUB64 r1, r48, r47
3: LD r31, r254, 80a, 144h
ADDI64 r254, r254, 224d
JALA r0, r31, 0a
new_bar:
ADDI64 r254, r254, -24d
ADDI64 r5, r254, 0d
BMC r1, 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: 1091
ret: 0
status: Ok(())

View file

@ -0,0 +1,30 @@
inb:
CP r1, r2
JALA r0, r31, 0a
main:
ADDI64 r254, r254, -32d
ST r31, r254, 0a, 32h
LI64 r32, 0d
LI64 r33, 100d
4: CP r2, r33
JAL r31, r0, :inb
ANDI r34, r1, 2d
JNE r34, r32, :0
LI64 r2, 96d
CP r3, r32
JAL r31, r0, :outb
3: CP r2, r33
JAL r31, r0, :inb
JEQ r1, r32, :1
LI64 r1, 1d
JMP :2
1: JMP :3
0: JMP :4
2: LD r31, r254, 0a, 32h
ADDI64 r254, r254, 32d
JALA r0, r31, 0a
outb:
JALA r0, r31, 0a
code size: 198
ret: 1
status: Ok(())

View file

@ -0,0 +1,34 @@
main:
ADDI64 r254, r254, -104d
ST r31, r254, 40a, 64h
LI64 r32, 4d
ADDI64 r33, r254, 24d
ADDI64 r34, r254, 0d
ST r32, r254, 24a, 8h
LI64 r35, 1d
ST r35, r254, 32a, 8h
ST r35, r254, 16a, 8h
BMC r33, r34, 16h
JAL r31, r0, :opaque
ST r1, r254, 0a, 16h
LD r36, r254, 8a, 8h
LD r37, r254, 16a, 8h
ADD64 r38, r37, r36
LD r37, r254, 0a, 8h
SUB64 r1, r37, r38
LD r31, r254, 40a, 64h
ADDI64 r254, r254, 104d
JALA r0, r31, 0a
opaque:
ADDI64 r254, r254, -16d
LI64 r3, 3d
ADDI64 r2, r254, 0d
ST r3, r254, 0a, 8h
LI64 r6, 2d
ST r6, r254, 8a, 8h
LD r1, r2, 0a, 16h
ADDI64 r254, r254, 16d
JALA r0, r31, 0a
code size: 323
ret: 0
status: Ok(())

View file

@ -3,17 +3,18 @@ clobber:
ST r3, r2, 0a, 8h ST r3, r2, 0a, 8h
JALA r0, r31, 0a JALA r0, r31, 0a
main: main:
ADDI64 r254, r254, -32d ADDI64 r254, r254, -40d
ST r31, r254, 8a, 24h ST r31, r254, 8a, 32h
LI64 r32, 2d
ADDI64 r2, r254, 0d ADDI64 r2, r254, 0d
LI64 r32, 2d
ST r32, r254, 0a, 8h ST r32, r254, 0a, 8h
JAL r31, r0, :clobber JAL r31, r0, :clobber
LD r33, r254, 0a, 8h LD r33, r254, 0a, 8h
ADDI64 r1, r33, -4d LI64 r34, 4d
LD r31, r254, 8a, 24h SUB64 r1, r34, r33
ADDI64 r254, r254, 32d LD r31, r254, 8a, 32h
ADDI64 r254, r254, 40d
JALA r0, r31, 0a JALA r0, r31, 0a
code size: 166 code size: 169
ret: 0 ret: 0
status: Ok(()) status: Ok(())

View file

@ -1,26 +1,23 @@
drop: drop:
JALA r0, r31, 0a JALA r0, r31, 0a
main: main:
ADDI64 r254, r254, -48d ADDI64 r254, r254, -32d
ST r31, r254, 8a, 40h ST r31, r254, 8a, 24h
ADDI64 r2, r254, 0d
LI64 r32, 1d LI64 r32, 1d
ADDI64 r33, r254, 0d
ADDI64 r34, r33, 8000d
ADDI64 r34, r34, -8000d
ST r32, r254, 0a, 8h ST r32, r254, 0a, 8h
CP r2, r34
JAL r31, r0, :modify JAL r31, r0, :modify
CP r2, r32 CP r2, r32
JAL r31, r0, :drop JAL r31, r0, :drop
LD r35, r34, 0a, 8h LD r33, r254, 0a, 8h
ADDI64 r1, r35, -2d ADDI64 r1, r33, -2d
LD r31, r254, 8a, 40h LD r31, r254, 8a, 24h
ADDI64 r254, r254, 48d ADDI64 r254, r254, 32d
JALA r0, r31, 0a JALA r0, r31, 0a
modify: modify:
LI64 r3, 2d LI64 r3, 2d
ST r3, r2, 0a, 8h ST r3, r2, 0a, 8h
JALA r0, r31, 0a JALA r0, r31, 0a
code size: 212 code size: 187
ret: 0 ret: 0
status: Ok(()) status: Ok(())

View file

@ -0,0 +1,6 @@
main:
LI64 r1, 0d
JALA r0, r31, 0a
code size: 29
ret: 0
status: Ok(())

View file

@ -0,0 +1,48 @@
create_back_buffer:
ADDI64 r254, r254, -56d
ST r31, r254, 0a, 56h
LI64 r32, 255d
JGTS r2, r32, :0
JAL r31, r0, :request_page
JMP :1
0: CP r33, r2
LI8 r34, 255b
CP r2, r34
JAL r31, r0, :request_page
LI64 r35, 0d
CP r2, r33
SUB64 r36, r2, r32
5: JGTS r36, r35, :2
JMP :1
2: CP r37, r1
JLTS r36, r32, :3
CP r2, r34
JAL r31, r0, :request_page
JMP :4
3: CP r2, r36
JAL r31, r0, :request_page
4: SUB64 r36, r36, r32
CP r1, r37
JMP :5
1: LD r31, r254, 0a, 56h
ADDI64 r254, r254, 56d
JALA r0, r31, 0a
main:
ADDI64 r254, r254, -8d
ST r31, r254, 0a, 8h
LI64 r2, 400d
JAL r31, r0, :create_back_buffer
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
JALA r0, r31, 0a
request_page:
LRA r4, r0, :"\0\u{1}xxxxxxxx\0"
ST r2, r4, 1a, 1h
LI64 r5, 12d
LI64 r3, 2d
LI64 r2, 3d
ECA
JALA r0, r31, 0a
code size: 331
ret: 42
status: Ok(())

View file

@ -0,0 +1,27 @@
main:
ADDI64 r254, r254, -100d
ST r31, r254, 4a, 96h
ADDI64 r32, r254, 0d
JAL r31, r0, :random_color
ST r1, r254, 0a, 4h
LD r33, r254, 0a, 1h
LD r34, r254, 1a, 1h
LD r35, r254, 2a, 1h
ANDI r36, r33, 255d
ANDI r37, r34, 255d
LD r38, r254, 3a, 1h
ANDI r39, r35, 255d
ADD64 r40, r37, r36
ANDI r41, r38, 255d
ADD64 r42, r40, r39
ADD64 r1, r42, r41
LD r31, r254, 4a, 96h
ADDI64 r254, r254, 100d
JALA r0, r31, 0a
random_color:
LRA r1, r0, :white
LD r1, r1, 0a, 4h
JALA r0, r31, 0a
code size: 241
ret: 1020
status: Ok(())

View file

@ -0,0 +1,6 @@
main:
LI64 r1, 1d
JALA r0, r31, 0a
code size: 29
ret: 1
status: Ok(())

View file

@ -0,0 +1,12 @@
main:
ADDI64 r254, r254, -4d
LRA r2, r0, :white
ADDI64 r3, r254, 0d
BMC r2, r3, 4h
LD r6, r254, 3a, 1h
ANDI r1, r6, 255d
ADDI64 r254, r254, 4d
JALA r0, r31, 0a
code size: 92
ret: 255
status: Ok(())

View file

@ -0,0 +1,29 @@
main:
ADDI64 r254, r254, -36d
ST r31, r254, 4a, 32h
LRA r32, r0, :white
ADDI64 r33, r254, 0d
LD r2, r32, 0a, 4h
JAL r31, r0, :u32_to_color
ST r1, r254, 0a, 4h
LD r34, r254, 0a, 1h
ANDI r1, r34, 255d
LD r31, r254, 4a, 32h
ADDI64 r254, r254, 36d
JALA r0, r31, 0a
u32_to_color:
ADDI64 r254, r254, -20d
ST r31, r254, 4a, 16h
JAL r31, r0, :u32_to_u32
ADDI64 r32, r254, 0d
ST r1, r254, 0a, 4h
LD r1, r32, 0a, 4h
LD r31, r254, 4a, 16h
ADDI64 r254, r254, 20d
JALA r0, r31, 0a
u32_to_u32:
CP r1, r2
JALA r0, r31, 0a
code size: 263
ret: 255
status: Ok(())

View file

@ -6,11 +6,7 @@ main:
ADDI64 r254, r254, 8d ADDI64 r254, r254, 8d
JALA r0, r31, 0a JALA r0, r31, 0a
some_func: some_func:
ADDI64 r254, r254, -8d
ST r31, r254, 0a, 8h
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
JALA r0, r31, 0a JALA r0, r31, 0a
code size: 133 code size: 85
ret: 0 ret: 0
status: Ok(()) status: Ok(())

Some files were not shown because too many files have changed in this diff Show more