removing old compiler

This commit is contained in:
Jakub Doka 2024-10-27 13:57:00 +01:00
parent ce7bb001da
commit b187af64a8
No known key found for this signature in database
GPG key ID: C6E9A89936B8C143
29 changed files with 349 additions and 3104 deletions

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

@ -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>,)*
} }

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::{Codegen, CodegenCtx},
},
}; };
extern crate alloc; extern crate alloc;
@ -74,8 +77,8 @@ unsafe fn compile_and_run(mut fuel: usize) {
}; };
let mut ct = { let mut ct = {
let mut c = Codegen::default(); let mut ctx = CodegenCtx::default();
c.files = files; let mut c = Codegen::new(&files, &mut ctx);
c.generate(root as FileId); c.generate(root as FileId);
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

@ -20,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
features = ["trace-log"] features = ["trace-log"]
[features] [features]
default = ["std", "opts"] default = ["std"]
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,6 +1,5 @@
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},
}, },
@ -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)?;
} }

View file

@ -1,6 +1,5 @@
use { use {
crate::{ crate::{
codegen,
parser::{self, Ast, Ctx, FileKind}, parser::{self, Ast, Ctx, FileKind},
son, son,
}, },
@ -39,6 +38,7 @@ pub struct Options {
pub fmt: bool, pub fmt: bool,
pub fmt_stdout: bool, pub fmt_stdout: bool,
pub dump_asm: bool, pub dump_asm: bool,
#[deprecated = "no longer has any effect"]
pub optimize: bool, pub optimize: bool,
pub extra_threads: usize, pub extra_threads: usize,
} }
@ -53,7 +53,6 @@ impl Options {
Ok(Options { Ok(Options {
fmt: args.contains(&"--fmt"), fmt: args.contains(&"--fmt"),
optimize: args.contains(&"--optimize"),
fmt_stdout: args.contains(&"--fmt-stdout"), fmt_stdout: args.contains(&"--fmt-stdout"),
dump_asm: args.contains(&"--dump-asm"), dump_asm: args.contains(&"--dump-asm"),
extra_threads: args extra_threads: args
@ -67,6 +66,7 @@ impl Options {
.transpose()? .transpose()?
.map_or(1, NonZeroUsize::get) .map_or(1, NonZeroUsize::get)
- 1, - 1,
..Default::default()
}) })
} }
} }
@ -81,11 +81,6 @@ pub fn run_compiler(root_file: &str, options: Options, out: &mut Vec<u8>) -> std
Ok(()) Ok(())
} }
if !options.optimize && !parsed.errors.is_empty() {
log::error!("{}", parsed.errors);
return Err(std::io::Error::other("parsing failed"));
}
if options.fmt { if options.fmt {
for parsed in parsed.ast { for parsed in parsed.ast {
format_ast(parsed)?; format_ast(parsed)?;
@ -93,7 +88,7 @@ pub fn run_compiler(root_file: &str, options: Options, out: &mut Vec<u8>) -> std
} else if options.fmt_stdout { } else if options.fmt_stdout {
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 if options.optimize { } else {
let mut ctx = crate::son::CodegenCtx::default(); let mut ctx = crate::son::CodegenCtx::default();
*ctx.parser.errors.get_mut() = parsed.errors; *ctx.parser.errors.get_mut() = parsed.errors;
let mut codegen = son::Codegen::new(&parsed.ast, &mut ctx); let mut codegen = son::Codegen::new(&parsed.ast, &mut ctx);
@ -106,19 +101,6 @@ pub fn run_compiler(root_file: &str, options: Options, out: &mut Vec<u8>) -> std
return Err(std::io::Error::other("compilation faoled")); return Err(std::io::Error::other("compilation faoled"));
} }
if options.dump_asm {
codegen
.disasm(unsafe { std::mem::transmute::<&mut Vec<u8>, &mut String>(out) })
.map_err(|e| io::Error::other(e.to_string()))?;
} else {
codegen.assemble(out);
}
} else {
let mut codegen = codegen::Codegen::default();
codegen.files = parsed.ast;
codegen.push_embeds(parsed.embeds);
codegen.generate(0);
if options.dump_asm { if options.dump_asm {
codegen codegen
.disasm(unsafe { std::mem::transmute::<&mut Vec<u8>, &mut String>(out) }) .disasm(unsafe { std::mem::transmute::<&mut Vec<u8>, &mut String>(out) })

View file

@ -4,8 +4,8 @@ use {
parser, parser,
son::{Codegen, CodegenCtx}, son::{Codegen, CodegenCtx},
}, },
alloc::string::String,
core::{fmt::Write, hash::BuildHasher, ops::Range}, core::{fmt::Write, hash::BuildHasher, ops::Range},
std::string::String,
}; };
#[derive(Default)] #[derive(Default)]

View file

@ -178,7 +178,7 @@ impl core::fmt::Debug for TokenKind {
} }
impl TokenKind { impl TokenKind {
#[allow(clippy::type_complexity)] #[expect(clippy::type_complexity)]
pub fn cond_op(self, signed: bool) -> Option<(fn(u8, u8, i16) -> EncodedInstr, bool)> { pub fn cond_op(self, signed: bool) -> Option<(fn(u8, u8, i16) -> EncodedInstr, bool)> {
use crate::instrs; use crate::instrs;
Some(( Some((
@ -225,7 +225,6 @@ impl TokenKind {
Some(ops[size.ilog2() as usize]) 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> { pub fn imm_binop(self, signed: bool, size: u32) -> Option<fn(u8, u8, u64) -> EncodedInstr> {
use crate::instrs::*; use crate::instrs::*;
macro_rules! def_op { macro_rules! def_op {

View file

@ -22,18 +22,17 @@
ptr_sub_ptr, ptr_sub_ptr,
slice_from_ptr_range, slice_from_ptr_range,
is_sorted, is_sorted,
iter_next_chunk iter_next_chunk,
pointer_is_aligned_to
)] )]
#![feature(pointer_is_aligned_to)]
#![warn(clippy::dbg_macro)] #![warn(clippy::dbg_macro)]
#![allow(stable_features, internal_features)] #![expect(stable_features, internal_features)]
#![no_std] #![no_std]
#[cfg(feature = "std")] #[cfg(feature = "std")]
pub use fs::*; pub use fs::*;
use { use {
self::{ self::{
ident::Ident,
lexer::TokenKind, lexer::TokenKind,
parser::{idfl, CommentOr, Expr, ExprRef, FileId, Pos}, parser::{idfl, CommentOr, Expr, ExprRef, FileId, Pos},
ty::ArrayLen, ty::ArrayLen,
@ -63,22 +62,17 @@ macro_rules! run_tests {
)*}; )*};
} }
pub mod codegen;
pub mod fmt; pub mod fmt;
#[cfg(any(feature = "std", test))] #[cfg(any(feature = "std", test))]
pub mod fs; pub mod fs;
pub mod fuzz;
pub mod lexer;
pub mod parser; pub mod parser;
#[cfg(feature = "opts")]
pub mod son; pub mod son;
pub mod lexer;
#[cfg(feature = "opts")]
mod vc; mod vc;
pub mod fuzz;
mod debug { mod debug {
pub fn panicking() -> bool { pub fn panicking() -> bool {
#[cfg(feature = "std")] #[cfg(feature = "std")]
{ {
@ -185,12 +179,10 @@ mod ctx_map {
.map(|(k, _)| &k.value) .map(|(k, _)| &k.value)
} }
#[cfg_attr(not(feature = "opts"), expect(dead_code))]
pub fn clear(&mut self) { pub fn clear(&mut self) {
self.inner.clear(); self.inner.clear();
} }
#[cfg_attr(not(feature = "opts"), expect(dead_code))]
pub fn remove(&mut self, value: &T, ctx: &T::Ctx) -> Option<T> { pub fn remove(&mut self, value: &T, ctx: &T::Ctx) -> Option<T> {
let (entry, _) = self.entry(value.key(ctx), ctx); let (entry, _) = self.entry(value.key(ctx), ctx);
match entry { match entry {
@ -241,46 +233,55 @@ mod task {
unpack(offset).is_ok() unpack(offset).is_ok()
} }
#[cfg_attr(not(feature = "opts"), expect(dead_code))]
pub fn id(index: usize) -> Offset { pub fn id(index: usize) -> Offset {
1 << 31 | index as u32 1 << 31 | index as u32
} }
} }
mod ident { #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug)]
pub type Ident = u32; pub struct Ident(u32);
impl Ident {
pub const INVALID: Self = Self(u32::MAX);
const LEN_BITS: u32 = 6; const LEN_BITS: u32 = 6;
pub fn len(ident: u32) -> u32 { pub fn len(self) -> u32 {
ident & ((1 << LEN_BITS) - 1) self.0 & ((1 << Self::LEN_BITS) - 1)
} }
pub fn is_null(ident: u32) -> bool { pub fn is_empty(self) -> bool {
(ident >> LEN_BITS) == 0 self.len() == 0
} }
pub fn pos(ident: u32) -> u32 { pub fn is_null(self) -> bool {
(ident >> LEN_BITS).saturating_sub(1) (self.0 >> Self::LEN_BITS) == 0
} }
pub fn new(pos: u32, len: u32) -> Option<u32> { pub fn pos(self) -> u32 {
(len < (1 << LEN_BITS)).then_some(((pos + 1) << LEN_BITS) | len) (self.0 >> Self::LEN_BITS).saturating_sub(1)
} }
pub fn range(ident: u32) -> core::ops::Range<usize> { pub fn new(pos: u32, len: u32) -> Option<Self> {
let (len, pos) = (len(ident) as usize, pos(ident) as usize); (len < (1 << Self::LEN_BITS)).then_some(((pos + 1) << Self::LEN_BITS) | len).map(Self)
}
pub fn range(self) -> core::ops::Range<usize> {
let (len, pos) = (self.len() as usize, self.pos() as usize);
pos..pos + len pos..pos + len
} }
fn builtin(builtin: u32) -> Ident {
debug_assert!(Self(builtin).is_null());
Self(builtin)
}
} }
mod ty { mod ty {
use { use {
crate::{ crate::{
ident,
lexer::TokenKind, lexer::TokenKind,
parser::{self, Pos}, parser::{self, FileId, Pos},
Size, Types, Ident, Size, Types,
}, },
core::{num::NonZeroU32, ops::Range}, core::{num::NonZeroU32, ops::Range},
}; };
@ -385,7 +386,9 @@ mod ty {
crate::SymKey::Decl(gb.file, gb.name) crate::SymKey::Decl(gb.file, gb.name)
} }
Kind::Slice(s) => crate::SymKey::Array(&ctx.slices[s as usize]), Kind::Slice(s) => crate::SymKey::Array(&ctx.slices[s as usize]),
Kind::Module(_) | Kind::Builtin(_) => crate::SymKey::Decl(u32::MAX, u32::MAX), Kind::Module(_) | Kind::Builtin(_) => {
crate::SymKey::Decl(FileId::MAX, Ident::INVALID)
}
} }
} }
} }
@ -399,16 +402,24 @@ mod ty {
impl Id { impl Id {
pub const DEFAULT_INT: Self = Self::UINT; pub const DEFAULT_INT: Self = Self::UINT;
pub fn bin_ret(self, op: TokenKind) -> Id {
use TokenKind as T;
match op {
T::Lt | T::Gt | T::Le | T::Ge | T::Ne | T::Eq => BOOL.into(),
_ => self,
}
}
pub fn is_signed(self) -> bool { pub fn is_signed(self) -> bool {
(I8..=INT).contains(&self.repr()) || self.is_never() matches!(self.repr(), I8..=INT) || self.is_never()
} }
pub fn is_unsigned(self) -> bool { pub fn is_unsigned(self) -> bool {
(U8..=UINT).contains(&self.repr()) || self.is_never() matches!(self.repr(), U8..=UINT) || self.is_never()
} }
pub fn is_integer(self) -> bool { pub fn is_integer(self) -> bool {
(U8..=INT).contains(&self.repr()) || self.is_never() matches!(self.repr(), U8..=INT) || self.is_never()
} }
pub fn is_never(self) -> bool { pub fn is_never(self) -> bool {
@ -426,7 +437,7 @@ mod ty {
matches!(self.expand(), Kind::Ptr(_)) || self.is_never() matches!(self.expand(), Kind::Ptr(_)) || self.is_never()
} }
pub fn try_upcast(self, ob: Self, kind: TyCheck) -> Option<Self> { pub fn try_upcast(self, ob: Self) -> Option<Self> {
let (oa, ob) = (Self(self.0.min(ob.0)), Self(self.0.max(ob.0))); let (oa, ob) = (Self(self.0.min(ob.0)), Self(self.0.max(ob.0)));
let (a, b) = (oa.strip_pointer(), ob.strip_pointer()); let (a, b) = (oa.strip_pointer(), ob.strip_pointer());
Some(match () { Some(match () {
@ -437,7 +448,7 @@ mod ty {
_ if a.is_signed() && b.is_signed() || a.is_unsigned() && b.is_unsigned() => ob, _ if a.is_signed() && b.is_signed() || a.is_unsigned() && b.is_unsigned() => ob,
_ if a.is_unsigned() && b.is_signed() && a.repr() - U8 < b.repr() - I8 => ob, _ if a.is_unsigned() && b.is_signed() && a.repr() - U8 < b.repr() - I8 => ob,
_ if a.is_unsigned() && b.is_signed() && a.repr() - U8 > b.repr() - I8 => oa, _ if a.is_unsigned() && b.is_signed() && a.repr() - U8 > b.repr() - I8 => oa,
_ if oa.is_integer() && ob.is_pointer() && kind == TyCheck::BinOp => ob, _ if oa.is_integer() && ob.is_pointer() => ob,
_ => return None, _ => return None,
}) })
} }
@ -498,13 +509,6 @@ mod ty {
Stack, Stack,
} }
#[derive(PartialEq, Eq, Default, Debug, Clone, Copy)]
pub enum TyCheck {
BinOp,
#[default]
Assign,
}
impl From<u64> for Id { impl From<u64> for Id {
fn from(id: u64) -> Self { fn from(id: u64) -> Self {
Self(unsafe { NonZeroU32::new_unchecked(id as _) }) Self(unsafe { NonZeroU32::new_unchecked(id as _) })
@ -544,7 +548,7 @@ mod ty {
};)* };)*
} }
#[allow(dead_code)] #[expect(dead_code)]
impl Id { impl Id {
$(pub const $name: Self = Kind::Builtin($name).compress();)* $(pub const $name: Self = Kind::Builtin($name).compress();)*
} }
@ -673,7 +677,7 @@ mod ty {
} }
TK::Struct(idx) => { TK::Struct(idx) => {
let record = &self.tys.ins.structs[idx as usize]; let record = &self.tys.ins.structs[idx as usize];
if ident::is_null(record.name) { if record.name.is_null() {
f.write_str("[")?; f.write_str("[")?;
idx.fmt(f)?; idx.fmt(f)?;
f.write_str("]{")?; f.write_str("]{")?;
@ -714,15 +718,6 @@ mod ty {
} }
} }
} }
#[cfg_attr(not(feature = "opts"), expect(dead_code))]
pub fn bin_ret(ty: Id, op: TokenKind) -> Id {
use TokenKind as T;
match op {
T::Lt | T::Gt | T::Le | T::Ge | T::Ne | T::Eq => BOOL.into(),
_ => ty,
}
}
} }
type EncodedInstr = (usize, [u8; instrs::MAX_SIZE]); type EncodedInstr = (usize, [u8; instrs::MAX_SIZE]);
@ -752,7 +747,6 @@ struct Func {
file: FileId, file: FileId,
name: Ident, name: Ident,
base: Option<ty::Func>, base: Option<ty::Func>,
computed: Option<ty::Id>,
expr: ExprRef, expr: ExprRef,
sig: Option<Sig>, sig: Option<Sig>,
offset: Offset, offset: Offset,
@ -765,9 +759,8 @@ impl Default for Func {
fn default() -> Self { fn default() -> Self {
Self { Self {
file: u32::MAX, file: u32::MAX,
name: 0, name: Default::default(),
base: None, base: None,
computed: None,
expr: Default::default(), expr: Default::default(),
sig: None, sig: None,
offset: u32::MAX, offset: u32::MAX,
@ -799,7 +792,7 @@ impl Default for Global {
offset: u32::MAX, offset: u32::MAX,
data: Default::default(), data: Default::default(),
file: u32::MAX, file: u32::MAX,
name: 0, name: Default::default(),
} }
} }
} }
@ -884,7 +877,7 @@ impl ParamAlloc {
} }
#[repr(packed)] #[repr(packed)]
#[allow(dead_code)] #[expect(dead_code)]
struct AbleOsExecutableHeader { struct AbleOsExecutableHeader {
magic_number: [u8; 3], magic_number: [u8; 3],
executable_version: u32, executable_version: u32,
@ -901,7 +894,7 @@ impl ctx_map::CtxEntry for Ident {
type Key<'a> = &'a str; type Key<'a> = &'a str;
fn key<'a>(&self, ctx: &'a Self::Ctx) -> Self::Key<'a> { fn key<'a>(&self, ctx: &'a Self::Ctx) -> Self::Key<'a> {
unsafe { ctx.get_unchecked(ident::range(*self)) } unsafe { ctx.get_unchecked(self.range()) }
} }
} }
@ -917,7 +910,7 @@ impl IdentInterner {
match entry { match entry {
hash_map::RawEntryMut::Occupied(o) => o.get_key_value().0.value, hash_map::RawEntryMut::Occupied(o) => o.get_key_value().0.value,
hash_map::RawEntryMut::Vacant(v) => { hash_map::RawEntryMut::Vacant(v) => {
let id = ident::new(self.strings.len() as _, ident.len() as _).unwrap(); let id = Ident::new(self.strings.len() as _, ident.len() as _).unwrap();
self.strings.push_str(ident); self.strings.push_str(ident);
v.insert(ctx_map::Key { hash, value: id }, ()); v.insert(ctx_map::Key { hash, value: id }, ());
id id
@ -926,7 +919,7 @@ impl IdentInterner {
} }
fn ident_str(&self, ident: Ident) -> &str { fn ident_str(&self, ident: Ident) -> &str {
&self.strings[ident::range(ident)] &self.strings[ident.range()]
} }
fn project(&self, ident: &str) -> Option<Ident> { fn project(&self, ident: &str) -> Option<Ident> {
@ -1052,9 +1045,9 @@ trait TypeParser {
ty::Kind::Struct(s) => &mut tys.ins.structs[s as usize].name, ty::Kind::Struct(s) => &mut tys.ins.structs[s as usize].name,
ty::Kind::Func(s) => &mut tys.ins.funcs[s as usize].name, ty::Kind::Func(s) => &mut tys.ins.funcs[s as usize].name,
ty::Kind::Global(s) => &mut tys.ins.globals[s as usize].name, ty::Kind::Global(s) => &mut tys.ins.globals[s as usize].name,
_ => &mut 0, _ => &mut Ident::default(),
}; };
if *nm == 0 { if nm.is_null() {
*nm = name; *nm = name;
} }
tys.syms.insert(SymKey::Decl(file, name), ty, &tys.ins); tys.syms.insert(SymKey::Decl(file, name), ty, &tys.ins);
@ -1088,7 +1081,7 @@ trait TypeParser {
let base = self.parse_ty(file, val, None, files); let base = self.parse_ty(file, val, None, files);
self.tys().make_ptr(base) self.tys().make_ptr(base)
} }
Expr::Ident { id, .. } if ident::is_null(id) => id.into(), Expr::Ident { id, .. } if id.is_null() => id.len().into(),
Expr::Ident { id, pos, .. } => self.find_type(pos, file, file, Ok(id), files), Expr::Ident { id, pos, .. } => self.find_type(pos, file, file, Ok(id), files),
Expr::Field { target, pos, name } Expr::Field { target, pos, name }
if let ty::Kind::Module(inside) = if let ty::Kind::Module(inside) =
@ -1136,7 +1129,7 @@ trait TypeParser {
tys.ins.structs.push(Struct { tys.ins.structs.push(Struct {
file, file,
pos, pos,
name: name.unwrap_or(0), name: name.unwrap_or_default(),
field_start: tys.ins.fields.len() as _, field_start: tys.ins.fields.len() as _,
explicit_alignment: packed.then_some(1), explicit_alignment: packed.then_some(1),
..Default::default() ..Default::default()
@ -1466,7 +1459,6 @@ impl Types {
} }
} }
#[cfg_attr(not(feature = "opts"), expect(dead_code))]
fn find_struct_field(&self, s: ty::Struct, name: &str) -> Option<usize> { fn find_struct_field(&self, s: ty::Struct, name: &str) -> Option<usize> {
let name = self.names.project(name)?; let name = self.names.project(name)?;
self.struct_fields(s).iter().position(|f| f.name == name) self.struct_fields(s).iter().position(|f| f.name == name)
@ -1536,7 +1528,6 @@ impl OffsetIter {
} }
} }
#[cfg(any(feature = "opts", feature = "std"))]
type HashMap<K, V> = hashbrown::HashMap<K, V, FnvBuildHasher>; type HashMap<K, V> = hashbrown::HashMap<K, V, FnvBuildHasher>;
type FnvBuildHasher = core::hash::BuildHasherDefault<FnvHasher>; type FnvBuildHasher = core::hash::BuildHasherDefault<FnvHasher>;

View file

@ -1,8 +1,8 @@
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::{
@ -126,11 +126,8 @@ impl<'a, 'b> Parser<'a, 'b> {
let mut idents = core::mem::take(&mut self.ctx.idents); let mut idents = core::mem::take(&mut self.ctx.idents);
for id in idents.drain(..) { for id in idents.drain(..) {
self.report( self.report(
ident::pos(id.ident), id.ident.pos(),
format_args!( format_args!("undeclared identifier: {}", self.lexer.slice(id.ident.range())),
"undeclared identifier: {}",
self.lexer.slice(ident::range(id.ident))
),
); );
} }
self.ctx.idents = idents; self.ctx.idents = idents;
@ -217,7 +214,7 @@ 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())
), ),
); );
} }
@ -229,7 +226,7 @@ impl<'a, 'b> Parser<'a, 'b> {
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; return;
} }
@ -242,7 +239,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
@ -250,14 +247,14 @@ 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 ident = match ident::new(token.start, name.len() as _) { let ident = match Ident::new(token.start, name.len() as _) {
None => { None => {
self.report(token.start, "identifier can at most have 64 characters"); self.report(token.start, "identifier can at most have 64 characters");
ident::new(token.start, 64).unwrap() Ident::new(token.start, 63).unwrap()
} }
Some(id) => id, Some(id) => id,
}; };
@ -725,7 +722,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(),)*
} }
@ -914,7 +911,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)),
@ -1192,7 +1189,7 @@ 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()]
} }
} }

