instruction scheduling somewhat works now
This commit is contained in:
parent
641d344d2d
commit
b177cbe7c7
3
hblang/formatter_arithmetic.actual
Normal file
3
hblang/formatter_arithmetic.actual
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
main := fn(): int {
|
||||||
|
return 10 - 20 / 2 + 4 * (2 + 2) - 4 * 4 + 1 << 0
|
||||||
|
}
|
3
hblang/formatter_arithmetic.expected
Normal file
3
hblang/formatter_arithmetic.expected
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
main := fn(): int {
|
||||||
|
return 10 - 20 / 2 + 4 * (2 + 2) - 4 * 4 + 1 << 0
|
||||||
|
}
|
|
@ -6,7 +6,7 @@ use {
|
||||||
lexer::{self, TokenKind},
|
lexer::{self, TokenKind},
|
||||||
log,
|
log,
|
||||||
parser::{self, find_symbol, idfl, CtorField, Expr, ExprRef, FileId, Pos},
|
parser::{self, find_symbol, idfl, CtorField, Expr, ExprRef, FileId, Pos},
|
||||||
HashMap,
|
HashMap, LoggedMem,
|
||||||
},
|
},
|
||||||
std::{collections::BTreeMap, fmt::Display, ops::Range, rc::Rc},
|
std::{collections::BTreeMap, fmt::Display, ops::Range, rc::Rc},
|
||||||
};
|
};
|
||||||
|
@ -1176,69 +1176,6 @@ struct Pool {
|
||||||
arg_locs: Vec<Loc>,
|
arg_locs: Vec<Loc>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct LoggedMem {
|
|
||||||
pub mem: hbvm::mem::HostMemory,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl hbvm::mem::Memory for LoggedMem {
|
|
||||||
unsafe fn load(
|
|
||||||
&mut self,
|
|
||||||
addr: hbvm::mem::Address,
|
|
||||||
target: *mut u8,
|
|
||||||
count: usize,
|
|
||||||
) -> Result<(), hbvm::mem::LoadError> {
|
|
||||||
log::trc!(
|
|
||||||
"load: {:x} {:?}",
|
|
||||||
addr.get(),
|
|
||||||
core::slice::from_raw_parts(addr.get() as *const u8, count)
|
|
||||||
.iter()
|
|
||||||
.rev()
|
|
||||||
.map(|&b| format!("{b:02x}"))
|
|
||||||
.collect::<String>()
|
|
||||||
);
|
|
||||||
self.mem.load(addr, target, count)
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn store(
|
|
||||||
&mut self,
|
|
||||||
addr: hbvm::mem::Address,
|
|
||||||
source: *const u8,
|
|
||||||
count: usize,
|
|
||||||
) -> Result<(), hbvm::mem::StoreError> {
|
|
||||||
log::trc!(
|
|
||||||
"store: {:x} {:?}",
|
|
||||||
addr.get(),
|
|
||||||
core::slice::from_raw_parts(source, count)
|
|
||||||
.iter()
|
|
||||||
.rev()
|
|
||||||
.map(|&b| format!("{b:02x}"))
|
|
||||||
.collect::<String>()
|
|
||||||
);
|
|
||||||
self.mem.store(addr, source, count)
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn prog_read<T: Copy>(&mut self, addr: hbvm::mem::Address) -> T {
|
|
||||||
log::trc!(
|
|
||||||
"read-typed: {:x} {} {:?}",
|
|
||||||
addr.get(),
|
|
||||||
std::any::type_name::<T>(),
|
|
||||||
if core::mem::size_of::<T>() == 1
|
|
||||||
&& let Some(nm) =
|
|
||||||
instrs::NAMES.get(std::ptr::read(addr.get() as *const u8) as usize)
|
|
||||||
{
|
|
||||||
nm.to_string()
|
|
||||||
} else {
|
|
||||||
core::slice::from_raw_parts(addr.get() as *const u8, core::mem::size_of::<T>())
|
|
||||||
.iter()
|
|
||||||
.map(|&b| format!("{:02x}", b))
|
|
||||||
.collect::<String>()
|
|
||||||
}
|
|
||||||
);
|
|
||||||
self.mem.prog_read(addr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const VM_STACK_SIZE: usize = 1024 * 1024 * 2;
|
const VM_STACK_SIZE: usize = 1024 * 1024 * 2;
|
||||||
|
|
||||||
struct Comptime {
|
struct Comptime {
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
macro_metavar_expr,
|
macro_metavar_expr,
|
||||||
anonymous_lifetime_in_impl_trait,
|
anonymous_lifetime_in_impl_trait,
|
||||||
core_intrinsics,
|
core_intrinsics,
|
||||||
new_uninit,
|
|
||||||
never_type,
|
never_type,
|
||||||
unwrap_infallible,
|
unwrap_infallible,
|
||||||
slice_partition_dedup,
|
slice_partition_dedup,
|
||||||
|
@ -791,6 +790,69 @@ pub fn run_compiler(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct LoggedMem {
|
||||||
|
pub mem: hbvm::mem::HostMemory,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl hbvm::mem::Memory for LoggedMem {
|
||||||
|
unsafe fn load(
|
||||||
|
&mut self,
|
||||||
|
addr: hbvm::mem::Address,
|
||||||
|
target: *mut u8,
|
||||||
|
count: usize,
|
||||||
|
) -> Result<(), hbvm::mem::LoadError> {
|
||||||
|
log::trc!(
|
||||||
|
"load: {:x} {:?}",
|
||||||
|
addr.get(),
|
||||||
|
core::slice::from_raw_parts(addr.get() as *const u8, count)
|
||||||
|
.iter()
|
||||||
|
.rev()
|
||||||
|
.map(|&b| format!("{b:02x}"))
|
||||||
|
.collect::<String>()
|
||||||
|
);
|
||||||
|
self.mem.load(addr, target, count)
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn store(
|
||||||
|
&mut self,
|
||||||
|
addr: hbvm::mem::Address,
|
||||||
|
source: *const u8,
|
||||||
|
count: usize,
|
||||||
|
) -> Result<(), hbvm::mem::StoreError> {
|
||||||
|
log::trc!(
|
||||||
|
"store: {:x} {:?}",
|
||||||
|
addr.get(),
|
||||||
|
core::slice::from_raw_parts(source, count)
|
||||||
|
.iter()
|
||||||
|
.rev()
|
||||||
|
.map(|&b| format!("{b:02x}"))
|
||||||
|
.collect::<String>()
|
||||||
|
);
|
||||||
|
self.mem.store(addr, source, count)
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn prog_read<T: Copy>(&mut self, addr: hbvm::mem::Address) -> T {
|
||||||
|
log::trc!(
|
||||||
|
"read-typed: {:x} {} {:?}",
|
||||||
|
addr.get(),
|
||||||
|
std::any::type_name::<T>(),
|
||||||
|
if core::mem::size_of::<T>() == 1
|
||||||
|
&& let Some(nm) =
|
||||||
|
instrs::NAMES.get(std::ptr::read(addr.get() as *const u8) as usize)
|
||||||
|
{
|
||||||
|
nm.to_string()
|
||||||
|
} else {
|
||||||
|
core::slice::from_raw_parts(addr.get() as *const u8, core::mem::size_of::<T>())
|
||||||
|
.iter()
|
||||||
|
.map(|&b| format!("{:02x}", b))
|
||||||
|
.collect::<String>()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
self.mem.prog_read(addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
|
@ -1250,8 +1250,6 @@ impl Drop for Ast {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let inner = unsafe { self.0.as_ref() };
|
let inner = unsafe { self.0.as_ref() };
|
||||||
if inner.ref_count.fetch_sub(1, std::sync::atomic::Ordering::Relaxed) == 1 {
|
if inner.ref_count.fetch_sub(1, std::sync::atomic::Ordering::Relaxed) == 1 {
|
||||||
unsafe { std::ptr::drop_in_place(self.0.as_ptr()) };
|
|
||||||
|
|
||||||
let layout = AstInner::layout(inner.symbols.len());
|
let layout = AstInner::layout(inner.symbols.len());
|
||||||
unsafe {
|
unsafe {
|
||||||
std::alloc::dealloc(self.0.as_ptr() as _, layout);
|
std::alloc::dealloc(self.0.as_ptr() as _, layout);
|
||||||
|
|
|
@ -12,14 +12,14 @@ use {
|
||||||
},
|
},
|
||||||
HashMap,
|
HashMap,
|
||||||
},
|
},
|
||||||
core::fmt,
|
core::{fmt, panic},
|
||||||
std::{
|
std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
collections::{hash_map, BTreeMap},
|
collections::{hash_map, BTreeMap},
|
||||||
fmt::{Display, Write},
|
fmt::{Debug, Display, Write},
|
||||||
hash::{Hash as _, Hasher},
|
hash::{Hash as _, Hasher},
|
||||||
mem::{self, MaybeUninit},
|
mem::{self, MaybeUninit},
|
||||||
ops::{self, Deref, DerefMut, Range},
|
ops::{self, Deref, DerefMut, Not, Range},
|
||||||
ptr::Unique,
|
ptr::Unique,
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
},
|
},
|
||||||
|
@ -45,7 +45,7 @@ impl Drop for Drom {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const VC_SIZE: usize = std::mem::size_of::<AllocedVc>();
|
const VC_SIZE: usize = 16;
|
||||||
const INLINE_ELEMS: usize = VC_SIZE / std::mem::size_of::<Nid>() - 1;
|
const INLINE_ELEMS: usize = VC_SIZE / std::mem::size_of::<Nid>() - 1;
|
||||||
|
|
||||||
union Vc {
|
union Vc {
|
||||||
|
@ -53,27 +53,65 @@ union Vc {
|
||||||
alloced: AllocedVc,
|
alloced: AllocedVc,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Vc {
|
||||||
|
fn default() -> Self {
|
||||||
|
Vc { inline: InlineVc { elems: MaybeUninit::uninit(), cap: 0 } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for Vc {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
self.as_slice().fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Vc {
|
impl Vc {
|
||||||
fn is_inline(&self) -> bool {
|
fn is_inline(&self) -> bool {
|
||||||
unsafe { self.inline.len <= INLINE_ELEMS as u32 }
|
unsafe { self.inline.cap <= INLINE_ELEMS as Nid }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout(&self) -> Option<std::alloc::Layout> {
|
fn layout(&self) -> Option<std::alloc::Layout> {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.is_inline()
|
self.is_inline()
|
||||||
|
.not()
|
||||||
.then(|| std::alloc::Layout::array::<Nid>(self.alloced.cap as _).unwrap_unchecked())
|
.then(|| std::alloc::Layout::array::<Nid>(self.alloced.cap as _).unwrap_unchecked())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn len(&self) -> usize {
|
fn len(&self) -> usize {
|
||||||
unsafe { self.inline.len as _ }
|
unsafe {
|
||||||
|
if self.is_inline() {
|
||||||
|
self.inline.cap as _
|
||||||
|
} else {
|
||||||
|
self.alloced.len as _
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_ptr(&self) -> *mut Nid {
|
fn len_mut(&mut self) -> &mut Nid {
|
||||||
|
unsafe {
|
||||||
|
if self.is_inline() {
|
||||||
|
&mut self.inline.cap
|
||||||
|
} else {
|
||||||
|
&mut self.alloced.len
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_ptr(&self) -> *const Nid {
|
||||||
unsafe {
|
unsafe {
|
||||||
match self.is_inline() {
|
match self.is_inline() {
|
||||||
true => self.alloced.base.as_ptr(),
|
true => self.inline.elems.as_ptr().cast(),
|
||||||
false => { self.inline.elems }.as_mut_ptr().cast(),
|
false => self.alloced.base.as_ptr(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_mut_ptr(&mut self) -> *mut Nid {
|
||||||
|
unsafe {
|
||||||
|
match self.is_inline() {
|
||||||
|
true => self.inline.elems.as_mut_ptr().cast(),
|
||||||
|
false => self.alloced.base.as_ptr(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,7 +121,63 @@ impl Vc {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_slice_mut(&mut self) -> &mut [Nid] {
|
fn as_slice_mut(&mut self) -> &mut [Nid] {
|
||||||
unsafe { std::slice::from_raw_parts_mut(self.as_ptr(), self.len()) }
|
unsafe { std::slice::from_raw_parts_mut(self.as_mut_ptr(), self.len()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push(&mut self, value: Nid) {
|
||||||
|
if let Some(layout) = self.layout()
|
||||||
|
&& unsafe { self.alloced.len == self.alloced.cap }
|
||||||
|
{
|
||||||
|
unsafe {
|
||||||
|
self.alloced.cap *= 2;
|
||||||
|
self.alloced.base = Unique::new_unchecked(
|
||||||
|
std::alloc::realloc(
|
||||||
|
self.alloced.base.as_ptr().cast(),
|
||||||
|
layout,
|
||||||
|
self.alloced.cap as usize * std::mem::size_of::<Nid>(),
|
||||||
|
)
|
||||||
|
.cast(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if self.len() == INLINE_ELEMS {
|
||||||
|
unsafe {
|
||||||
|
let mut allcd =
|
||||||
|
Self::alloc((self.inline.cap + 1).next_power_of_two() as _, self.len());
|
||||||
|
std::ptr::copy_nonoverlapping(self.as_ptr(), allcd.as_mut_ptr(), self.len());
|
||||||
|
*self = allcd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
*self.len_mut() += 1;
|
||||||
|
self.as_mut_ptr().add(self.len() - 1).write(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn alloc(cap: usize, len: usize) -> Self {
|
||||||
|
debug_assert!(cap > INLINE_ELEMS);
|
||||||
|
let layout = unsafe { std::alloc::Layout::array::<Nid>(cap).unwrap_unchecked() };
|
||||||
|
let alloc = unsafe { std::alloc::alloc(layout) };
|
||||||
|
unsafe {
|
||||||
|
Vc {
|
||||||
|
alloced: AllocedVc {
|
||||||
|
base: Unique::new_unchecked(alloc.cast()),
|
||||||
|
len: len as _,
|
||||||
|
cap: cap as _,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn swap_remove(&mut self, index: usize) {
|
||||||
|
let len = self.len() - 1;
|
||||||
|
self.as_slice_mut().swap(index, len);
|
||||||
|
*self.len_mut() -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove(&mut self, index: usize) {
|
||||||
|
self.as_slice_mut().copy_within(index + 1.., index);
|
||||||
|
*self.len_mut() -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,21 +193,78 @@ impl Drop for Vc {
|
||||||
|
|
||||||
impl Clone for Vc {
|
impl Clone for Vc {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
if self.is_inline() {
|
self.as_slice().into()
|
||||||
unsafe { std::ptr::read(self) }
|
}
|
||||||
} else {
|
}
|
||||||
let layout = unsafe { std::alloc::Layout::array::<Nid>(self.len()).unwrap_unchecked() };
|
|
||||||
let alloc = unsafe { std::alloc::alloc(layout) };
|
impl IntoIterator for Vc {
|
||||||
unsafe { std::ptr::copy_nonoverlapping(self.as_ptr(), alloc.cast(), self.len()) };
|
type IntoIter = VcIntoIter;
|
||||||
|
type Item = Nid;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
VcIntoIter { start: 0, end: self.len(), vc: self }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct VcIntoIter {
|
||||||
|
start: usize,
|
||||||
|
end: usize,
|
||||||
|
vc: Vc,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for VcIntoIter {
|
||||||
|
type Item = Nid;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
if self.start == self.end {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let ret = unsafe { std::ptr::read(self.vc.as_slice().get_unchecked(self.start)) };
|
||||||
|
self.start += 1;
|
||||||
|
Some(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
|
let len = self.end - self.start;
|
||||||
|
(len, Some(len))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DoubleEndedIterator for VcIntoIter {
|
||||||
|
fn next_back(&mut self) -> Option<Self::Item> {
|
||||||
|
if self.start == self.end {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.end -= 1;
|
||||||
|
Some(unsafe { std::ptr::read(self.vc.as_slice().get_unchecked(self.end)) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExactSizeIterator for VcIntoIter {}
|
||||||
|
|
||||||
|
impl<const SIZE: usize> From<[Nid; SIZE]> for Vc {
|
||||||
|
fn from(value: [Nid; SIZE]) -> Self {
|
||||||
|
value.as_slice().into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a [Nid]> for Vc {
|
||||||
|
fn from(value: &'a [Nid]) -> Self {
|
||||||
|
if value.len() <= INLINE_ELEMS {
|
||||||
|
let mut dflt = Self::default();
|
||||||
unsafe {
|
unsafe {
|
||||||
Vc {
|
std::ptr::copy_nonoverlapping(value.as_ptr(), dflt.as_mut_ptr(), value.len())
|
||||||
alloced: AllocedVc {
|
};
|
||||||
base: Unique::new_unchecked(alloc.cast()),
|
dflt.inline.cap = value.len() as _;
|
||||||
len: self.alloced.len,
|
dflt
|
||||||
cap: self.alloced.cap,
|
} else {
|
||||||
},
|
let mut allcd = unsafe { Self::alloc(value.len(), value.len()) };
|
||||||
}
|
unsafe {
|
||||||
}
|
std::ptr::copy_nonoverlapping(value.as_ptr(), allcd.as_mut_ptr(), value.len())
|
||||||
|
};
|
||||||
|
allcd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -135,16 +286,16 @@ impl DerefMut for Vc {
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
struct InlineVc {
|
struct InlineVc {
|
||||||
|
cap: Nid,
|
||||||
elems: MaybeUninit<[Nid; INLINE_ELEMS]>,
|
elems: MaybeUninit<[Nid; INLINE_ELEMS]>,
|
||||||
len: Nid,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
struct AllocedVc {
|
struct AllocedVc {
|
||||||
|
cap: Nid,
|
||||||
|
len: Nid,
|
||||||
base: Unique<Nid>,
|
base: Unique<Nid>,
|
||||||
cap: u32,
|
|
||||||
len: u32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
@ -162,7 +313,8 @@ impl BitSet {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
pub fn set(&mut self, idx: usize) -> bool {
|
pub fn set(&mut self, idx: Nid) -> bool {
|
||||||
|
let idx = idx as usize;
|
||||||
let data_idx = idx / Self::ELEM_SIZE;
|
let data_idx = idx / Self::ELEM_SIZE;
|
||||||
let sub_idx = idx % Self::ELEM_SIZE;
|
let sub_idx = idx % Self::ELEM_SIZE;
|
||||||
let prev = self.data[data_idx] & (1 << sub_idx);
|
let prev = self.data[data_idx] & (1 << sub_idx);
|
||||||
|
@ -170,14 +322,15 @@ impl BitSet {
|
||||||
prev == 0
|
prev == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unset(&mut self, idx: usize) {
|
fn unset(&mut self, idx: Nid) {
|
||||||
|
let idx = idx as usize;
|
||||||
let data_idx = idx / Self::ELEM_SIZE;
|
let data_idx = idx / Self::ELEM_SIZE;
|
||||||
let sub_idx = idx % Self::ELEM_SIZE;
|
let sub_idx = idx % Self::ELEM_SIZE;
|
||||||
self.data[data_idx] &= !(1 << sub_idx);
|
self.data[data_idx] &= !(1 << sub_idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Nid = u32;
|
type Nid = u16;
|
||||||
|
|
||||||
mod reg {
|
mod reg {
|
||||||
|
|
||||||
|
@ -572,7 +725,7 @@ mod ty {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LookupEntry {
|
struct LookupEntry {
|
||||||
nid: u32,
|
nid: Nid,
|
||||||
hash: u64,
|
hash: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -599,22 +752,24 @@ impl std::hash::Hash for LookupEntry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Lookup = std::collections::hash_map::HashMap<
|
||||||
|
LookupEntry,
|
||||||
|
(),
|
||||||
|
std::hash::BuildHasherDefault<IdentityHash>,
|
||||||
|
>;
|
||||||
|
|
||||||
struct Nodes {
|
struct Nodes {
|
||||||
values: Vec<Result<Node, u32>>,
|
values: Vec<Result<Node, Nid>>,
|
||||||
visited: BitSet,
|
visited: BitSet,
|
||||||
free: u32,
|
free: Nid,
|
||||||
lookup: std::collections::hash_map::HashMap<
|
lookup: Lookup,
|
||||||
LookupEntry,
|
|
||||||
(),
|
|
||||||
std::hash::BuildHasherDefault<IdentityHash>,
|
|
||||||
>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Nodes {
|
impl Default for Nodes {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
values: Default::default(),
|
values: Default::default(),
|
||||||
free: u32::MAX,
|
free: Nid::MAX,
|
||||||
lookup: Default::default(),
|
lookup: Default::default(),
|
||||||
visited: Default::default(),
|
visited: Default::default(),
|
||||||
}
|
}
|
||||||
|
@ -622,7 +777,7 @@ impl Default for Nodes {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Nodes {
|
impl Nodes {
|
||||||
fn remove_low(&mut self, id: u32) -> Node {
|
fn remove_low(&mut self, id: Nid) -> Node {
|
||||||
let value = mem::replace(&mut self.values[id as usize], Err(self.free)).unwrap();
|
let value = mem::replace(&mut self.values[id as usize], Err(self.free)).unwrap();
|
||||||
self.free = id;
|
self.free = id;
|
||||||
value
|
value
|
||||||
|
@ -631,15 +786,10 @@ impl Nodes {
|
||||||
fn clear(&mut self) {
|
fn clear(&mut self) {
|
||||||
self.values.clear();
|
self.values.clear();
|
||||||
self.lookup.clear();
|
self.lookup.clear();
|
||||||
self.free = u32::MAX;
|
self.free = Nid::MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_node_nop(
|
fn new_node_nop(&mut self, ty: impl Into<ty::Id>, kind: Kind, inps: impl Into<Vc>) -> Nid {
|
||||||
&mut self,
|
|
||||||
ty: impl Into<ty::Id>,
|
|
||||||
kind: Kind,
|
|
||||||
inps: impl Into<Vec<Nid>>,
|
|
||||||
) -> Nid {
|
|
||||||
let ty = ty.into();
|
let ty = ty.into();
|
||||||
|
|
||||||
let node = Node { inputs: inps.into(), kind, ty, ..Default::default() };
|
let node = Node { inputs: inps.into(), kind, ty, ..Default::default() };
|
||||||
|
@ -656,13 +806,13 @@ impl Nodes {
|
||||||
lookup_meta = Some((entry, hash));
|
lookup_meta = Some((entry, hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.free == u32::MAX {
|
if self.free == Nid::MAX {
|
||||||
self.free = self.values.len() as _;
|
self.free = self.values.len() as _;
|
||||||
self.values.push(Err(u32::MAX));
|
self.values.push(Err(Nid::MAX));
|
||||||
}
|
}
|
||||||
|
|
||||||
let free = self.free;
|
let free = self.free;
|
||||||
for &d in &node.inputs {
|
for &d in node.inputs.as_slice() {
|
||||||
debug_assert_ne!(d, free);
|
debug_assert_ne!(d, free);
|
||||||
self.values[d as usize].as_mut().unwrap().outputs.push(free);
|
self.values[d as usize].as_mut().unwrap().outputs.push(free);
|
||||||
}
|
}
|
||||||
|
@ -675,12 +825,8 @@ impl Nodes {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_node<'a>(
|
fn find_node<'a>(
|
||||||
lookup: &'a mut std::collections::hash_map::HashMap<
|
lookup: &'a mut Lookup,
|
||||||
LookupEntry,
|
values: &[Result<Node, Nid>],
|
||||||
(),
|
|
||||||
std::hash::BuildHasherDefault<IdentityHash>,
|
|
||||||
>,
|
|
||||||
values: &[Result<Node, u32>],
|
|
||||||
node: &Node,
|
node: &Node,
|
||||||
) -> (
|
) -> (
|
||||||
hash_map::RawEntryMut<'a, LookupEntry, (), std::hash::BuildHasherDefault<IdentityHash>>,
|
hash_map::RawEntryMut<'a, LookupEntry, (), std::hash::BuildHasherDefault<IdentityHash>>,
|
||||||
|
@ -710,7 +856,7 @@ impl Nodes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_node(&mut self, ty: impl Into<ty::Id>, kind: Kind, inps: impl Into<Vec<u32>>) -> Nid {
|
fn new_node(&mut self, ty: impl Into<ty::Id>, kind: Kind, inps: impl Into<Vc>) -> Nid {
|
||||||
let id = self.new_node_nop(ty, kind, inps);
|
let id = self.new_node_nop(ty, kind, inps);
|
||||||
if let Some(opt) = self.peephole(id) {
|
if let Some(opt) = self.peephole(id) {
|
||||||
debug_assert_ne!(opt, id);
|
debug_assert_ne!(opt, id);
|
||||||
|
@ -950,7 +1096,7 @@ impl Nodes {
|
||||||
write!(f, "{:?}.{}", self[self[node].inputs[0]].kind, index)?;
|
write!(f, "{:?}.{}", self[self[node].inputs[0]].kind, index)?;
|
||||||
} else if is_ready() {
|
} else if is_ready() {
|
||||||
writeln!(f, "{}: {:?}", node, self[node].kind)?;
|
writeln!(f, "{}: {:?}", node, self[node].kind)?;
|
||||||
for &o in &self[node].outputs {
|
for &o in self[node].outputs.iter() {
|
||||||
if self.is_cfg(o) {
|
if self.is_cfg(o) {
|
||||||
self.fmt(f, o, rcs)?;
|
self.fmt(f, o, rcs)?;
|
||||||
}
|
}
|
||||||
|
@ -964,7 +1110,7 @@ impl Nodes {
|
||||||
|
|
||||||
writeln!(f, "{}: {:?}", node, self[node].kind)?;
|
writeln!(f, "{}: {:?}", node, self[node].kind)?;
|
||||||
|
|
||||||
for &o in &self[node].outputs {
|
for &o in self[node].outputs.iter() {
|
||||||
self.fmt(f, o, rcs)?;
|
self.fmt(f, o, rcs)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -978,7 +1124,7 @@ impl Nodes {
|
||||||
self.fmt(f, value, rcs)?;
|
self.fmt(f, value, rcs)?;
|
||||||
}
|
}
|
||||||
writeln!(f, ")")?;
|
writeln!(f, ")")?;
|
||||||
for &o in &self[node].outputs {
|
for &o in self[node].outputs.iter() {
|
||||||
if self.is_cfg(o) {
|
if self.is_cfg(o) {
|
||||||
self.fmt(f, o, rcs)?;
|
self.fmt(f, o, rcs)?;
|
||||||
}
|
}
|
||||||
|
@ -1052,7 +1198,7 @@ impl Nodes {
|
||||||
|
|
||||||
fn basic_blocks_low(&mut self, out: &mut String, mut node: Nid) -> std::fmt::Result {
|
fn basic_blocks_low(&mut self, out: &mut String, mut node: Nid) -> std::fmt::Result {
|
||||||
let iter = |nodes: &Nodes, node| nodes[node].outputs.clone().into_iter().rev();
|
let iter = |nodes: &Nodes, node| nodes[node].outputs.clone().into_iter().rev();
|
||||||
while self.visited.set(node as _) {
|
while self.visited.set(node) {
|
||||||
match self[node].kind {
|
match self[node].kind {
|
||||||
Kind::Start => {
|
Kind::Start => {
|
||||||
writeln!(out, "start: {}", self[node].depth)?;
|
writeln!(out, "start: {}", self[node].depth)?;
|
||||||
|
@ -1098,7 +1244,7 @@ impl Nodes {
|
||||||
Kind::CInt { .. } => unreachable!(),
|
Kind::CInt { .. } => unreachable!(),
|
||||||
Kind::Phi => unreachable!(),
|
Kind::Phi => unreachable!(),
|
||||||
Kind::Tuple { .. } => {
|
Kind::Tuple { .. } => {
|
||||||
writeln!(out, "b{node}: {}", self[node].depth)?;
|
writeln!(out, "b{node}: {} {:?}", self[node].depth, self[node].outputs)?;
|
||||||
let mut cfg_index = Nid::MAX;
|
let mut cfg_index = Nid::MAX;
|
||||||
for o in iter(self, node) {
|
for o in iter(self, node) {
|
||||||
self.basic_blocks_instr(out, o)?;
|
self.basic_blocks_instr(out, o)?;
|
||||||
|
@ -1111,8 +1257,11 @@ impl Nodes {
|
||||||
Kind::BinOp { .. } => unreachable!(),
|
Kind::BinOp { .. } => unreachable!(),
|
||||||
Kind::Call { .. } => {
|
Kind::Call { .. } => {
|
||||||
let mut cfg_index = Nid::MAX;
|
let mut cfg_index = Nid::MAX;
|
||||||
|
let mut print_ret = true;
|
||||||
for o in iter(self, node) {
|
for o in iter(self, node) {
|
||||||
if self[o].inputs[0] == node {
|
if self[o].inputs[0] == node
|
||||||
|
&& (self[node].outputs[0] != o || std::mem::take(&mut print_ret))
|
||||||
|
{
|
||||||
self.basic_blocks_instr(out, o)?;
|
self.basic_blocks_instr(out, o)?;
|
||||||
}
|
}
|
||||||
if self.is_cfg(o) {
|
if self.is_cfg(o) {
|
||||||
|
@ -1154,7 +1303,7 @@ impl Nodes {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut allowed_cfgs = 1 + (node.kind == Kind::If) as usize;
|
let mut allowed_cfgs = 1 + (node.kind == Kind::If) as usize;
|
||||||
for &o in &node.outputs {
|
for &o in node.outputs.iter() {
|
||||||
if self.is_cfg(i) {
|
if self.is_cfg(i) {
|
||||||
if allowed_cfgs == 0 && self.is_cfg(o) {
|
if allowed_cfgs == 0 && self.is_cfg(o) {
|
||||||
log::err!(
|
log::err!(
|
||||||
|
@ -1167,13 +1316,6 @@ impl Nodes {
|
||||||
allowed_cfgs += self.is_cfg(o) as usize;
|
allowed_cfgs += self.is_cfg(o) as usize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if matches!(node.kind, Kind::Region | Kind::Loop)
|
|
||||||
&& !self.is_cfg(o)
|
|
||||||
&& self[o].kind != Kind::Phi
|
|
||||||
{
|
|
||||||
log::err!("unexpected output node on region: {:?}", self[o].kind);
|
|
||||||
failed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
let other = match &self.values[o as usize] {
|
let other = match &self.values[o as usize] {
|
||||||
Ok(other) => other,
|
Ok(other) => other,
|
||||||
|
@ -1209,7 +1351,7 @@ impl Nodes {
|
||||||
for i in 0..nodes[from].inputs.len() {
|
for i in 0..nodes[from].inputs.len() {
|
||||||
let n = nodes[from].inputs[i];
|
let n = nodes[from].inputs[i];
|
||||||
if n != Nid::MAX
|
if n != Nid::MAX
|
||||||
&& nodes.visited.set(n as usize)
|
&& nodes.visited.set(n)
|
||||||
&& !nodes.is_cfg(n)
|
&& !nodes.is_cfg(n)
|
||||||
&& (for_each(n, &nodes[n]) || climb_impl(nodes, n, for_each))
|
&& (for_each(n, &nodes[n]) || climb_impl(nodes, n, for_each))
|
||||||
{
|
{
|
||||||
|
@ -1257,16 +1399,16 @@ impl Nodes {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::Index<u32> for Nodes {
|
impl ops::Index<Nid> for Nodes {
|
||||||
type Output = Node;
|
type Output = Node;
|
||||||
|
|
||||||
fn index(&self, index: u32) -> &Self::Output {
|
fn index(&self, index: Nid) -> &Self::Output {
|
||||||
self.values[index as usize].as_ref().unwrap()
|
self.values[index as usize].as_ref().unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::IndexMut<u32> for Nodes {
|
impl ops::IndexMut<Nid> for Nodes {
|
||||||
fn index_mut(&mut self, index: u32) -> &mut Self::Output {
|
fn index_mut(&mut self, index: Nid) -> &mut Self::Output {
|
||||||
self.values[index as usize].as_mut().unwrap()
|
self.values[index as usize].as_mut().unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1337,15 +1479,16 @@ impl fmt::Display for Kind {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
|
//#[repr(align(64))]
|
||||||
struct Node {
|
struct Node {
|
||||||
inputs: Vec<Nid>,
|
inputs: Vc,
|
||||||
outputs: Vec<Nid>,
|
outputs: Vc,
|
||||||
kind: Kind,
|
kind: Kind,
|
||||||
color: u32,
|
color: Color,
|
||||||
depth: u32,
|
depth: IDomDepth,
|
||||||
lock_rc: u32,
|
lock_rc: LockRc,
|
||||||
ty: ty::Id,
|
ty: ty::Id,
|
||||||
loop_depth: u32,
|
loop_depth: LoopDepth,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Node {
|
impl Node {
|
||||||
|
@ -1384,6 +1527,11 @@ impl fmt::Display for Nodes {
|
||||||
type Offset = u32;
|
type Offset = u32;
|
||||||
type Size = u32;
|
type Size = u32;
|
||||||
type ArrayLen = u32;
|
type ArrayLen = u32;
|
||||||
|
type Color = u16;
|
||||||
|
type LoopDepth = u16;
|
||||||
|
type CallCount = u16;
|
||||||
|
type LockRc = u16;
|
||||||
|
type IDomDepth = u16;
|
||||||
|
|
||||||
struct Loop {
|
struct Loop {
|
||||||
node: Nid,
|
node: Nid,
|
||||||
|
@ -1400,8 +1548,8 @@ struct Variable {
|
||||||
|
|
||||||
struct ColorMeta {
|
struct ColorMeta {
|
||||||
rc: u32,
|
rc: u32,
|
||||||
depth: u32,
|
depth: LoopDepth,
|
||||||
call_count: u32,
|
call_count: CallCount,
|
||||||
loc: Loc,
|
loc: Loc,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1418,11 +1566,11 @@ struct ItemCtx {
|
||||||
end: Nid,
|
end: Nid,
|
||||||
ctrl: Nid,
|
ctrl: Nid,
|
||||||
|
|
||||||
loop_depth: u32,
|
loop_depth: LoopDepth,
|
||||||
colors: Vec<ColorMeta>,
|
colors: Vec<ColorMeta>,
|
||||||
call_count: u32,
|
call_count: u16,
|
||||||
filled: Vec<Nid>,
|
filled: Vec<Nid>,
|
||||||
delayed_frees: Vec<u32>,
|
delayed_frees: Vec<Color>,
|
||||||
|
|
||||||
loops: Vec<Loop>,
|
loops: Vec<Loop>,
|
||||||
vars: Vec<Variable>,
|
vars: Vec<Variable>,
|
||||||
|
@ -1433,7 +1581,7 @@ struct ItemCtx {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ItemCtx {
|
impl ItemCtx {
|
||||||
fn next_color(&mut self) -> u32 {
|
fn next_color(&mut self) -> Color {
|
||||||
self.colors.push(ColorMeta {
|
self.colors.push(ColorMeta {
|
||||||
rc: 0,
|
rc: 0,
|
||||||
call_count: self.call_count,
|
call_count: self.call_count,
|
||||||
|
@ -1448,7 +1596,7 @@ impl ItemCtx {
|
||||||
self.set_color(node, color);
|
self.set_color(node, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_color(&mut self, node: Nid, color: u32) {
|
fn set_color(&mut self, node: Nid, color: Color) {
|
||||||
if self.nodes[node].color != 0 {
|
if self.nodes[node].color != 0 {
|
||||||
debug_assert_ne!(self.nodes[node].color, color);
|
debug_assert_ne!(self.nodes[node].color, color);
|
||||||
self.colors[self.nodes[node].color as usize - 1].rc -= 1;
|
self.colors[self.nodes[node].color as usize - 1].rc -= 1;
|
||||||
|
@ -1457,7 +1605,7 @@ impl ItemCtx {
|
||||||
self.colors[color as usize - 1].rc += 1;
|
self.colors[color as usize - 1].rc += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn recolor(&mut self, node: Nid, from: u32, to: u32) {
|
fn recolor(&mut self, node: Nid, from: Color, to: Color) {
|
||||||
if from == to {
|
if from == to {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2097,7 +2245,7 @@ impl Codegen {
|
||||||
for var in &mut self.ci.vars {
|
for var in &mut self.ci.vars {
|
||||||
var.value = 0;
|
var.value = 0;
|
||||||
}
|
}
|
||||||
self.ci.nodes[0].lock_rc += self.ci.vars.len() as u32;
|
self.ci.nodes[0].lock_rc += self.ci.vars.len() as LockRc;
|
||||||
|
|
||||||
self.expr(body);
|
self.expr(body);
|
||||||
|
|
||||||
|
@ -2200,7 +2348,7 @@ impl Codegen {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut inps = vec![self.ci.ctrl];
|
let mut inps = Vc::from([self.ci.ctrl]);
|
||||||
for ((arg, carg), tyx) in args.iter().zip(cargs).zip(sig.args.range()) {
|
for ((arg, carg), tyx) in args.iter().zip(cargs).zip(sig.args.range()) {
|
||||||
let ty = self.tys.args[tyx];
|
let ty = self.tys.args[tyx];
|
||||||
if self.tys.size_of(ty) == 0 {
|
if self.tys.size_of(ty) == 0 {
|
||||||
|
@ -2382,8 +2530,8 @@ impl Codegen {
|
||||||
let ty = self.ci.nodes[var.value].ty;
|
let ty = self.ci.nodes[var.value].ty;
|
||||||
if self.ci.nodes.unlock_remove(var.value) {
|
if self.ci.nodes.unlock_remove(var.value) {
|
||||||
// mark as unused
|
// mark as unused
|
||||||
orig_vars[i].id = u32::MAX;
|
orig_vars[i].id = ty.repr();
|
||||||
orig_vars[i].value = ty.repr();
|
orig_vars[i].value = Nid::MAX;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2394,8 +2542,6 @@ impl Codegen {
|
||||||
log::inf!("{id} {name}: ");
|
log::inf!("{id} {name}: ");
|
||||||
self.ci.nodes.basic_blocks();
|
self.ci.nodes.basic_blocks();
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
{
|
{
|
||||||
self.ci.nodes.check_final_integrity();
|
self.ci.nodes.check_final_integrity();
|
||||||
|
@ -2413,7 +2559,7 @@ impl Codegen {
|
||||||
let call_count = self.ci.call_count;
|
let call_count = self.ci.call_count;
|
||||||
'_color_args: {
|
'_color_args: {
|
||||||
for var in &orig_vars {
|
for var in &orig_vars {
|
||||||
if var.id != u32::MAX {
|
if var.value != Nid::MAX {
|
||||||
self.ci.set_next_color(var.value);
|
self.ci.set_next_color(var.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2618,7 +2764,7 @@ impl Codegen {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use = "dont forget to drop the location"]
|
#[must_use = "dont forget to drop the location"]
|
||||||
fn color_expr_consume(&mut self, expr: Nid) -> Option<u32> {
|
fn color_expr_consume(&mut self, expr: Nid) -> Option<Color> {
|
||||||
if self.ci.nodes[expr].lock_rc == 0 && self.ci.nodes[expr].kind != Kind::Phi {
|
if self.ci.nodes[expr].lock_rc == 0 && self.ci.nodes[expr].kind != Kind::Phi {
|
||||||
self.ci.nodes[expr].depth = self.ci.loop_depth;
|
self.ci.nodes[expr].depth = self.ci.loop_depth;
|
||||||
self.color_expr(expr);
|
self.color_expr(expr);
|
||||||
|
@ -2653,7 +2799,7 @@ impl Codegen {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn use_colored_expr(&mut self, expr: Nid) -> Option<u32> {
|
fn use_colored_expr(&mut self, expr: Nid) -> Option<Color> {
|
||||||
self.ci.nodes[expr].lock_rc += 1;
|
self.ci.nodes[expr].lock_rc += 1;
|
||||||
debug_assert_ne!(self.ci.nodes[expr].color, 0, "{:?}", self.ci.nodes[expr].kind);
|
debug_assert_ne!(self.ci.nodes[expr].color, 0, "{:?}", self.ci.nodes[expr].kind);
|
||||||
(self.ci.nodes[expr].lock_rc as usize >= self.ci.nodes[expr].outputs.len()
|
(self.ci.nodes[expr].lock_rc as usize >= self.ci.nodes[expr].outputs.len()
|
||||||
|
@ -2941,10 +3087,10 @@ impl Codegen {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_expr(&mut self, expr: Nid) {
|
fn emit_expr(&mut self, expr: Nid) {
|
||||||
if self.ci.nodes[expr].depth == u32::MAX {
|
if self.ci.nodes[expr].depth == IDomDepth::MAX {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.ci.nodes[expr].depth = u32::MAX;
|
self.ci.nodes[expr].depth = IDomDepth::MAX;
|
||||||
self.ci.filled.push(expr);
|
self.ci.filled.push(expr);
|
||||||
|
|
||||||
match self.ci.nodes[expr].kind {
|
match self.ci.nodes[expr].kind {
|
||||||
|
@ -2963,8 +3109,8 @@ impl Codegen {
|
||||||
|
|
||||||
let mut params = self.tys.parama(self.ci.ret.unwrap());
|
let mut params = self.tys.parama(self.ci.ret.unwrap());
|
||||||
for (i, var) in self.ci.vars.iter().enumerate() {
|
for (i, var) in self.ci.vars.iter().enumerate() {
|
||||||
if var.id == u32::MAX {
|
if var.value == Nid::MAX {
|
||||||
match self.tys.size_of(ty::Id::from_bt(var.value)) {
|
match self.tys.size_of(ty::Id::from_bt(var.id)) {
|
||||||
0 => {}
|
0 => {}
|
||||||
1..=8 => _ = params.next(),
|
1..=8 => _ = params.next(),
|
||||||
s => todo!("{s}"),
|
s => todo!("{s}"),
|
||||||
|
@ -2994,7 +3140,7 @@ impl Codegen {
|
||||||
|
|
||||||
if let Kind::CInt { value } = self.ci.nodes[right].kind
|
if let Kind::CInt { value } = self.ci.nodes[right].kind
|
||||||
&& (node_loc!(self, right) == Loc::default()
|
&& (node_loc!(self, right) == Loc::default()
|
||||||
|| self.ci.nodes[right].depth != u32::MAX)
|
|| self.ci.nodes[right].depth != IDomDepth::MAX)
|
||||||
&& let Some(op) = Self::imm_math_op(op, ty.is_signed(), self.tys.size_of(ty))
|
&& let Some(op) = Self::imm_math_op(op, ty.is_signed(), self.tys.size_of(ty))
|
||||||
{
|
{
|
||||||
let instr =
|
let instr =
|
||||||
|
@ -3361,7 +3507,7 @@ impl Codegen {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gcm(&mut self) {
|
fn gcm(&mut self) {
|
||||||
fn loop_depth(target: Nid, nodes: &mut Nodes) -> u32 {
|
fn loop_depth(target: Nid, nodes: &mut Nodes) -> LoopDepth {
|
||||||
if nodes[target].loop_depth != 0 {
|
if nodes[target].loop_depth != 0 {
|
||||||
return nodes[target].loop_depth;
|
return nodes[target].loop_depth;
|
||||||
}
|
}
|
||||||
|
@ -3402,7 +3548,7 @@ impl Codegen {
|
||||||
|| nodes[then].kind == Kind::If
|
|| nodes[then].kind == Kind::If
|
||||||
}
|
}
|
||||||
|
|
||||||
fn idepth(nodes: &mut Nodes, target: Nid) -> u32 {
|
fn idepth(nodes: &mut Nodes, target: Nid) -> IDomDepth {
|
||||||
if target == 0 {
|
if target == 0 {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -3433,7 +3579,7 @@ impl Codegen {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_up(nodes: &mut Nodes, node: Nid) {
|
fn push_up(nodes: &mut Nodes, node: Nid) {
|
||||||
if !nodes.visited.set(node as _) {
|
if !nodes.visited.set(node) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3475,7 +3621,7 @@ impl Codegen {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_down(nodes: &mut Nodes, node: Nid) {
|
fn push_down(nodes: &mut Nodes, node: Nid) {
|
||||||
if !nodes.visited.set(node as _) {
|
if !nodes.visited.set(node) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3551,75 +3697,12 @@ impl Codegen {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct LoggedMem {
|
|
||||||
pub mem: hbvm::mem::HostMemory,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl hbvm::mem::Memory for LoggedMem {
|
|
||||||
unsafe fn load(
|
|
||||||
&mut self,
|
|
||||||
addr: hbvm::mem::Address,
|
|
||||||
target: *mut u8,
|
|
||||||
count: usize,
|
|
||||||
) -> Result<(), hbvm::mem::LoadError> {
|
|
||||||
log::trc!(
|
|
||||||
"load: {:x} {:?}",
|
|
||||||
addr.get(),
|
|
||||||
core::slice::from_raw_parts(addr.get() as *const u8, count)
|
|
||||||
.iter()
|
|
||||||
.rev()
|
|
||||||
.map(|&b| format!("{b:02x}"))
|
|
||||||
.collect::<String>()
|
|
||||||
);
|
|
||||||
self.mem.load(addr, target, count)
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn store(
|
|
||||||
&mut self,
|
|
||||||
addr: hbvm::mem::Address,
|
|
||||||
source: *const u8,
|
|
||||||
count: usize,
|
|
||||||
) -> Result<(), hbvm::mem::StoreError> {
|
|
||||||
log::trc!(
|
|
||||||
"store: {:x} {:?}",
|
|
||||||
addr.get(),
|
|
||||||
core::slice::from_raw_parts(source, count)
|
|
||||||
.iter()
|
|
||||||
.rev()
|
|
||||||
.map(|&b| format!("{b:02x}"))
|
|
||||||
.collect::<String>()
|
|
||||||
);
|
|
||||||
self.mem.store(addr, source, count)
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn prog_read<T: Copy>(&mut self, addr: hbvm::mem::Address) -> T {
|
|
||||||
log::trc!(
|
|
||||||
"read-typed: {:x} {} {:?}",
|
|
||||||
addr.get(),
|
|
||||||
std::any::type_name::<T>(),
|
|
||||||
if core::mem::size_of::<T>() == 1
|
|
||||||
&& let Some(nm) =
|
|
||||||
instrs::NAMES.get(std::ptr::read(addr.get() as *const u8) as usize)
|
|
||||||
{
|
|
||||||
nm.to_string()
|
|
||||||
} else {
|
|
||||||
core::slice::from_raw_parts(addr.get() as *const u8, core::mem::size_of::<T>())
|
|
||||||
.iter()
|
|
||||||
.map(|&b| format!("{:02x}", b))
|
|
||||||
.collect::<String>()
|
|
||||||
}
|
|
||||||
);
|
|
||||||
self.mem.prog_read(addr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
parser::{self, FileId},
|
parser::{self, FileId},
|
||||||
son::LoggedMem,
|
LoggedMem,
|
||||||
},
|
},
|
||||||
std::io,
|
std::io,
|
||||||
};
|
};
|
||||||
|
@ -3656,13 +3739,13 @@ mod tests {
|
||||||
let mut last_start = 0;
|
let mut last_start = 0;
|
||||||
let mut last_module_name = "test";
|
let mut last_module_name = "test";
|
||||||
for (i, m) in input.match_indices("// in module: ") {
|
for (i, m) in input.match_indices("// in module: ") {
|
||||||
parser::test::format(ident, input[last_start..i].trim());
|
//parser::test::format(ident, input[last_start..i].trim());
|
||||||
module_map.push((last_module_name, &input[last_start..i]));
|
module_map.push((last_module_name, &input[last_start..i]));
|
||||||
let (module_name, _) = input[i + m.len()..].split_once('\n').unwrap();
|
let (module_name, _) = input[i + m.len()..].split_once('\n').unwrap();
|
||||||
last_module_name = module_name;
|
last_module_name = module_name;
|
||||||
last_start = i + m.len() + module_name.len() + 1;
|
last_start = i + m.len() + module_name.len() + 1;
|
||||||
}
|
}
|
||||||
parser::test::format(ident, input[last_start..].trim());
|
//parser::test::format(ident, input[last_start..].trim());
|
||||||
module_map.push((last_module_name, input[last_start..].trim()));
|
module_map.push((last_module_name, input[last_start..].trim()));
|
||||||
|
|
||||||
let loader = |path: &str, _: &str| {
|
let loader = |path: &str, _: &str| {
|
||||||
|
@ -3702,8 +3785,6 @@ mod tests {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
let mut stack = [0_u64; 128];
|
let mut stack = [0_u64; 128];
|
||||||
|
|
||||||
let mut vm = unsafe {
|
let mut vm = unsafe {
|
||||||
|
|
Loading…
Reference in a new issue