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>> {
writeln!(generated, "#![allow(dead_code)] #![allow(clippy::upper_case_acronyms)]")?;
writeln!(generated, "#![expect(dead_code)]")?;
writeln!(generated, "use crate::*;")?;
'_opcode_structs: {

View file

@ -665,7 +665,6 @@ mod db {
($vis:vis struct $name:ident {
$($qname:ident: $code:expr,)*
}) => {
#[allow(dead_code)]
$vis struct $name<'a> {
$($vis $qname: rusqlite::Statement<'a>,)*
}

View file

@ -4,7 +4,10 @@
use {
alloc::{string::String, vec::Vec},
hblang::{codegen::Codegen, parser::FileId},
hblang::{
parser::FileId,
son::{Codegen, CodegenCtx},
},
};
extern crate alloc;
@ -74,8 +77,8 @@ unsafe fn compile_and_run(mut fuel: usize) {
};
let mut ct = {
let mut c = Codegen::default();
c.files = files;
let mut ctx = CodegenCtx::default();
let mut c = Codegen::new(&files, &mut ctx);
c.generate(root as FileId);
c.assemble_comptime()
};

View file

@ -104,7 +104,7 @@ pub struct ArenaAllocator<const SIZE: usize> {
}
impl<const SIZE: usize> ArenaAllocator<SIZE> {
#[allow(clippy::new_without_default)]
#[expect(clippy::new_without_default)]
pub const fn new() -> Self {
ArenaAllocator {
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) {
(*self.head.get()) = self.arena.get().cast::<u8>().add(SIZE);
}

View file

@ -20,11 +20,9 @@ log = "0.4.22"
[dependencies.regalloc2]
git = "https://github.com/jakubDoka/regalloc2"
branch = "reuse-allocations"
optional = true
features = ["trace-log"]
[features]
default = ["std", "opts"]
default = ["std"]
std = []
opts = ["regalloc2"]
no_log = ["log/max_level_off"]

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,5 @@
use {
crate::{
ident,
lexer::{self, Lexer, TokenKind},
parser::{self, CommentOr, CtorField, Expr, Poser, Radix, StructField},
},
@ -256,7 +255,7 @@ impl<'a> Formatter<'a> {
fields,
|s: &mut Self, CtorField { name, value, .. }: &_, f| {
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(": ")?;
s.fmt(value, f)?;
}

View file

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

View file

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

View file

@ -178,7 +178,7 @@ impl core::fmt::Debug for 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)> {
use crate::instrs;
Some((
@ -225,7 +225,6 @@ impl TokenKind {
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 {

View file

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

View file

@ -1,8 +1,8 @@
use {
crate::{
fmt::Formatter,
ident::{self, Ident},
lexer::{self, Lexer, Token, TokenKind},
Ident,
},
alloc::{boxed::Box, string::String, vec::Vec},
core::{
@ -126,11 +126,8 @@ impl<'a, 'b> Parser<'a, 'b> {
let mut idents = core::mem::take(&mut self.ctx.idents);
for id in idents.drain(..) {
self.report(
ident::pos(id.ident),
format_args!(
"undeclared identifier: {}",
self.lexer.slice(ident::range(id.ident))
),
id.ident.pos(),
format_args!("undeclared identifier: {}", self.lexer.slice(id.ident.range())),
);
}
self.ctx.idents = idents;
@ -217,7 +214,7 @@ impl<'a, 'b> Parser<'a, 'b> {
pos,
format_args!(
"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) {
self.report(
pos,
format_args!("redeclaration of identifier: {}", self.lexer.slice(ident::range(id))),
format_args!("redeclaration of identifier: {}", self.lexer.slice(id.range())),
);
return;
}
@ -242,7 +239,7 @@ impl<'a, 'b> Parser<'a, 'b> {
let name = self.lexer.slice(token.range());
if let Some(builtin) = crate::ty::from_str(name) {
return (builtin, false);
return (Ident::builtin(builtin), false);
}
let (i, id, bl) = match self
@ -250,14 +247,14 @@ impl<'a, 'b> Parser<'a, 'b> {
.idents
.iter_mut()
.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),
None => {
let ident = match ident::new(token.start, name.len() as _) {
let ident = match Ident::new(token.start, name.len() as _) {
None => {
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,
};
@ -725,7 +722,7 @@ macro_rules! generate_expr {
}
pub fn pos(&self) -> Pos {
#[allow(unused_variables)]
#[expect(unused_variables)]
match self {
$(Self::$variant { $($field),* } => generate_expr!(@first $(($field),)*).posi(),)*
}
@ -914,7 +911,7 @@ generate_expr! {
impl Expr<'_> {
pub fn declares(&self, iden: Result<Ident, &str>, source: &str) -> Option<Ident> {
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)
}
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 {
&self.file[ident::range(ident)]
&self.file[ident.range()]
}
}

View file

@ -2,9 +2,7 @@ use {
self::strong_ref::StrongRef,
crate::{
ctx_map::CtxEntry,
debug,
ident::Ident,
instrs,
debug, instrs,
lexer::{self, TokenKind},
parser::{
self,
@ -14,8 +12,8 @@ use {
reg, task,
ty::{self, Arg, ArrayLen, Loc, Tuple},
vc::{BitSet, Vc},
Comptime, FTask, Func, Global, HashMap, Offset, OffsetIter, PLoc, Reloc, Sig, StringRef,
SymKey, TypeParser, TypedReloc, Types,
Comptime, FTask, Func, Global, HashMap, Ident, Offset, OffsetIter, PLoc, Reloc, Sig,
StringRef, SymKey, TypeParser, TypedReloc, Types,
},
alloc::{borrow::ToOwned, string::String, vec::Vec},
core::{
@ -28,7 +26,6 @@ use {
hashbrown::hash_map,
hbbytecode::DisasmError,
regalloc2::VReg,
std::panic,
};
const VOID: Nid = 0;
@ -146,26 +143,25 @@ impl Nodes {
Ok(())
}
#[allow(dead_code)]
fn graphviz(&self, tys: &Types, files: &[parser::Ast]) {
let out = &mut String::new();
_ = self.graphviz_low(tys, files, 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"))]
{
// let out = &mut String::new();
// _ = self.graphviz_low(tys, files, out);
// if !std::process::Command::new("brave")
// .arg(format!("https://dreampuf.github.io/GraphvizOnline/#{out}"))
// .status()
// .unwrap()
// .success()
// {
// log::error!("{out}");
// }
let out = &mut String::new();
_ = self.graphviz_low(_tys, _files, out);
if !std::process::Command::new("brave")
.arg(format!("https://dreampuf.github.io/GraphvizOnline/#{out}"))
.status()
.unwrap()
.success()
{
log::error!("{out}");
}
}
}
@ -177,18 +173,6 @@ impl Nodes {
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) {
self.values.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);
if let Some(opt) = self.peephole(id) {
debug_assert_ne!(opt, id);
self.lock(opt);
self.remove(id);
self.unlock(opt);
(opt, true)
opt
} 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 {
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) {
@ -292,8 +272,6 @@ impl Nodes {
return false;
}
debug_assert!(!matches!(self[target].kind, Kind::Call { .. }), "{:?}", self[target]);
for i in 0..self[target].inputs.len() {
let inp = self[target].inputs[i];
let index = self[inp].outputs.iter().position(|&p| p == target).unwrap();
@ -302,7 +280,15 @@ impl Nodes {
}
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
}
@ -664,7 +650,7 @@ impl Nodes {
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 {
if self[node].kind != Kind::Loop && self[node].kind != Kind::Region {
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) {
'o: for stack in self[MEM].outputs.clone() {
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]);
debug_assert_eq!(loops, 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>) {
@ -2033,6 +2019,18 @@ impl<'a> Codegen<'a> {
}
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() {
return 1;
}
@ -2048,7 +2046,6 @@ impl<'a> Codegen<'a> {
let func = Func {
file,
name: 0,
relocs: mem::take(&mut self.ci.relocs),
code: mem::take(&mut self.ci.code),
..Default::default()
@ -2145,6 +2142,13 @@ impl<'a> Codegen<'a> {
self.complete_call_graph();
}
pub fn assemble_comptime(&mut self) -> Comptime {
self.ct.code.clear();
self.tys.reassemble(&mut self.ct.code);
self.ct.reset();
core::mem::take(self.ct)
}
pub fn assemble(&mut self, buf: &mut Vec<u8>) {
self.tys.reassemble(buf);
}
@ -2450,11 +2454,7 @@ impl<'a> Codegen<'a> {
self.strip_var(&mut rhs);
let ty = self.binop_ty(pos, &mut lhs, &mut rhs, op);
let inps = [VOID, lhs.id, rhs.id];
Some(self.ci.nodes.new_node_lit(
ty::bin_ret(ty, op),
Kind::BinOp { op },
inps,
))
Some(self.ci.nodes.new_node_lit(ty.bin_ret(op), Kind::BinOp { op }, inps))
}
ty::Kind::Struct(s) if op.is_homogenous() => {
self.ci.nodes.lock(lhs.id);
@ -3598,7 +3598,7 @@ impl<'a> Codegen<'a> {
#[must_use]
#[track_caller]
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 {
Some(lhs)
} else if rhs.ty != upcasted {
@ -3641,7 +3641,7 @@ impl<'a> Codegen<'a> {
expected: ty::Id,
hint: impl fmt::Display,
) -> bool {
if let Some(upcasted) = src.ty.try_upcast(expected, ty::TyCheck::Assign)
if let Some(upcasted) = src.ty.try_upcast(expected)
&& upcasted == expected
{
if src.ty != upcasted {
@ -3999,7 +3999,7 @@ impl<'a> Function<'a> {
let (ret, mut parama) = self.tys.parama(self.sig.ret);
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();
while let Some(ty) = typs.next_value(self.tys) {
let arg = args.next().unwrap();

View file

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

View file

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

View file

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

View file

@ -1,17 +1,17 @@
main:
ADDI64 r254, r254, -128d
LI8 r7, 69b
LI8 r5, 69b
LI64 r6, 128d
LI64 r8, 0d
LI64 r7, 0d
ADDI64 r4, r254, 0d
2: JLTU r8, r6, :0
LD r3, r254, 42a, 1h
ANDI r1, r3, 255d
2: JLTU r7, r6, :0
LD r1, r254, 42a, 1h
ANDI r1, r1, 255d
JMP :1
0: ADDI64 r5, r8, 1d
ADD64 r12, r4, r8
ST r7, r12, 0a, 1h
CP r8, r5
0: ADDI64 r3, r7, 1d
ADD64 r7, r4, r7
ST r5, r7, 0a, 1h
CP r7, r3
JMP :2
1: ADDI64 r254, r254, 128d
JALA r0, r31, 0a

View file

@ -1,17 +1,17 @@
main:
LI64 r8, 6d
LRA r4, r0, :gb
LI64 r7, 0d
LD r9, r4, 0a, 8h
CMPU r10, r9, r7
CMPUI r10, r10, 0d
ORI r12, r10, 0d
ANDI r12, r12, 255d
JNE r12, r0, :0
CP r5, r8
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 r5, 1d
1: SUB64 r1, r5, r8
0: LI64 r4, 1d
1: SUB64 r1, r4, r7
JALA r0, r31, 0a
code size: 131
ret: 0

View file

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

View file

@ -5,8 +5,9 @@ fib:
CP r10, r4
2: JNE r2, r5, :0
JMP :1
0: ADD64 r3, r10, r1
0: ADD64 r1, r10, r1
SUB64 r2, r2, r4
CP r3, r1
CP r1, r10
CP r10, r3
JMP :2
@ -19,6 +20,6 @@ main:
LD r31, r254, 0a, 8h
ADDI64 r254, r254, 8d
JALA r0, r31, 0a
code size: 150
code size: 153
ret: 55
status: Ok(())

View file

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

View file

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

View file

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

View file

@ -25,8 +25,9 @@ fib_iter:
CP r10, r4
2: JNE r2, r5, :0
JMP :1
0: ADD64 r3, r10, r1
0: ADD64 r1, r10, r1
SUB64 r2, r2, r4
CP r3, r1
CP r1, r10
CP r10, r3
JMP :2
@ -48,6 +49,6 @@ main:
LD r31, r254, 2a, 24h
ADDI64 r254, r254, 26d
JALA r0, r31, 0a
code size: 351
code size: 354
ret: 0
status: Ok(())

View file

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

View file

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

View file

@ -6,10 +6,10 @@ main:
CP r3, r4
JAL r31, r0, :maina
ST r1, r254, 0a, 16h
LD r9, r254, 12a, 1h
LD r8, r254, 3a, 1h
SUB8 r12, r8, r9
ANDI r1, r12, 255d
LD r8, r254, 12a, 1h
LD r9, r254, 3a, 1h
SUB8 r11, r9, r8
ANDI r1, r11, 255d
LD r31, r254, 16a, 8h
ADDI64 r254, r254, 24d
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.
///
/// If page is not found, execute page fault trap handler.
#[allow(clippy::too_many_arguments)] // Silence peasant
fn memory_access(
&mut self,
reason: MemoryAccessReason,

View file

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