View file

@ -2,9 +2,7 @@ use {
self::strong_ref::StrongRef, self::strong_ref::StrongRef,
crate::{ crate::{
ctx_map::CtxEntry, ctx_map::CtxEntry,
debug, debug, instrs,
ident::Ident,
instrs,
lexer::{self, TokenKind}, lexer::{self, TokenKind},
parser::{ parser::{
self, self,
@ -14,8 +12,8 @@ use {
reg, task, reg, task,
ty::{self, Arg, ArrayLen, Loc, Tuple}, ty::{self, Arg, ArrayLen, Loc, Tuple},
vc::{BitSet, Vc}, vc::{BitSet, Vc},
Comptime, FTask, Func, Global, HashMap, Offset, OffsetIter, PLoc, Reloc, Sig, StringRef, Comptime, FTask, Func, Global, HashMap, Ident, Offset, OffsetIter, PLoc, Reloc, Sig,
SymKey, TypeParser, TypedReloc, Types, StringRef, SymKey, TypeParser, TypedReloc, Types,
}, },
alloc::{borrow::ToOwned, string::String, vec::Vec}, alloc::{borrow::ToOwned, string::String, vec::Vec},
core::{ core::{
@ -28,7 +26,6 @@ use {
hashbrown::hash_map, hashbrown::hash_map,
hbbytecode::DisasmError, hbbytecode::DisasmError,
regalloc2::VReg, regalloc2::VReg,
std::panic,
}; };
const VOID: Nid = 0; const VOID: Nid = 0;
@ -146,26 +143,25 @@ impl Nodes {
Ok(()) Ok(())
} }
#[allow(dead_code)]
fn graphviz(&self, tys: &Types, files: &[parser::Ast]) { fn graphviz(&self, tys: &Types, files: &[parser::Ast]) {
let out = &mut String::new(); let out = &mut String::new();
_ = self.graphviz_low(tys, files, out); _ = self.graphviz_low(tys, files, out);
log::info!("{out}"); log::info!("{out}");
} }
fn graphviz_in_browser(&self, tys: &Types, files: &[parser::Ast]) { fn graphviz_in_browser(&self, _tys: &Types, _files: &[parser::Ast]) {
#[cfg(all(debug_assertions, feature = "std"))] #[cfg(all(debug_assertions, feature = "std"))]
{ {
// let out = &mut String::new(); let out = &mut String::new();
// _ = self.graphviz_low(tys, files, out); _ = self.graphviz_low(_tys, _files, out);
// if !std::process::Command::new("brave") if !std::process::Command::new("brave")
// .arg(format!("https://dreampuf.github.io/GraphvizOnline/#{out}")) .arg(format!("https://dreampuf.github.io/GraphvizOnline/#{out}"))
// .status() .status()
// .unwrap() .unwrap()
// .success() .success()
// { {
// log::error!("{out}"); log::error!("{out}");
// } }
} }
} }
@ -177,18 +173,6 @@ impl Nodes {
push_down(self, VOID); push_down(self, VOID);
} }
fn remove_low(&mut self, id: Nid) -> Node {
if cfg!(debug_assertions) {
let value =
mem::replace(&mut self.values[id as usize], Err((self.free, debug::trace())))
.unwrap();
self.free = id;
value
} else {
mem::replace(&mut self.values[id as usize], Err((Nid::MAX, debug::trace()))).unwrap()
}
}
fn clear(&mut self) { fn clear(&mut self) {
self.values.clear(); self.values.clear();
self.lookup.clear(); self.lookup.clear();
@ -257,25 +241,21 @@ impl Nodes {
} }
} }
fn new_node_low(&mut self, ty: ty::Id, kind: Kind, inps: impl Into<Vc>) -> (Nid, bool) { fn new_node(&mut self, ty: ty::Id, kind: Kind, inps: impl Into<Vc>) -> Nid {
let id = self.new_node_nop(ty, kind, inps); let id = self.new_node_nop(ty, kind, inps);
if let Some(opt) = self.peephole(id) { if let Some(opt) = self.peephole(id) {
debug_assert_ne!(opt, id); debug_assert_ne!(opt, id);
self.lock(opt); self.lock(opt);
self.remove(id); self.remove(id);
self.unlock(opt); self.unlock(opt);
(opt, true) opt
} else { } else {
(id, false) id
} }
} }
fn new_node(&mut self, ty: ty::Id, kind: Kind, inps: impl Into<Vc>) -> Nid {
self.new_node_low(ty, kind, inps).0
}
fn new_node_lit(&mut self, ty: ty::Id, kind: Kind, inps: impl Into<Vc>) -> Value { fn new_node_lit(&mut self, ty: ty::Id, kind: Kind, inps: impl Into<Vc>) -> Value {
Value::new(self.new_node_low(ty, kind, inps).0).ty(ty) Value::new(self.new_node(ty, kind, inps)).ty(ty)
} }
fn lock(&mut self, target: Nid) { fn lock(&mut self, target: Nid) {
@ -292,8 +272,6 @@ impl Nodes {
return false; return false;
} }
debug_assert!(!matches!(self[target].kind, Kind::Call { .. }), "{:?}", self[target]);
for i in 0..self[target].inputs.len() { for i in 0..self[target].inputs.len() {
let inp = self[target].inputs[i]; let inp = self[target].inputs[i];
let index = self[inp].outputs.iter().position(|&p| p == target).unwrap(); let index = self[inp].outputs.iter().position(|&p| p == target).unwrap();
@ -302,7 +280,15 @@ impl Nodes {
} }
self.remove_node_lookup(target); self.remove_node_lookup(target);
self.remove_low(target);
if cfg!(debug_assertions) {
mem::replace(&mut self.values[target as usize], Err((Nid::MAX, debug::trace())))
.unwrap();
} else {
mem::replace(&mut self.values[target as usize], Err((self.free, debug::trace())))
.unwrap();
self.free = target;
}
true true
} }
@ -664,7 +650,7 @@ impl Nodes {
self.values.iter().enumerate().filter_map(|(i, s)| Some((i as _, s.as_ref().ok()?))) self.values.iter().enumerate().filter_map(|(i, s)| Some((i as _, s.as_ref().ok()?)))
} }
#[allow(clippy::format_in_format_args)] #[expect(clippy::format_in_format_args)]
fn basic_blocks_instr(&mut self, out: &mut String, node: Nid) -> core::fmt::Result { fn basic_blocks_instr(&mut self, out: &mut String, node: Nid) -> core::fmt::Result {
if self[node].kind != Kind::Loop && self[node].kind != Kind::Region { if self[node].kind != Kind::Loop && self[node].kind != Kind::Region {
write!(out, " {node:>2}-c{:>2}: ", self[node].ralloc_backref)?; write!(out, " {node:>2}-c{:>2}: ", self[node].ralloc_backref)?;
@ -913,7 +899,6 @@ impl Nodes {
} }
} }
#[allow(dead_code)]
fn eliminate_stack_temporaries(&mut self) { fn eliminate_stack_temporaries(&mut self) {
'o: for stack in self[MEM].outputs.clone() { 'o: for stack in self[MEM].outputs.clone() {
if self.values[stack as usize].is_err() || self[stack].kind != Kind::Stck { if self.values[stack as usize].is_err() || self[stack].kind != Kind::Stck {
@ -1385,7 +1370,8 @@ impl ItemCtx {
let loops = self.nodes.new_node(ty::Id::VOID, Kind::Loops, [VOID]); let loops = self.nodes.new_node(ty::Id::VOID, Kind::Loops, [VOID]);
debug_assert_eq!(loops, LOOPS); debug_assert_eq!(loops, LOOPS);
self.nodes.lock(loops); self.nodes.lock(loops);
self.scope.store = Variable::new(0, ty::Id::VOID, false, MEM, &mut self.nodes); self.scope.store =
Variable::new(Ident::default(), ty::Id::VOID, false, MEM, &mut self.nodes);
} }
fn finalize(&mut self, stack: &mut Vec<Nid>) { fn finalize(&mut self, stack: &mut Vec<Nid>) {
@ -2033,6 +2019,18 @@ impl<'a> Codegen<'a> {
} }
fn emit_and_eval(&mut self, file: FileId, ret: ty::Id, ret_loc: &mut [u8]) -> u64 { fn emit_and_eval(&mut self, file: FileId, ret: ty::Id, ret_loc: &mut [u8]) -> u64 {
let mut rets =
self.ci.nodes[NEVER].inputs.iter().filter(|&&i| self.ci.nodes[i].kind == Kind::Return);
if let Some(&ret) = rets.next()
&& rets.next().is_none()
&& let Kind::CInt { value } = self.ci.nodes[self.ci.nodes[ret].inputs[1]].kind
{
if let len @ 1..=8 = ret_loc.len() {
ret_loc.copy_from_slice(&value.to_ne_bytes()[..len])
}
return value as _;
}
if !self.complete_call_graph() { if !self.complete_call_graph() {
return 1; return 1;
} }
@ -2048,7 +2046,6 @@ impl<'a> Codegen<'a> {
let func = Func { let func = Func {
file, file,
name: 0,
relocs: mem::take(&mut self.ci.relocs), relocs: mem::take(&mut self.ci.relocs),
code: mem::take(&mut self.ci.code), code: mem::take(&mut self.ci.code),
..Default::default() ..Default::default()
@ -2145,6 +2142,13 @@ impl<'a> Codegen<'a> {
self.complete_call_graph(); self.complete_call_graph();
} }
pub fn assemble_comptime(&mut self) -> Comptime {
self.ct.code.clear();
self.tys.reassemble(&mut self.ct.code);
self.ct.reset();
core::mem::take(self.ct)
}
pub fn assemble(&mut self, buf: &mut Vec<u8>) { pub fn assemble(&mut self, buf: &mut Vec<u8>) {
self.tys.reassemble(buf); self.tys.reassemble(buf);
} }
@ -2450,11 +2454,7 @@ impl<'a> Codegen<'a> {
self.strip_var(&mut rhs); self.strip_var(&mut rhs);
let ty = self.binop_ty(pos, &mut lhs, &mut rhs, op); let ty = self.binop_ty(pos, &mut lhs, &mut rhs, op);
let inps = [VOID, lhs.id, rhs.id]; let inps = [VOID, lhs.id, rhs.id];
Some(self.ci.nodes.new_node_lit( Some(self.ci.nodes.new_node_lit(ty.bin_ret(op), Kind::BinOp { op }, inps))
ty::bin_ret(ty, op),
Kind::BinOp { op },
inps,
))
} }
ty::Kind::Struct(s) if op.is_homogenous() => { ty::Kind::Struct(s) if op.is_homogenous() => {
self.ci.nodes.lock(lhs.id); self.ci.nodes.lock(lhs.id);
@ -3598,7 +3598,7 @@ impl<'a> Codegen<'a> {
#[must_use] #[must_use]
#[track_caller] #[track_caller]
fn binop_ty(&mut self, pos: Pos, lhs: &mut Value, rhs: &mut Value, op: TokenKind) -> ty::Id { fn binop_ty(&mut self, pos: Pos, lhs: &mut Value, rhs: &mut Value, op: TokenKind) -> ty::Id {
if let Some(upcasted) = lhs.ty.try_upcast(rhs.ty, ty::TyCheck::BinOp) { if let Some(upcasted) = lhs.ty.try_upcast(rhs.ty) {
let to_correct = if lhs.ty != upcasted { let to_correct = if lhs.ty != upcasted {
Some(lhs) Some(lhs)
} else if rhs.ty != upcasted { } else if rhs.ty != upcasted {
@ -3641,7 +3641,7 @@ impl<'a> Codegen<'a> {
expected: ty::Id, expected: ty::Id,
hint: impl fmt::Display, hint: impl fmt::Display,
) -> bool { ) -> bool {
if let Some(upcasted) = src.ty.try_upcast(expected, ty::TyCheck::Assign) if let Some(upcasted) = src.ty.try_upcast(expected)
&& upcasted == expected && upcasted == expected
{ {
if src.ty != upcasted { if src.ty != upcasted {
@ -3999,7 +3999,7 @@ impl<'a> Function<'a> {
let (ret, mut parama) = self.tys.parama(self.sig.ret); let (ret, mut parama) = self.tys.parama(self.sig.ret);
let mut typs = self.sig.args.args(); let mut typs = self.sig.args.args();
#[allow(clippy::unnecessary_to_owned)] #[expect(clippy::unnecessary_to_owned)]
let mut args = self.nodes[VOID].outputs[ARG_START..].to_owned().into_iter(); let mut args = self.nodes[VOID].outputs[ARG_START..].to_owned().into_iter();
while let Some(ty) = typs.next_value(self.tys) { while let Some(ty) = typs.next_value(self.tys) {
let arg = args.next().unwrap(); let arg = args.next().unwrap();

View file

@ -24,12 +24,12 @@ main:
JALA r0, r31, 0a JALA r0, r31, 0a
pass: pass:
LD r4, r2, 8a, 8h LD r4, r2, 8a, 8h
MULI64 r8, r4, 8d MULI64 r7, r4, 8d
LD r5, r2, 0a, 8h LD r5, r2, 0a, 8h
ADD64 r11, r8, r2 ADD64 r10, r7, r2
ADD64 r10, r4, r5 ADD64 r9, r4, r5
LD r11, r11, 0a, 8h LD r1, r10, 0a, 8h
ADD64 r1, r11, r10 ADD64 r1, r1, r9
JALA r0, r31, 0a JALA r0, r31, 0a
code size: 316 code size: 316
ret: 8 ret: 8

View file

@ -25,15 +25,15 @@ main:
JEQ r2, r11, :2 JEQ r2, r11, :2
LI64 r1, 64d LI64 r1, 64d
JMP :1 JMP :1
2: LD r10, r254, 0a, 1h 2: LD r11, r254, 0a, 1h
LD r9, r254, 4a, 4h LD r9, r254, 4a, 4h
LD r11, r254, 8a, 4h LD r12, r254, 8a, 4h
LD r5, r254, 1a, 1h LD r5, r254, 1a, 1h
ANDI r4, r10, 255d ANDI r4, r11, 255d
ADD32 r6, r11, r9 ADD32 r3, r12, r9
LD r11, r254, 2a, 1h LD r11, r254, 2a, 1h
ANDI r10, r5, 255d ANDI r10, r5, 255d
ADD32 r9, r6, r4 ADD32 r9, r3, r4
LD r5, r254, 3a, 1h LD r5, r254, 3a, 1h
ANDI r4, r11, 255d ANDI r4, r11, 255d
ADD32 r3, r9, r10 ADD32 r3, r9, r10

View file

@ -86,12 +86,12 @@ push:
MULI64 r8, r6, 8d MULI64 r8, r6, 8d
LD r12, r38, 0a, 8h LD r12, r38, 0a, 8h
ADD64 r11, r12, r8 ADD64 r11, r12, r8
CP r8, r39 CP r3, r39
9: JNE r11, r12, :5 9: JNE r11, r12, :5
LD r5, r38, 8a, 8h LD r8, r38, 8a, 8h
JEQ r5, r1, :6 JEQ r8, r1, :6
CP r4, r37 CP r4, r37
MUL64 r3, r5, r4 MUL64 r3, r8, r4
LD r2, r38, 0a, 8h LD r2, r38, 0a, 8h
JAL r31, r0, :free JAL r31, r0, :free
CP r5, r39 CP r5, r39
@ -101,11 +101,11 @@ push:
JMP :8 JMP :8
5: CP r4, r37 5: CP r4, r37
CP r5, r39 CP r5, r39
ADDI64 r6, r8, 8d ADDI64 r6, r3, 8d
ADDI64 r7, r12, 8d ADDI64 r7, r12, 8d
LD r9, r12, 0a, 8h LD r8, r12, 0a, 8h
ST r9, r8, 0a, 8h ST r8, r3, 0a, 8h
CP r8, r6 CP r3, r6
CP r12, r7 CP r12, r7
JMP :9 JMP :9
0: CP r38, r34 0: CP r38, r34

View file

@ -1,17 +1,17 @@
main: main:
ADDI64 r254, r254, -128d ADDI64 r254, r254, -128d
LI8 r7, 69b LI8 r5, 69b
LI64 r6, 128d LI64 r6, 128d
LI64 r8, 0d LI64 r7, 0d
ADDI64 r4, r254, 0d ADDI64 r4, r254, 0d
2: JLTU r8, r6, :0 2: JLTU r7, r6, :0
LD r3, r254, 42a, 1h LD r1, r254, 42a, 1h
ANDI r1, r3, 255d ANDI r1, r1, 255d
JMP :1 JMP :1
0: ADDI64 r5, r8, 1d 0: ADDI64 r3, r7, 1d
ADD64 r12, r4, r8 ADD64 r7, r4, r7
ST r7, r12, 0a, 1h ST r5, r7, 0a, 1h
CP r8, r5 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

View file

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

View file

@ -32,14 +32,14 @@ structs:
ST r7, r254, 16a, 8h ST r7, r254, 16a, 8h
LD r11, r254, 0a, 8h LD r11, r254, 0a, 8h
LD r1, r254, 8a, 8h LD r1, r254, 8a, 8h
ADD64 r5, r1, r11 ADD64 r3, r1, r11
SUB64 r5, r5, r7 SUB64 r5, r3, r7
ST r5, r254, 24a, 8h ST r5, r254, 24a, 8h
ST r4, r254, 32a, 8h ST r4, r254, 32a, 8h
LD r9, r254, 40a, 8h LD r9, r254, 40a, 8h
LD r11, r254, 24a, 8h LD r11, r254, 24a, 8h
ADD64 r2, r11, r9 ADD64 r1, r11, r9
SUB64 r1, r2, r4 SUB64 r1, r1, r4
ADDI64 r254, r254, 48d ADDI64 r254, r254, 48d
JALA r0, r31, 0a JALA r0, r31, 0a
code size: 373 code size: 373

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

@ -6,12 +6,12 @@ main:
ADDI64 r254, r254, -16d ADDI64 r254, r254, -16d
ST r31, r254, 8a, 8h ST r31, r254, 8a, 8h
ADDI64 r2, r254, 0d ADDI64 r2, r254, 0d
LI64 r4, 2d LI64 r3, 2d
ST r4, r254, 0a, 8h ST r3, r254, 0a, 8h
JAL r31, r0, :clobber JAL r31, r0, :clobber
LD r8, r254, 0a, 8h LD r8, r254, 0a, 8h
LI64 r7, 4d LI64 r9, 4d
SUB64 r1, r7, r8 SUB64 r1, r9, r8
LD r31, r254, 8a, 8h LD r31, r254, 8a, 8h
ADDI64 r254, r254, 16d ADDI64 r254, r254, 16d
JALA r0, r31, 0a JALA r0, r31, 0a

View file

@ -1,41 +1,41 @@
main: main:
ADDI64 r254, r254, -40d ADDI64 r254, r254, -40d
LI64 r6, 4d LI64 r6, 4d
LI64 r8, 1d LI64 r7, 1d
LI64 r4, 0d LI64 r4, 0d
ADDI64 r5, r254, 0d ADDI64 r5, r254, 0d
CP r9, r4 CP r8, r4
6: JNE r9, r6, :0 6: JNE r8, r6, :0
LI64 r6, 2d LI64 r6, 2d
ADDI64 r7, r254, 32d ADDI64 r1, r254, 32d
CP r9, r4 CP r8, r4
4: JNE r9, r8, :1 4: JNE r8, r7, :1
LD r1, r254, 0a, 8h LD r1, r254, 0a, 8h
JMP :2 JMP :2
1: MUL64 r12, r9, r6 1: MUL64 r11, r8, r6
ADD64 r9, r9, r8 ADD64 r8, r8, r7
SUB64 r10, r6, r9 SUB64 r9, r6, r8
MUL64 r10, r10, r6 MUL64 r9, r9, r6
CP r3, r4 CP r2, r4
5: JNE r3, r6, :3 5: JNE r2, r6, :3
JMP :4 JMP :4
3: ADD64 r11, r3, r8 3: ADD64 r3, r2, r7
ADD64 r1, r12, r3 ADD64 r10, r11, r2
MULI64 r1, r1, 8d MULI64 r10, r10, 8d
ADD64 r2, r10, r3 ADD64 r2, r9, r2
ADD64 r1, r5, r1 ADD64 r10, r5, r10
MULI64 r2, r2, 8d MULI64 r12, r2, 8d
ADD64 r2, r5, r2 ADD64 r12, r5, r12
BMC r1, r7, 8h BMC r10, r1, 8h
BMC r2, r1, 8h BMC r12, r10, 8h
BMC r7, r2, 8h BMC r1, r12, 8h
CP r3, r11 CP r2, r3
JMP :5 JMP :5
0: ADD64 r2, r9, r8 0: ADD64 r1, r8, r7
MULI64 r12, r9, 8d MULI64 r12, r8, 8d
ADD64 r7, r5, r12 ADD64 r9, r5, r12
ST r9, r7, 0a, 8h ST r8, r9, 0a, 8h
CP r9, r2 CP r8, r1
JMP :6 JMP :6
2: ADDI64 r254, r254, 40d 2: ADDI64 r254, r254, 40d
JALA r0, r31, 0a JALA r0, r31, 0a

View file

@ -30,82 +30,82 @@ main:
LD r7, r254, 150a, 1h LD r7, r254, 150a, 1h
ADD8 r9, r7, r6 ADD8 r9, r7, r6
LD r11, r254, 148a, 1h LD r11, r254, 148a, 1h
ADD8 r3, r11, r9 ADD8 r1, r11, r9
LI8 r4, 4b LI8 r3, 4b
ADD8 r3, r3, r2 ADD8 r6, r1, r2
ANDI r6, r6, 255d
ANDI r3, r3, 255d ANDI r3, r3, 255d
ANDI r4, r4, 255d JEQ r6, r3, :0
JEQ r3, r4, :0
LI64 r1, 1008d LI64 r1, 1008d
JMP :1 JMP :1
0: LI64 r11, 1d 0: LI64 r10, 1d
ADDI64 r2, r254, 80d ADDI64 r1, r254, 80d
ST r11, r254, 80a, 8h ST r10, r254, 80a, 8h
LI64 r3, 2d LI64 r2, 2d
ST r3, r254, 88a, 8h ST r2, r254, 88a, 8h
LI64 r7, 3d LI64 r6, 3d
ST r7, r254, 32a, 8h ST r6, r254, 32a, 8h
LI64 r10, 4d LI64 r9, 4d
ST r10, r254, 40a, 8h ST r9, r254, 40a, 8h
LD r4, r254, 32a, 8h
LD r5, r254, 80a, 8h
ADDI64 r3, r254, 0d
ADD64 r7, r4, r5
ST r7, r254, 0a, 8h
LD r11, r254, 40a, 8h
LD r12, r254, 88a, 8h
ADD64 r4, r11, r12
ST r4, r254, 8a, 8h
LD r6, r254, 80a, 8h
LD r7, r254, 32a, 8h
SUB64 r9, r7, r6
ST r9, r254, 16a, 8h
LD r1, r254, 88a, 8h
LD r4, r254, 40a, 8h
SUB64 r4, r4, r1
ST r4, r254, 24a, 8h
ADDI64 r7, r254, 112d
BMC r3, r7, 32h
LI64 r10, 0d
ST r10, r254, 96a, 8h
ST r10, r254, 104a, 8h
LD r3, r254, 32a, 8h LD r3, r254, 32a, 8h
LD r4, r254, 96a, 8h LD r4, r254, 80a, 8h
ADDI64 r10, r254, 48d ADDI64 r2, r254, 0d
SUB64 r7, r4, r3 ADD64 r6, r3, r4
ST r7, r254, 48a, 8h ST r6, r254, 0a, 8h
LD r11, r254, 40a, 8h LD r10, r254, 40a, 8h
LD r12, r254, 104a, 8h LD r11, r254, 88a, 8h
SUB64 r3, r12, r11 ADD64 r3, r10, r11
ST r3, r254, 56a, 8h ST r3, r254, 8a, 8h
ADDI64 r12, r10, 16d LD r5, r254, 80a, 8h
BMC r2, r12, 16h LD r6, r254, 32a, 8h
LD r9, r254, 112a, 8h SUB64 r8, r6, r5
LD r10, r254, 48a, 8h ST r8, r254, 16a, 8h
ADD64 r12, r10, r9 LD r12, r254, 88a, 8h
ST r12, r254, 48a, 8h LD r3, r254, 40a, 8h
LD r4, r254, 120a, 8h SUB64 r3, r3, r12
LD r5, r254, 56a, 8h ST r3, r254, 24a, 8h
ADD64 r7, r4, r5 ADDI64 r6, r254, 112d
ST r7, r254, 56a, 8h BMC r2, r6, 32h
LD r12, r254, 128a, 8h LI64 r9, 0d
ST r9, r254, 96a, 8h
ST r9, r254, 104a, 8h
LD r2, r254, 32a, 8h
LD r3, r254, 96a, 8h
ADDI64 r9, r254, 48d
SUB64 r6, r3, r2
ST r6, r254, 48a, 8h
LD r10, r254, 40a, 8h
LD r11, r254, 104a, 8h
SUB64 r2, r11, r10
ST r2, r254, 56a, 8h
ADDI64 r11, r9, 16d
BMC r1, r11, 16h
LD r8, r254, 112a, 8h
LD r9, r254, 48a, 8h
ADD64 r11, r9, r8
ST r11, r254, 48a, 8h
LD r3, r254, 120a, 8h
LD r4, r254, 56a, 8h
ADD64 r6, r3, r4
ST r6, r254, 56a, 8h
LD r11, r254, 128a, 8h
LD r12, r254, 64a, 8h
ADD64 r2, r11, r12
ST r2, r254, 64a, 8h
LD r6, r254, 136a, 8h
LD r7, r254, 72a, 8h
ADD64 r9, r6, r7
ST r9, r254, 72a, 8h
LD r1, r254, 64a, 8h LD r1, r254, 64a, 8h
ADD64 r3, r12, r1 LD r2, r254, 48a, 8h
ST r3, r254, 64a, 8h ADD64 r4, r1, r2
LD r7, r254, 136a, 8h ST r4, r254, 152a, 8h
LD r8, r254, 72a, 8h LD r8, r254, 72a, 8h
ADD64 r10, r7, r8 LD r9, r254, 56a, 8h
ST r10, r254, 72a, 8h ADD64 r11, r8, r9
LD r2, r254, 64a, 8h ST r11, r254, 160a, 8h
LD r3, r254, 48a, 8h LD r2, r254, 152a, 8h
ADD64 r5, r2, r3 ADD64 r1, r2, r11
ST r5, r254, 152a, 8h
LD r9, r254, 72a, 8h
LD r10, r254, 56a, 8h
ADD64 r12, r9, r10
ST r12, r254, 160a, 8h
LD r3, r254, 152a, 8h
ADD64 r1, r3, r12
1: ADDI64 r254, r254, 168d 1: ADDI64 r254, r254, 168d
JALA r0, r31, 0a JALA r0, r31, 0a
code size: 1145 code size: 1145

View file

@ -25,8 +25,9 @@ fib_iter:
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
@ -48,6 +49,6 @@ main:
LD r31, r254, 2a, 24h LD r31, r254, 2a, 24h
ADDI64 r254, r254, 26d ADDI64 r254, r254, 26d
JALA r0, r31, 0a JALA r0, r31, 0a
code size: 351 code size: 354
ret: 0 ret: 0
status: Ok(()) status: Ok(())

View file

@ -15,19 +15,19 @@ main:
ADDI64 r2, r254, 32d ADDI64 r2, r254, 32d
JAL r31, r0, :foo JAL r31, r0, :foo
ST r1, r254, 32a, 16h ST r1, r254, 32a, 16h
ADDI64 r8, r254, 16d ADDI64 r7, r254, 16d
JAL r31, r0, :foo JAL r31, r0, :foo
ST r1, r254, 16a, 16h ST r1, r254, 16a, 16h
ADDI64 r2, r254, 0d ADDI64 r2, r254, 0d
JAL r31, r0, :foo JAL r31, r0, :foo
ST r1, r254, 0a, 16h ST r1, r254, 0a, 16h
LD r2, r254, 24a, 4h LD r1, r254, 24a, 4h
LD r7, r254, 12a, 4h LD r7, r254, 12a, 4h
ANDI r5, r2, 4294967295d ANDI r4, r1, 4294967295d
LD r1, r254, 32a, 8h LD r1, r254, 32a, 8h
ANDI r11, r7, 4294967295d ANDI r11, r7, 4294967295d
ADD64 r10, r1, r5 ADD64 r8, r1, r4
ADD64 r2, r10, r11 ADD64 r2, r8, r11
LI64 r3, 7d LI64 r3, 7d
SUB64 r1, r3, r2 SUB64 r1, r3, r2
LD r31, r254, 48a, 8h LD r31, r254, 48a, 8h

View file

@ -2,26 +2,26 @@ main:
ADDI64 r254, r254, -10240d ADDI64 r254, r254, -10240d
LI8 r6, 64b LI8 r6, 64b
LI64 r7, 1024d LI64 r7, 1024d
LI64 r9, 1d LI64 r8, 1d
LI64 r8, 0d LI64 r9, 0d
ADDI64 r5, r254, 0d ADDI64 r5, r254, 0d
4: JLTU r8, r7, :0 4: JLTU r9, r7, :0
LI64 r6, 10d LI64 r4, 10d
CP r7, r9 CP r6, r8
3: JLTU r7, r6, :1 3: JLTU r6, r4, :1
LD r12, r254, 2048a, 1h LD r10, r254, 2048a, 1h
ANDI r1, r12, 255d ANDI r1, r10, 255d
JMP :2 JMP :2
1: ADD64 r2, r7, r9 1: ADD64 r12, r6, r8
MULI64 r1, r7, 1024d MULI64 r1, r6, 1024d
ADD64 r7, r5, r1 ADD64 r6, r5, r1
BMC r5, r7, 1024h BMC r5, r6, 1024h
CP r7, r2 CP r6, r12
JMP :3 JMP :3
0: ADD64 r2, r8, r9 0: ADD64 r1, r9, r8
ADD64 r8, r5, r8 ADD64 r10, r5, r9
ST r6, r8, 0a, 1h ST r6, r10, 0a, 1h
CP r8, r2 CP r9, r1
JMP :4 JMP :4
2: ADDI64 r254, r254, 10240d 2: ADDI64 r254, r254, 10240d
JALA r0, r31, 0a JALA r0, r31, 0a

View file

@ -6,10 +6,10 @@ main:
CP r3, r4 CP r3, r4
JAL r31, r0, :maina JAL r31, r0, :maina
ST r1, r254, 0a, 16h ST r1, r254, 0a, 16h
LD r9, r254, 12a, 1h LD r8, r254, 12a, 1h
LD r8, r254, 3a, 1h LD r9, r254, 3a, 1h
SUB8 r12, r8, r9 SUB8 r11, r9, r8
ANDI r1, r12, 255d ANDI r1, r11, 255d
LD r31, r254, 16a, 8h LD r31, r254, 16a, 8h
ADDI64 r254, r254, 24d ADDI64 r254, r254, 24d
JALA r0, r31, 0a JALA r0, r31, 0a

View file

@ -99,7 +99,6 @@ impl<PfH: HandlePageFault, const OUT_PROG_EXEC: bool> SoftPagedMem<'_, PfH, OUT_
/// to a specified function. /// to a specified function.
/// ///
/// If page is not found, execute page fault trap handler. /// If page is not found, execute page fault trap handler.
#[allow(clippy::too_many_arguments)] // Silence peasant
fn memory_access( fn memory_access(
&mut self, &mut self,
reason: MemoryAccessReason, reason: MemoryAccessReason,

View file

@ -17,9 +17,8 @@ use {
macro_rules! handler { macro_rules! handler {
($self:expr, |$ty:ident ($($ident:pat),* $(,)?)| $expr:expr) => {{ ($self:expr, |$ty:ident ($($ident:pat),* $(,)?)| $expr:expr) => {{
#[allow(unused_unsafe)] let $ty($($ident),*) = $self.decode::<$ty>();
let $ty($($ident),*) = unsafe { $self.decode::<$ty>() }; let e = $expr;
#[allow(clippy::no_effect)] let e = $expr;
$self.bump_pc::<$ty>(); $self.bump_pc::<$ty>();
e e
}}; }};
@ -475,22 +474,24 @@ where
/// Fused division-remainder /// Fused division-remainder
#[inline(always)] #[inline(always)]
unsafe fn dir<T: ValueVariant + CheckedDivRem>(&mut self) { unsafe fn dir<T: ValueVariant + CheckedDivRem>(&mut self) {
handler!(self, |OpsRRRR(td, tr, a0, a1)| { unsafe {
let a0 = self.read_reg(a0).cast::<T>(); handler!(self, |OpsRRRR(td, tr, a0, a1)| {
let a1 = self.read_reg(a1).cast::<T>(); let a0 = self.read_reg(a0).cast::<T>();
let a1 = self.read_reg(a1).cast::<T>();
if let Some(div) = a0.checked_div(a1) { if let Some(div) = a0.checked_div(a1) {
self.write_reg(td, div); self.write_reg(td, div);
} else { } else {
self.write_reg(td, -1_i64); self.write_reg(td, -1_i64);
} }
if let Some(rem) = a0.checked_rem(a1) { if let Some(rem) = a0.checked_rem(a1) {
self.write_reg(tr, rem); self.write_reg(tr, rem);
} else { } else {
self.write_reg(tr, a0); self.write_reg(tr, a0);
} }
}); });
}
} }
/// Fused multiply-add /// Fused multiply-add
@ -499,22 +500,26 @@ where
where where
T: ValueVariant + core::ops::Mul<Output = T> + core::ops::Add<Output = T>, T: ValueVariant + core::ops::Mul<Output = T> + core::ops::Add<Output = T>,
{ {
handler!(self, |OpsRRRR(tg, a0, a1, a2)| { unsafe {
let a0 = self.read_reg(a0).cast::<T>(); handler!(self, |OpsRRRR(tg, a0, a1, a2)| {
let a1 = self.read_reg(a1).cast::<T>(); let a0 = self.read_reg(a0).cast::<T>();
let a2 = self.read_reg(a2).cast::<T>(); let a1 = self.read_reg(a1).cast::<T>();
self.write_reg(tg, a0 * a1 + a2) let a2 = self.read_reg(a2).cast::<T>();
}); self.write_reg(tg, a0 * a1 + a2)
});
}
} }
/// Float comparsion /// Float comparsion
#[inline(always)] #[inline(always)]
unsafe fn fcmp<T: PartialOrd + ValueVariant>(&mut self, nan: Ordering) { unsafe fn fcmp<T: PartialOrd + ValueVariant>(&mut self, nan: Ordering) {
handler!(self, |OpsRRR(tg, a0, a1)| { unsafe {
let a0 = self.read_reg(a0).cast::<T>(); handler!(self, |OpsRRR(tg, a0, a1)| {
let a1 = self.read_reg(a1).cast::<T>(); let a0 = self.read_reg(a0).cast::<T>();
self.write_reg(tg, (a0.partial_cmp(&a1).unwrap_or(nan) as i8 + 1) as u8) let a1 = self.read_reg(a1).cast::<T>();
}); self.write_reg(tg, (a0.partial_cmp(&a1).unwrap_or(nan) as i8 + 1) as u8)
});
}
} }
/// Calculate pc-relative address /// Calculate pc-relative address