unifiing context key maps
This commit is contained in:
parent
2361e166cd
commit
f1ea01ef0c
|
@ -741,29 +741,32 @@ impl Codegen {
|
|||
fields: &[CommentOr<StructField>],
|
||||
) -> ty::Struct {
|
||||
let sym = pos.map(|pos| SymKey::Struct(file, pos));
|
||||
if let Some(ref sym) = sym
|
||||
&& let Some(&ty) = self.tys.syms.get(sym)
|
||||
if let Some(sym) = sym
|
||||
&& let Some(&ty) = self.tys.syms.get(sym, &self.tys.ins)
|
||||
{
|
||||
return ty.expand().inner();
|
||||
}
|
||||
|
||||
let prev_tmp = self.tys.ins.fields.len();
|
||||
let prev_tmp = self.tys.tmp.fields.len();
|
||||
for sf in fields.iter().filter_map(CommentOr::or) {
|
||||
let f = Field { name: self.tys.names.intern(sf.name), ty: self.ty(&sf.ty) };
|
||||
self.tys.ins.fields.push(f);
|
||||
self.tys.tmp.fields.push(f);
|
||||
}
|
||||
self.tys.ins.structs.push(Struct {
|
||||
field_start: self.tys.ins.fields.len() as _,
|
||||
pos: pos.unwrap_or(Pos::MAX),
|
||||
explicit_alignment,
|
||||
file,
|
||||
..Default::default()
|
||||
});
|
||||
self.tys.ins.fields.extend(self.tys.ins.fields.drain(prev_tmp..));
|
||||
self.tys.ins.fields.extend(self.tys.tmp.fields.drain(prev_tmp..));
|
||||
|
||||
if let Some(sym) = sym {
|
||||
self.tys
|
||||
.syms
|
||||
.insert(sym, ty::Kind::Struct(self.tys.ins.structs.len() as u32 - 1).compress());
|
||||
self.tys.syms.insert(
|
||||
sym,
|
||||
ty::Kind::Struct(self.tys.ins.structs.len() as u32 - 1).compress(),
|
||||
&self.tys.ins,
|
||||
);
|
||||
}
|
||||
|
||||
self.tys.ins.structs.len() as u32 - 1
|
||||
|
@ -884,7 +887,7 @@ impl Codegen {
|
|||
self.report(func_ast.pos(), "first argument of inline needs to be a function");
|
||||
};
|
||||
|
||||
let fuc = &self.tys.funcs[func as usize];
|
||||
let fuc = &self.tys.ins.funcs[func as usize];
|
||||
let fast = self.files[fuc.file as usize].clone();
|
||||
let E::BinOp { right: &E::Closure { args: cargs, body, .. }, .. } =
|
||||
fuc.expr.get(&fast).unwrap()
|
||||
|
@ -899,7 +902,7 @@ impl Codegen {
|
|||
|
||||
if scope == self.ci.vars.len() {
|
||||
for ((arg, ti), carg) in args.iter().zip(sig.args.range()).zip(cargs) {
|
||||
let ty = self.tys.args[ti];
|
||||
let ty = self.tys.ins.args[ti];
|
||||
let loc = self.expr_ctx(arg, Ctx::default().with_ty(ty))?.loc;
|
||||
self.ci.vars.push(Variable { id: carg.id, value: Value { ty, loc } });
|
||||
}
|
||||
|
@ -909,7 +912,7 @@ impl Codegen {
|
|||
|
||||
let loc = self.alloc_ret(sig.ret, ctx, true);
|
||||
let prev_ret_reg = core::mem::replace(&mut self.ci.inline_ret_loc, loc);
|
||||
let fuc = &self.tys.funcs[func as usize];
|
||||
let fuc = &self.tys.ins.funcs[func as usize];
|
||||
let prev_file = core::mem::replace(&mut self.ci.file, fuc.file);
|
||||
let prev_ret = core::mem::replace(&mut self.ci.ret, Some(sig.ret));
|
||||
self.expr(body);
|
||||
|
@ -1347,7 +1350,7 @@ impl Codegen {
|
|||
//self.output.trunc(&snap);
|
||||
self.ci.vars.truncate(scope);
|
||||
|
||||
let fuc = &self.tys.funcs[func as usize];
|
||||
let fuc = &self.tys.ins.funcs[func as usize];
|
||||
let ast = self.files[fuc.file as usize].clone();
|
||||
let E::BinOp { right: &E::Closure { args: cargs, .. }, .. } =
|
||||
fuc.expr.get(&ast).unwrap()
|
||||
|
@ -1363,7 +1366,7 @@ impl Codegen {
|
|||
self.assert_arg_count(expr.pos(), args.len(), cargs.len(), "function call");
|
||||
|
||||
for (i, (arg, carg)) in args.iter().zip(cargs).enumerate() {
|
||||
let ty = self.tys.args[sig_args.next().unwrap()];
|
||||
let ty = self.tys.ins.args[sig_args.next().unwrap()];
|
||||
let sym = parser::find_symbol(&ast.symbols, carg.id);
|
||||
if sym.flags & idfl::COMPTIME != 0 {
|
||||
sig_args.next().unwrap();
|
||||
|
@ -1740,7 +1743,7 @@ impl Codegen {
|
|||
}
|
||||
|
||||
fn compute_signature(&mut self, func: &mut ty::Func, pos: Pos, args: &[Expr]) -> Option<Sig> {
|
||||
let fuc = &self.tys.funcs[*func as usize];
|
||||
let fuc = &self.tys.ins.funcs[*func as usize];
|
||||
let fast = self.files[fuc.file as usize].clone();
|
||||
let Expr::BinOp { right: &Expr::Closure { args: cargs, ret, .. }, .. } =
|
||||
fuc.expr.get(&fast).unwrap()
|
||||
|
@ -1751,11 +1754,11 @@ impl Codegen {
|
|||
Some(if let Some(sig) = fuc.sig {
|
||||
sig
|
||||
} else {
|
||||
let arg_base = self.tys.args.len();
|
||||
let arg_base = self.tys.ins.args.len();
|
||||
|
||||
for (arg, carg) in args.iter().zip(cargs) {
|
||||
let ty = self.ty(&carg.ty);
|
||||
self.tys.args.push(ty);
|
||||
self.tys.ins.args.push(ty);
|
||||
let sym = parser::find_symbol(&fast.symbols, carg.id);
|
||||
let loc = if sym.flags & idfl::COMPTIME == 0 {
|
||||
// FIXME: could fuck us
|
||||
|
@ -1767,7 +1770,7 @@ impl Codegen {
|
|||
"TODO: we dont support anything except type generics"
|
||||
);
|
||||
let arg = self.expr_ctx(arg, Ctx::default().with_ty(ty))?;
|
||||
self.tys.args.push(arg.loc.to_ty().unwrap());
|
||||
self.tys.ins.args.push(arg.loc.to_ty().unwrap());
|
||||
arg.loc
|
||||
};
|
||||
|
||||
|
@ -1778,11 +1781,13 @@ impl Codegen {
|
|||
let ret = self.ty(ret);
|
||||
|
||||
let sym = SymKey::FuncInst(*func, args);
|
||||
let ct = || {
|
||||
let func_id = self.tys.funcs.len();
|
||||
let fuc = &self.tys.funcs[*func as usize];
|
||||
self.tys.funcs.push(Func {
|
||||
let ct = |ins: &mut crate::TypeIns| {
|
||||
let func_id = ins.funcs.len();
|
||||
let fuc = &ins.funcs[*func as usize];
|
||||
ins.funcs.push(Func {
|
||||
file: fuc.file,
|
||||
name: fuc.name,
|
||||
base: Some(*func),
|
||||
sig: Some(Sig { args, ret }),
|
||||
expr: fuc.expr,
|
||||
..Default::default()
|
||||
|
@ -1790,7 +1795,7 @@ impl Codegen {
|
|||
|
||||
ty::Kind::Func(func_id as _).compress()
|
||||
};
|
||||
*func = self.tys.syms.entry(sym).or_insert_with(ct).expand().inner();
|
||||
*func = self.tys.syms.get_or_insert(sym, &mut self.tys.ins, ct).expand().inner();
|
||||
|
||||
Sig { args, ret }
|
||||
})
|
||||
|
@ -2084,7 +2089,7 @@ impl Codegen {
|
|||
}
|
||||
|
||||
fn handle_task(&mut self, FTask { file, id }: FTask) {
|
||||
let func = &self.tys.funcs[id as usize];
|
||||
let func = &self.tys.ins.funcs[id as usize];
|
||||
debug_assert!(func.file == file);
|
||||
let sig = func.sig.unwrap();
|
||||
let ast = self.files[file as usize].clone();
|
||||
|
@ -2114,10 +2119,10 @@ impl Codegen {
|
|||
let mut parama = self.tys.parama(sig.ret);
|
||||
let mut sig_args = sig.args.range();
|
||||
for arg in args.iter() {
|
||||
let ty = self.tys.args[sig_args.next().unwrap()];
|
||||
let ty = self.tys.ins.args[sig_args.next().unwrap()];
|
||||
let sym = parser::find_symbol(&ast.symbols, arg.id).flags;
|
||||
let loc = match sym & idfl::COMPTIME != 0 {
|
||||
true => Loc::ty(self.tys.args[sig_args.next().unwrap()]),
|
||||
true => Loc::ty(self.tys.ins.args[sig_args.next().unwrap()]),
|
||||
false => self.load_arg(sym, ty, &mut parama),
|
||||
};
|
||||
self.ci.vars.push(Variable { id: arg.id, value: Value { ty, loc } });
|
||||
|
@ -2144,8 +2149,8 @@ impl Codegen {
|
|||
self.ci.finalize();
|
||||
self.ci.emit(jala(ZERO, RET_ADDR, 0));
|
||||
self.ci.regs.free(core::mem::take(&mut self.ci.ret_reg));
|
||||
self.tys.funcs[id as usize].code.append(&mut self.ci.code);
|
||||
self.tys.funcs[id as usize].relocs.append(&mut self.ci.relocs);
|
||||
self.tys.ins.funcs[id as usize].code.append(&mut self.ci.code);
|
||||
self.tys.ins.funcs[id as usize].relocs.append(&mut self.ci.relocs);
|
||||
self.pool.cis.push(core::mem::replace(&mut self.ci, prev_ci));
|
||||
self.ct.vm.write_reg(reg::STACK_PTR, ct_stack_base);
|
||||
}
|
||||
|
@ -2423,15 +2428,14 @@ impl Codegen {
|
|||
.compress();
|
||||
self.ci.vars.truncate(prev_len);
|
||||
self.ct.vm.write_reg(1, stru.repr() as u64);
|
||||
debug_assert_ne!(stru.expand().inner(), 1);
|
||||
}
|
||||
trap::Trap::MomizedCall(trap::MomizedCall { func }) => {
|
||||
let sym = SymKey::MomizedCall(func);
|
||||
if let Some(&ty) = self.tys.syms.get(&sym) {
|
||||
if let Some(ty) = self.tys.ins.funcs[func as usize].computed {
|
||||
self.ct.vm.write_reg(1, ty.repr());
|
||||
} else {
|
||||
self.run_vm();
|
||||
self.tys.syms.insert(sym, self.ct.vm.read_reg(1).0.into());
|
||||
self.tys.ins.funcs[func as usize].computed =
|
||||
Some(self.ct.vm.read_reg(1).0.into());
|
||||
}
|
||||
code_index += jal(0, 0, 0).0 + tx().0;
|
||||
}
|
||||
|
@ -2463,9 +2467,9 @@ impl Codegen {
|
|||
};
|
||||
|
||||
let key = SymKey::Decl(file, ident);
|
||||
if let Some(existing) = self.tys.syms.get(&key) {
|
||||
if let Some(existing) = self.tys.syms.get(key, &self.tys.ins) {
|
||||
if let ty::Kind::Func(id) = existing.expand()
|
||||
&& let func = &mut self.tys.funcs[id as usize]
|
||||
&& let func = &mut self.tys.ins.funcs[id as usize]
|
||||
&& let Err(idx) = task::unpack(func.offset)
|
||||
&& idx < self.tasks.len()
|
||||
{
|
||||
|
@ -2479,22 +2483,23 @@ impl Codegen {
|
|||
let prev_file = core::mem::replace(&mut self.ci.file, file);
|
||||
let sym = match expr {
|
||||
Expr::BinOp {
|
||||
left: &Expr::Ident { .. },
|
||||
left: &Expr::Ident { id, .. },
|
||||
op: TokenKind::Decl,
|
||||
right: &Expr::Closure { pos, args, ret, .. },
|
||||
} => {
|
||||
let func = Func {
|
||||
file,
|
||||
name: id,
|
||||
sig: 'b: {
|
||||
let arg_base = self.tys.args.len();
|
||||
let arg_base = self.tys.ins.args.len();
|
||||
for arg in args {
|
||||
let sym = find_symbol(&self.files[file as usize].symbols, arg.id);
|
||||
if sym.flags & idfl::COMPTIME != 0 {
|
||||
self.tys.args.truncate(arg_base);
|
||||
self.tys.ins.args.truncate(arg_base);
|
||||
break 'b None;
|
||||
}
|
||||
let ty = self.ty(&arg.ty);
|
||||
self.tys.args.push(ty);
|
||||
self.tys.ins.args.push(ty);
|
||||
}
|
||||
|
||||
let args = self.pack_args(pos, arg_base);
|
||||
|
@ -2510,8 +2515,8 @@ impl Codegen {
|
|||
..Default::default()
|
||||
};
|
||||
|
||||
let id = self.tys.funcs.len() as _;
|
||||
self.tys.funcs.push(func);
|
||||
let id = self.tys.ins.funcs.len() as _;
|
||||
self.tys.ins.funcs.push(func);
|
||||
|
||||
ty::Kind::Func(id)
|
||||
}
|
||||
|
@ -2545,12 +2550,12 @@ impl Codegen {
|
|||
e => unimplemented!("{e:#?}"),
|
||||
};
|
||||
self.ci.file = prev_file;
|
||||
self.tys.syms.insert(key, sym.compress());
|
||||
self.tys.syms.insert(key, sym.compress(), &self.tys.ins);
|
||||
sym
|
||||
}
|
||||
|
||||
fn make_func_reachable(&mut self, func: ty::Func) {
|
||||
let fuc = &mut self.tys.funcs[func as usize];
|
||||
let fuc = &mut self.tys.ins.funcs[func as usize];
|
||||
if fuc.offset == u32::MAX {
|
||||
fuc.offset = task::id(self.tasks.len() as _);
|
||||
self.tasks.push(Some(FTask { file: fuc.file, id: func }));
|
||||
|
@ -2604,11 +2609,11 @@ impl Codegen {
|
|||
}
|
||||
|
||||
if ret.is_ok() {
|
||||
let last_fn = self.tys.funcs.len();
|
||||
self.tys.funcs.push(Default::default());
|
||||
let last_fn = self.tys.ins.funcs.len();
|
||||
self.tys.ins.funcs.push(Default::default());
|
||||
|
||||
self.tys.funcs[last_fn].code = core::mem::take(&mut self.ci.code);
|
||||
self.tys.funcs[last_fn].relocs = core::mem::take(&mut self.ci.relocs);
|
||||
self.tys.ins.funcs[last_fn].code = core::mem::take(&mut self.ci.code);
|
||||
self.tys.ins.funcs[last_fn].relocs = core::mem::take(&mut self.ci.relocs);
|
||||
|
||||
if is_on_stack {
|
||||
let size =
|
||||
|
@ -2619,7 +2624,8 @@ impl Codegen {
|
|||
}
|
||||
|
||||
self.tys.dump_reachable(last_fn as _, &mut self.ct.code);
|
||||
let entry = &mut self.ct.code[self.tys.funcs[last_fn].offset as usize] as *mut _ as _;
|
||||
let entry =
|
||||
&mut self.ct.code[self.tys.ins.funcs[last_fn].offset as usize] as *mut _ as _;
|
||||
let prev_pc = core::mem::replace(&mut self.ct.vm.pc, hbvm::mem::Address::new(entry))
|
||||
- self.ct.code.as_ptr() as usize;
|
||||
|
||||
|
@ -2640,7 +2646,7 @@ impl Codegen {
|
|||
self.run_vm();
|
||||
self.ct.vm.pc = prev_pc + self.ct.code.as_ptr() as usize;
|
||||
|
||||
let func = self.tys.funcs.pop().unwrap();
|
||||
let func = self.tys.ins.funcs.pop().unwrap();
|
||||
self.ci.code = func.code;
|
||||
self.ci.code.clear();
|
||||
self.ci.relocs = func.relocs;
|
||||
|
@ -2729,15 +2735,15 @@ impl Codegen {
|
|||
}
|
||||
|
||||
fn pack_args(&mut self, pos: Pos, arg_base: usize) -> ty::Tuple {
|
||||
let needle = &self.tys.args[arg_base..];
|
||||
let needle = &self.tys.ins.args[arg_base..];
|
||||
if needle.is_empty() {
|
||||
return ty::Tuple::empty();
|
||||
}
|
||||
let len = needle.len();
|
||||
// FIXME: maybe later when this becomes a bottleneck we use more
|
||||
// efficient search (SIMD?, indexing?)
|
||||
let sp = self.tys.args.windows(needle.len()).position(|val| val == needle).unwrap();
|
||||
self.tys.args.truncate((sp + needle.len()).max(arg_base));
|
||||
let sp = self.tys.ins.args.windows(needle.len()).position(|val| val == needle).unwrap();
|
||||
self.tys.ins.args.truncate((sp + needle.len()).max(arg_base));
|
||||
ty::Tuple::new(sp, len)
|
||||
.unwrap_or_else(|| self.report(pos, "amount of arguments not supported"))
|
||||
}
|
||||
|
@ -2753,7 +2759,7 @@ impl Codegen {
|
|||
}
|
||||
|
||||
pub fn assemble(&mut self, buf: &mut Vec<u8>) {
|
||||
self.tys.funcs.iter_mut().for_each(|f| f.offset = u32::MAX);
|
||||
self.tys.ins.funcs.iter_mut().for_each(|f| f.offset = u32::MAX);
|
||||
self.tys.ins.globals.iter_mut().for_each(|g| g.offset = u32::MAX);
|
||||
self.tys.assemble(buf)
|
||||
}
|
||||
|
@ -2764,6 +2770,9 @@ mod tests {
|
|||
use alloc::{string::String, vec::Vec};
|
||||
|
||||
fn generate(ident: &'static str, input: &'static str, output: &mut String) {
|
||||
_ = log::set_logger(&crate::fs::Logger);
|
||||
log::set_max_level(log::LevelFilter::Error);
|
||||
|
||||
let mut codegen =
|
||||
super::Codegen { files: crate::test_parse_files(ident, input), ..Default::default() };
|
||||
|
||||
|
|
|
@ -123,18 +123,18 @@ mod ctx_map {
|
|||
impl<T: CtxEntry> CtxMap<T> {
|
||||
pub fn entry<'a, 'b>(
|
||||
&'a mut self,
|
||||
value: T::Key<'b>,
|
||||
key: T::Key<'b>,
|
||||
ctx: &'b T::Ctx,
|
||||
) -> (hashbrown::hash_map::RawEntryMut<'a, Key<T>, (), HashBuilder>, Hash) {
|
||||
let hash = crate::FnvBuildHasher::default().hash_one(&value);
|
||||
(self.inner.raw_entry_mut().from_hash(hash, |k| k.value.key(ctx) == value), hash)
|
||||
let hash = crate::FnvBuildHasher::default().hash_one(&key);
|
||||
(self.inner.raw_entry_mut().from_hash(hash, |k| k.value.key(ctx) == key), hash)
|
||||
}
|
||||
|
||||
pub fn get<'a>(&self, value: T::Key<'a>, ctx: &'a T::Ctx) -> Option<&T> {
|
||||
let hash = crate::FnvBuildHasher::default().hash_one(&value);
|
||||
pub fn get<'a>(&self, key: T::Key<'a>, ctx: &'a T::Ctx) -> Option<&T> {
|
||||
let hash = crate::FnvBuildHasher::default().hash_one(&key);
|
||||
self.inner
|
||||
.raw_entry()
|
||||
.from_hash(hash, |k| k.value.key(ctx) == value)
|
||||
.from_hash(hash, |k| k.value.key(ctx) == key)
|
||||
.map(|(k, _)| &k.value)
|
||||
}
|
||||
|
||||
|
@ -142,13 +142,38 @@ mod ctx_map {
|
|||
self.inner.clear();
|
||||
}
|
||||
|
||||
pub fn remove<'a>(&mut self, value: &T, ctx: &'a T::Ctx) -> Option<T> {
|
||||
pub fn remove(&mut self, value: &T, ctx: &T::Ctx) -> Option<T> {
|
||||
let (entry, _) = self.entry(value.key(ctx), ctx);
|
||||
match entry {
|
||||
hashbrown::hash_map::RawEntryMut::Occupied(o) => Some(o.remove_entry().0.value),
|
||||
hashbrown::hash_map::RawEntryMut::Vacant(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert<'a>(&mut self, key: T::Key<'a>, value: T, ctx: &'a T::Ctx) {
|
||||
let (entry, hash) = self.entry(key, ctx);
|
||||
match entry {
|
||||
hashbrown::hash_map::RawEntryMut::Occupied(_) => unreachable!(),
|
||||
hashbrown::hash_map::RawEntryMut::Vacant(v) => {
|
||||
_ = v.insert(Key { hash, value }, ())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_or_insert<'a>(
|
||||
&mut self,
|
||||
key: T::Key<'a>,
|
||||
ctx: &'a mut T::Ctx,
|
||||
with: impl FnOnce(&'a mut T::Ctx) -> T,
|
||||
) -> &mut T {
|
||||
let (entry, hash) = self.entry(key, unsafe { &mut *(&mut *ctx as *mut _) });
|
||||
match entry {
|
||||
hashbrown::hash_map::RawEntryMut::Occupied(o) => &mut o.into_key_value().0.value,
|
||||
hashbrown::hash_map::RawEntryMut::Vacant(v) => {
|
||||
&mut v.insert(Key { hash, value: with(ctx) }, ()).0.value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -205,7 +230,7 @@ mod ty {
|
|||
crate::{
|
||||
ident,
|
||||
lexer::TokenKind,
|
||||
parser::{self},
|
||||
parser::{self, Pos},
|
||||
},
|
||||
core::{num::NonZeroU32, ops::Range},
|
||||
};
|
||||
|
@ -254,11 +279,32 @@ mod ty {
|
|||
pub struct Id(NonZeroU32);
|
||||
|
||||
impl crate::ctx_map::CtxEntry for Id {
|
||||
type Ctx = TypeInsts;
|
||||
type Ctx = crate::TypeIns;
|
||||
type Key<'a> = crate::SymKey<'a>;
|
||||
|
||||
fn key<'a>(&self, ctx: &'a Self::Ctx) -> Self::Key<'a> {
|
||||
todo!()
|
||||
match self.expand() {
|
||||
Kind::Struct(s) => {
|
||||
let st = &ctx.structs[s as usize];
|
||||
debug_assert_ne!(st.pos, Pos::MAX);
|
||||
crate::SymKey::Struct(st.file, st.pos)
|
||||
}
|
||||
Kind::Ptr(p) => crate::SymKey::Pointer(&ctx.ptrs[p as usize]),
|
||||
Kind::Func(f) => {
|
||||
let fc = &ctx.funcs[f as usize];
|
||||
if let Some(base) = fc.base {
|
||||
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];
|
||||
crate::SymKey::Decl(gb.file, gb.name)
|
||||
}
|
||||
Kind::Slice(s) => crate::SymKey::Array(&ctx.arrays[s as usize]),
|
||||
Kind::Module(_) | Kind::Builtin(_) => crate::SymKey::Decl(u32::MAX, u32::MAX),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -521,12 +567,11 @@ fn emit(out: &mut Vec<u8>, (len, instr): EncodedInstr) {
|
|||
out.extend_from_slice(&instr[..len]);
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Hash)]
|
||||
enum SymKey<'a> {
|
||||
#[derive(PartialEq, Eq, Hash, Clone, Copy)]
|
||||
pub enum SymKey<'a> {
|
||||
Pointer(&'a Ptr),
|
||||
Struct(FileId, Pos),
|
||||
FuncInst(ty::Func, ty::Tuple),
|
||||
MomizedCall(ty::Func),
|
||||
Decl(FileId, Ident),
|
||||
Array(&'a Array),
|
||||
}
|
||||
|
@ -539,6 +584,9 @@ struct Sig {
|
|||
|
||||
struct Func {
|
||||
file: FileId,
|
||||
name: Ident,
|
||||
base: Option<ty::Func>,
|
||||
computed: Option<ty::Id>,
|
||||
expr: ExprRef,
|
||||
sig: Option<Sig>,
|
||||
offset: Offset,
|
||||
|
@ -551,6 +599,9 @@ impl Default for Func {
|
|||
fn default() -> Self {
|
||||
Self {
|
||||
file: u32::MAX,
|
||||
name: 0,
|
||||
base: None,
|
||||
computed: None,
|
||||
expr: Default::default(),
|
||||
sig: None,
|
||||
offset: u32::MAX,
|
||||
|
@ -620,6 +671,7 @@ struct Field {
|
|||
#[derive(Default)]
|
||||
struct Struct {
|
||||
name: Ident,
|
||||
pos: Pos,
|
||||
file: FileId,
|
||||
size: Cell<Size>,
|
||||
align: Cell<u8>,
|
||||
|
@ -628,12 +680,12 @@ struct Struct {
|
|||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Hash)]
|
||||
struct Ptr {
|
||||
pub struct Ptr {
|
||||
base: ty::Id,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||
struct Array {
|
||||
pub struct Array {
|
||||
ty: ty::Id,
|
||||
len: ArrayLen,
|
||||
}
|
||||
|
@ -710,7 +762,7 @@ struct TypesTmp {
|
|||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct TypeIns {
|
||||
pub struct TypeIns {
|
||||
funcs: Vec<Func>,
|
||||
args: Vec<ty::Id>,
|
||||
globals: Vec<Global>,
|
||||
|
@ -734,7 +786,8 @@ 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
|
||||
.ins
|
||||
.structs
|
||||
.get(strct as usize + 1)
|
||||
.map_or(self.ins.fields.len(), |s| s.field_start as usize);
|
||||
start..end
|
||||
|
@ -751,7 +804,7 @@ impl Types {
|
|||
files: &[parser::Ast],
|
||||
) -> Option<ty::Id> {
|
||||
if let Ok(id) = id
|
||||
&& let Some(&ty) = self.syms.get(&SymKey::Decl(file, id))
|
||||
&& let Some(&ty) = self.syms.get(SymKey::Decl(file, id), &self.ins)
|
||||
{
|
||||
if let ty::Kind::Global(g) = ty.expand() {
|
||||
let g = &self.ins.globals[g as usize];
|
||||
|
@ -775,7 +828,7 @@ impl Types {
|
|||
self.ins.structs[s as usize].name = name;
|
||||
}
|
||||
|
||||
self.syms.insert(SymKey::Decl(file, name), ty);
|
||||
self.syms.insert(SymKey::Decl(file, name), ty, &self.ins);
|
||||
Some(ty)
|
||||
}
|
||||
|
||||
|
@ -806,29 +859,30 @@ impl Types {
|
|||
}
|
||||
Expr::Struct { pos, fields, packed, .. } => {
|
||||
let sym = SymKey::Struct(file, pos);
|
||||
if let Some(&ty) = self.syms.get(&sym) {
|
||||
if let Some(&ty) = self.syms.get(sym, &self.ins) {
|
||||
return Some(ty);
|
||||
}
|
||||
|
||||
let prev_tmp = self.ins.fields.len();
|
||||
let prev_tmp = self.tmp.fields.len();
|
||||
for field in fields.iter().filter_map(CommentOr::or) {
|
||||
let Some(ty) = self.ty(file, &field.ty, files) else {
|
||||
self.ins.fields.truncate(prev_tmp);
|
||||
self.tmp.fields.truncate(prev_tmp);
|
||||
return None;
|
||||
};
|
||||
self.ins.fields.push(Field { name: self.names.intern(field.name), ty });
|
||||
self.tmp.fields.push(Field { name: self.names.intern(field.name), ty });
|
||||
}
|
||||
|
||||
self.ins.structs.push(Struct {
|
||||
file,
|
||||
pos,
|
||||
field_start: self.ins.fields.len() as _,
|
||||
explicit_alignment: packed.then_some(1),
|
||||
..Default::default()
|
||||
});
|
||||
self.ins.fields.extend(self.ins.fields.drain(prev_tmp..));
|
||||
self.ins.fields.extend(self.tmp.fields.drain(prev_tmp..));
|
||||
|
||||
let ty = ty::Kind::Struct(self.ins.structs.len() as u32 - 1).compress();
|
||||
self.syms.insert(sym, ty);
|
||||
self.syms.insert(sym, ty, &self.ins);
|
||||
ty
|
||||
}
|
||||
_ => return None,
|
||||
|
@ -841,7 +895,7 @@ impl Types {
|
|||
emit(to, instrs::jal(reg::RET_ADDR, reg::ZERO, 0));
|
||||
emit(to, instrs::tx());
|
||||
let exe = self.dump_reachable(0, to);
|
||||
Reloc::new(HEADER_SIZE, 3, 4).apply_jump(to, self.funcs[0].offset, 0);
|
||||
Reloc::new(HEADER_SIZE, 3, 4).apply_jump(to, self.ins.funcs[0].offset, 0);
|
||||
|
||||
unsafe { *to.as_mut_ptr().cast::<AbleOsExecutableHeader>() = exe }
|
||||
}
|
||||
|
@ -849,13 +903,13 @@ impl Types {
|
|||
fn dump_reachable(&mut self, from: ty::Func, to: &mut Vec<u8>) -> AbleOsExecutableHeader {
|
||||
debug_assert!(self.tmp.frontier.is_empty());
|
||||
debug_assert!(self.tmp.funcs.is_empty());
|
||||
debug_assert!(self.ins.globals.is_empty());
|
||||
debug_assert!(self.tmp.globals.is_empty());
|
||||
|
||||
self.tmp.frontier.push(ty::Kind::Func(from).compress());
|
||||
while let Some(itm) = self.tmp.frontier.pop() {
|
||||
match itm.expand() {
|
||||
ty::Kind::Func(func) => {
|
||||
let fuc = &mut self.funcs[func as usize];
|
||||
let fuc = &mut self.ins.funcs[func as usize];
|
||||
if task::is_done(fuc.offset) {
|
||||
continue;
|
||||
}
|
||||
|
@ -869,21 +923,21 @@ impl Types {
|
|||
continue;
|
||||
}
|
||||
glb.offset = 0;
|
||||
self.ins.globals.push(glob);
|
||||
self.tmp.globals.push(glob);
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
for &func in &self.tmp.funcs {
|
||||
let fuc = &mut self.funcs[func as usize];
|
||||
let fuc = &mut self.ins.funcs[func as usize];
|
||||
fuc.offset = to.len() as _;
|
||||
to.extend(&fuc.code);
|
||||
}
|
||||
|
||||
let code_length = to.len();
|
||||
|
||||
for global in self.ins.globals.drain(..) {
|
||||
for global in self.tmp.globals.drain(..) {
|
||||
let global = &mut self.ins.globals[global as usize];
|
||||
global.offset = to.len() as _;
|
||||
to.extend(&global.data);
|
||||
|
@ -892,10 +946,10 @@ impl Types {
|
|||
let data_length = to.len() - code_length;
|
||||
|
||||
for func in self.tmp.funcs.drain(..) {
|
||||
let fuc = &self.funcs[func as usize];
|
||||
let fuc = &self.ins.funcs[func as usize];
|
||||
for rel in &fuc.relocs {
|
||||
let offset = match rel.target.expand() {
|
||||
ty::Kind::Func(fun) => self.funcs[fun as usize].offset,
|
||||
ty::Kind::Func(fun) => self.ins.funcs[fun as usize].offset,
|
||||
ty::Kind::Global(glo) => self.ins.globals[glo as usize].offset,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
@ -923,6 +977,7 @@ impl Types {
|
|||
) -> Result<(), hbbytecode::DisasmError<'a>> {
|
||||
use instrs::DisasmItem;
|
||||
let functions = self
|
||||
.ins
|
||||
.funcs
|
||||
.iter()
|
||||
.filter(|f| task::is_done(f.offset))
|
||||
|
@ -962,14 +1017,25 @@ impl Types {
|
|||
}
|
||||
|
||||
fn make_ptr_low(&mut self, base: ty::Id) -> ty::Ptr {
|
||||
self.syms
|
||||
.entry(SymKey::Pointer(base))
|
||||
.or_insert_with(|| {
|
||||
self.ins.ptrs.push(Ptr { base });
|
||||
ty::Kind::Ptr(self.ins.ptrs.len() as u32 - 1).compress()
|
||||
})
|
||||
.expand()
|
||||
.inner()
|
||||
let ptr = Ptr { base };
|
||||
let (entry, hash) = self.syms.entry(SymKey::Pointer(&ptr), &self.ins);
|
||||
match entry {
|
||||
hash_map::RawEntryMut::Occupied(o) => o.get_key_value().0.value,
|
||||
hash_map::RawEntryMut::Vacant(v) => {
|
||||
self.ins.ptrs.push(ptr);
|
||||
v.insert(
|
||||
ctx_map::Key {
|
||||
value: ty::Kind::Ptr(self.ins.ptrs.len() as u32 - 1).compress(),
|
||||
hash,
|
||||
},
|
||||
(),
|
||||
)
|
||||
.0
|
||||
.value
|
||||
}
|
||||
}
|
||||
.expand()
|
||||
.inner()
|
||||
}
|
||||
|
||||
fn make_array(&mut self, ty: ty::Id, len: ArrayLen) -> ty::Id {
|
||||
|
@ -978,13 +1044,32 @@ impl Types {
|
|||
|
||||
fn make_array_low(&mut self, ty: ty::Id, len: ArrayLen) -> ty::Slice {
|
||||
self.syms
|
||||
.entry(SymKey::Array(ty, len))
|
||||
.or_insert_with(|| {
|
||||
self.ins.arrays.push(Array { ty, len });
|
||||
ty::Kind::Slice(self.ins.arrays.len() as u32 - 1).compress()
|
||||
.get_or_insert(SymKey::Array(&Array { ty, len }), &mut self.ins, |ins| {
|
||||
ins.arrays.push(Array { ty, len });
|
||||
ty::Kind::Slice(ins.arrays.len() as u32 - 1).compress()
|
||||
})
|
||||
.expand()
|
||||
.inner()
|
||||
|
||||
//let array = Array { ty, len };
|
||||
//let (entry, hash) = self.syms.entry(SymKey::Array(&array), &self.ins);
|
||||
//match entry {
|
||||
// hash_map::RawEntryMut::Occupied(o) => o.get_key_value().0.value,
|
||||
// hash_map::RawEntryMut::Vacant(v) => {
|
||||
// self.ins.arrays.push(array);
|
||||
// v.insert(
|
||||
// ctx_map::Key {
|
||||
// value: ty::Kind::Slice(self.ins.ptrs.len() as u32 - 1).compress(),
|
||||
// hash,
|
||||
// },
|
||||
// (),
|
||||
// )
|
||||
// .0
|
||||
// .value
|
||||
// }
|
||||
//}
|
||||
//.expand()
|
||||
//.inner()
|
||||
}
|
||||
|
||||
fn size_of(&self, ty: ty::Id) -> Size {
|
||||
|
@ -1082,7 +1167,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 field = &tys.ins.fields[self.ins.fields.next()?];
|
||||
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);
|
||||
self.offset = (self.offset + align - 1) & !(align - 1);
|
||||
|
|
|
@ -20,9 +20,7 @@ use {
|
|||
cell::RefCell,
|
||||
convert::identity,
|
||||
fmt::{self, Debug, Display, Write},
|
||||
format_args as fa,
|
||||
hash::BuildHasher,
|
||||
mem, ops, usize,
|
||||
format_args as fa, mem, ops,
|
||||
},
|
||||
hashbrown::hash_map,
|
||||
regalloc2::VReg,
|
||||
|
@ -1033,7 +1031,7 @@ impl Codegen {
|
|||
}
|
||||
|
||||
fn make_func_reachable(&mut self, func: ty::Func) {
|
||||
let fuc = &mut self.tys.funcs[func as usize];
|
||||
let fuc = &mut self.tys.ins.funcs[func as usize];
|
||||
if fuc.offset == u32::MAX {
|
||||
fuc.offset = task::id(self.tasks.len() as _);
|
||||
self.tasks.push(Some(FTask { file: fuc.file, id: func }));
|
||||
|
@ -1237,7 +1235,7 @@ impl Codegen {
|
|||
|
||||
self.make_func_reachable(func);
|
||||
|
||||
let fuc = &self.tys.funcs[func as usize];
|
||||
let fuc = &self.tys.ins.funcs[func as usize];
|
||||
let sig = fuc.sig.expect("TODO: generic functions");
|
||||
let ast = self.files[fuc.file as usize].clone();
|
||||
let Expr::BinOp { right: &Expr::Closure { args: cargs, .. }, .. } =
|
||||
|
@ -1259,7 +1257,7 @@ impl Codegen {
|
|||
|
||||
let mut inps = Vc::from([self.ci.ctrl]);
|
||||
for ((arg, carg), tyx) in args.iter().zip(cargs).zip(sig.args.range()) {
|
||||
let ty = self.tys.args[tyx];
|
||||
let ty = self.tys.ins.args[tyx];
|
||||
if self.tys.size_of(ty) == 0 {
|
||||
continue;
|
||||
}
|
||||
|
@ -1639,7 +1637,7 @@ impl Codegen {
|
|||
}
|
||||
|
||||
fn emit_func(&mut self, FTask { file, id }: FTask) {
|
||||
let func = &mut self.tys.funcs[id as usize];
|
||||
let func = &mut self.tys.ins.funcs[id as usize];
|
||||
func.offset = u32::MAX - 1;
|
||||
debug_assert!(func.file == file);
|
||||
let sig = func.sig.unwrap();
|
||||
|
@ -1676,7 +1674,7 @@ impl Codegen {
|
|||
|
||||
let mut sig_args = sig.args.range();
|
||||
for (arg, index) in args.iter().zip(0u32..) {
|
||||
let ty = self.tys.args[sig_args.next().unwrap()];
|
||||
let ty = self.tys.ins.args[sig_args.next().unwrap()];
|
||||
let value = self.ci.nodes.new_node(ty, Kind::Arg { index }, [VOID]);
|
||||
self.ci.nodes.lock(value);
|
||||
let sym = parser::find_symbol(&ast.symbols, arg.id);
|
||||
|
@ -1802,8 +1800,8 @@ impl Codegen {
|
|||
self.ci.emit(instrs::jala(reg::ZERO, reg::RET_ADDR, 0));
|
||||
}
|
||||
|
||||
self.tys.funcs[id as usize].code.append(&mut self.ci.code);
|
||||
self.tys.funcs[id as usize].relocs.append(&mut self.ci.relocs);
|
||||
self.tys.ins.funcs[id as usize].code.append(&mut self.ci.code);
|
||||
self.tys.ins.funcs[id as usize].relocs.append(&mut self.ci.relocs);
|
||||
self.ci.nodes.clear();
|
||||
self.ci.filled.clear();
|
||||
self.pool.cis.push(core::mem::replace(&mut self.ci, prev_ci));
|
||||
|
@ -2012,9 +2010,9 @@ impl Codegen {
|
|||
};
|
||||
|
||||
let key = SymKey::Decl(file, ident);
|
||||
if let Some(existing) = self.tys.syms.get(&key) {
|
||||
if let Some(existing) = self.tys.syms.get(key, &self.tys.ins) {
|
||||
if let ty::Kind::Func(id) = existing.expand()
|
||||
&& let func = &mut self.tys.funcs[id as usize]
|
||||
&& let func = &mut self.tys.ins.funcs[id as usize]
|
||||
&& let Err(idx) = task::unpack(func.offset)
|
||||
&& idx < self.tasks.len()
|
||||
{
|
||||
|
@ -2028,19 +2026,20 @@ impl Codegen {
|
|||
let prev_file = core::mem::replace(&mut self.ci.file, file);
|
||||
let sym = match expr {
|
||||
Expr::BinOp {
|
||||
left: Expr::Ident { .. },
|
||||
left: &Expr::Ident { id, .. },
|
||||
op: TokenKind::Decl,
|
||||
right: &Expr::Closure { pos, args, ret, .. },
|
||||
} => {
|
||||
let func = Func {
|
||||
file,
|
||||
name: id,
|
||||
sig: '_b: {
|
||||
let arg_base = self.tys.args.len();
|
||||
let arg_base = self.tys.ins.args.len();
|
||||
for arg in args {
|
||||
let sym = parser::find_symbol(&f.symbols, arg.id);
|
||||
assert!(sym.flags & idfl::COMPTIME == 0, "TODO");
|
||||
let ty = self.ty(&arg.ty);
|
||||
self.tys.args.push(ty);
|
||||
self.tys.ins.args.push(ty);
|
||||
}
|
||||
|
||||
let Some(args) = self.pack_args(arg_base) else {
|
||||
|
@ -2061,8 +2060,8 @@ impl Codegen {
|
|||
..Default::default()
|
||||
};
|
||||
|
||||
let id = self.tys.funcs.len() as _;
|
||||
self.tys.funcs.push(func);
|
||||
let id = self.tys.ins.funcs.len() as _;
|
||||
self.tys.ins.funcs.push(func);
|
||||
|
||||
ty::Kind::Func(id)
|
||||
}
|
||||
|
@ -2074,7 +2073,7 @@ impl Codegen {
|
|||
e => unimplemented!("{e:#?}"),
|
||||
};
|
||||
self.ci.file = prev_file;
|
||||
self.tys.syms.insert(key, sym.compress());
|
||||
self.tys.syms.insert(key, sym.compress(), &self.tys.ins);
|
||||
sym
|
||||
}
|
||||
|
||||
|
@ -2153,15 +2152,15 @@ impl Codegen {
|
|||
}
|
||||
|
||||
fn pack_args(&mut self, arg_base: usize) -> Option<ty::Tuple> {
|
||||
let needle = &self.tys.args[arg_base..];
|
||||
let needle = &self.tys.ins.args[arg_base..];
|
||||
if needle.is_empty() {
|
||||
return Some(ty::Tuple::empty());
|
||||
}
|
||||
let len = needle.len();
|
||||
// FIXME: maybe later when this becomes a bottleneck we use more
|
||||
// efficient search (SIMD?, indexing?)
|
||||
let sp = self.tys.args.windows(needle.len()).position(|val| val == needle).unwrap();
|
||||
self.tys.args.truncate((sp + needle.len()).max(arg_base));
|
||||
let sp = self.tys.ins.args.windows(needle.len()).position(|val| val == needle).unwrap();
|
||||
self.tys.ins.args.truncate((sp + needle.len()).max(arg_base));
|
||||
ty::Tuple::new(sp, len)
|
||||
}
|
||||
|
||||
|
@ -2397,7 +2396,7 @@ impl<'a> Function<'a> {
|
|||
for (arg, ti) in
|
||||
self.nodes[VOID].clone().outputs.into_iter().skip(2).zip(self.sig.args.range())
|
||||
{
|
||||
let ty = self.tys.args[ti];
|
||||
let ty = self.tys.ins.args[ti];
|
||||
match self.tys.size_of(ty) {
|
||||
0 => continue,
|
||||
1..=8 => {
|
||||
|
@ -2446,7 +2445,7 @@ impl<'a> Function<'a> {
|
|||
self.nodes[nid].ralloc_backref = self.nodes[prev].ralloc_backref;
|
||||
let mut ops = vec![];
|
||||
|
||||
let fuc = self.tys.funcs[func as usize].sig.unwrap();
|
||||
let fuc = self.tys.ins.funcs[func as usize].sig.unwrap();
|
||||
if self.tys.size_of(fuc.ret) != 0 {
|
||||
self.def_nid(nid);
|
||||
ops.push(regalloc2::Operand::reg_fixed_def(
|
||||
|
@ -2457,7 +2456,7 @@ impl<'a> Function<'a> {
|
|||
|
||||
let mut parama = self.tys.parama(fuc.ret);
|
||||
for (&(mut i), ti) in node.inputs[1..].iter().zip(fuc.args.range()) {
|
||||
let ty = self.tys.args[ti];
|
||||
let ty = self.tys.ins.args[ti];
|
||||
loop {
|
||||
match self.nodes[i].kind {
|
||||
Kind::Stre { .. } => i = self.nodes[i].inputs[2],
|
||||
|
|
Loading…
Reference in a new issue