forked from AbleOS/holey-bytes
binary no longer contains comptime code and inoptimized impl is grately simplified
This commit is contained in:
parent
39c4526797
commit
fbdabd8314
File diff suppressed because it is too large
Load diff
|
@ -17,12 +17,13 @@
|
||||||
extract_if,
|
extract_if,
|
||||||
ptr_internals
|
ptr_internals
|
||||||
)]
|
)]
|
||||||
#![allow(internal_features, clippy::format_collect, dead_code)]
|
#![allow(internal_features, clippy::format_collect)]
|
||||||
|
|
||||||
use {
|
use {
|
||||||
self::{
|
self::{
|
||||||
ident::Ident,
|
ident::Ident,
|
||||||
parser::{ExprRef, FileId},
|
parser::{Expr, ExprRef, FileId},
|
||||||
|
son::reg,
|
||||||
ty::ArrayLen,
|
ty::ArrayLen,
|
||||||
},
|
},
|
||||||
parser::Ast,
|
parser::Ast,
|
||||||
|
@ -53,6 +54,108 @@ pub mod son;
|
||||||
mod instrs;
|
mod instrs;
|
||||||
mod lexer;
|
mod lexer;
|
||||||
|
|
||||||
|
mod task {
|
||||||
|
use super::Offset;
|
||||||
|
|
||||||
|
pub fn unpack(offset: Offset) -> Result<Offset, usize> {
|
||||||
|
if offset >> 31 != 0 {
|
||||||
|
Err((offset & !(1 << 31)) as usize)
|
||||||
|
} else {
|
||||||
|
Ok(offset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_done(offset: Offset) -> bool {
|
||||||
|
unpack(offset).is_ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn id(index: usize) -> Offset {
|
||||||
|
1 << 31 | index as u32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod ident {
|
||||||
|
pub type Ident = u32;
|
||||||
|
|
||||||
|
const LEN_BITS: u32 = 6;
|
||||||
|
|
||||||
|
pub fn len(ident: u32) -> u32 {
|
||||||
|
ident & ((1 << LEN_BITS) - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_null(ident: u32) -> bool {
|
||||||
|
(ident >> LEN_BITS) == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pos(ident: u32) -> u32 {
|
||||||
|
(ident >> LEN_BITS).saturating_sub(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(pos: u32, len: u32) -> u32 {
|
||||||
|
debug_assert!(len < (1 << LEN_BITS));
|
||||||
|
((pos + 1) << LEN_BITS) | len
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn range(ident: u32) -> std::ops::Range<usize> {
|
||||||
|
let (len, pos) = (len(ident) as usize, pos(ident) as usize);
|
||||||
|
pos..pos + len
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod log {
|
||||||
|
#![allow(unused_macros)]
|
||||||
|
|
||||||
|
#[derive(PartialOrd, PartialEq, Ord, Eq, Debug)]
|
||||||
|
pub enum Level {
|
||||||
|
Err,
|
||||||
|
Wrn,
|
||||||
|
Inf,
|
||||||
|
Dbg,
|
||||||
|
Trc,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const LOG_LEVEL: Level = match option_env!("LOG_LEVEL") {
|
||||||
|
Some(val) => match val.as_bytes()[0] {
|
||||||
|
b'e' => Level::Err,
|
||||||
|
b'w' => Level::Wrn,
|
||||||
|
b'i' => Level::Inf,
|
||||||
|
b'd' => Level::Dbg,
|
||||||
|
b't' => Level::Trc,
|
||||||
|
_ => panic!("Invalid log level."),
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
Level::Dbg
|
||||||
|
} else {
|
||||||
|
Level::Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
macro_rules! log {
|
||||||
|
($level:expr, $fmt:literal $($expr:tt)*) => {
|
||||||
|
if $level <= $crate::log::LOG_LEVEL {
|
||||||
|
eprintln!("{:?}: {}", $level, format_args!($fmt $($expr)*));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
($level:expr, $($arg:expr),+) => {
|
||||||
|
if $level <= $crate::log::LOG_LEVEL {
|
||||||
|
$(eprintln!("[{}:{}:{}][{:?}]: {} = {:?}", line!(), column!(), file!(), $level, stringify!($arg), $arg);)*
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! err { ($($arg:tt)*) => { $crate::log::log!($crate::log::Level::Err, $($arg)*) }; }
|
||||||
|
macro_rules! wrn { ($($arg:tt)*) => { $crate::log::log!($crate::log::Level::Wrn, $($arg)*) }; }
|
||||||
|
macro_rules! inf { ($($arg:tt)*) => { $crate::log::log!($crate::log::Level::Inf, $($arg)*) }; }
|
||||||
|
macro_rules! dbg { ($($arg:tt)*) => { $crate::log::log!($crate::log::Level::Dbg, $($arg)*) }; }
|
||||||
|
macro_rules! trc { ($($arg:tt)*) => { $crate::log::log!($crate::log::Level::Trc, $($arg)*) }; }
|
||||||
|
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
pub(crate) use {dbg, err, inf, log, trc, wrn};
|
||||||
|
}
|
||||||
|
|
||||||
mod ty {
|
mod ty {
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
|
@ -70,7 +173,6 @@ mod ty {
|
||||||
pub type Func = u32;
|
pub type Func = u32;
|
||||||
pub type Global = u32;
|
pub type Global = u32;
|
||||||
pub type Module = u32;
|
pub type Module = u32;
|
||||||
pub type Param = u32;
|
|
||||||
pub type Slice = u32;
|
pub type Slice = u32;
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
|
@ -102,10 +204,6 @@ mod ty {
|
||||||
self.0 as usize & Self::LEN_MASK
|
self.0 as usize & Self::LEN_MASK
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_empty(self) -> bool {
|
|
||||||
self.0 == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn empty() -> Self {
|
pub fn empty() -> Self {
|
||||||
Self(0)
|
Self(0)
|
||||||
}
|
}
|
||||||
|
@ -435,8 +533,8 @@ impl Default for Global {
|
||||||
ty: Default::default(),
|
ty: Default::default(),
|
||||||
offset: u32::MAX,
|
offset: u32::MAX,
|
||||||
data: Default::default(),
|
data: Default::default(),
|
||||||
file: 0,
|
file: u32::MAX,
|
||||||
name: 0,
|
name: u32::MAX,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -511,7 +609,99 @@ struct Types {
|
||||||
arrays: Vec<Array>,
|
arrays: Vec<Array>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn emit(out: &mut Vec<u8>, (len, instr): (usize, [u8; instrs::MAX_SIZE])) {
|
||||||
|
out.extend_from_slice(&instr[..len]);
|
||||||
|
}
|
||||||
|
|
||||||
impl Types {
|
impl Types {
|
||||||
|
fn assemble(&mut self, to: &mut Vec<u8>) {
|
||||||
|
emit(to, instrs::jal(reg::RET_ADDR, reg::ZERO, 0));
|
||||||
|
emit(to, instrs::tx());
|
||||||
|
self.dump_reachable(0, to);
|
||||||
|
Reloc::new(0, 3, 4).apply_jump(to, self.funcs[0].offset, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dump_reachable(&mut self, from: ty::Func, to: &mut Vec<u8>) {
|
||||||
|
let mut frontier = vec![ty::Kind::Func(from).compress()];
|
||||||
|
|
||||||
|
while let Some(itm) = frontier.pop() {
|
||||||
|
match itm.expand() {
|
||||||
|
ty::Kind::Func(func) => {
|
||||||
|
let fuc = &mut self.funcs[func as usize];
|
||||||
|
if task::is_done(fuc.offset) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
fuc.offset = to.len() as _;
|
||||||
|
to.extend(&fuc.code);
|
||||||
|
frontier.extend(fuc.relocs.iter().map(|r| r.target));
|
||||||
|
}
|
||||||
|
ty::Kind::Global(glob) => {
|
||||||
|
let glb = &mut self.globals[glob as usize];
|
||||||
|
if task::is_done(glb.offset) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
glb.offset = to.len() as _;
|
||||||
|
to.extend(&glb.data);
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for fuc in &self.funcs {
|
||||||
|
if !task::is_done(fuc.offset) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for rel in &fuc.relocs {
|
||||||
|
let offset = match rel.target.expand() {
|
||||||
|
ty::Kind::Func(fun) => self.funcs[fun as usize].offset,
|
||||||
|
ty::Kind::Global(glo) => self.globals[glo as usize].offset,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
rel.reloc.apply_jump(to, offset, fuc.offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn disasm(
|
||||||
|
&self,
|
||||||
|
mut sluce: &[u8],
|
||||||
|
files: &[parser::Ast],
|
||||||
|
output: &mut impl std::io::Write,
|
||||||
|
eca_handler: impl FnMut(&mut &[u8]),
|
||||||
|
) -> std::io::Result<()> {
|
||||||
|
use crate::DisasmItem;
|
||||||
|
let functions = self
|
||||||
|
.funcs
|
||||||
|
.iter()
|
||||||
|
.filter(|f| task::is_done(f.offset))
|
||||||
|
.map(|f| {
|
||||||
|
let name = if f.file != u32::MAX {
|
||||||
|
let file = &files[f.file as usize];
|
||||||
|
let Expr::BinOp { left: &Expr::Ident { name, .. }, .. } =
|
||||||
|
f.expr.get(file).unwrap()
|
||||||
|
else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
name
|
||||||
|
} else {
|
||||||
|
"target_fn"
|
||||||
|
};
|
||||||
|
(f.offset, (name, f.code.len() as u32, DisasmItem::Func))
|
||||||
|
})
|
||||||
|
.chain(self.globals.iter().filter(|g| task::is_done(g.offset)).map(|g| {
|
||||||
|
let name = if g.file == u32::MAX {
|
||||||
|
std::str::from_utf8(&g.data).unwrap()
|
||||||
|
} else {
|
||||||
|
let file = &files[g.file as usize];
|
||||||
|
file.ident_str(g.name)
|
||||||
|
};
|
||||||
|
(g.offset, (name, g.data.len() as Size, DisasmItem::Global))
|
||||||
|
}))
|
||||||
|
.collect::<BTreeMap<_, _>>();
|
||||||
|
crate::disasm(&mut sluce, &functions, output, eca_handler)
|
||||||
|
}
|
||||||
|
|
||||||
fn parama(&self, ret: impl Into<ty::Id>) -> ParamAlloc {
|
fn parama(&self, ret: impl Into<ty::Id>) -> ParamAlloc {
|
||||||
ParamAlloc(2 + (9..=16).contains(&self.size_of(ret.into())) as u8..12)
|
ParamAlloc(2 + (9..=16).contains(&self.size_of(ret.into())) as u8..12)
|
||||||
}
|
}
|
||||||
|
@ -622,88 +812,6 @@ impl Types {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mod ident {
|
|
||||||
pub type Ident = u32;
|
|
||||||
|
|
||||||
const LEN_BITS: u32 = 6;
|
|
||||||
|
|
||||||
pub fn len(ident: u32) -> u32 {
|
|
||||||
ident & ((1 << LEN_BITS) - 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_null(ident: u32) -> bool {
|
|
||||||
(ident >> LEN_BITS) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pos(ident: u32) -> u32 {
|
|
||||||
(ident >> LEN_BITS).saturating_sub(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new(pos: u32, len: u32) -> u32 {
|
|
||||||
debug_assert!(len < (1 << LEN_BITS));
|
|
||||||
((pos + 1) << LEN_BITS) | len
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn range(ident: u32) -> std::ops::Range<usize> {
|
|
||||||
let (len, pos) = (len(ident) as usize, pos(ident) as usize);
|
|
||||||
pos..pos + len
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod log {
|
|
||||||
#![allow(unused_macros)]
|
|
||||||
|
|
||||||
#[derive(PartialOrd, PartialEq, Ord, Eq, Debug)]
|
|
||||||
pub enum Level {
|
|
||||||
Err,
|
|
||||||
Wrn,
|
|
||||||
Inf,
|
|
||||||
Dbg,
|
|
||||||
Trc,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const LOG_LEVEL: Level = match option_env!("LOG_LEVEL") {
|
|
||||||
Some(val) => match val.as_bytes()[0] {
|
|
||||||
b'e' => Level::Err,
|
|
||||||
b'w' => Level::Wrn,
|
|
||||||
b'i' => Level::Inf,
|
|
||||||
b'd' => Level::Dbg,
|
|
||||||
b't' => Level::Trc,
|
|
||||||
_ => panic!("Invalid log level."),
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
if cfg!(debug_assertions) {
|
|
||||||
Level::Dbg
|
|
||||||
} else {
|
|
||||||
Level::Err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
macro_rules! log {
|
|
||||||
($level:expr, $fmt:literal $($expr:tt)*) => {
|
|
||||||
if $level <= $crate::log::LOG_LEVEL {
|
|
||||||
eprintln!("{:?}: {}", $level, format_args!($fmt $($expr)*));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
($level:expr, $($arg:expr),+) => {
|
|
||||||
if $level <= $crate::log::LOG_LEVEL {
|
|
||||||
$(eprintln!("[{}:{}:{}][{:?}]: {} = {:?}", line!(), column!(), file!(), $level, stringify!($arg), $arg);)*
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! err { ($($arg:tt)*) => { $crate::log::log!($crate::log::Level::Err, $($arg)*) }; }
|
|
||||||
macro_rules! wrn { ($($arg:tt)*) => { $crate::log::log!($crate::log::Level::Wrn, $($arg)*) }; }
|
|
||||||
macro_rules! inf { ($($arg:tt)*) => { $crate::log::log!($crate::log::Level::Inf, $($arg)*) }; }
|
|
||||||
macro_rules! dbg { ($($arg:tt)*) => { $crate::log::log!($crate::log::Level::Dbg, $($arg)*) }; }
|
|
||||||
macro_rules! trc { ($($arg:tt)*) => { $crate::log::log!($crate::log::Level::Trc, $($arg)*) }; }
|
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
|
||||||
pub(crate) use {dbg, err, inf, log, trc, wrn};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn encode<T>(instr: T) -> (usize, [u8; instrs::MAX_SIZE]) {
|
unsafe fn encode<T>(instr: T) -> (usize, [u8; instrs::MAX_SIZE]) {
|
||||||
let mut buf = [0; instrs::MAX_SIZE];
|
let mut buf = [0; instrs::MAX_SIZE];
|
||||||
|
@ -1463,7 +1571,9 @@ pub fn run_compiler(
|
||||||
if options.dump_asm {
|
if options.dump_asm {
|
||||||
codegen.disasm(out)?;
|
codegen.disasm(out)?;
|
||||||
} else {
|
} else {
|
||||||
codegen.dump(out)?;
|
let mut buf = Vec::new();
|
||||||
|
codegen.assemble(&mut buf);
|
||||||
|
out.write_all(&buf)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
codegen,
|
|
||||||
ident::{self, Ident},
|
ident::{self, Ident},
|
||||||
lexer::{self, Lexer, Token, TokenKind},
|
lexer::{self, Lexer, Token, TokenKind},
|
||||||
},
|
},
|
||||||
|
@ -224,7 +223,7 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
let is_ct = token.kind == TokenKind::CtIdent;
|
let is_ct = token.kind == TokenKind::CtIdent;
|
||||||
let name = self.lexer.slice(token.range());
|
let name = self.lexer.slice(token.range());
|
||||||
|
|
||||||
if let Some(builtin) = codegen::ty::from_str(name) {
|
if let Some(builtin) = crate::ty::from_str(name) {
|
||||||
return (builtin, 0);
|
return (builtin, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,12 +10,12 @@ use {
|
||||||
idfl::{self},
|
idfl::{self},
|
||||||
Expr, ExprRef, FileId, Pos,
|
Expr, ExprRef, FileId, Pos,
|
||||||
},
|
},
|
||||||
ty, Field, Func, Reloc, Sig, Struct, SymKey, TypedReloc, Types,
|
task, ty, Field, Func, Reloc, Sig, Struct, SymKey, TypedReloc, Types,
|
||||||
},
|
},
|
||||||
core::fmt,
|
core::fmt,
|
||||||
std::{
|
std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
collections::{hash_map, BTreeMap},
|
collections::hash_map,
|
||||||
fmt::{Debug, Display, Write},
|
fmt::{Debug, Display, Write},
|
||||||
hash::{Hash as _, Hasher},
|
hash::{Hash as _, Hasher},
|
||||||
mem::{self, MaybeUninit},
|
mem::{self, MaybeUninit},
|
||||||
|
@ -331,7 +331,7 @@ impl BitSet {
|
||||||
|
|
||||||
type Nid = u16;
|
type Nid = u16;
|
||||||
|
|
||||||
mod reg {
|
pub mod reg {
|
||||||
|
|
||||||
pub const STACK_PTR: Reg = 254;
|
pub const STACK_PTR: Reg = 254;
|
||||||
pub const ZERO: Reg = 0;
|
pub const ZERO: Reg = 0;
|
||||||
|
@ -1327,7 +1327,7 @@ impl ItemCtx {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit(&mut self, instr: (usize, [u8; instrs::MAX_SIZE])) {
|
fn emit(&mut self, instr: (usize, [u8; instrs::MAX_SIZE])) {
|
||||||
emit(&mut self.code, instr);
|
crate::emit(&mut self.code, instr);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn free_loc(&mut self, loc: impl Into<Option<Loc>>) {
|
fn free_loc(&mut self, loc: impl Into<Option<Loc>>) {
|
||||||
|
@ -1337,31 +1337,11 @@ impl ItemCtx {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit(out: &mut Vec<u8>, (len, instr): (usize, [u8; instrs::MAX_SIZE])) {
|
|
||||||
out.extend_from_slice(&instr[..len]);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_reloc(doce: &mut [u8], offset: usize, value: i64, size: u16) {
|
fn write_reloc(doce: &mut [u8], offset: usize, value: i64, size: u16) {
|
||||||
let value = value.to_ne_bytes();
|
let value = value.to_ne_bytes();
|
||||||
doce[offset..offset + size as usize].copy_from_slice(&value[..size as usize]);
|
doce[offset..offset + size as usize].copy_from_slice(&value[..size as usize]);
|
||||||
}
|
}
|
||||||
|
|
||||||
mod task {
|
|
||||||
use super::Offset;
|
|
||||||
|
|
||||||
pub fn unpack(offset: Offset) -> Result<Offset, usize> {
|
|
||||||
if offset >> 31 != 0 {
|
|
||||||
Err((offset & !(1 << 31)) as usize)
|
|
||||||
} else {
|
|
||||||
Ok(offset)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn id(index: usize) -> Offset {
|
|
||||||
1 << 31 | index as u32
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct FTask {
|
struct FTask {
|
||||||
file: FileId,
|
file: FileId,
|
||||||
id: ty::Func,
|
id: ty::Func,
|
||||||
|
@ -1417,83 +1397,6 @@ impl Codegen {
|
||||||
self.complete_call_graph_low();
|
self.complete_call_graph_low();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assemble(&mut self, to: &mut Vec<u8>) {
|
|
||||||
emit(to, instrs::jal(reg::RET_ADDR, reg::ZERO, 0));
|
|
||||||
emit(to, instrs::tx());
|
|
||||||
self.dump_reachable(0, to);
|
|
||||||
Reloc::new(0, 3, 4).apply_jump(to, self.tys.funcs[0].offset, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dump_reachable(&mut self, from: ty::Func, to: &mut Vec<u8>) {
|
|
||||||
let mut frontier = vec![ty::Kind::Func(from).compress()];
|
|
||||||
|
|
||||||
while let Some(itm) = frontier.pop() {
|
|
||||||
match itm.expand() {
|
|
||||||
ty::Kind::Func(func) => {
|
|
||||||
let fuc = &mut self.tys.funcs[func as usize];
|
|
||||||
if task::unpack(fuc.offset).is_ok() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
fuc.offset = to.len() as _;
|
|
||||||
to.extend(&fuc.code);
|
|
||||||
frontier.extend(fuc.relocs.iter().map(|r| r.target));
|
|
||||||
}
|
|
||||||
ty::Kind::Global(glob) => {
|
|
||||||
let glb = &mut self.tys.globals[glob as usize];
|
|
||||||
if task::unpack(glb.offset).is_ok() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
glb.offset = to.len() as _;
|
|
||||||
to.extend(&glb.data);
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for fuc in &self.tys.funcs {
|
|
||||||
if task::unpack(fuc.offset).is_err() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for rel in &fuc.relocs {
|
|
||||||
let offset = match rel.target.expand() {
|
|
||||||
ty::Kind::Func(fun) => self.tys.funcs[fun as usize].offset,
|
|
||||||
ty::Kind::Global(glo) => self.tys.globals[glo as usize].offset,
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
rel.reloc.apply_jump(to, offset, fuc.offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn disasm(
|
|
||||||
&mut self,
|
|
||||||
mut sluce: &[u8],
|
|
||||||
output: &mut impl std::io::Write,
|
|
||||||
) -> std::io::Result<()> {
|
|
||||||
use crate::DisasmItem;
|
|
||||||
let functions = self
|
|
||||||
.tys
|
|
||||||
.funcs
|
|
||||||
.iter()
|
|
||||||
.filter(|f| task::unpack(f.offset).is_ok())
|
|
||||||
.map(|f| {
|
|
||||||
let file = &self.files[f.file as usize];
|
|
||||||
let Expr::BinOp { left: &Expr::Ident { name, .. }, .. } = f.expr.get(file).unwrap()
|
|
||||||
else {
|
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
(f.offset, (name, f.code.len() as u32, DisasmItem::Func))
|
|
||||||
})
|
|
||||||
.chain(self.tys.globals.iter().filter(|g| task::unpack(g.offset).is_ok()).map(|g| {
|
|
||||||
let file = &self.files[g.file as usize];
|
|
||||||
|
|
||||||
(g.offset, (file.ident_str(g.name), self.tys.size_of(g.ty), DisasmItem::Global))
|
|
||||||
}))
|
|
||||||
.collect::<BTreeMap<_, _>>();
|
|
||||||
crate::disasm(&mut sluce, &functions, output, |_| {})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn make_func_reachable(&mut self, func: ty::Func) {
|
fn make_func_reachable(&mut self, func: ty::Func) {
|
||||||
let fuc = &mut self.tys.funcs[func as usize];
|
let fuc = &mut self.tys.funcs[func as usize];
|
||||||
if fuc.offset == u32::MAX {
|
if fuc.offset == u32::MAX {
|
||||||
|
@ -2556,7 +2459,10 @@ impl Codegen {
|
||||||
1..=8 => {
|
1..=8 => {
|
||||||
let reg = params.next();
|
let reg = params.next();
|
||||||
if i == index as usize - 1 {
|
if i == index as usize - 1 {
|
||||||
emit(&mut self.ci.code, instrs::cp(node_loc!(self, expr).reg, reg));
|
crate::emit(
|
||||||
|
&mut self.ci.code,
|
||||||
|
instrs::cp(node_loc!(self, expr).reg, reg),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s => todo!("{s}"),
|
s => todo!("{s}"),
|
||||||
|
@ -3142,10 +3048,10 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
codegen.assemble(&mut out);
|
codegen.tys.assemble(&mut out);
|
||||||
|
|
||||||
let mut buf = Vec::<u8>::new();
|
let mut buf = Vec::<u8>::new();
|
||||||
let err = codegen.disasm(&out, &mut buf);
|
let err = codegen.tys.disasm(&out, &codegen.files, &mut buf, |_| {});
|
||||||
output.push_str(String::from_utf8(buf).unwrap().as_str());
|
output.push_str(String::from_utf8(buf).unwrap().as_str());
|
||||||
if let Err(e) = err {
|
if let Err(e) = err {
|
||||||
writeln!(output, "!!! asm is invalid: {e}").unwrap();
|
writeln!(output, "!!! asm is invalid: {e}").unwrap();
|
||||||
|
|
Loading…
Reference in a new issue