making type manipulation nicer
This commit is contained in:
parent
0ef74d89cb
commit
68c0248189
|
@ -5,8 +5,9 @@
|
|||
use {
|
||||
alloc::{string::String, vec::Vec},
|
||||
hblang::{
|
||||
parser::FileId,
|
||||
son::{hbvm::HbvmBackend, Codegen, CodegenCtx},
|
||||
ty::Module,
|
||||
Ent,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -60,7 +61,7 @@ unsafe fn compile_and_run(mut fuel: usize) {
|
|||
let files = {
|
||||
let paths = files.iter().map(|f| f.path).collect::<Vec<_>>();
|
||||
let mut loader = |path: &str, _: &str, kind| match kind {
|
||||
hblang::parser::FileKind::Module => Ok(paths.binary_search(&path).unwrap() as FileId),
|
||||
hblang::parser::FileKind::Module => Ok(paths.binary_search(&path).unwrap()),
|
||||
hblang::parser::FileKind::Embed => Err("embeds are not supported".into()),
|
||||
};
|
||||
files
|
||||
|
@ -79,7 +80,7 @@ unsafe fn compile_and_run(mut fuel: usize) {
|
|||
|
||||
let mut ct = {
|
||||
let mut backend = HbvmBackend::default();
|
||||
Codegen::new(&mut backend, &files, &mut ctx).generate(root as FileId);
|
||||
Codegen::new(&mut backend, &files, &mut ctx).generate(Module::new(root));
|
||||
|
||||
if !ctx.parser.errors.borrow().is_empty() {
|
||||
log::error!("{}", ctx.parser.errors.borrow());
|
||||
|
|
|
@ -2,6 +2,7 @@ use {
|
|||
crate::{
|
||||
parser::{Ast, Ctx, FileKind},
|
||||
son::{self, hbvm::HbvmBackend},
|
||||
ty,
|
||||
},
|
||||
alloc::{string::String, vec::Vec},
|
||||
core::{fmt::Write, num::NonZeroUsize, ops::Deref},
|
||||
|
@ -96,7 +97,7 @@ pub fn run_compiler(root_file: &str, options: Options, out: &mut Vec<u8>) -> std
|
|||
let mut codegen = son::Codegen::new(&mut backend, &parsed.ast, &mut ctx);
|
||||
|
||||
codegen.push_embeds(parsed.embeds);
|
||||
codegen.generate(0);
|
||||
codegen.generate(ty::Module::MAIN);
|
||||
|
||||
if !codegen.errors.borrow().is_empty() {
|
||||
drop(codegen);
|
||||
|
@ -242,10 +243,10 @@ pub fn parse_from_fs(extra_threads: usize, root: &str) -> io::Result<Loaded> {
|
|||
}
|
||||
}
|
||||
|
||||
type Task = (u32, PathBuf);
|
||||
type Task = (usize, PathBuf);
|
||||
|
||||
let seen_modules = Mutex::new(crate::HashMap::<PathBuf, u32>::default());
|
||||
let seen_embeds = Mutex::new(crate::HashMap::<PathBuf, u32>::default());
|
||||
let seen_modules = Mutex::new(crate::HashMap::<PathBuf, usize>::default());
|
||||
let seen_embeds = Mutex::new(crate::HashMap::<PathBuf, usize>::default());
|
||||
let tasks = TaskQueue::<Task>::new(extra_threads + 1);
|
||||
let ast = Mutex::new(Vec::<io::Result<Ast>>::new());
|
||||
let embeds = Mutex::new(Vec::<Vec<u8>>::new());
|
||||
|
@ -264,7 +265,7 @@ pub fn parse_from_fs(extra_threads: usize, root: &str) -> io::Result<Loaded> {
|
|||
}
|
||||
hash_map::Entry::Vacant(entry) => {
|
||||
physiscal_path = entry.insert_entry(len as _).key().clone();
|
||||
len as u32
|
||||
len
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -289,7 +290,7 @@ pub fn parse_from_fs(extra_threads: usize, root: &str) -> io::Result<Loaded> {
|
|||
}
|
||||
hash_map::Entry::Vacant(entry) => {
|
||||
physiscal_path = entry.insert_entry(len as _).key().clone();
|
||||
len as u32
|
||||
len
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -331,9 +332,9 @@ pub fn parse_from_fs(extra_threads: usize, root: &str) -> io::Result<Loaded> {
|
|||
while let Some(task @ (indx, ..)) = tasks.pop() {
|
||||
let res = execute_task(&mut ctx, task, &mut tmp);
|
||||
let mut ast = ast.lock().unwrap();
|
||||
let len = ast.len().max(indx as usize + 1);
|
||||
let len = ast.len().max(indx + 1);
|
||||
ast.resize_with(len, || Err(io::ErrorKind::InvalidData.into()));
|
||||
ast[indx as usize] = res;
|
||||
ast[indx] = res;
|
||||
}
|
||||
ctx.errors.into_inner()
|
||||
};
|
||||
|
|
|
@ -3,6 +3,7 @@ use {
|
|||
lexer::TokenKind,
|
||||
parser,
|
||||
son::{hbvm::HbvmBackend, Codegen, CodegenCtx},
|
||||
ty::Module,
|
||||
},
|
||||
alloc::string::String,
|
||||
core::{fmt::Write, hash::BuildHasher, ops::Range},
|
||||
|
@ -135,6 +136,6 @@ pub fn fuzz(seed_range: Range<u64>) {
|
|||
|
||||
let mut backend = HbvmBackend::default();
|
||||
let mut cdg = Codegen::new(&mut backend, core::slice::from_ref(&parsed), &mut ctx);
|
||||
cdg.generate(0);
|
||||
cdg.generate(Module::MAIN);
|
||||
}
|
||||
}
|
||||
|
|
349
lang/src/lib.rs
349
lang/src/lib.rs
|
@ -32,11 +32,13 @@
|
|||
|
||||
#[cfg(feature = "std")]
|
||||
pub use fs::*;
|
||||
pub use utils::Ent;
|
||||
use {
|
||||
self::{
|
||||
lexer::TokenKind,
|
||||
parser::{idfl, CommentOr, Expr, ExprRef, FileId, Pos},
|
||||
ty::ArrayLen,
|
||||
parser::{idfl, CommentOr, Expr, ExprRef, Pos},
|
||||
ty::{ArrayLen, Builtin, Module},
|
||||
utils::EntVec,
|
||||
},
|
||||
alloc::{string::String, vec::Vec},
|
||||
core::{cell::Cell, fmt::Display, ops::Range},
|
||||
|
@ -251,17 +253,17 @@ impl Ident {
|
|||
pos..pos + len
|
||||
}
|
||||
|
||||
fn builtin(builtin: u32) -> Ident {
|
||||
debug_assert!(Self(builtin).is_null());
|
||||
Self(builtin)
|
||||
fn builtin(builtin: Builtin) -> Ident {
|
||||
Self(builtin.index() as _)
|
||||
}
|
||||
}
|
||||
|
||||
mod ty {
|
||||
pub mod ty {
|
||||
use {
|
||||
crate::{
|
||||
lexer::TokenKind,
|
||||
parser::{self, FileId, Pos},
|
||||
parser::{self, Pos},
|
||||
utils::Ent,
|
||||
Ident, Size, Types,
|
||||
},
|
||||
core::{num::NonZeroU32, ops::Range},
|
||||
|
@ -269,16 +271,10 @@ mod ty {
|
|||
|
||||
pub type ArrayLen = u32;
|
||||
|
||||
pub type Builtin = u32;
|
||||
pub type Struct = u32;
|
||||
pub type Opt = u32;
|
||||
pub type Ptr = u32;
|
||||
pub type Func = u32;
|
||||
pub type Global = u32;
|
||||
pub type Module = u32;
|
||||
pub type Slice = u32;
|
||||
|
||||
pub const ECA: Func = Func::MAX;
|
||||
impl Func {
|
||||
pub const ECA: Func = Func(u32::MAX);
|
||||
pub const MAIN: Func = Func(u32::MIN);
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default, PartialOrd, Ord)]
|
||||
pub struct Tuple(pub u32);
|
||||
|
@ -305,6 +301,10 @@ mod ty {
|
|||
self.0 as usize & Self::LEN_MASK
|
||||
}
|
||||
|
||||
pub fn is_empty(self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
pub fn empty() -> Self {
|
||||
Self(0)
|
||||
}
|
||||
|
@ -350,28 +350,30 @@ mod ty {
|
|||
fn key<'a>(&self, ctx: &'a Self::Ctx) -> Self::Key<'a> {
|
||||
match self.expand() {
|
||||
Kind::Struct(s) => {
|
||||
let st = &ctx.structs[s as usize];
|
||||
let st = &ctx.structs[s];
|
||||
debug_assert_ne!(st.pos, Pos::MAX);
|
||||
crate::SymKey::Struct(st.file, st.pos, st.captures)
|
||||
}
|
||||
Kind::Ptr(p) => crate::SymKey::Pointer(&ctx.ptrs[p as usize]),
|
||||
Kind::Opt(p) => crate::SymKey::Optional(&ctx.opts[p as usize]),
|
||||
Kind::Ptr(p) => crate::SymKey::Pointer(&ctx.ptrs[p]),
|
||||
Kind::Opt(p) => crate::SymKey::Optional(&ctx.opts[p]),
|
||||
Kind::Func(f) => {
|
||||
let fc = &ctx.funcs[f as usize];
|
||||
let fc = &ctx.funcs[f];
|
||||
if let Some(base) = fc.base {
|
||||
// TODO: merge base and sig
|
||||
crate::SymKey::FuncInst(base, fc.sig.unwrap().args)
|
||||
} else {
|
||||
crate::SymKey::Decl(fc.file, fc.name)
|
||||
}
|
||||
}
|
||||
Kind::Global(g) => {
|
||||
let gb = &ctx.globals[g as usize];
|
||||
let gb = &ctx.globals[g];
|
||||
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]),
|
||||
Kind::Module(_) | Kind::Builtin(_) => {
|
||||
crate::SymKey::Decl(FileId::MAX, Ident::INVALID)
|
||||
crate::SymKey::Decl(Module::default(), Ident::INVALID)
|
||||
}
|
||||
Kind::Const(c) => crate::SymKey::Constant(&ctx.consts[c]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -388,7 +390,7 @@ mod ty {
|
|||
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(),
|
||||
T::Lt | T::Gt | T::Le | T::Ge | T::Ne | T::Eq => Id::BOOL,
|
||||
_ => self,
|
||||
}
|
||||
}
|
||||
|
@ -415,7 +417,7 @@ mod ty {
|
|||
|
||||
pub fn strip_pointer(self) -> Self {
|
||||
match self.expand() {
|
||||
Kind::Ptr(_) => Kind::Builtin(UINT).compress(),
|
||||
Kind::Ptr(_) => Id::UINT,
|
||||
_ => self,
|
||||
}
|
||||
}
|
||||
|
@ -432,8 +434,8 @@ mod ty {
|
|||
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 () {
|
||||
_ if oa == Self::from(NEVER) => ob,
|
||||
_ if ob == Self::from(NEVER) => oa,
|
||||
_ if oa == Id::NEVER => ob,
|
||||
_ if ob == Id::NEVER => oa,
|
||||
_ if oa == ob => oa,
|
||||
_ if ob.is_optional() => ob,
|
||||
_ if oa.is_pointer() && ob.is_pointer() => return None,
|
||||
|
@ -456,12 +458,12 @@ mod ty {
|
|||
pub(crate) fn simple_size(&self) -> Option<Size> {
|
||||
Some(match self.expand() {
|
||||
Kind::Ptr(_) => 8,
|
||||
Kind::Builtin(VOID) => 0,
|
||||
Kind::Builtin(NEVER) => 0,
|
||||
Kind::Builtin(INT | UINT | F64) => 8,
|
||||
Kind::Builtin(I32 | U32 | TYPE | F32) => 4,
|
||||
Kind::Builtin(I16 | U16) => 2,
|
||||
Kind::Builtin(I8 | U8 | BOOL) => 1,
|
||||
Kind::Builtin(Builtin(VOID)) => 0,
|
||||
Kind::Builtin(Builtin(NEVER)) => 0,
|
||||
Kind::Builtin(Builtin(INT | UINT | F64)) => 8,
|
||||
Kind::Builtin(Builtin(I32 | U32 | TYPE | F32)) => 4,
|
||||
Kind::Builtin(Builtin(I16 | U16)) => 2,
|
||||
Kind::Builtin(Builtin(I8 | U8 | BOOL)) => 1,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
@ -479,7 +481,7 @@ mod ty {
|
|||
pub(crate) fn loc(&self, tys: &Types) -> Loc {
|
||||
match self.expand() {
|
||||
Kind::Opt(o)
|
||||
if let ty = tys.ins.opts[o as usize].base
|
||||
if let ty = tys.ins.opts[o].base
|
||||
&& ty.loc(tys) == Loc::Reg
|
||||
&& (ty.is_pointer() || tys.size_of(ty) < 8) =>
|
||||
{
|
||||
|
@ -488,7 +490,9 @@ mod ty {
|
|||
Kind::Ptr(_) | Kind::Builtin(_) => Loc::Reg,
|
||||
Kind::Struct(_) if tys.size_of(*self) == 0 => Loc::Reg,
|
||||
Kind::Struct(_) | Kind::Slice(_) | Kind::Opt(_) => Loc::Stack,
|
||||
Kind::Func(_) | Kind::Global(_) | Kind::Module(_) => unreachable!(),
|
||||
Kind::Func(_) | Kind::Global(_) | Kind::Module(_) | Kind::Const(_) => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -496,7 +500,7 @@ mod ty {
|
|||
match self.expand() {
|
||||
Kind::Struct(s) => tys.struct_fields(s).iter().any(|f| f.ty.has_pointers(tys)),
|
||||
Kind::Ptr(_) => true,
|
||||
Kind::Slice(s) => tys.ins.slices[s as usize].len == ArrayLen::MAX,
|
||||
Kind::Slice(s) => tys.ins.slices[s].len == ArrayLen::MAX,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -514,12 +518,6 @@ mod ty {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<u32> for Id {
|
||||
fn from(id: u32) -> Self {
|
||||
Kind::Builtin(id).compress()
|
||||
}
|
||||
}
|
||||
|
||||
const fn array_to_lower_case<const N: usize>(array: [u8; N]) -> [u8; N] {
|
||||
let mut result = [0; N];
|
||||
let mut i = 0;
|
||||
|
@ -533,7 +531,7 @@ mod ty {
|
|||
|
||||
macro_rules! builtin_type {
|
||||
($($name:ident;)*) => {
|
||||
$(pub const $name: Builtin = ${index(0)} + 1;)*
|
||||
$(const $name: u32 = ${index(0)} + 1;)*
|
||||
|
||||
mod __lc_names {
|
||||
use super::*;
|
||||
|
@ -547,20 +545,23 @@ mod ty {
|
|||
};)*
|
||||
}
|
||||
|
||||
#[expect(dead_code)]
|
||||
impl Id {
|
||||
$(pub const $name: Self = Kind::Builtin($name).compress();)*
|
||||
$(pub const $name: Self = Kind::Builtin(Builtin($name)).compress();)*
|
||||
}
|
||||
|
||||
impl Kind {
|
||||
$(pub const $name: Self = Kind::Builtin(Builtin($name));)*
|
||||
}
|
||||
|
||||
pub fn from_str(name: &str) -> Option<Builtin> {
|
||||
match name {
|
||||
$(__lc_names::$name => Some($name),)*
|
||||
$(__lc_names::$name => Some(Builtin($name)),)*
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_str(ty: Builtin) -> &'static str {
|
||||
match ty {
|
||||
match ty.0 {
|
||||
$($name => __lc_names::$name,)*
|
||||
v => unreachable!("invalid type: {}", v),
|
||||
}
|
||||
|
@ -590,6 +591,10 @@ mod ty {
|
|||
|
||||
macro_rules! type_kind {
|
||||
($(#[$meta:meta])* $vis:vis enum $name:ident {$( $variant:ident, )*}) => {
|
||||
crate::utils::decl_ent! {
|
||||
$(pub struct $variant(u32);)*
|
||||
}
|
||||
|
||||
$(#[$meta])*
|
||||
$vis enum $name {
|
||||
$($variant($variant),)*
|
||||
|
@ -603,24 +608,32 @@ mod ty {
|
|||
$vis fn from_ty(ty: Id) -> Self {
|
||||
let (flag, index) = (ty.repr() >> Self::FLAG_OFFSET, ty.repr() & Self::INDEX_MASK);
|
||||
match flag {
|
||||
$(${index(0)} => Self::$variant(index),)*
|
||||
$(${index(0)} => Self::$variant($variant(index)),)*
|
||||
i => unreachable!("{i}"),
|
||||
}
|
||||
}
|
||||
|
||||
$vis const fn compress(self) -> Id {
|
||||
let (index, flag) = match self {
|
||||
$(Self::$variant(index) => (index, ${index(0)}),)*
|
||||
$(Self::$variant(index) => (index.0, ${index(0)}),)*
|
||||
};
|
||||
Id(unsafe { NonZeroU32::new_unchecked((flag << Self::FLAG_OFFSET) | index) })
|
||||
}
|
||||
}
|
||||
|
||||
$vis const fn inner(self) -> u32 {
|
||||
match self {
|
||||
$(Self::$variant(index) => index,)*
|
||||
$(
|
||||
impl From<$variant> for $name {
|
||||
fn from(value: $variant) -> Self {
|
||||
Self::$variant(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$variant> for Id {
|
||||
fn from(value: $variant) -> Self {
|
||||
$name::$variant(value).compress()
|
||||
}
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -635,12 +648,35 @@ mod ty {
|
|||
Func,
|
||||
Global,
|
||||
Module,
|
||||
Const,
|
||||
}
|
||||
}
|
||||
|
||||
impl Module {
|
||||
pub const MAIN: Self = Self(0);
|
||||
}
|
||||
|
||||
impl Default for Module {
|
||||
fn default() -> Self {
|
||||
Self(u32::MAX)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Ident> for Builtin {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(value: Ident) -> Result<Self, Self::Error> {
|
||||
if value.is_null() {
|
||||
Ok(Self(value.len()))
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Kind {
|
||||
fn default() -> Self {
|
||||
Self::Builtin(UNDECLARED)
|
||||
Id::UNDECLARED.expand()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -666,7 +702,7 @@ mod ty {
|
|||
match TK::from_ty(self.ty) {
|
||||
TK::Module(idx) => {
|
||||
f.write_str("@use(\"")?;
|
||||
self.files[idx as usize].path.fmt(f)?;
|
||||
self.files[idx.index()].path.fmt(f)?;
|
||||
f.write_str(")[")?;
|
||||
idx.fmt(f)?;
|
||||
f.write_str("]")
|
||||
|
@ -674,14 +710,14 @@ mod ty {
|
|||
TK::Builtin(ty) => f.write_str(to_str(ty)),
|
||||
TK::Opt(ty) => {
|
||||
f.write_str("?")?;
|
||||
self.rety(self.tys.ins.opts[ty as usize].base).fmt(f)
|
||||
self.rety(self.tys.ins.opts[ty].base).fmt(f)
|
||||
}
|
||||
TK::Ptr(ty) => {
|
||||
f.write_str("^")?;
|
||||
self.rety(self.tys.ins.ptrs[ty as usize].base).fmt(f)
|
||||
self.rety(self.tys.ins.ptrs[ty].base).fmt(f)
|
||||
}
|
||||
TK::Struct(idx) => {
|
||||
let record = &self.tys.ins.structs[idx as usize];
|
||||
let record = &self.tys.ins.structs[idx];
|
||||
if record.name.is_null() {
|
||||
f.write_str("[")?;
|
||||
idx.fmt(f)?;
|
||||
|
@ -698,7 +734,7 @@ mod ty {
|
|||
}
|
||||
f.write_str("}")
|
||||
} else {
|
||||
let file = &self.files[record.file as usize];
|
||||
let file = &self.files[record.file.index()];
|
||||
f.write_str(file.ident_str(record.name))
|
||||
}
|
||||
}
|
||||
|
@ -707,11 +743,12 @@ mod ty {
|
|||
idx.fmt(f)
|
||||
}
|
||||
TK::Global(idx) => {
|
||||
f.write_str("global")?;
|
||||
idx.fmt(f)
|
||||
let global = &self.tys.ins.globals[idx];
|
||||
let file = &self.files[global.file.index()];
|
||||
f.write_str(file.ident_str(global.name))
|
||||
}
|
||||
TK::Slice(idx) => {
|
||||
let array = self.tys.ins.slices[idx as usize];
|
||||
let array = self.tys.ins.slices[idx];
|
||||
f.write_str("[")?;
|
||||
self.rety(array.elem).fmt(f)?;
|
||||
if array.len != ArrayLen::MAX {
|
||||
|
@ -720,6 +757,11 @@ mod ty {
|
|||
}
|
||||
f.write_str("]")
|
||||
}
|
||||
TK::Const(idx) => {
|
||||
let cnst = &self.tys.ins.consts[idx];
|
||||
let file = &self.files[cnst.file.index()];
|
||||
f.write_str(file.ident_str(cnst.name))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -732,10 +774,11 @@ type Size = u32;
|
|||
pub enum SymKey<'a> {
|
||||
Pointer(&'a Ptr),
|
||||
Optional(&'a Opt),
|
||||
Struct(FileId, Pos, ty::Tuple),
|
||||
Struct(Module, Pos, ty::Tuple),
|
||||
FuncInst(ty::Func, ty::Tuple),
|
||||
Decl(FileId, Ident),
|
||||
Decl(Module, Ident),
|
||||
Array(&'a Array),
|
||||
Constant(&'a Const),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
|
@ -744,8 +787,9 @@ pub struct Sig {
|
|||
ret: ty::Id,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct Func {
|
||||
file: FileId,
|
||||
file: Module,
|
||||
name: Ident,
|
||||
base: Option<ty::Func>,
|
||||
expr: ExprRef,
|
||||
|
@ -753,19 +797,6 @@ struct Func {
|
|||
comp_state: [CompState; 2],
|
||||
}
|
||||
|
||||
impl Default for Func {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
file: u32::MAX,
|
||||
name: Default::default(),
|
||||
base: None,
|
||||
expr: Default::default(),
|
||||
sig: None,
|
||||
comp_state: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, PartialEq, Eq)]
|
||||
enum CompState {
|
||||
#[default]
|
||||
|
@ -780,23 +811,19 @@ struct TypedReloc {
|
|||
reloc: Reloc,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Default)]
|
||||
struct Global {
|
||||
file: FileId,
|
||||
file: Module,
|
||||
name: Ident,
|
||||
ty: ty::Id,
|
||||
data: Vec<u8>,
|
||||
}
|
||||
|
||||
impl Default for Global {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
ty: Default::default(),
|
||||
data: Default::default(),
|
||||
file: u32::MAX,
|
||||
name: Default::default(),
|
||||
}
|
||||
}
|
||||
#[derive(PartialEq, Eq, Hash)]
|
||||
pub struct Const {
|
||||
ast: ExprRef,
|
||||
name: Ident,
|
||||
file: Module,
|
||||
}
|
||||
|
||||
// TODO: make into bit struct (width: u2, sub_offset: u3, offset: u27)
|
||||
|
@ -835,7 +862,7 @@ struct Field {
|
|||
struct Struct {
|
||||
name: Ident,
|
||||
pos: Pos,
|
||||
file: FileId,
|
||||
file: Module,
|
||||
size: Cell<Size>,
|
||||
align: Cell<u8>,
|
||||
captures: ty::Tuple,
|
||||
|
@ -934,18 +961,19 @@ struct TypesTmp {
|
|||
|
||||
#[derive(Default)]
|
||||
pub struct TypeIns {
|
||||
funcs: Vec<Func>,
|
||||
args: Vec<ty::Id>,
|
||||
globals: Vec<Global>,
|
||||
structs: Vec<Struct>,
|
||||
fields: Vec<Field>,
|
||||
ptrs: Vec<Ptr>,
|
||||
opts: Vec<Opt>,
|
||||
slices: Vec<Array>,
|
||||
funcs: EntVec<ty::Func, Func>,
|
||||
globals: EntVec<ty::Global, Global>,
|
||||
consts: EntVec<ty::Const, Const>,
|
||||
structs: EntVec<ty::Struct, Struct>,
|
||||
ptrs: EntVec<ty::Ptr, Ptr>,
|
||||
opts: EntVec<ty::Opt, Opt>,
|
||||
slices: EntVec<ty::Slice, Array>,
|
||||
}
|
||||
|
||||
struct FTask {
|
||||
file: FileId,
|
||||
file: Module,
|
||||
id: ty::Func,
|
||||
ct: bool,
|
||||
}
|
||||
|
@ -953,11 +981,11 @@ struct FTask {
|
|||
struct StringRef(ty::Global);
|
||||
|
||||
impl ctx_map::CtxEntry for StringRef {
|
||||
type Ctx = [Global];
|
||||
type Ctx = EntVec<ty::Global, Global>;
|
||||
type Key<'a> = &'a [u8];
|
||||
|
||||
fn key<'a>(&self, ctx: &'a Self::Ctx) -> Self::Key<'a> {
|
||||
&ctx[self.0 as usize].data
|
||||
&ctx[self.0].data
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -975,16 +1003,16 @@ trait TypeParser {
|
|||
fn tys(&mut self) -> &mut Types;
|
||||
fn on_reuse(&mut self, existing: ty::Id);
|
||||
fn find_local_ty(&mut self, name: Ident) -> Option<ty::Id>;
|
||||
fn eval_const(&mut self, file: FileId, expr: &Expr, ty: ty::Id) -> u64;
|
||||
fn eval_global(&mut self, file: FileId, name: Ident, expr: &Expr) -> ty::Id;
|
||||
fn eval_const(&mut self, file: Module, expr: &Expr, ty: ty::Id) -> u64;
|
||||
fn eval_global(&mut self, file: Module, name: Ident, expr: &Expr) -> ty::Id;
|
||||
fn infer_type(&mut self, expr: &Expr) -> ty::Id;
|
||||
fn report(&self, file: FileId, pos: Pos, msg: impl Display) -> ty::Id;
|
||||
fn report(&self, file: Module, pos: Pos, msg: impl Display) -> ty::Id;
|
||||
|
||||
fn find_type(
|
||||
&mut self,
|
||||
pos: Pos,
|
||||
from_file: FileId,
|
||||
file: FileId,
|
||||
from_file: Module,
|
||||
file: Module,
|
||||
id: Result<Ident, &str>,
|
||||
files: &[parser::Ast],
|
||||
) -> ty::Id {
|
||||
|
@ -999,9 +1027,9 @@ trait TypeParser {
|
|||
self.on_reuse(ty);
|
||||
ty
|
||||
} else {
|
||||
let f = &files[file as usize];
|
||||
let f = &files[file.index()];
|
||||
|
||||
let Some((Expr::BinOp { left, right, .. }, name)) = f.find_decl(id) else {
|
||||
let Some((expr @ Expr::BinOp { left, right, .. }, name)) = f.find_decl(id) else {
|
||||
return match id {
|
||||
Ok(_) => ty::Id::NEVER,
|
||||
Err("main") => self.report(
|
||||
|
@ -1025,20 +1053,19 @@ trait TypeParser {
|
|||
ty
|
||||
} else {
|
||||
let ty = left
|
||||
.find_pattern_path(name, right, |right| {
|
||||
.find_pattern_path(name, right, |right, is_ct| {
|
||||
if is_ct {
|
||||
self.tys()
|
||||
.ins
|
||||
.consts
|
||||
.push(Const { ast: ExprRef::new(expr), name, file })
|
||||
.into()
|
||||
} else {
|
||||
self.parse_ty(file, right, Some(name), files)
|
||||
}
|
||||
})
|
||||
.unwrap_or_else(|_| unreachable!());
|
||||
let tys = self.tys();
|
||||
let nm = match ty.expand() {
|
||||
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 Ident::default(),
|
||||
};
|
||||
if nm.is_null() {
|
||||
*nm = name;
|
||||
}
|
||||
tys.syms.insert(SymKey::Decl(file, name), ty, &tys.ins);
|
||||
ty
|
||||
}
|
||||
|
@ -1046,7 +1073,7 @@ trait TypeParser {
|
|||
|
||||
let tys = self.tys();
|
||||
if let ty::Kind::Global(g) = ty.expand() {
|
||||
let g = &tys.ins.globals[g as usize];
|
||||
let g = &tys.ins.globals[g];
|
||||
if g.ty == ty::Id::TYPE {
|
||||
return ty::Id::from(
|
||||
u32::from_ne_bytes(g.data.as_slice().try_into().unwrap()) as u64
|
||||
|
@ -1059,7 +1086,7 @@ trait TypeParser {
|
|||
/// returns none if comptime eval is required
|
||||
fn parse_ty(
|
||||
&mut self,
|
||||
file: FileId,
|
||||
file: Module,
|
||||
expr: &Expr,
|
||||
name: Option<Ident>,
|
||||
files: &[parser::Ast],
|
||||
|
@ -1074,7 +1101,7 @@ trait TypeParser {
|
|||
let base = self.parse_ty(file, val, None, files);
|
||||
self.tys().make_opt(base)
|
||||
}
|
||||
Expr::Ident { id, .. } if id.is_null() => id.len().into(),
|
||||
Expr::Ident { id, .. } if let Ok(bt) = ty::Builtin::try_from(id) => bt.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) =
|
||||
|
@ -1119,18 +1146,21 @@ trait TypeParser {
|
|||
}
|
||||
|
||||
let tys = self.tys();
|
||||
tys.ins.structs.push(Struct {
|
||||
let ty = tys
|
||||
.ins
|
||||
.structs
|
||||
.push(Struct {
|
||||
file,
|
||||
pos,
|
||||
name: name.unwrap_or_default(),
|
||||
field_start: tys.ins.fields.len() as _,
|
||||
explicit_alignment: packed.then_some(1),
|
||||
..Default::default()
|
||||
});
|
||||
})
|
||||
.into();
|
||||
|
||||
tys.ins.fields.extend(tys.tmp.fields.drain(prev_tmp..));
|
||||
|
||||
let ty = ty::Kind::Struct(tys.ins.structs.len() as u32 - 1).compress();
|
||||
tys.syms.insert(sym, ty, &tys.ins);
|
||||
ty
|
||||
}
|
||||
|
@ -1141,7 +1171,7 @@ trait TypeParser {
|
|||
sig: 'b: {
|
||||
let arg_base = self.tys().tmp.args.len();
|
||||
for arg in args {
|
||||
let sym = parser::find_symbol(&files[file as usize].symbols, arg.id);
|
||||
let sym = parser::find_symbol(&files[file.index()].symbols, arg.id);
|
||||
if sym.flags & idfl::COMPTIME != 0 {
|
||||
self.tys().tmp.args.truncate(arg_base);
|
||||
break 'b None;
|
||||
|
@ -1161,10 +1191,7 @@ trait TypeParser {
|
|||
..Default::default()
|
||||
};
|
||||
|
||||
let id = self.tys().ins.funcs.len() as _;
|
||||
self.tys().ins.funcs.push(func);
|
||||
|
||||
ty::Kind::Func(id).compress()
|
||||
self.tys().ins.funcs.push(func).into()
|
||||
}
|
||||
_ if let Some(name) = name => self.eval_global(file, name, expr),
|
||||
_ => ty::Id::from(self.eval_const(file, expr, ty::Id::TYPE)),
|
||||
|
@ -1174,12 +1201,9 @@ trait TypeParser {
|
|||
|
||||
impl Types {
|
||||
fn struct_field_range(&self, strct: ty::Struct) -> Range<usize> {
|
||||
let start = self.ins.structs[strct as usize].field_start as usize;
|
||||
let end = self
|
||||
.ins
|
||||
.structs
|
||||
.get(strct as usize + 1)
|
||||
.map_or(self.ins.fields.len(), |s| s.field_start as usize);
|
||||
let start = self.ins.structs[strct].field_start as usize;
|
||||
let end =
|
||||
self.ins.structs.next(strct).map_or(self.ins.fields.len(), |s| s.field_start as usize);
|
||||
start..end
|
||||
}
|
||||
|
||||
|
@ -1210,49 +1234,30 @@ impl Types {
|
|||
}
|
||||
|
||||
fn make_opt(&mut self, base: ty::Id) -> ty::Id {
|
||||
self.make_generic_ty(
|
||||
Opt { base },
|
||||
|ins| &mut ins.opts,
|
||||
|e| SymKey::Optional(e),
|
||||
ty::Kind::Opt,
|
||||
)
|
||||
self.make_generic_ty(Opt { base }, |ins| &mut ins.opts, |e| SymKey::Optional(e))
|
||||
}
|
||||
|
||||
fn make_ptr(&mut self, base: ty::Id) -> ty::Id {
|
||||
self.make_generic_ty(
|
||||
Ptr { base },
|
||||
|ins| &mut ins.ptrs,
|
||||
|e| SymKey::Pointer(e),
|
||||
ty::Kind::Ptr,
|
||||
)
|
||||
self.make_generic_ty(Ptr { base }, |ins| &mut ins.ptrs, |e| SymKey::Pointer(e))
|
||||
}
|
||||
|
||||
fn make_array(&mut self, elem: ty::Id, len: ArrayLen) -> ty::Id {
|
||||
self.make_generic_ty(
|
||||
Array { elem, len },
|
||||
|ins| &mut ins.slices,
|
||||
|e| SymKey::Array(e),
|
||||
ty::Kind::Slice,
|
||||
)
|
||||
self.make_generic_ty(Array { elem, len }, |ins| &mut ins.slices, |e| SymKey::Array(e))
|
||||
}
|
||||
|
||||
fn make_generic_ty<T: Copy>(
|
||||
fn make_generic_ty<K: Ent + Into<ty::Id>, T: Copy>(
|
||||
&mut self,
|
||||
ty: T,
|
||||
get_col: fn(&mut TypeIns) -> &mut Vec<T>,
|
||||
get_col: fn(&mut TypeIns) -> &mut EntVec<K, T>,
|
||||
key: fn(&T) -> SymKey,
|
||||
kind: fn(u32) -> ty::Kind,
|
||||
) -> ty::Id {
|
||||
*self.syms.get_or_insert(key(&{ ty }), &mut self.ins, |ins| {
|
||||
get_col(ins).push(ty);
|
||||
kind(get_col(ins).len() as u32 - 1).compress()
|
||||
})
|
||||
*self.syms.get_or_insert(key(&{ ty }), &mut self.ins, |ins| get_col(ins).push(ty).into())
|
||||
}
|
||||
|
||||
fn size_of(&self, ty: ty::Id) -> Size {
|
||||
match ty.expand() {
|
||||
ty::Kind::Slice(arr) => {
|
||||
let arr = &self.ins.slices[arr as usize];
|
||||
let arr = &self.ins.slices[arr];
|
||||
match arr.len {
|
||||
0 => 0,
|
||||
ArrayLen::MAX => 16,
|
||||
|
@ -1260,17 +1265,17 @@ impl Types {
|
|||
}
|
||||
}
|
||||
ty::Kind::Struct(stru) => {
|
||||
if self.ins.structs[stru as usize].size.get() != 0 {
|
||||
return self.ins.structs[stru as usize].size.get();
|
||||
if self.ins.structs[stru].size.get() != 0 {
|
||||
return self.ins.structs[stru].size.get();
|
||||
}
|
||||
|
||||
let mut oiter = OffsetIter::new(stru, self);
|
||||
while oiter.next(self).is_some() {}
|
||||
self.ins.structs[stru as usize].size.set(oiter.offset);
|
||||
self.ins.structs[stru].size.set(oiter.offset);
|
||||
oiter.offset
|
||||
}
|
||||
ty::Kind::Opt(opt) => {
|
||||
let base = self.ins.opts[opt as usize].base;
|
||||
let base = self.ins.opts[opt].base;
|
||||
if self.nieche_of(base).is_some() {
|
||||
self.size_of(base)
|
||||
} else {
|
||||
|
@ -1285,10 +1290,10 @@ impl Types {
|
|||
fn align_of(&self, ty: ty::Id) -> Size {
|
||||
match ty.expand() {
|
||||
ty::Kind::Struct(stru) => {
|
||||
if self.ins.structs[stru as usize].align.get() != 0 {
|
||||
return self.ins.structs[stru as usize].align.get() as _;
|
||||
if self.ins.structs[stru].align.get() != 0 {
|
||||
return self.ins.structs[stru].align.get() as _;
|
||||
}
|
||||
let align = self.ins.structs[stru as usize].explicit_alignment.map_or_else(
|
||||
let align = self.ins.structs[stru].explicit_alignment.map_or_else(
|
||||
|| {
|
||||
self.struct_fields(stru)
|
||||
.iter()
|
||||
|
@ -1298,11 +1303,11 @@ impl Types {
|
|||
},
|
||||
|a| a as _,
|
||||
);
|
||||
self.ins.structs[stru as usize].align.set(align.try_into().unwrap());
|
||||
self.ins.structs[stru].align.set(align.try_into().unwrap());
|
||||
align
|
||||
}
|
||||
ty::Kind::Slice(arr) => {
|
||||
let arr = &self.ins.slices[arr as usize];
|
||||
let arr = &self.ins.slices[arr];
|
||||
match arr.len {
|
||||
ArrayLen::MAX => 8,
|
||||
_ => self.align_of(arr.elem),
|
||||
|
@ -1314,14 +1319,14 @@ impl Types {
|
|||
|
||||
fn base_of(&self, ty: ty::Id) -> Option<ty::Id> {
|
||||
match ty.expand() {
|
||||
ty::Kind::Ptr(p) => Some(self.ins.ptrs[p as usize].base),
|
||||
ty::Kind::Ptr(p) => Some(self.ins.ptrs[p].base),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn inner_of(&self, ty: ty::Id) -> Option<ty::Id> {
|
||||
match ty.expand() {
|
||||
ty::Kind::Opt(o) => Some(self.ins.opts[o as usize].base),
|
||||
ty::Kind::Opt(o) => Some(self.ins.opts[o].base),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -1401,7 +1406,7 @@ impl OffsetIter {
|
|||
}
|
||||
|
||||
fn next<'a>(&mut self, tys: &'a Types) -> Option<(&'a Field, Offset)> {
|
||||
let stru = &tys.ins.structs[self.strct as usize];
|
||||
let stru = &tys.ins.structs[self.strct];
|
||||
let field = &tys.ins.fields[self.fields.next()?];
|
||||
|
||||
let align = stru.explicit_alignment.map_or_else(|| tys.align_of(field.ty), |a| a as u32);
|
||||
|
@ -1579,12 +1584,10 @@ fn test_parse_files(
|
|||
FileKind::Module => module_map
|
||||
.iter()
|
||||
.position(|&(name, _)| name == path)
|
||||
.map(|i| i as parser::FileId)
|
||||
.ok_or("Module Not Found".to_string()),
|
||||
FileKind::Embed => embed_map
|
||||
.iter()
|
||||
.position(|&(name, _)| name == path)
|
||||
.map(|i| i as parser::FileId)
|
||||
.ok_or("Embed Not Found".to_string()),
|
||||
};
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@ use {
|
|||
crate::{
|
||||
fmt::Formatter,
|
||||
lexer::{self, Lexer, Token, TokenKind},
|
||||
ty::{Global, Module},
|
||||
utils::Ent as _,
|
||||
Ident,
|
||||
},
|
||||
alloc::{boxed::Box, string::String, vec::Vec},
|
||||
|
@ -19,10 +21,9 @@ use {
|
|||
|
||||
pub type Pos = u32;
|
||||
pub type IdentFlags = u32;
|
||||
pub type FileId = u32;
|
||||
pub type IdentIndex = u16;
|
||||
pub type LoaderError = String;
|
||||
pub type Loader<'a> = &'a mut (dyn FnMut(&str, &str, FileKind) -> Result<FileId, LoaderError> + 'a);
|
||||
pub type Loader<'a> = &'a mut (dyn FnMut(&str, &str, FileKind) -> Result<usize, LoaderError> + 'a);
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
pub enum FileKind {
|
||||
|
@ -63,7 +64,7 @@ pub mod idfl {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn no_loader(_: &str, _: &str, _: FileKind) -> Result<FileId, LoaderError> {
|
||||
pub fn no_loader(_: &str, _: &str, _: FileKind) -> Result<usize, LoaderError> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
|
@ -307,7 +308,7 @@ impl<'a, 'b> Parser<'a, 'b> {
|
|||
pos,
|
||||
path,
|
||||
id: match (self.loader)(path, self.path, FileKind::Module) {
|
||||
Ok(id) => id,
|
||||
Ok(id) => Module::new(id),
|
||||
Err(e) => {
|
||||
self.report(str.start, format_args!("error loading dependency: {e:#}"))?
|
||||
}
|
||||
|
@ -325,7 +326,7 @@ impl<'a, 'b> Parser<'a, 'b> {
|
|||
pos,
|
||||
path,
|
||||
id: match (self.loader)(path, self.path, FileKind::Embed) {
|
||||
Ok(id) => id,
|
||||
Ok(id) => Global::new(id),
|
||||
Err(e) => self.report(
|
||||
str.start,
|
||||
format_args!("error loading embedded file: {e:#}"),
|
||||
|
@ -929,13 +930,13 @@ generate_expr! {
|
|||
/// `'@use' '(' String ')'`
|
||||
Mod {
|
||||
pos: Pos,
|
||||
id: FileId,
|
||||
id: Module,
|
||||
path: &'a str,
|
||||
},
|
||||
/// `'@use' '(' String ')'`
|
||||
Embed {
|
||||
pos: Pos,
|
||||
id: FileId,
|
||||
id: Global,
|
||||
path: &'a str,
|
||||
},
|
||||
}
|
||||
|
@ -960,14 +961,14 @@ impl Expr<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn find_pattern_path<T, F: FnOnce(&Expr) -> T>(
|
||||
pub fn find_pattern_path<T, F: FnOnce(&Expr, bool) -> T>(
|
||||
&self,
|
||||
ident: Ident,
|
||||
target: &Expr,
|
||||
mut with_final: F,
|
||||
) -> Result<T, F> {
|
||||
match *self {
|
||||
Self::Ident { id, .. } if id == ident => Ok(with_final(target)),
|
||||
Self::Ident { id, is_ct, .. } if id == ident => Ok(with_final(target, is_ct)),
|
||||
Self::Ctor { fields, .. } => {
|
||||
for &CtorField { name, value, pos } in fields {
|
||||
match value.find_pattern_path(
|
||||
|
@ -1234,7 +1235,7 @@ impl Default for Ast {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||
#[repr(packed)]
|
||||
pub struct ExprRef(NonNull<Expr<'static>>);
|
||||
|
||||
|
|
123
lang/src/son.rs
123
lang/src/son.rs
|
@ -10,20 +10,20 @@ use {
|
|||
parser::{
|
||||
self,
|
||||
idfl::{self},
|
||||
CtorField, Expr, FileId, Pos,
|
||||
CtorField, Expr, Pos,
|
||||
},
|
||||
ty::{self, Arg, ArrayLen, Loc, Tuple},
|
||||
utils::{BitSet, Vc},
|
||||
ty::{self, Arg, ArrayLen, Loc, Module, Tuple},
|
||||
utils::{BitSet, Ent, Vc},
|
||||
CompState, FTask, Func, Global, Ident, Offset, OffsetIter, OptLayout, Sig, StringRef,
|
||||
SymKey, TypeParser, Types,
|
||||
},
|
||||
alloc::{rc::Rc, string::String, vec::Vec},
|
||||
alloc::{string::String, vec::Vec},
|
||||
core::{
|
||||
assert_matches::debug_assert_matches,
|
||||
cell::{Cell, RefCell},
|
||||
fmt::{self, Debug, Display, Write},
|
||||
format_args as fa, mem,
|
||||
ops::{self, Deref},
|
||||
ops::{self},
|
||||
},
|
||||
hashbrown::hash_map,
|
||||
hbbytecode::DisasmError,
|
||||
|
@ -2016,7 +2016,7 @@ impl Scope {
|
|||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct ItemCtx {
|
||||
file: FileId,
|
||||
file: Module,
|
||||
pos: Vec<Pos>,
|
||||
ret: Option<ty::Id>,
|
||||
task_base: usize,
|
||||
|
@ -2031,7 +2031,7 @@ pub struct ItemCtx {
|
|||
}
|
||||
|
||||
impl ItemCtx {
|
||||
fn init(&mut self, file: FileId, ret: Option<ty::Id>, task_base: usize) {
|
||||
fn init(&mut self, file: Module, ret: Option<ty::Id>, task_base: usize) {
|
||||
debug_assert_eq!(self.loops.len(), 0);
|
||||
debug_assert_eq!(self.scope.vars.len(), 0);
|
||||
debug_assert_eq!(self.scope.aclasses.len(), 0);
|
||||
|
@ -2106,7 +2106,7 @@ pub struct Pool {
|
|||
impl Pool {
|
||||
fn push_ci(
|
||||
&mut self,
|
||||
file: FileId,
|
||||
file: Module,
|
||||
ret: Option<ty::Id>,
|
||||
task_base: usize,
|
||||
target: &mut ItemCtx,
|
||||
|
@ -2173,8 +2173,8 @@ impl Value {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn ty(self, ty: impl Into<ty::Id>) -> Self {
|
||||
Self { ty: ty.into(), ..self }
|
||||
fn ty(self, ty: ty::Id) -> Self {
|
||||
Self { ty, ..self }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2239,24 +2239,24 @@ impl<'a> Codegen<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn generate(&mut self, entry: FileId) {
|
||||
pub fn generate(&mut self, entry: Module) {
|
||||
self.find_type(0, entry, entry, Err("main"), self.files);
|
||||
if self.tys.ins.funcs.is_empty() {
|
||||
return;
|
||||
}
|
||||
self.make_func_reachable(0);
|
||||
self.make_func_reachable(ty::Func::MAIN);
|
||||
self.complete_call_graph();
|
||||
}
|
||||
|
||||
pub fn assemble_comptime(&mut self) -> Comptime {
|
||||
self.ct.code.clear();
|
||||
self.ct_backend.assemble_bin(0, self.tys, &mut self.ct.code);
|
||||
self.ct_backend.assemble_bin(ty::Func::MAIN, self.tys, &mut self.ct.code);
|
||||
self.ct.reset();
|
||||
core::mem::take(self.ct)
|
||||
}
|
||||
|
||||
pub fn assemble(&mut self, buf: &mut Vec<u8>) {
|
||||
self.backend.assemble_bin(0, self.tys, buf);
|
||||
self.backend.assemble_bin(ty::Func::MAIN, self.tys, buf);
|
||||
}
|
||||
|
||||
pub fn disasm(&mut self, output: &mut String, bin: &[u8]) -> Result<(), DisasmError> {
|
||||
|
@ -2264,17 +2264,17 @@ impl<'a> Codegen<'a> {
|
|||
}
|
||||
|
||||
pub fn push_embeds(&mut self, embeds: Vec<Vec<u8>>) {
|
||||
self.tys.ins.globals = embeds
|
||||
.into_iter()
|
||||
.map(|data| Global {
|
||||
for data in embeds {
|
||||
let g = Global {
|
||||
ty: self.tys.make_array(ty::Id::U8, data.len() as _),
|
||||
data,
|
||||
..Default::default()
|
||||
})
|
||||
.collect();
|
||||
};
|
||||
self.tys.ins.globals.push(g);
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_and_eval(&mut self, file: FileId, ret: ty::Id, ret_loc: &mut [u8]) -> u64 {
|
||||
fn emit_and_eval(&mut self, file: Module, 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()
|
||||
|
@ -2291,8 +2291,7 @@ impl<'a> Codegen<'a> {
|
|||
return 1;
|
||||
}
|
||||
|
||||
let fuc = self.tys.ins.funcs.len() as ty::Func;
|
||||
self.tys.ins.funcs.push(Func {
|
||||
let fuc = self.tys.ins.funcs.push(Func {
|
||||
file,
|
||||
sig: Some(Sig { args: Tuple::empty(), ret }),
|
||||
..Default::default()
|
||||
|
@ -2413,7 +2412,7 @@ impl<'a> Codegen<'a> {
|
|||
|
||||
fn make_func_reachable(&mut self, func: ty::Func) {
|
||||
let state_slot = self.ct.active() as usize;
|
||||
let fuc = &mut self.tys.ins.funcs[func as usize];
|
||||
let fuc = &mut self.tys.ins.funcs[func];
|
||||
if fuc.comp_state[state_slot] == CompState::Dead {
|
||||
fuc.comp_state[state_slot] = CompState::Queued(self.tys.tasks.len() as _);
|
||||
self.tys.tasks.push(Some(FTask { file: fuc.file, id: func, ct: self.ct.active() }));
|
||||
|
@ -2500,9 +2499,9 @@ impl<'a> Codegen<'a> {
|
|||
Expr::Ident { id, pos, .. } => {
|
||||
let decl = self.find_type(pos, self.ci.file, self.ci.file, Ok(id), self.files);
|
||||
match decl.expand() {
|
||||
ty::Kind::Builtin(ty::NEVER) => Value::NEVER,
|
||||
ty::Kind::NEVER => Value::NEVER,
|
||||
ty::Kind::Global(global) => {
|
||||
let gl = &self.tys.ins.globals[global as usize];
|
||||
let gl = &self.tys.ins.globals[global];
|
||||
let value = self.ci.nodes.new_node(gl.ty, Kind::Global { global }, [VOID]);
|
||||
self.ci.nodes[value].aclass = GLOBAL_ACLASS as _;
|
||||
Some(Value::ptr(value).ty(gl.ty))
|
||||
|
@ -2527,7 +2526,7 @@ impl<'a> Codegen<'a> {
|
|||
occupied_entry.get_key_value().0.value.0
|
||||
}
|
||||
(hash_map::RawEntryMut::Vacant(vacant_entry), hash) => {
|
||||
let global = self.tys.ins.globals.len() as ty::Global;
|
||||
let global =
|
||||
self.tys.ins.globals.push(Global { data, ty, ..Default::default() });
|
||||
vacant_entry
|
||||
.insert(crate::ctx_map::Key { value: StringRef(global), hash }, ())
|
||||
|
@ -2626,9 +2625,9 @@ impl<'a> Codegen<'a> {
|
|||
.find_type(pos, self.ci.file, m, Err(name), self.files)
|
||||
.expand()
|
||||
{
|
||||
ty::Kind::Builtin(ty::NEVER) => Value::NEVER,
|
||||
ty::Kind::NEVER => Value::NEVER,
|
||||
ty::Kind::Global(global) => {
|
||||
let gl = &self.tys.ins.globals[global as usize];
|
||||
let gl = &self.tys.ins.globals[global];
|
||||
let value =
|
||||
self.ci.nodes.new_node(gl.ty, Kind::Global { global }, [VOID]);
|
||||
self.ci.nodes[value].aclass = GLOBAL_ACLASS as _;
|
||||
|
@ -2781,7 +2780,7 @@ impl<'a> Codegen<'a> {
|
|||
return Value::NEVER;
|
||||
};
|
||||
|
||||
Some(Value::new(self.gen_null_check(cmped, ty, op)).ty(ty::BOOL))
|
||||
Some(Value::new(self.gen_null_check(cmped, ty, op)).ty(ty::Id::BOOL))
|
||||
}
|
||||
Expr::BinOp { left, pos, op, right }
|
||||
if !matches!(op, TokenKind::Assign | TokenKind::Decl) =>
|
||||
|
@ -2850,7 +2849,7 @@ impl<'a> Codegen<'a> {
|
|||
return Value::NEVER;
|
||||
};
|
||||
|
||||
let elem = self.tys.ins.slices[s as usize].elem;
|
||||
let elem = self.tys.ins.slices[s].elem;
|
||||
let mut idx = self.expr_ctx(index, Ctx::default().with_ty(ty::Id::DEFAULT_INT))?;
|
||||
self.assert_ty(index.pos(), &mut idx, ty::Id::DEFAULT_INT, "subscript");
|
||||
let size = self.ci.nodes.new_const(ty::Id::INT, self.tys.size_of(elem));
|
||||
|
@ -2866,7 +2865,7 @@ impl<'a> Codegen<'a> {
|
|||
Some(Value::ptr(ptr).ty(elem))
|
||||
}
|
||||
Expr::Embed { id, .. } => {
|
||||
let glob = &self.tys.ins.globals[id as usize];
|
||||
let glob = &self.tys.ins.globals[id];
|
||||
let g = self.ci.nodes.new_node(glob.ty, Kind::Global { global: id }, [VOID]);
|
||||
Some(Value::ptr(g).ty(glob.ty))
|
||||
}
|
||||
|
@ -3092,7 +3091,7 @@ impl<'a> Codegen<'a> {
|
|||
|
||||
inps[0] = self.ci.ctrl.get();
|
||||
self.ci.ctrl.set(
|
||||
self.ci.nodes.new_node(ty, Kind::Call { func: ty::ECA, args }, inps),
|
||||
self.ci.nodes.new_node(ty, Kind::Call { func: ty::Func::ECA, args }, inps),
|
||||
&mut self.ci.nodes,
|
||||
);
|
||||
|
||||
|
@ -3115,8 +3114,8 @@ impl<'a> Codegen<'a> {
|
|||
};
|
||||
self.make_func_reachable(fu);
|
||||
|
||||
let fuc = &self.tys.ins.funcs[fu as usize];
|
||||
let ast = &self.files[fuc.file as usize];
|
||||
let fuc = &self.tys.ins.funcs[fu];
|
||||
let ast = &self.files[fuc.file.index()];
|
||||
let &Expr::Closure { args: cargs, .. } = fuc.expr.get(ast) else { unreachable!() };
|
||||
|
||||
if args.len() != cargs.len() {
|
||||
|
@ -3195,9 +3194,9 @@ impl<'a> Codegen<'a> {
|
|||
return Value::NEVER;
|
||||
};
|
||||
|
||||
let Func { expr, file, .. } = self.tys.ins.funcs[fu as usize];
|
||||
let Func { expr, file, .. } = self.tys.ins.funcs[fu];
|
||||
|
||||
let ast = &self.files[file as usize];
|
||||
let ast = &self.files[file.index()];
|
||||
let &Expr::Closure { args: cargs, body, .. } = expr.get(ast) else {
|
||||
unreachable!()
|
||||
};
|
||||
|
@ -3342,7 +3341,7 @@ impl<'a> Codegen<'a> {
|
|||
Some(Value::ptr(mem).ty(sty))
|
||||
}
|
||||
ty::Kind::Slice(s) => {
|
||||
let slice = &self.tys.ins.slices[s as usize];
|
||||
let slice = &self.tys.ins.slices[s];
|
||||
let len = slice.len().unwrap_or(fields.len());
|
||||
let elem = slice.elem;
|
||||
let elem_size = self.tys.size_of(elem);
|
||||
|
@ -3839,8 +3838,8 @@ impl<'a> Codegen<'a> {
|
|||
}
|
||||
|
||||
fn compute_signature(&mut self, func: &mut ty::Func, pos: Pos, args: &[Expr]) -> Option<Sig> {
|
||||
let fuc = &self.tys.ins.funcs[*func as usize];
|
||||
let fast = self.files[fuc.file as usize].clone();
|
||||
let fuc = &self.tys.ins.funcs[*func];
|
||||
let fast = self.files[fuc.file.index()].clone();
|
||||
let &Expr::Closure { args: cargs, ret, .. } = fuc.expr.get(&fast) else {
|
||||
unreachable!();
|
||||
};
|
||||
|
@ -3895,20 +3894,24 @@ impl<'a> Codegen<'a> {
|
|||
|
||||
let sym = SymKey::FuncInst(*func, args);
|
||||
let ct = |ins: &mut crate::TypeIns| {
|
||||
let func_id = ins.funcs.len();
|
||||
let fuc = &ins.funcs[*func as usize];
|
||||
ins.funcs.push(Func {
|
||||
let fuc = &ins.funcs[*func];
|
||||
ins.funcs
|
||||
.push(Func {
|
||||
file: fuc.file,
|
||||
name: fuc.name,
|
||||
base: Some(*func),
|
||||
sig: Some(Sig { args, ret }),
|
||||
expr: fuc.expr,
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
ty::Kind::Func(func_id as _).compress()
|
||||
})
|
||||
.into()
|
||||
};
|
||||
*func = self.tys.syms.get_or_insert(sym, &mut self.tys.ins, ct).expand().inner();
|
||||
let ty::Kind::Func(f) =
|
||||
self.tys.syms.get_or_insert(sym, &mut self.tys.ins, ct).expand()
|
||||
else {
|
||||
unreachable!()
|
||||
};
|
||||
*func = f;
|
||||
|
||||
Sig { args, ret }
|
||||
})
|
||||
|
@ -4034,13 +4037,13 @@ impl<'a> Codegen<'a> {
|
|||
}
|
||||
|
||||
fn emit_func(&mut self, FTask { file, id, ct }: FTask) {
|
||||
let func = &mut self.tys.ins.funcs[id as usize];
|
||||
let func = &mut self.tys.ins.funcs[id];
|
||||
debug_assert_eq!(func.file, file);
|
||||
let cct = self.ct.active();
|
||||
debug_assert_eq!(cct, ct);
|
||||
func.comp_state[cct as usize] = CompState::Compiled;
|
||||
let sig = func.sig.expect("to emmit only concrete functions");
|
||||
let ast = &self.files[file as usize];
|
||||
let ast = &self.files[file.index()];
|
||||
let expr = func.expr.get(ast);
|
||||
|
||||
self.pool.push_ci(file, Some(sig.ret), 0, &mut self.ci);
|
||||
|
@ -4192,8 +4195,6 @@ impl<'a> Codegen<'a> {
|
|||
self.ci.nodes.gcm(&mut self.pool.nid_stack, &mut self.pool.nid_set);
|
||||
self.ci.nodes.basic_blocks();
|
||||
self.ci.nodes.graphviz(self.ty_display(ty::Id::VOID));
|
||||
} else {
|
||||
self.ci.nodes.graphviz_in_browser(self.ty_display(ty::Id::VOID));
|
||||
}
|
||||
|
||||
self.errors.borrow().len() == prev_err_len
|
||||
|
@ -4438,7 +4439,7 @@ impl<'a> Codegen<'a> {
|
|||
}
|
||||
|
||||
fn file(&self) -> &'a parser::Ast {
|
||||
&self.files[self.ci.file as usize]
|
||||
&self.files[self.ci.file.index()]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4447,7 +4448,7 @@ impl TypeParser for Codegen<'_> {
|
|||
self.tys
|
||||
}
|
||||
|
||||
fn eval_const(&mut self, file: FileId, expr: &Expr, ret: ty::Id) -> u64 {
|
||||
fn eval_const(&mut self, file: Module, expr: &Expr, ret: ty::Id) -> u64 {
|
||||
self.ct.activate();
|
||||
let mut scope = mem::take(&mut self.ci.scope.vars);
|
||||
self.pool.push_ci(file, Some(ret), self.tys.tasks.len(), &mut self.ci);
|
||||
|
@ -4480,7 +4481,7 @@ impl TypeParser for Codegen<'_> {
|
|||
fn on_reuse(&mut self, existing: ty::Id) {
|
||||
let state_slot = self.ct.active() as usize;
|
||||
if let ty::Kind::Func(id) = existing.expand()
|
||||
&& let func = &mut self.tys.ins.funcs[id as usize]
|
||||
&& let func = &mut self.tys.ins.funcs[id]
|
||||
&& let CompState::Queued(idx) = func.comp_state[state_slot]
|
||||
&& idx < self.tys.tasks.len()
|
||||
{
|
||||
|
@ -4490,11 +4491,10 @@ impl TypeParser for Codegen<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
fn eval_global(&mut self, file: FileId, name: Ident, expr: &Expr) -> ty::Id {
|
||||
fn eval_global(&mut self, file: Module, name: Ident, expr: &Expr) -> ty::Id {
|
||||
self.ct.activate();
|
||||
|
||||
let gid = self.tys.ins.globals.len() as ty::Global;
|
||||
self.tys.ins.globals.push(Global { file, name, ..Default::default() });
|
||||
let gid = self.tys.ins.globals.push(Global { file, name, ..Default::default() });
|
||||
|
||||
let ty = ty::Kind::Global(gid);
|
||||
self.pool.push_ci(file, None, self.tys.tasks.len(), &mut self.ci);
|
||||
|
@ -4506,19 +4506,19 @@ impl TypeParser for Codegen<'_> {
|
|||
if self.finalize(prev_err_len) {
|
||||
let mut mem = vec![0u8; self.tys.size_of(ret) as usize];
|
||||
self.emit_and_eval(file, ret, &mut mem);
|
||||
self.tys.ins.globals[gid as usize].data = mem;
|
||||
self.tys.ins.globals[gid].data = mem;
|
||||
}
|
||||
|
||||
self.pool.pop_ci(&mut self.ci);
|
||||
self.tys.ins.globals[gid as usize].ty = ret;
|
||||
self.tys.ins.globals[gid].ty = ret;
|
||||
|
||||
self.ct.deactivate();
|
||||
ty.compress()
|
||||
}
|
||||
|
||||
fn report(&self, file: FileId, pos: Pos, msg: impl Display) -> ty::Id {
|
||||
fn report(&self, file: Module, pos: Pos, msg: impl Display) -> ty::Id {
|
||||
let mut buf = self.errors.borrow_mut();
|
||||
write!(buf, "{}", self.files[file as usize].report(pos, msg)).unwrap();
|
||||
write!(buf, "{}", self.files[file.index()].report(pos, msg)).unwrap();
|
||||
ty::Id::NEVER
|
||||
}
|
||||
|
||||
|
@ -4531,6 +4531,7 @@ impl TypeParser for Codegen<'_> {
|
|||
mod tests {
|
||||
use {
|
||||
super::{hbvm::HbvmBackend, CodegenCtx},
|
||||
crate::ty,
|
||||
alloc::{string::String, vec::Vec},
|
||||
core::fmt::Write,
|
||||
};
|
||||
|
@ -4546,7 +4547,7 @@ mod tests {
|
|||
let mut codegen = super::Codegen::new(&mut backend, files, &mut ctx);
|
||||
codegen.push_embeds(embeds);
|
||||
|
||||
codegen.generate(0);
|
||||
codegen.generate(ty::Module::MAIN);
|
||||
|
||||
{
|
||||
let errors = codegen.errors.borrow();
|
||||
|
|
|
@ -4,7 +4,8 @@ use {
|
|||
lexer::TokenKind,
|
||||
parser, reg,
|
||||
son::{debug_assert_matches, write_reloc, Kind, MEM},
|
||||
ty::{self, Loc},
|
||||
ty::{self, Loc, Module},
|
||||
utils::{Ent, EntVec},
|
||||
Offset, Reloc, Size, TypedReloc, Types,
|
||||
},
|
||||
alloc::{boxed::Box, collections::BTreeMap, string::String, vec::Vec},
|
||||
|
@ -47,8 +48,8 @@ struct Assembler {
|
|||
|
||||
#[derive(Default)]
|
||||
pub struct HbvmBackend {
|
||||
funcs: Vec<FuncDt>,
|
||||
globals: Vec<GlobalDt>,
|
||||
funcs: EntVec<ty::Func, FuncDt>,
|
||||
globals: EntVec<ty::Global, GlobalDt>,
|
||||
asm: Assembler,
|
||||
ralloc: their_regalloc::Regalloc,
|
||||
ralloc_my: my_regalloc::Res,
|
||||
|
@ -98,13 +99,13 @@ impl Backend for HbvmBackend {
|
|||
debug_assert!(self.asm.funcs.is_empty());
|
||||
debug_assert!(self.asm.globals.is_empty());
|
||||
|
||||
self.globals.resize_with(types.ins.globals.len(), Default::default);
|
||||
self.globals.shadow(types.ins.globals.len());
|
||||
|
||||
self.asm.frontier.push(ty::Kind::Func(from).compress());
|
||||
while let Some(itm) = self.asm.frontier.pop() {
|
||||
match itm.expand() {
|
||||
ty::Kind::Func(func) => {
|
||||
let fuc = &mut self.funcs[func as usize];
|
||||
let fuc = &mut self.funcs[func];
|
||||
debug_assert!(!fuc.code.is_empty());
|
||||
if fuc.offset != u32::MAX {
|
||||
continue;
|
||||
|
@ -114,7 +115,7 @@ impl Backend for HbvmBackend {
|
|||
self.asm.frontier.extend(fuc.relocs.iter().map(|r| r.target));
|
||||
}
|
||||
ty::Kind::Global(glob) => {
|
||||
let glb = &mut self.globals[glob as usize];
|
||||
let glb = &mut self.globals[glob];
|
||||
if glb.offset != u32::MAX {
|
||||
continue;
|
||||
}
|
||||
|
@ -128,7 +129,7 @@ impl Backend for HbvmBackend {
|
|||
let init_len = to.len();
|
||||
|
||||
for &func in &self.asm.funcs {
|
||||
let fuc = &mut self.funcs[func as usize];
|
||||
let fuc = &mut self.funcs[func];
|
||||
fuc.offset = to.len() as _;
|
||||
debug_assert!(!fuc.code.is_empty());
|
||||
to.extend(&fuc.code);
|
||||
|
@ -137,18 +138,18 @@ impl Backend for HbvmBackend {
|
|||
let code_length = to.len() - init_len;
|
||||
|
||||
for global in self.asm.globals.drain(..) {
|
||||
self.globals[global as usize].offset = to.len() as _;
|
||||
to.extend(&types.ins.globals[global as usize].data);
|
||||
self.globals[global].offset = to.len() as _;
|
||||
to.extend(&types.ins.globals[global].data);
|
||||
}
|
||||
|
||||
let data_length = to.len() - code_length - init_len;
|
||||
|
||||
for func in self.asm.funcs.drain(..) {
|
||||
let fuc = &self.funcs[func as usize];
|
||||
let fuc = &self.funcs[func];
|
||||
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,
|
||||
ty::Kind::Func(fun) => self.funcs[fun].offset,
|
||||
ty::Kind::Global(glo) => self.globals[glo].offset,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
rel.reloc.apply_jump(to, offset, fuc.offset);
|
||||
|
@ -158,7 +159,7 @@ impl Backend for HbvmBackend {
|
|||
AssemblySpec {
|
||||
code_length: code_length as _,
|
||||
data_length: data_length as _,
|
||||
entry: self.funcs[from as usize].offset,
|
||||
entry: self.funcs[from].offset,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -175,11 +176,11 @@ impl Backend for HbvmBackend {
|
|||
.ins
|
||||
.funcs
|
||||
.iter()
|
||||
.zip(&self.funcs)
|
||||
.zip(self.funcs.iter())
|
||||
.filter(|(_, f)| f.offset != u32::MAX)
|
||||
.map(|(f, fd)| {
|
||||
let name = if f.file != u32::MAX {
|
||||
let file = &files[f.file as usize];
|
||||
let name = if f.file != Module::default() {
|
||||
let file = &files[f.file.index()];
|
||||
file.ident_str(f.name)
|
||||
} else {
|
||||
"target_fn"
|
||||
|
@ -191,13 +192,13 @@ impl Backend for HbvmBackend {
|
|||
.ins
|
||||
.globals
|
||||
.iter()
|
||||
.zip(&self.globals)
|
||||
.zip(self.globals.iter())
|
||||
.filter(|(_, g)| g.offset != u32::MAX)
|
||||
.map(|(g, gd)| {
|
||||
let name = if g.file == u32::MAX {
|
||||
let name = if g.file == Module::default() {
|
||||
core::str::from_utf8(&g.data).unwrap_or("invalid utf-8")
|
||||
} else {
|
||||
let file = &files[g.file as usize];
|
||||
let file = &files[g.file.index()];
|
||||
file.ident_str(g.name)
|
||||
};
|
||||
(gd.offset, (name, g.data.len() as Size, DisasmItem::Global))
|
||||
|
@ -215,13 +216,13 @@ impl Backend for HbvmBackend {
|
|||
files: &[parser::Ast],
|
||||
) {
|
||||
self.emit_body(id, nodes, tys, files);
|
||||
let fd = &mut self.funcs[id as usize];
|
||||
let fd = &mut self.funcs[id];
|
||||
fd.code.truncate(fd.code.len() - instrs::jala(0, 0, 0).0);
|
||||
emit(&mut fd.code, instrs::tx());
|
||||
}
|
||||
|
||||
fn emit_body(&mut self, id: ty::Func, nodes: &mut Nodes, tys: &Types, files: &[parser::Ast]) {
|
||||
let sig = tys.ins.funcs[id as usize].sig.unwrap();
|
||||
let sig = tys.ins.funcs[id].sig.unwrap();
|
||||
|
||||
debug_assert!(self.code.is_empty());
|
||||
|
||||
|
@ -319,11 +320,9 @@ impl Backend for HbvmBackend {
|
|||
self.emit(instrs::jala(reg::ZERO, reg::RET_ADDR, 0));
|
||||
}
|
||||
|
||||
if self.funcs.get(id as usize).is_none() {
|
||||
self.funcs.resize_with(id as usize + 1, Default::default);
|
||||
}
|
||||
self.funcs[id as usize].code = mem::take(&mut self.code);
|
||||
self.funcs[id as usize].relocs = mem::take(&mut self.relocs);
|
||||
self.funcs.shadow(tys.ins.funcs.len());
|
||||
self.funcs[id].code = mem::take(&mut self.code);
|
||||
self.funcs[id].relocs = mem::take(&mut self.relocs);
|
||||
|
||||
debug_assert_eq!(self.ret_relocs.len(), 0);
|
||||
debug_assert_eq!(self.relocs.len(), 0);
|
||||
|
|
|
@ -305,7 +305,7 @@ impl HbvmBackend {
|
|||
!matches!(ret, Some(PLoc::Ref(..))) || allocs.next().is_some()
|
||||
);
|
||||
|
||||
if func == ty::ECA {
|
||||
if func == ty::Func::ECA {
|
||||
self.emit(instrs::eca());
|
||||
} else {
|
||||
self.relocs.push(TypedReloc {
|
||||
|
@ -647,7 +647,7 @@ impl<'a> Function<'a> {
|
|||
}
|
||||
}
|
||||
Kind::Call { func, .. } => {
|
||||
self.tail &= func == ty::ECA;
|
||||
self.tail &= func == ty::Func::ECA;
|
||||
|
||||
self.add_instr(nid);
|
||||
|
||||
|
|
|
@ -315,7 +315,7 @@ impl HbvmBackend {
|
|||
!matches!(ret, Some(PLoc::Ref(..))) || allocs.next().is_some()
|
||||
);
|
||||
|
||||
if func == ty::ECA {
|
||||
if func == ty::Func::ECA {
|
||||
self.emit(instrs::eca());
|
||||
} else {
|
||||
self.relocs.push(TypedReloc {
|
||||
|
@ -710,7 +710,7 @@ impl<'a> Function<'a> {
|
|||
self.add_instr(nid, ops);
|
||||
}
|
||||
Kind::Call { args, func } => {
|
||||
self.tail &= func == ty::ECA;
|
||||
self.tail &= func == ty::Func::ECA;
|
||||
self.backrefs[nid as usize] = self.backrefs[prev as usize];
|
||||
let mut ops = vec![];
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ use {
|
|||
alloc::Layout,
|
||||
fmt::Debug,
|
||||
hint::unreachable_unchecked,
|
||||
marker::PhantomData,
|
||||
mem::MaybeUninit,
|
||||
ops::{Deref, DerefMut, Not},
|
||||
ptr::Unique,
|
||||
|
@ -532,3 +533,97 @@ struct AllocedVc {
|
|||
len: Nid,
|
||||
base: Unique<Nid>,
|
||||
}
|
||||
|
||||
pub trait Ent: Copy {
|
||||
fn new(index: usize) -> Self;
|
||||
fn index(self) -> usize;
|
||||
}
|
||||
|
||||
pub struct EntVec<K: Ent, T> {
|
||||
data: ::alloc::vec::Vec<T>,
|
||||
k: PhantomData<fn(K)>,
|
||||
}
|
||||
|
||||
impl<K: Ent, T> Default for EntVec<K, T> {
|
||||
fn default() -> Self {
|
||||
Self { data: Default::default(), k: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Ent, T> EntVec<K, T> {
|
||||
pub fn clear(&mut self) {
|
||||
self.data.clear();
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.data.is_empty()
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.data.len()
|
||||
}
|
||||
|
||||
pub fn push(&mut self, value: T) -> K {
|
||||
let k = K::new(self.data.len());
|
||||
self.data.push(value);
|
||||
k
|
||||
}
|
||||
|
||||
pub fn next(&self, index: K) -> Option<&T> {
|
||||
self.data.get(index.index() + 1)
|
||||
}
|
||||
|
||||
pub fn shadow(&mut self, len: usize)
|
||||
where
|
||||
T: Default,
|
||||
{
|
||||
if self.data.len() < len {
|
||||
self.data.resize_with(len, Default::default);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> core::slice::Iter<T> {
|
||||
self.data.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Ent, T> core::ops::Index<K> for EntVec<K, T> {
|
||||
type Output = T;
|
||||
|
||||
fn index(&self, index: K) -> &Self::Output {
|
||||
&self.data[index.index()]
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Ent, T> core::ops::IndexMut<K> for EntVec<K, T> {
|
||||
fn index_mut(&mut self, index: K) -> &mut Self::Output {
|
||||
&mut self.data[index.index()]
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! decl_ent {
|
||||
($(
|
||||
$vis:vis struct $name:ident($index:ty);
|
||||
)*) => {$(
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
$vis struct $name($index);
|
||||
|
||||
impl crate::utils::Ent for $name {
|
||||
fn new(index: usize) -> Self {
|
||||
Self(index as $index)
|
||||
}
|
||||
|
||||
fn index(self) -> usize {
|
||||
self.0 as _
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl core::fmt::Display for $name {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
write!(f, concat!(stringify!($name), "{}"), self.0)
|
||||
}
|
||||
}
|
||||
)*};
|
||||
}
|
||||
pub(crate) use decl_ent;
|
||||
|
|
Loading…
Reference in a new issue