forked from AbleOS/holey-bytes
making compiler a bit smarter about evaluating types (more shortcuts)
This commit is contained in:
parent
d293e02f62
commit
b2254e9820
|
@ -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
|
ty::Kind::Global(id) => self.handle_global(id),
|
||||||
.get(&SymKey { ident: id, file: self.ci.file })
|
tk => Some(Value::ty(tk.compress())),
|
||||||
.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),
|
|
||||||
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,
|
||||||
.compress();
|
packed.then_some(1),
|
||||||
|
None,
|
||||||
|
fields,
|
||||||
|
))
|
||||||
|
.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 =
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue