making compiler a bit smarter about evaluating types (more shortcuts)

This commit is contained in:
Jakub Doka 2024-10-01 17:43:15 +02:00
parent d293e02f62
commit b2254e9820
No known key found for this signature in database
GPG key ID: C6E9A89936B8C143
4 changed files with 149 additions and 93 deletions

View file

@ -736,9 +736,17 @@ impl Codegen {
fn build_struct( fn build_struct(
&mut self, &mut self,
file: FileId, file: FileId,
pos: Option<Pos>,
explicit_alignment: Option<u8>, explicit_alignment: Option<u8>,
fields: &[CommentOr<StructField>], fields: &[CommentOr<StructField>],
) -> ty::Struct { ) -> 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)
{
return ty.expand().inner();
}
let prev_tmp = self.tys.fields_tmp.len(); let prev_tmp = self.tys.fields_tmp.len();
for sf in fields.iter().filter_map(CommentOr::or) { for sf in fields.iter().filter_map(CommentOr::or) {
let f = Field { name: self.tys.field_names.intern(sf.name), ty: self.ty(&sf.ty) }; let f = Field { name: self.tys.field_names.intern(sf.name), ty: self.ty(&sf.ty) };
@ -752,6 +760,12 @@ impl Codegen {
}); });
self.tys.fields.extend(self.tys.fields_tmp.drain(prev_tmp..)); self.tys.fields.extend(self.tys.fields_tmp.drain(prev_tmp..));
if let Some(sym) = sym {
self.tys
.syms
.insert(sym, ty::Kind::Struct(self.tys.structs.len() as u32 - 1).compress());
}
self.tys.structs.len() as u32 - 1 self.tys.structs.len() as u32 - 1
} }
@ -759,11 +773,12 @@ impl Codegen {
use {Expr as E, TokenKind as T}; use {Expr as E, TokenKind as T};
let value = match *expr { let value = match *expr {
E::Mod { id, .. } => Some(Value::ty(ty::Kind::Module(id).compress())), E::Mod { id, .. } => Some(Value::ty(ty::Kind::Module(id).compress())),
E::Struct { captured, packed, fields, .. } => { E::Struct { captured, packed, fields, pos, .. } => {
if captured.is_empty() { if captured.is_empty() {
Some(Value::ty( Some(Value::ty(
ty::Kind::Struct(self.build_struct( ty::Kind::Struct(self.build_struct(
self.ci.file, self.ci.file,
Some(pos),
packed.then_some(1), packed.then_some(1),
fields, fields,
)) ))
@ -902,7 +917,7 @@ impl Codegen {
self.ci.file = prev_file; self.ci.file = prev_file;
self.ci.ret = prev_ret; self.ci.ret = prev_ret;
let mut vars = std::mem::take(&mut self.ci.vars); let mut vars = core::mem::take(&mut self.ci.vars);
for var in vars.drain(scope..) { for var in vars.drain(scope..) {
self.ci.free_loc(var.value.loc); self.ci.free_loc(var.value.loc);
} }
@ -1204,7 +1219,7 @@ impl Codegen {
ty::Kind::Builtin(ty::TYPE) => { ty::Kind::Builtin(ty::TYPE) => {
self.ci.free_loc(tal.loc); self.ci.free_loc(tal.loc);
self.ci.revert(checkpoint); self.ci.revert(checkpoint);
match ty::Kind::from_ty(self.ty(target)) { match self.ty(target).expand() {
ty::Kind::Module(idx) => { ty::Kind::Module(idx) => {
match self.find_or_declare(target.pos(), idx, Err(field), "") { match self.find_or_declare(target.pos(), idx, Err(field), "") {
ty::Kind::Global(idx) => self.handle_global(idx), ty::Kind::Global(idx) => self.handle_global(idx),
@ -1393,17 +1408,12 @@ impl Codegen {
let loc = var.value.loc.as_ref(); let loc = var.value.loc.as_ref();
Some(Value { ty: self.ci.vars[var_index].value.ty, loc }) Some(Value { ty: self.ci.vars[var_index].value.ty, loc })
} }
E::Ident { id, name, .. } => match self E::Ident { id, name, .. } => {
.tys match self.find_or_declare(ident::pos(id), self.ci.file, Ok(id), name) {
.syms
.get(&SymKey { ident: id, file: self.ci.file })
.copied()
.map(ty::Kind::from_ty)
.unwrap_or_else(|| self.find_or_declare(ident::pos(id), self.ci.file, Ok(id), name))
{
ty::Kind::Global(id) => self.handle_global(id), ty::Kind::Global(id) => self.handle_global(id),
tk => Some(Value::ty(tk.compress())), tk => Some(Value::ty(tk.compress())),
}, }
}
E::Return { pos, val, .. } => { E::Return { pos, val, .. } => {
let size = self.ci.ret.map_or(17, |ty| self.tys.size_of(ty)); let size = self.ci.ret.map_or(17, |ty| self.tys.size_of(ty));
let loc = match size { let loc = match size {
@ -1767,7 +1777,7 @@ impl Codegen {
let args = self.pack_args(pos, arg_base); let args = self.pack_args(pos, arg_base);
let ret = self.ty(ret); let ret = self.ty(ret);
let sym = SymKey { file: !args.repr(), ident: ty::Kind::Func(*func).compress().repr() }; let sym = SymKey::FuncInst(*func, args);
let ct = || { let ct = || {
let func_id = self.tys.funcs.len(); let func_id = self.tys.funcs.len();
let fuc = &self.tys.funcs[*func as usize]; let fuc = &self.tys.funcs[*func as usize];
@ -2125,7 +2135,7 @@ impl Codegen {
self.report(body.pos(), "expected all paths in the fucntion to return"); self.report(body.pos(), "expected all paths in the fucntion to return");
} }
let mut vars = std::mem::take(&mut self.ci.vars); let mut vars = core::mem::take(&mut self.ci.vars);
for var in vars.drain(..) { for var in vars.drain(..) {
self.ci.free_loc(var.value.loc); self.ci.free_loc(var.value.loc);
} }
@ -2350,9 +2360,18 @@ impl Codegen {
} }
fn ty(&mut self, expr: &Expr) -> ty::Id { fn ty(&mut self, expr: &Expr) -> ty::Id {
self.tys let ty = self.tys.ty(self.ci.file, expr, &self.files);
.ty(self.ci.file, expr, &self.files) let evaled_ty = ty::Id::from(self.eval_const(expr, ty::TYPE));
.unwrap_or_else(|| ty::Id::from(self.eval_const(expr, ty::TYPE))) if let Some(ty) = ty {
debug_assert_eq!(
ty,
evaled_ty,
"{} {}",
self.ty_display(ty),
self.ty_display(evaled_ty)
);
}
evaled_ty
} }
fn read_trap(addr: u64) -> Option<&'static trap::Trap> { fn read_trap(addr: u64) -> Option<&'static trap::Trap> {
@ -2395,15 +2414,19 @@ impl Codegen {
}); });
} }
let stru = let stru = ty::Kind::Struct(self.build_struct(
ty::Kind::Struct(self.build_struct(self.ci.file, packed.then_some(1), fields)) self.ci.file,
packed.then_some(1),
None,
fields,
))
.compress(); .compress();
self.ci.vars.truncate(prev_len); self.ci.vars.truncate(prev_len);
self.ct.vm.write_reg(1, stru.repr() as u64); self.ct.vm.write_reg(1, stru.repr() as u64);
debug_assert_ne!(stru.expand().inner(), 1); debug_assert_ne!(stru.expand().inner(), 1);
} }
trap::Trap::MomizedCall(trap::MomizedCall { func }) => { trap::Trap::MomizedCall(trap::MomizedCall { func }) => {
let sym = SymKey { file: u32::MAX, ident: ty::Kind::Func(func).compress().repr() }; let sym = SymKey::MomizedCall(func);
if let Some(&ty) = self.tys.syms.get(&sym) { if let Some(&ty) = self.tys.syms.get(&sym) {
self.ct.vm.write_reg(1, ty.repr()); self.ct.vm.write_reg(1, ty.repr());
} else { } else {
@ -2426,6 +2449,10 @@ impl Codegen {
lit_name: &str, lit_name: &str,
) -> ty::Kind { ) -> ty::Kind {
log::trace!("find_or_declare: {lit_name} {file}"); log::trace!("find_or_declare: {lit_name} {file}");
if let Some(ty) = self.tys.find_type(file, name, &self.files) {
return ty.expand();
}
let f = self.files[file as usize].clone(); let f = self.files[file as usize].clone();
let Some((expr, ident)) = f.find_decl(name) else { let Some((expr, ident)) = f.find_decl(name) else {
match name { match name {
@ -2435,7 +2462,8 @@ impl Codegen {
} }
}; };
if let Some(existing) = self.tys.syms.get(&SymKey { file, ident }) { let key = SymKey::Decl(file, ident);
if let Some(existing) = self.tys.syms.get(&key) {
if let ty::Kind::Func(id) = existing.expand() if let ty::Kind::Func(id) = existing.expand()
&& let func = &mut self.tys.funcs[id as usize] && let func = &mut self.tys.funcs[id as usize]
&& let Err(idx) = task::unpack(func.offset) && let Err(idx) = task::unpack(func.offset)
@ -2517,7 +2545,7 @@ impl Codegen {
e => unimplemented!("{e:#?}"), e => unimplemented!("{e:#?}"),
}; };
self.ci.file = prev_file; self.ci.file = prev_file;
self.tys.syms.insert(SymKey { ident, file }, sym.compress()); self.tys.syms.insert(key, sym.compress());
sym sym
} }
@ -2552,7 +2580,7 @@ impl Codegen {
self.ci.free_loc(ret.loc); self.ci.free_loc(ret.loc);
Global { ty: ret.ty, file, name, data, ..Default::default() } Global { ty: ret.ty, file, name, data, ast: ExprRef::new(expr), ..Default::default() }
} }
fn ct_eval<T, E>( fn ct_eval<T, E>(
@ -2579,8 +2607,8 @@ impl Codegen {
let last_fn = self.tys.funcs.len(); let last_fn = self.tys.funcs.len();
self.tys.funcs.push(Default::default()); self.tys.funcs.push(Default::default());
self.tys.funcs[last_fn].code = std::mem::take(&mut self.ci.code); self.tys.funcs[last_fn].code = core::mem::take(&mut self.ci.code);
self.tys.funcs[last_fn].relocs = std::mem::take(&mut self.ci.relocs); self.tys.funcs[last_fn].relocs = core::mem::take(&mut self.ci.relocs);
if is_on_stack { if is_on_stack {
let size = let size =

View file

@ -31,12 +31,12 @@ use {
self::{ self::{
ident::Ident, ident::Ident,
lexer::TokenKind, lexer::TokenKind,
parser::{CommentOr, Expr, ExprRef, FileId}, parser::{CommentOr, Expr, ExprRef, FileId, Pos},
son::reg, son::reg,
ty::ArrayLen, ty::ArrayLen,
}, },
alloc::{collections::BTreeMap, string::String, vec::Vec}, alloc::{collections::BTreeMap, string::String, vec::Vec},
core::{cell::Cell, fmt::Display, hash::BuildHasher, ops::Range}, core::{cell::Cell, fmt::Display, hash::BuildHasher, ops::Range, usize},
hashbrown::hash_map, hashbrown::hash_map,
hbbytecode as instrs, hbbytecode as instrs,
}; };
@ -124,7 +124,7 @@ mod ty {
lexer::TokenKind, lexer::TokenKind,
parser::{self}, parser::{self},
}, },
core::{num::NonZeroU32, ops::Range}, core::{num::NonZeroU32, ops::Range, usize},
}; };
pub type ArrayLen = u32; pub type ArrayLen = u32;
@ -137,7 +137,7 @@ mod ty {
pub type Module = u32; pub type Module = u32;
pub type Slice = u32; pub type Slice = u32;
#[derive(Clone, Copy)] #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub struct Tuple(pub u32); pub struct Tuple(pub u32);
impl Tuple { impl Tuple {
@ -384,7 +384,7 @@ mod ty {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
use Kind as TK; use Kind as TK;
match TK::from_ty(self.ty) { match TK::from_ty(self.ty) {
TK::Module(idx) => write!(f, "module{}", idx), TK::Module(idx) => write!(f, "@use({:?})[{}]", self.files[idx as usize].path, idx),
TK::Builtin(ty) => write!(f, "{}", to_str(ty)), TK::Builtin(ty) => write!(f, "{}", to_str(ty)),
TK::Ptr(ty) => { TK::Ptr(ty) => {
write!(f, "^{}", self.rety(self.tys.ptrs[ty as usize].base)) write!(f, "^{}", self.rety(self.tys.ptrs[ty as usize].base))
@ -443,15 +443,14 @@ fn emit(out: &mut Vec<u8>, (len, instr): EncodedInstr) {
} }
#[derive(PartialEq, Eq, Hash, Debug)] #[derive(PartialEq, Eq, Hash, Debug)]
struct SymKey { enum SymKey {
file: u32, Pointer(ty::Id),
ident: u32, Struct(FileId, Pos),
} FuncInst(ty::Func, ty::Tuple),
MomizedCall(ty::Func),
impl SymKey { Decl(FileId, Ident),
pub fn pointer_to(ty: ty::Id) -> Self { Slice(ty::Id),
Self { file: u32::MAX, ident: ty.repr() } Array(ty::Id, ArrayLen),
}
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
@ -492,6 +491,7 @@ struct Global {
file: FileId, file: FileId,
name: Ident, name: Ident,
ty: ty::Id, ty: ty::Id,
ast: ExprRef,
offset: Offset, offset: Offset,
data: Vec<u8>, data: Vec<u8>,
} }
@ -502,6 +502,7 @@ impl Default for Global {
ty: Default::default(), ty: Default::default(),
offset: u32::MAX, offset: u32::MAX,
data: Default::default(), data: Default::default(),
ast: ExprRef::default(),
file: u32::MAX, file: u32::MAX,
name: u32::MAX, name: u32::MAX,
} }
@ -690,35 +691,68 @@ impl Types {
&self.fields[self.struct_field_range(strct)] &self.fields[self.struct_field_range(strct)]
} }
fn find_type(
&mut self,
file: FileId,
id: Result<Ident, &str>,
files: &[parser::Ast],
) -> Option<ty::Id> {
if let Ok(id) = id
&& let Some(&ty) = self.syms.get(&SymKey::Decl(file, id))
{
if let ty::Kind::Global(g) = ty.expand() {
let g = &self.globals[g as usize];
if g.ty == ty::Id::TYPE {
return Some(ty::Id::from(
u32::from_ne_bytes(*g.data.first_chunk().unwrap()) as u64
));
}
}
return Some(ty);
}
let f = &files[file as usize];
let (Expr::BinOp { left, right, .. }, name) = f.find_decl(id)? else { unreachable!() };
let ty = left
.find_pattern_path(name, right, |right| self.ty(file, right, files))
.unwrap_or_else(|_| unreachable!())?;
if let ty::Kind::Struct(s) = ty.expand() {
self.structs[s as usize].name = name;
}
self.syms.insert(SymKey::Decl(file, name), ty);
Some(ty)
}
/// returns none if comptime eval is required /// returns none if comptime eval is required
fn ty(&mut self, file: FileId, expr: &Expr, files: &[parser::Ast]) -> Option<ty::Id> { fn ty(&mut self, file: FileId, expr: &Expr, files: &[parser::Ast]) -> Option<ty::Id> {
Some(match *expr { Some(match *expr {
Expr::Mod { id, .. } => ty::Kind::Module(id).compress(),
Expr::UnOp { op: TokenKind::Xor, val, .. } => { Expr::UnOp { op: TokenKind::Xor, val, .. } => {
let base = self.ty(file, val, files)?; let base = self.ty(file, val, files)?;
self.make_ptr(base) self.make_ptr(base)
} }
Expr::Ident { id, .. } if ident::is_null(id) => id.into(), Expr::Ident { id, .. } if ident::is_null(id) => id.into(),
Expr::Ident { id, .. } => { Expr::Ident { id, .. } => self.find_type(file, Ok(id), files)?,
let f = &files[file as usize]; Expr::Field { target, name, .. } => {
let (Expr::BinOp { right, .. }, name) = f.find_decl(Ok(id))? else { let ty::Kind::Module(file) = self.ty(file, target, files)?.expand() else {
unreachable!() return None;
}; };
let ty = self.ty(file, right, files)?;
if let ty::Kind::Struct(s) = ty.expand() { self.find_type(file, Err(name), files)?
self.structs[s as usize].name = name;
}
ty
} }
Expr::Slice { size: None, item, .. } => { Expr::Slice { size: None, item, .. } => {
let ty = self.ty(file, item, files)?; let ty = self.ty(file, item, files)?;
self.make_array(ty, ArrayLen::MAX) self.make_array(ty, ArrayLen::MAX)
} }
//Expr::Slice { size: Some(&Expr::Number { value, .. }), item, .. } => { Expr::Slice { size: Some(&Expr::Number { value, .. }), item, .. } => {
// let ty = self.ty(file, item, files)?; let ty = self.ty(file, item, files)?;
// self.make_array(ty, value as _) self.make_array(ty, value as _)
//} }
Expr::Struct { pos, fields, packed, .. } => { Expr::Struct { pos, fields, packed, .. } => {
let sym = SymKey { file, ident: pos }; let sym = SymKey::Struct(file, pos);
if let Some(&ty) = self.syms.get(&sym) { if let Some(&ty) = self.syms.get(&sym) {
return Some(ty); return Some(ty);
} }
@ -875,10 +909,8 @@ impl Types {
} }
fn make_ptr_low(&mut self, base: ty::Id) -> ty::Ptr { fn make_ptr_low(&mut self, base: ty::Id) -> ty::Ptr {
let id = SymKey::pointer_to(base);
self.syms self.syms
.entry(id) .entry(SymKey::Pointer(base))
.or_insert_with(|| { .or_insert_with(|| {
self.ptrs.push(Ptr { base }); self.ptrs.push(Ptr { base });
ty::Kind::Ptr(self.ptrs.len() as u32 - 1).compress() ty::Kind::Ptr(self.ptrs.len() as u32 - 1).compress()
@ -892,16 +924,8 @@ impl Types {
} }
fn make_array_low(&mut self, ty: ty::Id, len: ArrayLen) -> ty::Slice { fn make_array_low(&mut self, ty: ty::Id, len: ArrayLen) -> ty::Slice {
let id = SymKey {
file: match len {
ArrayLen::MAX => ArrayLen::MAX - 1,
len => ArrayLen::MAX - len - 2,
},
ident: ty.repr(),
};
self.syms self.syms
.entry(id) .entry(SymKey::Array(ty, len))
.or_insert_with(|| { .or_insert_with(|| {
self.arrays.push(Array { ty, len }); self.arrays.push(Array { ty, len });
ty::Kind::Slice(self.arrays.len() as u32 - 1).compress() ty::Kind::Slice(self.arrays.len() as u32 - 1).compress()

View file

@ -7,12 +7,12 @@ use {
core::{ core::{
cell::UnsafeCell, cell::UnsafeCell,
fmt::{self}, fmt::{self},
intrinsics::unlikely,
marker::PhantomData, marker::PhantomData,
ops::Deref, ops::Deref,
ptr::NonNull, ptr::NonNull,
sync::atomic::AtomicUsize, sync::atomic::AtomicUsize,
}, },
std::intrinsics::unlikely,
}; };
pub type Pos = u32; pub type Pos = u32;
@ -54,6 +54,7 @@ pub struct Symbol {
struct ScopeIdent { struct ScopeIdent {
ident: Ident, ident: Ident,
declared: bool, declared: bool,
ordered: bool,
flags: IdentFlags, flags: IdentFlags,
} }
@ -195,7 +196,9 @@ impl<'a, 'b> Parser<'a, 'b> {
fn declare_rec(&mut self, expr: &Expr, top_level: bool) { fn declare_rec(&mut self, expr: &Expr, top_level: bool) {
match *expr { match *expr {
Expr::Ident { pos, id, is_first, .. } => self.declare(pos, id, is_first || top_level), Expr::Ident { pos, id, is_first, .. } => {
self.declare(pos, id, !top_level, is_first || top_level)
}
Expr::Ctor { fields, .. } => { Expr::Ctor { fields, .. } => {
for CtorField { value, .. } in fields { for CtorField { value, .. } in fields {
self.declare_rec(value, top_level) self.declare_rec(value, top_level)
@ -205,7 +208,7 @@ impl<'a, 'b> Parser<'a, 'b> {
} }
} }
fn declare(&mut self, pos: Pos, id: Ident, valid_order: bool) { fn declare(&mut self, pos: Pos, id: Ident, ordered: bool, valid_order: bool) {
if !valid_order { if !valid_order {
self.report( self.report(
pos, pos,
@ -223,6 +226,8 @@ impl<'a, 'b> Parser<'a, 'b> {
format_args!("redeclaration of identifier: {}", self.lexer.slice(ident::range(id))), format_args!("redeclaration of identifier: {}", self.lexer.slice(ident::range(id))),
) )
} }
self.idents[index].ordered = ordered;
} }
fn resolve_ident(&mut self, token: Token) -> (Ident, bool) { fn resolve_ident(&mut self, token: Token) -> (Ident, bool) {
@ -242,13 +247,18 @@ impl<'a, 'b> Parser<'a, 'b> {
Some((i, elem)) => (i, elem, false), Some((i, elem)) => (i, elem, false),
None => { None => {
let id = ident::new(token.start, name.len() as _); let id = ident::new(token.start, name.len() as _);
self.idents.push(ScopeIdent { ident: id, declared: false, flags: 0 }); self.idents.push(ScopeIdent {
ident: id,
declared: false,
ordered: false,
flags: 0,
});
(self.idents.len() - 1, self.idents.last_mut().unwrap(), true) (self.idents.len() - 1, self.idents.last_mut().unwrap(), true)
} }
}; };
id.flags |= idfl::COMPTIME * is_ct as u32; id.flags |= idfl::COMPTIME * is_ct as u32;
if id.declared && self.ns_bound > i { if id.declared && id.ordered && self.ns_bound > i {
id.flags |= idfl::COMPTIME; id.flags |= idfl::COMPTIME;
self.captured.push(id.ident); self.captured.push(id.ident);
} }
@ -374,7 +384,7 @@ impl<'a, 'b> Parser<'a, 'b> {
self.collect_list(T::Comma, T::RParen, |s| { self.collect_list(T::Comma, T::RParen, |s| {
let name = s.advance_ident(); let name = s.advance_ident();
let (id, _) = s.resolve_ident(name); let (id, _) = s.resolve_ident(name);
s.declare(name.start, id, true); s.declare(name.start, id, true, true);
s.expect_advance(T::Colon); s.expect_advance(T::Colon);
Arg { Arg {
pos: name.start, pos: name.start,
@ -839,17 +849,14 @@ impl<'a> Expr<'a> {
} }
} }
pub fn find_pattern_path<F: FnOnce(&Expr)>( pub fn find_pattern_path<T, F: FnOnce(&Expr) -> T>(
&self, &self,
ident: Ident, ident: Ident,
target: &Expr, target: &Expr,
mut with_final: F, mut with_final: F,
) -> Result<(), F> { ) -> Result<T, F> {
match *self { match *self {
Self::Ident { id, .. } if id == ident => { Self::Ident { id, .. } if id == ident => Ok(with_final(target)),
with_final(target);
Ok(())
}
Self::Ctor { fields, .. } => { Self::Ctor { fields, .. } => {
for &CtorField { name, value, pos } in fields { for &CtorField { name, value, pos } in fields {
match value.find_pattern_path( match value.find_pattern_path(
@ -857,7 +864,7 @@ impl<'a> Expr<'a> {
&Expr::Field { pos, target, name }, &Expr::Field { pos, target, name },
with_final, with_final,
) { ) {
Ok(()) => return Ok(()), Ok(value) => return Ok(value),
Err(e) => with_final = e, Err(e) => with_final = e,
} }
} }
@ -1457,7 +1464,7 @@ impl StackAlloc {
unsafe fn push<T: Copy>(&mut self, _view: &mut StackAllocView<T>, value: T) { unsafe fn push<T: Copy>(&mut self, _view: &mut StackAllocView<T>, value: T) {
if unlikely(self.len + core::mem::size_of::<T>() > self.cap) { if unlikely(self.len + core::mem::size_of::<T>() > self.cap) {
let next_cap = self.cap.max(16 * 32).max(std::mem::size_of::<T>()) * 2; let next_cap = self.cap.max(16 * 32).max(core::mem::size_of::<T>()) * 2;
if self.cap == 0 { if self.cap == 0 {
let layout = let layout =
core::alloc::Layout::from_size_align_unchecked(next_cap, Self::MAX_ALIGN); core::alloc::Layout::from_size_align_unchecked(next_cap, Self::MAX_ALIGN);
@ -1471,15 +1478,7 @@ impl StackAlloc {
} }
let dst = self.data.add(self.len) as *mut T; let dst = self.data.add(self.len) as *mut T;
debug_assert!( debug_assert!(dst.is_aligned(),);
dst.is_aligned(),
"{:?} {:?} {} {} {}",
dst,
std::mem::size_of::<T>(),
std::mem::align_of::<T>(),
self.len,
self.cap
);
self.len += core::mem::size_of::<T>(); self.len += core::mem::size_of::<T>();
core::ptr::write(dst, value); core::ptr::write(dst, value);
} }

View file

@ -25,6 +25,7 @@ use {
}, },
hashbrown::hash_map, hashbrown::hash_map,
regalloc2::VReg, regalloc2::VReg,
std::process::id,
}; };
const VOID: Nid = 0; const VOID: Nid = 0;
@ -2016,6 +2017,9 @@ impl Codegen {
lit_name: &str, lit_name: &str,
) -> ty::Kind { ) -> ty::Kind {
log::trace!("find_or_declare: {lit_name} {file}"); log::trace!("find_or_declare: {lit_name} {file}");
if let Some(ty) = self.tys.find_type(file, name.ok_or(lit_name), &self.files) {
return ty.expand();
}
let f = self.files[file as usize].clone(); let f = self.files[file as usize].clone();
let Some((expr, ident)) = f.find_decl(name.ok_or(lit_name)) else { let Some((expr, ident)) = f.find_decl(name.ok_or(lit_name)) else {
@ -2037,7 +2041,8 @@ impl Codegen {
return ty::Kind::Builtin(ty::NEVER); return ty::Kind::Builtin(ty::NEVER);
}; };
if let Some(existing) = self.tys.syms.get(&SymKey { file, ident }) { let key = SymKey::Decl(file, ident);
if let Some(existing) = self.tys.syms.get(&key) {
if let ty::Kind::Func(id) = existing.expand() if let ty::Kind::Func(id) = existing.expand()
&& let func = &mut self.tys.funcs[id as usize] && let func = &mut self.tys.funcs[id as usize]
&& let Err(idx) = task::unpack(func.offset) && let Err(idx) = task::unpack(func.offset)
@ -2099,7 +2104,7 @@ impl Codegen {
e => unimplemented!("{e:#?}"), e => unimplemented!("{e:#?}"),
}; };
self.ci.file = prev_file; self.ci.file = prev_file;
self.tys.syms.insert(SymKey { ident, file }, sym.compress()); self.tys.syms.insert(key, sym.compress());
sym sym
} }