slices (offsets now real in backend)

This commit is contained in:
2024-12-07 23:56:00 -05:00
parent 0e0dbd647d
commit 606cb30c6b
14 changed files with 305 additions and 215 deletions

View File

@@ -1,8 +1,8 @@
use crate::compiler::arch::riscv64::Reg;
use std::fmt::Write;
use super::{arch::riscv64::RV64Instruction, DataID, FnID, VarID};
use super::{arch::riscv64::RV64Instruction, DataID, FnID, Len, VarID};
use crate::{compiler::arch::riscv64::Reg, util::Padder};
#[derive(Debug)]
pub struct IRUFunction {
pub name: String,
pub args: Vec<VarID>,
@@ -22,6 +22,11 @@ pub enum IRUInstruction {
dest: VarID,
src: DataID,
},
LoadSlice {
dest: VarID,
src: DataID,
len: Len,
},
LoadFn {
dest: VarID,
src: FnID,
@@ -70,6 +75,7 @@ impl std::fmt::Debug for IRUInstruction {
Self::Ref { dest, src } => write!(f, "{dest:?} <- &{src:?}"),
Self::LoadData { dest, src } => write!(f, "{dest:?} <- {src:?}"),
Self::LoadFn { dest, src } => write!(f, "{dest:?} <- {src:?}"),
Self::LoadSlice { dest, src, len } => write!(f, "{dest:?} <- &[{src:?}; {len}]"),
Self::Call {
dest,
f: func,
@@ -80,3 +86,21 @@ impl std::fmt::Debug for IRUInstruction {
}
}
}
impl std::fmt::Debug for IRUFunction {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}{:?}", &self.name, self.args)?;
if !self.instructions.is_empty() {
f.write_str("{\n ")?;
let mut padder = Padder::new(f);
for i in &self.instructions {
// they don't expose wrap_buf :grief:
padder.write_str(&format!("{i:?};\n"))?;
}
f.write_char('}')?;
} else {
f.write_str("{}")?;
}
Ok(())
}
}

View File

@@ -19,7 +19,7 @@ pub struct Namespace {
impl Namespace {
pub fn new() -> Self {
let mut s = Self {
Self {
fn_defs: Vec::new(),
var_defs: Vec::new(),
type_defs: Vec::new(),
@@ -28,11 +28,7 @@ impl Namespace {
fns: Vec::new(),
temp: 0,
stack: vec![HashMap::new()],
};
for b in BuiltinType::enumerate() {
s.def_type(b.def());
}
s
}
pub fn push(&mut self) -> NamespaceGuard {
self.stack.push(HashMap::new());
@@ -76,6 +72,27 @@ impl Namespace {
self.var_defs.push(var);
VarID(i)
}
pub fn size_of_type(&self, ty: &Type) -> Option<Size> {
// TODO: target matters
Some(match ty {
Type::Concrete(id) => {
let def = &self.type_defs[id.0];
todo!()
}
Type::Bits(b) => *b,
Type::Generic { base, args } => todo!(),
Type::Fn { args, ret } => todo!(),
Type::Ref(_) => 64,
Type::Array(ty, len) => self.size_of_type(ty)? * len,
Type::Slice(_) => 128,
Type::Infer => return None,
Type::Error => return None,
Type::Unit => 0,
})
}
pub fn size_of_var(&self, var: &VarID) -> Option<Size> {
self.size_of_type(&self.var_defs[var.0].ty)
}
pub fn temp_var(&mut self, origin: FileSpan, ty: Type) -> VarID {
let v = self.def_var(VarDef {
name: format!("temp{}", self.temp),
@@ -151,7 +168,9 @@ impl Namespace {
Type::Error => str += "{error}",
Type::Infer => str += "{inferred}",
Type::Bits(size) => str += &format!("b{}", size),
Type::Array(t) => str += &format!("[{}]", self.type_name(t)),
Type::Array(t, len) => str += &format!("[{}; {len}]", self.type_name(t)),
Type::Unit => str += "()",
Type::Slice(t) => str += &format!("&[{}]", self.type_name(t)),
}
str
}
@@ -167,6 +186,16 @@ impl Namespace {
pub fn write_fn(&mut self, id: FnID, f: IRUFunction) {
self.fns[id.0] = Some(f);
}
pub fn iter_vars(&self) -> impl Iterator<Item = (VarID, &VarDef)> {
(0..self.var_defs.len())
.map(|i| VarID(i))
.zip(self.var_defs.iter())
}
pub fn iter_fns(&self) -> impl Iterator<Item = (FnID, Option<&IRUFunction>)> {
(0..self.fns.len())
.map(|i| FnID(i))
.zip(self.fns.iter().map(|f| f.as_ref()))
}
}
pub struct NamespaceGuard<'a>(&'a mut Namespace);

View File

@@ -1,4 +1,4 @@
use super::{Origin, TypeDef, TypeID};
use super::{Len, TypeID};
#[derive(Clone)]
pub enum Type {
@@ -7,47 +7,21 @@ pub enum Type {
Generic { base: TypeID, args: Vec<Type> },
Fn { args: Vec<Type>, ret: Box<Type> },
Ref(Box<Type>),
Array(Box<Type>),
Slice(Box<Type>),
Array(Box<Type>, Len),
Infer,
Error,
Unit,
}
impl Type {
pub fn rf(self) -> Self {
Self::Ref(Box::new(self))
}
pub fn arr(self) -> Self {
Self::Array(Box::new(self))
pub fn arr(self, len: Len) -> Self {
Self::Array(Box::new(self), len)
}
pub fn slice(self) -> Self {
Self::Slice(Box::new(self))
}
}
#[repr(usize)]
#[derive(Debug, Clone, Copy)]
pub enum BuiltinType {
Unit,
}
impl BuiltinType {
pub fn enumerate() -> &'static [Self; 1] {
&[Self::Unit]
}
pub fn def(&self) -> TypeDef {
match self {
BuiltinType::Unit => TypeDef {
name: "()".to_string(),
args: 0,
origin: Origin::Builtin,
},
}
}
pub fn id(&self) -> TypeID {
TypeID::builtin(self)
}
}
impl TypeID {
pub fn builtin(ty: &BuiltinType) -> Self {
Self(*ty as usize)
}
}