forked from AbleOS/holey-bytes
save
This commit is contained in:
parent
b2254e9820
commit
bdc2c43773
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -110,6 +110,12 @@ version = "0.14.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.15.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hbbytecode"
|
name = "hbbytecode"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -123,7 +129,7 @@ name = "hblang"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"hashbrown",
|
"hashbrown 0.15.0",
|
||||||
"hbbytecode",
|
"hbbytecode",
|
||||||
"hbvm",
|
"hbvm",
|
||||||
"log",
|
"log",
|
||||||
|
@ -191,7 +197,7 @@ source = "git+https://github.com/jakubDoka/regalloc2?branch=reuse-allocations#41
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"allocator-api2",
|
"allocator-api2",
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"hashbrown",
|
"hashbrown 0.14.5",
|
||||||
"log",
|
"log",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
|
|
|
@ -8,7 +8,7 @@ name = "hbc"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
hashbrown = { version = "0.14.5", default-features = false }
|
hashbrown = { version = "0.15.0", default-features = false, features = ["raw-entry"] }
|
||||||
hbbytecode = { version = "0.1.0", path = "../hbbytecode" }
|
hbbytecode = { version = "0.1.0", path = "../hbbytecode" }
|
||||||
hbvm = { path = "../hbvm", features = ["nightly"] }
|
hbvm = { path = "../hbvm", features = ["nightly"] }
|
||||||
log = { version = "0.4.22", features = ["release_max_level_error"] }
|
log = { version = "0.4.22", features = ["release_max_level_error"] }
|
||||||
|
|
|
@ -747,10 +747,10 @@ impl Codegen {
|
||||||
return ty.expand().inner();
|
return ty.expand().inner();
|
||||||
}
|
}
|
||||||
|
|
||||||
let prev_tmp = self.tys.fields_tmp.len();
|
let prev_tmp = self.tys.tmp.fields.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.names.intern(sf.name), ty: self.ty(&sf.ty) };
|
||||||
self.tys.fields_tmp.push(f);
|
self.tys.tmp.fields.push(f);
|
||||||
}
|
}
|
||||||
self.tys.structs.push(Struct {
|
self.tys.structs.push(Struct {
|
||||||
field_start: self.tys.fields.len() as _,
|
field_start: self.tys.fields.len() as _,
|
||||||
|
@ -758,7 +758,7 @@ impl Codegen {
|
||||||
file,
|
file,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
self.tys.fields.extend(self.tys.fields_tmp.drain(prev_tmp..));
|
self.tys.fields.extend(self.tys.tmp.fields.drain(prev_tmp..));
|
||||||
|
|
||||||
if let Some(sym) = sym {
|
if let Some(sym) = sym {
|
||||||
self.tys
|
self.tys
|
||||||
|
@ -2580,7 +2580,7 @@ impl Codegen {
|
||||||
|
|
||||||
self.ci.free_loc(ret.loc);
|
self.ci.free_loc(ret.loc);
|
||||||
|
|
||||||
Global { ty: ret.ty, file, name, data, ast: ExprRef::new(expr), ..Default::default() }
|
Global { ty: ret.ty, file, name, data, ..Default::default() }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ct_eval<T, E>(
|
fn ct_eval<T, E>(
|
||||||
|
|
|
@ -36,7 +36,7 @@ use {
|
||||||
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, usize},
|
core::{cell::Cell, fmt::Display, ops::Range},
|
||||||
hashbrown::hash_map,
|
hashbrown::hash_map,
|
||||||
hbbytecode as instrs,
|
hbbytecode as instrs,
|
||||||
};
|
};
|
||||||
|
@ -69,6 +69,89 @@ pub mod son;
|
||||||
mod lexer;
|
mod lexer;
|
||||||
mod vc;
|
mod vc;
|
||||||
|
|
||||||
|
mod ctx_map {
|
||||||
|
use core::hash::BuildHasher;
|
||||||
|
|
||||||
|
pub type Hash = u64;
|
||||||
|
pub type HashBuilder = core::hash::BuildHasherDefault<IdentityHasher>;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct IdentityHasher(u64);
|
||||||
|
|
||||||
|
impl core::hash::Hasher for IdentityHasher {
|
||||||
|
fn finish(&self) -> u64 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write(&mut self, _: &[u8]) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_u64(&mut self, i: u64) {
|
||||||
|
self.0 = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Key<T> {
|
||||||
|
pub value: T,
|
||||||
|
pub hash: Hash,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> core::hash::Hash for Key<T> {
|
||||||
|
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
|
||||||
|
state.write_u64(self.hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait CtxEntry {
|
||||||
|
type Ctx: ?Sized;
|
||||||
|
type Key<'a>: Eq + core::hash::Hash;
|
||||||
|
|
||||||
|
fn key<'a>(&self, ctx: &'a Self::Ctx) -> Self::Key<'a>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CtxMap<T> {
|
||||||
|
inner: hashbrown::HashMap<Key<T>, (), HashBuilder>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Default for CtxMap<T> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self { inner: Default::default() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: CtxEntry> CtxMap<T> {
|
||||||
|
pub fn entry<'a, 'b>(
|
||||||
|
&'a mut self,
|
||||||
|
value: 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get<'a>(&self, value: T::Key<'a>, ctx: &'a T::Ctx) -> Option<&T> {
|
||||||
|
let hash = crate::FnvBuildHasher::default().hash_one(&value);
|
||||||
|
self.inner
|
||||||
|
.raw_entry()
|
||||||
|
.from_hash(hash, |k| k.value.key(ctx) == value)
|
||||||
|
.map(|(k, _)| &k.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear(&mut self) {
|
||||||
|
self.inner.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove<'a>(&mut self, value: &T, ctx: &'a 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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mod task {
|
mod task {
|
||||||
use super::Offset;
|
use super::Offset;
|
||||||
|
|
||||||
|
@ -124,7 +207,7 @@ mod ty {
|
||||||
lexer::TokenKind,
|
lexer::TokenKind,
|
||||||
parser::{self},
|
parser::{self},
|
||||||
},
|
},
|
||||||
core::{num::NonZeroU32, ops::Range, usize},
|
core::{num::NonZeroU32, ops::Range},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type ArrayLen = u32;
|
pub type ArrayLen = u32;
|
||||||
|
@ -153,10 +236,6 @@ mod ty {
|
||||||
Some(Self((pos << Self::LEN_BITS | len) as u32))
|
Some(Self((pos << Self::LEN_BITS | len) as u32))
|
||||||
}
|
}
|
||||||
|
|
||||||
//pub fn view(self, slice: &[Id]) -> &[Id] {
|
|
||||||
// &slice[self.0 as usize >> Self::LEN_BITS..][..self.len()]
|
|
||||||
//}
|
|
||||||
|
|
||||||
pub fn range(self) -> Range<usize> {
|
pub fn range(self) -> Range<usize> {
|
||||||
let start = self.0 as usize >> Self::LEN_BITS;
|
let start = self.0 as usize >> Self::LEN_BITS;
|
||||||
start..start + self.len()
|
start..start + self.len()
|
||||||
|
@ -169,15 +248,20 @@ mod ty {
|
||||||
pub fn empty() -> Self {
|
pub fn empty() -> Self {
|
||||||
Self(0)
|
Self(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn repr(&self) -> u32 {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
||||||
pub struct Id(NonZeroU32);
|
pub struct Id(NonZeroU32);
|
||||||
|
|
||||||
|
impl crate::ctx_map::CtxEntry for Id {
|
||||||
|
type Ctx = TypeInsts;
|
||||||
|
type Key<'a> = crate::SymKey<'a>;
|
||||||
|
|
||||||
|
fn key<'a>(&self, ctx: &'a Self::Ctx) -> Self::Key<'a> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for Id {
|
impl Default for Id {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self(unsafe { NonZeroU32::new_unchecked(UNDECLARED) })
|
Self(unsafe { NonZeroU32::new_unchecked(UNDECLARED) })
|
||||||
|
@ -399,12 +483,7 @@ mod ty {
|
||||||
if i != 0 {
|
if i != 0 {
|
||||||
write!(f, ", ")?;
|
write!(f, ", ")?;
|
||||||
}
|
}
|
||||||
write!(
|
write!(f, "{}: {}", self.tys.names.ident_str(name), self.rety(ty))?;
|
||||||
f,
|
|
||||||
"{}: {}",
|
|
||||||
self.tys.field_names.ident_str(name),
|
|
||||||
self.rety(ty)
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
write!(f, "}}")
|
write!(f, "}}")
|
||||||
} else {
|
} else {
|
||||||
|
@ -442,15 +521,14 @@ fn emit(out: &mut Vec<u8>, (len, instr): EncodedInstr) {
|
||||||
out.extend_from_slice(&instr[..len]);
|
out.extend_from_slice(&instr[..len]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Hash, Debug)]
|
#[derive(PartialEq, Eq, Hash)]
|
||||||
enum SymKey {
|
enum SymKey<'a> {
|
||||||
Pointer(ty::Id),
|
Pointer(&'a Ptr),
|
||||||
Struct(FileId, Pos),
|
Struct(FileId, Pos),
|
||||||
FuncInst(ty::Func, ty::Tuple),
|
FuncInst(ty::Func, ty::Tuple),
|
||||||
MomizedCall(ty::Func),
|
MomizedCall(ty::Func),
|
||||||
Decl(FileId, Ident),
|
Decl(FileId, Ident),
|
||||||
Slice(ty::Id),
|
Array(&'a Array),
|
||||||
Array(ty::Id, ArrayLen),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
|
@ -491,7 +569,6 @@ 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,7 +579,6 @@ 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,
|
||||||
}
|
}
|
||||||
|
@ -551,11 +627,12 @@ struct Struct {
|
||||||
field_start: u32,
|
field_start: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, Hash)]
|
||||||
struct Ptr {
|
struct Ptr {
|
||||||
base: ty::Id,
|
base: ty::Id,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
struct Array {
|
struct Array {
|
||||||
ty: ty::Id,
|
ty: ty::Id,
|
||||||
len: ArrayLen,
|
len: ArrayLen,
|
||||||
|
@ -586,56 +663,30 @@ struct AbleOsExecutableHeader {
|
||||||
metadata_length: u64,
|
metadata_length: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct IdentEntry {
|
impl ctx_map::CtxEntry for Ident {
|
||||||
hash: u32,
|
type Ctx = str;
|
||||||
ident: Ident,
|
type Key<'a> = &'a str;
|
||||||
}
|
|
||||||
|
|
||||||
impl core::hash::Hash for IdentEntry {
|
fn key<'a>(&self, ctx: &'a Self::Ctx) -> Self::Key<'a> {
|
||||||
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
|
unsafe { ctx.get_unchecked(ident::range(*self)) }
|
||||||
state.write_u64((self.hash as u64) << 32);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
struct IdentityHasher(u64);
|
|
||||||
|
|
||||||
impl core::hash::Hasher for IdentityHasher {
|
|
||||||
fn finish(&self) -> u64 {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write(&mut self, _: &[u8]) {
|
|
||||||
unimplemented!()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_u64(&mut self, i: u64) {
|
|
||||||
self.0 = i;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct IdentInterner {
|
struct IdentInterner {
|
||||||
lookup: hashbrown::HashMap<IdentEntry, (), core::hash::BuildHasherDefault<IdentityHasher>>,
|
lookup: ctx_map::CtxMap<Ident>,
|
||||||
strings: String,
|
strings: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IdentInterner {
|
impl IdentInterner {
|
||||||
fn intern(&mut self, ident: &str) -> Ident {
|
fn intern(&mut self, ident: &str) -> Ident {
|
||||||
let hash = FnvBuildHasher::default().hash_one(ident) & 0xFFFFFFFF00000000;
|
let (entry, hash) = self.lookup.entry(ident, &self.strings);
|
||||||
match self.lookup.raw_entry_mut().from_hash(
|
match entry {
|
||||||
hash,
|
hash_map::RawEntryMut::Occupied(o) => o.get_key_value().0.value,
|
||||||
|k| unsafe { self.strings.get_unchecked(ident::range(k.ident)) } == ident,
|
|
||||||
) {
|
|
||||||
hash_map::RawEntryMut::Occupied(o) => o.get_key_value().0.ident,
|
|
||||||
hash_map::RawEntryMut::Vacant(v) => {
|
hash_map::RawEntryMut::Vacant(v) => {
|
||||||
let id = ident::new(self.strings.len() as _, ident.len() as _);
|
let id = ident::new(self.strings.len() as _, ident.len() as _);
|
||||||
self.strings.push_str(ident);
|
self.strings.push_str(ident);
|
||||||
v.insert_hashed_nocheck(
|
v.insert(ctx_map::Key { hash, value: id }, ());
|
||||||
hash,
|
|
||||||
IdentEntry { hash: (hash >> 32) as _, ident: id },
|
|
||||||
(),
|
|
||||||
);
|
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -646,33 +697,35 @@ impl IdentInterner {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn project(&self, ident: &str) -> Option<Ident> {
|
fn project(&self, ident: &str) -> Option<Ident> {
|
||||||
let hash = FnvBuildHasher::default().hash_one(ident) & 0xFFFFFFFF00000000;
|
self.lookup.get(ident, &self.strings).copied()
|
||||||
self.lookup
|
|
||||||
.raw_entry()
|
|
||||||
.from_hash(
|
|
||||||
hash,
|
|
||||||
|k| unsafe { self.strings.get_unchecked(ident::range(k.ident)) } == ident,
|
|
||||||
)
|
|
||||||
.map(|(k, _)| k.ident)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct Types {
|
struct TypesTmp {
|
||||||
syms: HashMap<SymKey, ty::Id>,
|
fields: Vec<Field>,
|
||||||
|
frontier: Vec<ty::Id>,
|
||||||
|
globals: Vec<ty::Global>,
|
||||||
|
funcs: Vec<ty::Func>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct TypeIns {
|
||||||
funcs: Vec<Func>,
|
funcs: Vec<Func>,
|
||||||
args: Vec<ty::Id>,
|
args: Vec<ty::Id>,
|
||||||
globals: Vec<Global>,
|
globals: Vec<Global>,
|
||||||
structs: Vec<Struct>,
|
structs: Vec<Struct>,
|
||||||
fields: Vec<Field>,
|
fields: Vec<Field>,
|
||||||
field_names: IdentInterner,
|
|
||||||
ptrs: Vec<Ptr>,
|
ptrs: Vec<Ptr>,
|
||||||
arrays: Vec<Array>,
|
arrays: Vec<Array>,
|
||||||
|
}
|
||||||
|
|
||||||
fields_tmp: Vec<Field>,
|
#[derive(Default)]
|
||||||
frontier_tmp: Vec<ty::Id>,
|
struct Types {
|
||||||
reachable_globals: Vec<ty::Global>,
|
syms: ctx_map::CtxMap<ty::Id>,
|
||||||
reachable_funcs: Vec<ty::Func>,
|
names: IdentInterner,
|
||||||
|
ins: TypeIns,
|
||||||
|
tmp: TypesTmp,
|
||||||
}
|
}
|
||||||
|
|
||||||
const HEADER_SIZE: usize = core::mem::size_of::<AbleOsExecutableHeader>();
|
const HEADER_SIZE: usize = core::mem::size_of::<AbleOsExecutableHeader>();
|
||||||
|
@ -757,13 +810,13 @@ impl Types {
|
||||||
return Some(ty);
|
return Some(ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
let prev_tmp = self.fields_tmp.len();
|
let prev_tmp = self.tmp.fields.len();
|
||||||
for field in fields.iter().filter_map(CommentOr::or) {
|
for field in fields.iter().filter_map(CommentOr::or) {
|
||||||
let Some(ty) = self.ty(file, &field.ty, files) else {
|
let Some(ty) = self.ty(file, &field.ty, files) else {
|
||||||
self.fields_tmp.truncate(prev_tmp);
|
self.tmp.fields.truncate(prev_tmp);
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
self.fields_tmp.push(Field { name: self.field_names.intern(field.name), ty });
|
self.tmp.fields.push(Field { name: self.names.intern(field.name), ty });
|
||||||
}
|
}
|
||||||
|
|
||||||
self.structs.push(Struct {
|
self.structs.push(Struct {
|
||||||
|
@ -772,7 +825,7 @@ impl Types {
|
||||||
explicit_alignment: packed.then_some(1),
|
explicit_alignment: packed.then_some(1),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
self.fields.extend(self.fields_tmp.drain(prev_tmp..));
|
self.fields.extend(self.tmp.fields.drain(prev_tmp..));
|
||||||
|
|
||||||
let ty = ty::Kind::Struct(self.structs.len() as u32 - 1).compress();
|
let ty = ty::Kind::Struct(self.structs.len() as u32 - 1).compress();
|
||||||
self.syms.insert(sym, ty);
|
self.syms.insert(sym, ty);
|
||||||
|
@ -794,12 +847,12 @@ impl Types {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dump_reachable(&mut self, from: ty::Func, to: &mut Vec<u8>) -> AbleOsExecutableHeader {
|
fn dump_reachable(&mut self, from: ty::Func, to: &mut Vec<u8>) -> AbleOsExecutableHeader {
|
||||||
debug_assert!(self.frontier_tmp.is_empty());
|
debug_assert!(self.tmp.frontier.is_empty());
|
||||||
debug_assert!(self.reachable_funcs.is_empty());
|
debug_assert!(self.tmp.funcs.is_empty());
|
||||||
debug_assert!(self.reachable_globals.is_empty());
|
debug_assert!(self.tmp.globals.is_empty());
|
||||||
|
|
||||||
self.frontier_tmp.push(ty::Kind::Func(from).compress());
|
self.tmp.frontier.push(ty::Kind::Func(from).compress());
|
||||||
while let Some(itm) = self.frontier_tmp.pop() {
|
while let Some(itm) = self.tmp.frontier.pop() {
|
||||||
match itm.expand() {
|
match itm.expand() {
|
||||||
ty::Kind::Func(func) => {
|
ty::Kind::Func(func) => {
|
||||||
let fuc = &mut self.funcs[func as usize];
|
let fuc = &mut self.funcs[func as usize];
|
||||||
|
@ -807,8 +860,8 @@ impl Types {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
fuc.offset = 0;
|
fuc.offset = 0;
|
||||||
self.reachable_funcs.push(func);
|
self.tmp.funcs.push(func);
|
||||||
self.frontier_tmp.extend(fuc.relocs.iter().map(|r| r.target));
|
self.tmp.frontier.extend(fuc.relocs.iter().map(|r| r.target));
|
||||||
}
|
}
|
||||||
ty::Kind::Global(glob) => {
|
ty::Kind::Global(glob) => {
|
||||||
let glb = &mut self.globals[glob as usize];
|
let glb = &mut self.globals[glob as usize];
|
||||||
|
@ -816,13 +869,13 @@ impl Types {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
glb.offset = 0;
|
glb.offset = 0;
|
||||||
self.reachable_globals.push(glob);
|
self.tmp.globals.push(glob);
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for &func in &self.reachable_funcs {
|
for &func in &self.tmp.funcs {
|
||||||
let fuc = &mut self.funcs[func as usize];
|
let fuc = &mut self.funcs[func as usize];
|
||||||
fuc.offset = to.len() as _;
|
fuc.offset = to.len() as _;
|
||||||
to.extend(&fuc.code);
|
to.extend(&fuc.code);
|
||||||
|
@ -830,7 +883,7 @@ impl Types {
|
||||||
|
|
||||||
let code_length = to.len();
|
let code_length = to.len();
|
||||||
|
|
||||||
for global in self.reachable_globals.drain(..) {
|
for global in self.tmp.globals.drain(..) {
|
||||||
let global = &mut self.globals[global as usize];
|
let global = &mut self.globals[global as usize];
|
||||||
global.offset = to.len() as _;
|
global.offset = to.len() as _;
|
||||||
to.extend(&global.data);
|
to.extend(&global.data);
|
||||||
|
@ -838,7 +891,7 @@ impl Types {
|
||||||
|
|
||||||
let data_length = to.len() - code_length;
|
let data_length = to.len() - code_length;
|
||||||
|
|
||||||
for func in self.reachable_funcs.drain(..) {
|
for func in self.tmp.funcs.drain(..) {
|
||||||
let fuc = &self.funcs[func as usize];
|
let fuc = &self.funcs[func as usize];
|
||||||
for rel in &fuc.relocs {
|
for rel in &fuc.relocs {
|
||||||
let offset = match rel.target.expand() {
|
let offset = match rel.target.expand() {
|
||||||
|
@ -1003,7 +1056,7 @@ impl Types {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_struct_field(&self, s: ty::Struct, name: &str) -> Option<usize> {
|
fn find_struct_field(&self, s: ty::Struct, name: &str) -> Option<usize> {
|
||||||
let name = self.field_names.project(name)?;
|
let name = self.names.project(name)?;
|
||||||
self.struct_fields(s).iter().position(|f| f.name == name)
|
self.struct_fields(s).iter().position(|f| f.name == name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1020,7 +1073,7 @@ impl OffsetIter {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn offset_of(tys: &Types, idx: ty::Struct, field: &str) -> Option<(Offset, ty::Id)> {
|
fn offset_of(tys: &Types, idx: ty::Struct, field: &str) -> Option<(Offset, ty::Id)> {
|
||||||
let field_id = tys.field_names.project(field)?;
|
let field_id = tys.names.project(field)?;
|
||||||
OffsetIter::new(idx, tys)
|
OffsetIter::new(idx, tys)
|
||||||
.into_iter(tys)
|
.into_iter(tys)
|
||||||
.find(|(f, _)| f.name == field_id)
|
.find(|(f, _)| f.name == field_id)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
|
ctx_map::CtxEntry,
|
||||||
ident::Ident,
|
ident::Ident,
|
||||||
instrs,
|
instrs,
|
||||||
lexer::{self, TokenKind},
|
lexer::{self, TokenKind},
|
||||||
|
@ -11,7 +12,7 @@ use {
|
||||||
task,
|
task,
|
||||||
ty::{self},
|
ty::{self},
|
||||||
vc::{BitSet, Vc},
|
vc::{BitSet, Vc},
|
||||||
Func, HashMap, IdentityHasher, Offset, OffsetIter, Reloc, Sig, SymKey, TypedReloc, Types,
|
Func, HashMap, Offset, OffsetIter, Reloc, Sig, SymKey, TypedReloc, Types,
|
||||||
},
|
},
|
||||||
alloc::{borrow::ToOwned, string::String, vec::Vec},
|
alloc::{borrow::ToOwned, string::String, vec::Vec},
|
||||||
core::{
|
core::{
|
||||||
|
@ -20,12 +21,11 @@ use {
|
||||||
convert::identity,
|
convert::identity,
|
||||||
fmt::{self, Debug, Display, Write},
|
fmt::{self, Debug, Display, Write},
|
||||||
format_args as fa,
|
format_args as fa,
|
||||||
hash::{BuildHasher, Hasher},
|
hash::BuildHasher,
|
||||||
mem, ops,
|
mem, ops, usize,
|
||||||
},
|
},
|
||||||
hashbrown::hash_map,
|
hashbrown::hash_map,
|
||||||
regalloc2::VReg,
|
regalloc2::VReg,
|
||||||
std::process::id,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const VOID: Nid = 0;
|
const VOID: Nid = 0;
|
||||||
|
@ -44,19 +44,17 @@ pub mod reg {
|
||||||
pub type Reg = u8;
|
pub type Reg = u8;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LookupEntry {
|
type Lookup = crate::ctx_map::CtxMap<Nid>;
|
||||||
nid: Nid,
|
|
||||||
hash: u64,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl core::hash::Hash for LookupEntry {
|
impl crate::ctx_map::CtxEntry for Nid {
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
type Ctx = [Result<Node, Nid>];
|
||||||
state.write_u64(self.hash);
|
type Key<'a> = (Kind, &'a [Nid], ty::Id);
|
||||||
|
|
||||||
|
fn key<'a>(&self, ctx: &'a Self::Ctx) -> Self::Key<'a> {
|
||||||
|
ctx[*self as usize].as_ref().unwrap().key()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Lookup = hashbrown::HashMap<LookupEntry, (), core::hash::BuildHasherDefault<IdentityHasher>>;
|
|
||||||
|
|
||||||
struct Nodes {
|
struct Nodes {
|
||||||
values: Vec<Result<Node, Nid>>,
|
values: Vec<Result<Node, Nid>>,
|
||||||
visited: BitSet,
|
visited: BitSet,
|
||||||
|
@ -106,10 +104,10 @@ impl Nodes {
|
||||||
|
|
||||||
let mut lookup_meta = None;
|
let mut lookup_meta = None;
|
||||||
if !node.is_lazy_phi() {
|
if !node.is_lazy_phi() {
|
||||||
let (raw_entry, hash) = Self::find_node(&mut self.lookup, &self.values, &node);
|
let (raw_entry, hash) = self.lookup.entry(node.key(), &self.values);
|
||||||
|
|
||||||
let entry = match raw_entry {
|
let entry = match raw_entry {
|
||||||
hash_map::RawEntryMut::Occupied(o) => return o.get_key_value().0.nid,
|
hash_map::RawEntryMut::Occupied(o) => return o.get_key_value().0.value,
|
||||||
hash_map::RawEntryMut::Vacant(v) => v,
|
hash_map::RawEntryMut::Vacant(v) => v,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -129,38 +127,14 @@ impl Nodes {
|
||||||
self.free = mem::replace(&mut self.values[free as usize], Ok(node)).unwrap_err();
|
self.free = mem::replace(&mut self.values[free as usize], Ok(node)).unwrap_err();
|
||||||
|
|
||||||
if let Some((entry, hash)) = lookup_meta {
|
if let Some((entry, hash)) = lookup_meta {
|
||||||
entry.insert(LookupEntry { nid: free, hash }, ());
|
entry.insert(crate::ctx_map::Key { value: free, hash }, ());
|
||||||
}
|
}
|
||||||
free
|
free
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_node<'a>(
|
|
||||||
lookup: &'a mut Lookup,
|
|
||||||
values: &[Result<Node, Nid>],
|
|
||||||
node: &Node,
|
|
||||||
) -> (
|
|
||||||
hash_map::RawEntryMut<'a, LookupEntry, (), core::hash::BuildHasherDefault<IdentityHasher>>,
|
|
||||||
u64,
|
|
||||||
) {
|
|
||||||
let hash = crate::FnvBuildHasher::default().hash_one(node.key());
|
|
||||||
let entry = lookup
|
|
||||||
.raw_entry_mut()
|
|
||||||
.from_hash(hash, |n| values[n.nid as usize].as_ref().unwrap().key() == node.key());
|
|
||||||
(entry, hash)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn remove_node_lookup(&mut self, target: Nid) {
|
fn remove_node_lookup(&mut self, target: Nid) {
|
||||||
if !self[target].is_lazy_phi() {
|
if !self[target].is_lazy_phi() {
|
||||||
match Self::find_node(
|
self.lookup.remove(&target, &self.values).unwrap();
|
||||||
&mut self.lookup,
|
|
||||||
&self.values,
|
|
||||||
self.values[target as usize].as_ref().unwrap(),
|
|
||||||
)
|
|
||||||
.0
|
|
||||||
{
|
|
||||||
hash_map::RawEntryMut::Occupied(o) => o.remove(),
|
|
||||||
hash_map::RawEntryMut::Vacant(_) => unreachable!(),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,20 +353,16 @@ impl Nodes {
|
||||||
|
|
||||||
let prev = self[target].inputs[inp_index];
|
let prev = self[target].inputs[inp_index];
|
||||||
self[target].inputs[inp_index] = with;
|
self[target].inputs[inp_index] = with;
|
||||||
let (entry, hash) = Self::find_node(
|
let (entry, hash) = self.lookup.entry(target.key(&self.values), &self.values);
|
||||||
&mut self.lookup,
|
|
||||||
&self.values,
|
|
||||||
self.values[target as usize].as_ref().unwrap(),
|
|
||||||
);
|
|
||||||
match entry {
|
match entry {
|
||||||
hash_map::RawEntryMut::Occupied(other) => {
|
hash_map::RawEntryMut::Occupied(other) => {
|
||||||
let rpl = other.get_key_value().0.nid;
|
let rpl = other.get_key_value().0.value;
|
||||||
self[target].inputs[inp_index] = prev;
|
self[target].inputs[inp_index] = prev;
|
||||||
self.replace(target, rpl);
|
self.replace(target, rpl);
|
||||||
rpl
|
rpl
|
||||||
}
|
}
|
||||||
hash_map::RawEntryMut::Vacant(slot) => {
|
hash_map::RawEntryMut::Vacant(slot) => {
|
||||||
slot.insert(LookupEntry { nid: target, hash }, ());
|
slot.insert(crate::ctx_map::Key { value: target, hash }, ());
|
||||||
let index = self[prev].outputs.iter().position(|&o| o == target).unwrap();
|
let index = self[prev].outputs.iter().position(|&o| o == target).unwrap();
|
||||||
self[prev].outputs.swap_remove(index);
|
self[prev].outputs.swap_remove(index);
|
||||||
self[with].outputs.push(target);
|
self[with].outputs.push(target);
|
||||||
|
@ -845,7 +815,7 @@ impl fmt::Display for Kind {
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
//#[repr(align(64))]
|
//#[repr(align(64))]
|
||||||
struct Node {
|
pub struct Node {
|
||||||
kind: Kind,
|
kind: Kind,
|
||||||
inputs: Vc,
|
inputs: Vc,
|
||||||
outputs: Vc,
|
outputs: Vc,
|
||||||
|
@ -1144,7 +1114,7 @@ impl Codegen {
|
||||||
.tys
|
.tys
|
||||||
.struct_fields(s)
|
.struct_fields(s)
|
||||||
.iter()
|
.iter()
|
||||||
.map(|f| self.tys.field_names.ident_str(f.name))
|
.map(|f| self.tys.names.ident_str(f.name))
|
||||||
.intersperse("', '")
|
.intersperse("', '")
|
||||||
.collect::<String>();
|
.collect::<String>();
|
||||||
self.report(
|
self.report(
|
||||||
|
@ -1374,7 +1344,7 @@ impl Codegen {
|
||||||
.iter()
|
.iter()
|
||||||
.zip(offs)
|
.zip(offs)
|
||||||
.filter(|&(_, (ty, _))| ty != ty::Id::UNDECLARED)
|
.filter(|&(_, (ty, _))| ty != ty::Id::UNDECLARED)
|
||||||
.map(|(f, _)| self.tys.field_names.ident_str(f.name))
|
.map(|(f, _)| self.tys.names.ident_str(f.name))
|
||||||
.intersperse(", ")
|
.intersperse(", ")
|
||||||
.collect::<String>();
|
.collect::<String>();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue