This commit is contained in:
nora 2023-05-23 13:21:56 +02:00
parent d3846e3357
commit 77e18126e7
9 changed files with 312 additions and 129 deletions

1
Cargo.lock generated
View file

@ -574,6 +574,7 @@ name = "uwucc"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"analysis", "analysis",
"bumpalo",
"dbg-pls", "dbg-pls",
"parser", "parser",
] ]

View file

@ -9,6 +9,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
bumpalo = "3.10.0"
analysis = { path = "./analysis" } analysis = { path = "./analysis" }
parser = { path = "./parser" } parser = { path = "./parser" }
dbg-pls = { version = "0.3.2", features = ["derive", "colors"] } dbg-pls = { version = "0.3.2", features = ["derive", "colors"] }

View file

@ -33,6 +33,8 @@
mod pretty; mod pretty;
use std::fmt::{Debug, Display};
use parser::{Span, Symbol}; use parser::{Span, Symbol};
pub use pretty::{func_to_string, ir_to_string}; pub use pretty::{func_to_string, ir_to_string};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
@ -43,30 +45,33 @@ use crate::ty::Ty;
pub struct DefId(u32); pub struct DefId(u32);
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct TyLayout { pub struct TyLayout<'cx> {
pub ty: Ty, pub ty: Ty<'cx>,
pub layout: Layout, pub layout: &'cx Layout,
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Layout { pub struct Layout {
pub size: u64, pub size: u64,
pub align: u64, pub align: u64,
} }
pub struct Ir { pub struct Ir<'cx> {
pub funcs: FxHashMap<DefId, Func>, pub funcs: FxHashMap<DefId, Func<'cx>>,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Func { pub struct Func<'cx> {
pub regs: Vec<RegisterData>, pub regs: Vec<RegisterData<'cx>>,
pub bbs: Vec<BasicBlock>, pub bbs: Vec<BasicBlock>,
pub name: Symbol, pub name: Symbol,
pub def_span: Span, pub def_span: Span,
pub ret_ty: Ty, pub ret_ty: Ty<'cx>,
} }
#[derive(Clone, Copy)]
pub struct BbIdx(pub u32);
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct BasicBlock { pub struct BasicBlock {
pub statements: Vec<Statement>, pub statements: Vec<Statement>,
@ -74,8 +79,8 @@ pub struct BasicBlock {
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct RegisterData { pub struct RegisterData<'cx> {
pub tyl: TyLayout, pub tyl: TyLayout<'cx>,
pub name: Option<Symbol>, pub name: Option<Symbol>,
} }
@ -133,8 +138,12 @@ pub enum Operand {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Branch { pub enum Branch {
Goto(u32), Goto(BbIdx),
Switch { cond: Operand, yes: u32, no: u32 }, Switch {
cond: Operand,
yes: BbIdx,
no: BbIdx,
},
Ret(Operand), Ret(Operand),
} }
@ -159,6 +168,33 @@ pub enum ConstValue {
Int(u128), Int(u128),
} }
impl Func<'_> {
pub fn bb_mut(&mut self, i: BbIdx) -> &mut BasicBlock {
&mut self.bbs[i.as_usize()]
}
}
impl BbIdx {
pub fn from_usize(n: usize) -> Self {
Self(n.try_into().unwrap())
}
pub fn as_usize(self) -> usize {
self.0 as _
}
}
impl Debug for BbIdx {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "bb{}", self.0)
}
}
impl Display for BbIdx {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "bb{}", self.0)
}
}
impl Layout { impl Layout {
pub fn size_align(size: u64, align: u64) -> Self { pub fn size_align(size: u64, align: u64) -> Self {
Self { size, align } Self { size, align }

View file

@ -1,15 +1,15 @@
use std::fmt::{Display, Formatter, Result, Write}; use std::fmt::{Display, Formatter, Result, Write};
use super::{BinKind, Branch, ConstValue, Func, Ir, Operand, StatementKind}; use super::{BinKind, Branch, ConstValue, Func, Ir, Operand, StatementKind, BbIdx};
use crate::ir::Register; use crate::ir::Register;
pub fn ir_to_string(ir: &Ir) -> String { pub fn ir_to_string(ir: &Ir<'_>) -> String {
let mut buf = String::new(); let mut buf = String::new();
PrettyPrinter { out: &mut buf }.ir(ir).unwrap(); PrettyPrinter { out: &mut buf }.ir(ir).unwrap();
buf buf
} }
pub fn func_to_string(func: &Func) -> String { pub fn func_to_string(func: &Func<'_>) -> String {
let mut buf = String::new(); let mut buf = String::new();
PrettyPrinter { out: &mut buf }.func(func).unwrap(); PrettyPrinter { out: &mut buf }.func(func).unwrap();
buf buf
@ -20,14 +20,14 @@ pub struct PrettyPrinter<W> {
} }
impl<W: Write> PrettyPrinter<W> { impl<W: Write> PrettyPrinter<W> {
pub fn ir(&mut self, ir: &Ir) -> Result { pub fn ir(&mut self, ir: &Ir<'_>) -> Result {
for (_, func) in &ir.funcs { for (_, func) in &ir.funcs {
self.func(func)?; self.func(func)?;
} }
Ok(()) Ok(())
} }
pub fn func(&mut self, func: &Func) -> Result { pub fn func(&mut self, func: &Func<'_>) -> Result {
writeln!(self.out, "def {}() {{", func.name)?; writeln!(self.out, "def {}() {{", func.name)?;
let print_reg = |reg: Register| { let print_reg = |reg: Register| {
@ -48,7 +48,7 @@ impl<W: Write> PrettyPrinter<W> {
if i > 0 { if i > 0 {
writeln!(self.out)?; writeln!(self.out)?;
} }
writeln!(self.out, " {i}:")?; writeln!(self.out, " {}:", BbIdx::from_usize(i))?;
for stmt in &bb.statements { for stmt in &bb.statements {
match stmt.kind { match stmt.kind {
@ -144,9 +144,11 @@ impl<W: Write> PrettyPrinter<W> {
match bb.term { match bb.term {
Branch::Goto(bbn) => writeln!(self.out, " goto {}", bbn)?, Branch::Goto(bbn) => writeln!(self.out, " goto {}", bbn)?,
Branch::Switch { cond, yes, no } => { Branch::Switch { cond, yes, no } => writeln!(
writeln!(self.out, " switch {}, {yes}, {no}", print_op(cond))? self.out,
} " switch {}, then {yes}, else {no}",
print_op(cond)
)?,
Branch::Ret(op) => writeln!(self.out, " ret {}", print_op(op))?, Branch::Ret(op) => writeln!(self.out, " ret {}", print_op(op))?,
} }
} }

View file

@ -1,24 +1,104 @@
mod builder; mod builder;
use std::cell::RefCell;
use parser::{ use parser::{
ast::{self, Atom, DeclAttr, Expr, ExternalDecl, Stmt, TranslationUnit, TypeSpecifier}, ast::{self, Atom, DeclAttr, Expr, ExternalDecl, Stmt, TranslationUnit, TypeSpecifier},
Span, Symbol, Span, Symbol,
}; };
use rustc_hash::FxHashMap; use rustc_hash::{FxHashMap, FxHashSet};
use self::builder::FuncBuilder; use self::builder::FuncBuilder;
use crate::{ use crate::{
ir::{BinKind, ConstValue, Func, Ir, Layout, Operand, Register, TyLayout}, ir::{BinKind, Branch, ConstValue, Func, Ir, Layout, Operand, Register, TyLayout},
ty::Ty, ty::{Ty, TyKind},
Error, Error,
}; };
type Result<T, E = Error> = std::result::Result<T, E>; type Result<T, E = Error> = std::result::Result<T, E>;
struct LoweringCx {} #[derive(Debug)]
struct LoweringCx<'cx> {
tys: RefCell<FxHashSet<&'cx TyKind<'cx>>>,
layouts: RefCell<FxHashSet<&'cx Layout>>,
arena: &'cx bumpalo::Bump,
}
pub fn lower_translation_unit(ast: &TranslationUnit) -> Result<Ir, Error> { impl<'cx> LoweringCx<'cx> {
let mut lcx = LoweringCx {}; fn lower_ty(&self, ty: &TypeSpecifier) -> Ty<'cx> {
let kind = match ty {
TypeSpecifier::Void => TyKind::Void,
TypeSpecifier::Char => TyKind::Char,
TypeSpecifier::SChar => TyKind::SChar,
TypeSpecifier::UChar => TyKind::UChar,
TypeSpecifier::Integer(int) => TyKind::Integer(*int),
TypeSpecifier::Float => TyKind::Float,
TypeSpecifier::Double => TyKind::Double,
TypeSpecifier::LongDouble => TyKind::LongDouble,
TypeSpecifier::Bool => TyKind::Bool,
};
self.intern_ty(kind)
}
fn intern_ty(&self, kind: TyKind<'cx>) -> Ty<'cx> {
let opt_kind = self.tys.borrow().get(&kind).copied();
match opt_kind {
Some(ty) => Ty::new_unchecked(ty),
None => {
let kind = self.arena.alloc(kind);
self.tys.borrow_mut().insert(kind);
Ty::new_unchecked(kind)
}
}
}
fn intern_layout(&self, layout: Layout) -> &'cx Layout {
let opt_layout = self.layouts.borrow().get(&layout).copied();
match opt_layout {
Some(layout) => layout,
None => {
let layout = self.arena.alloc(layout);
self.layouts.borrow_mut().insert(layout);
layout
}
}
}
fn layout_of(&self, ty: Ty<'cx>) -> TyLayout<'cx> {
let layout = match *ty {
TyKind::Void => Layout::size_align(0, 1),
TyKind::Char => Layout::size_align(1, 1),
TyKind::SChar => Layout::size_align(1, 1),
TyKind::UChar => Layout::size_align(1, 1),
TyKind::Integer(int) => match int.kind {
parser::ast::IntTyKind::Short => Layout::size_align(2, 2),
parser::ast::IntTyKind::Int => Layout::size_align(4, 4),
parser::ast::IntTyKind::Long => Layout::size_align(8, 8),
parser::ast::IntTyKind::LongLong => Layout::size_align(8, 8),
},
TyKind::Float => Layout::size_align(4, 4),
TyKind::Double => Layout::size_align(8, 8),
TyKind::LongDouble => Layout::size_align(8, 8),
TyKind::Bool => Layout::size_align(1, 1),
TyKind::Struct(_) => todo!("layout_of struct"),
TyKind::Union(_) => todo!("layout_of union"),
TyKind::Enum(_) => todo!("layout_of enum"),
TyKind::Ptr(_) => Layout::size_align(8, 8),
};
let layout = self.intern_layout(layout);
TyLayout { ty, layout }
}
}
pub fn lower_translation_unit<'cx>(
arena: &'cx bumpalo::Bump,
ast: &TranslationUnit,
) -> Result<Ir<'cx>, Error> {
let mut lcx = LoweringCx {
tys: RefCell::default(),
layouts: RefCell::default(),
arena,
};
for (decl, _) in ast { for (decl, _) in ast {
match decl { match decl {
@ -26,7 +106,7 @@ pub fn lower_translation_unit(ast: &TranslationUnit) -> Result<Ir, Error> {
ExternalDecl::FunctionDef(def) => { ExternalDecl::FunctionDef(def) => {
let decl = def.decl.uwnrap_normal(); let decl = def.decl.uwnrap_normal();
let body = &def.body; let body = &def.body;
let ret_ty = lower_ty(&decl.decl_spec.ty); let ret_ty = lcx.lower_ty(&decl.decl_spec.ty);
lower_body( lower_body(
&mut lcx, &mut lcx,
body, body,
@ -38,17 +118,18 @@ pub fn lower_translation_unit(ast: &TranslationUnit) -> Result<Ir, Error> {
} }
} }
todo!() todo!("building is not really")
} }
#[derive(Debug)] #[derive(Debug)]
struct FnLoweringCtxt { struct FnLoweringCtxt<'a, 'cx> {
scopes: Vec<FxHashMap<Symbol, VariableInfo>>, scopes: Vec<FxHashMap<Symbol, VariableInfo<'cx>>>,
build: FuncBuilder, build: FuncBuilder<'a, 'cx>,
lcx: &'a LoweringCx<'cx>,
} }
impl FnLoweringCtxt { impl<'a, 'cx> FnLoweringCtxt<'a, 'cx> {
fn resolve_ident(&self, ident: Symbol) -> Option<&VariableInfo> { fn resolve_ident(&self, ident: Symbol) -> Option<&VariableInfo<'cx>> {
self.scopes.iter().rev().find_map(|s| s.get(&ident)) self.scopes.iter().rev().find_map(|s| s.get(&ident))
} }
@ -63,11 +144,11 @@ impl FnLoweringCtxt {
match stmt { match stmt {
Stmt::Decl(decl) => { Stmt::Decl(decl) => {
let decl = decl.uwnrap_normal(); let decl = decl.uwnrap_normal();
let ty = lower_ty(&decl.decl_spec.ty); let ty = self.lcx.lower_ty(&decl.decl_spec.ty);
let decl_attr = decl.decl_spec.attrs; let decl_attr = decl.decl_spec.attrs;
for (var, def_span) in &decl.init_declarators { for (var, def_span) in &decl.init_declarators {
let tyl = layout_of(ty.clone()); let tyl = self.lcx.layout_of(ty.clone());
let (name, _) = var.declarator.decl.name(); let (name, _) = var.declarator.decl.name();
let ptr_to = self.build.alloca(&tyl.layout, Some(name), stmt_span); let ptr_to = self.build.alloca(&tyl.layout, Some(name), stmt_span);
@ -75,18 +156,50 @@ impl FnLoweringCtxt {
def_span: *def_span, def_span: *def_span,
ptr_to, ptr_to,
decl_attr, decl_attr,
tyl, tyl: tyl.clone(),
}; };
self.scopes.last_mut().unwrap().insert(name, variable_info); self.scopes.last_mut().unwrap().insert(name, variable_info);
if let Some((init, init_span)) = &var.init {
let init = self.lower_expr(init, *init_span)?;
self.build.store(ptr_to, init, tyl.layout, *init_span);
}
} }
} }
Stmt::Labeled { .. } => todo!("labels are not implemented"), Stmt::Labeled { .. } => todo!("labels are not implemented"),
Stmt::Compound(_) => todo!("blocks are not implemented"), Stmt::Compound(_) => todo!("blocks are not implemented"),
Stmt::If { Stmt::If {
cond, cond,
then, then: then_body,
otherwise, otherwise,
} => todo!(), } => {
let cond = self.lower_expr(&cond.0, cond.1)?;
let pred = self.build.current_bb;
let then = self.build.new_block();
let els = otherwise
.as_deref()
.map(|oth| (oth, self.build.new_block()));
let cont = self.build.new_block();
self.build.current_bb = then;
self.lower_body(&then_body)?;
self.build.cur_bb_mut().term = Branch::Goto(cont);
let false_branch = match els {
Some((otherwise, els)) => {
self.build.current_bb = els;
self.lower_body(&otherwise)?;
self.build.cur_bb_mut().term = Branch::Goto(cont);
els
}
None => cont,
};
self.build.bb_mut(pred).term = Branch::Switch {
cond,
yes: then,
no: false_branch,
};
self.build.current_bb = cont;
}
Stmt::Switch => todo!(), Stmt::Switch => todo!(),
Stmt::While { cond, body } => todo!(), Stmt::While { cond, body } => todo!(),
Stmt::For { Stmt::For {
@ -160,7 +273,13 @@ impl FnLoweringCtxt {
ast::BinaryOp::Assign(_) => todo!("no assign"), ast::BinaryOp::Assign(_) => todo!("no assign"),
}; };
let reg = self.build.binary(kind, lhs, rhs, span, layout_of(Ty::Void)); let reg = self.build.binary(
kind,
lhs,
rhs,
span,
self.lcx.layout_of(self.lcx.intern_ty(TyKind::Void)),
);
Ok(Operand::Reg(reg)) Ok(Operand::Reg(reg))
} }
@ -173,7 +292,12 @@ impl FnLoweringCtxt {
.map(|(arg, sp)| self.lower_expr(arg, *sp)) .map(|(arg, sp)| self.lower_expr(arg, *sp))
.collect::<Result<_, _>>()?; .collect::<Result<_, _>>()?;
let reg = self.build.call(layout_of(Ty::Void), lhs, args, span); let reg = self.build.call(
self.lcx.layout_of(self.lcx.intern_ty(TyKind::Void)),
lhs,
args,
span,
);
Ok(Operand::Reg(reg)) Ok(Operand::Reg(reg))
} }
ast::PostfixOp::Member(_) => todo!("member expr"), ast::PostfixOp::Member(_) => todo!("member expr"),
@ -189,65 +313,28 @@ impl FnLoweringCtxt {
} }
#[derive(Debug)] #[derive(Debug)]
struct VariableInfo { struct VariableInfo<'cx> {
def_span: Span, def_span: Span,
tyl: TyLayout, tyl: TyLayout<'cx>,
ptr_to: Register, ptr_to: Register,
decl_attr: DeclAttr, decl_attr: DeclAttr,
} }
fn lower_body( fn lower_body<'cx>(
// may be used later // may be used later
_lcx: &mut LoweringCx, lcx: &LoweringCx<'cx>,
body: &[(Stmt, Span)], body: &[(Stmt, Span)],
def_span: Span, def_span: Span,
name: Symbol, name: Symbol,
ret_ty: Ty, ret_ty: Ty<'cx>,
) -> Result<Func, Error> { ) -> Result<Func<'cx>, Error> {
let mut cx: FnLoweringCtxt = FnLoweringCtxt { let mut cx = FnLoweringCtxt {
scopes: vec![FxHashMap::default()], scopes: vec![FxHashMap::default()],
build: FuncBuilder::new(name, def_span, ret_ty), build: FuncBuilder::new(name, def_span, ret_ty, lcx),
lcx,
}; };
cx.lower_body(body)?; cx.lower_body(body)?;
Ok(cx.build.finish()) Ok(cx.build.finish())
} }
fn lower_ty(ty: &TypeSpecifier) -> Ty {
match ty {
TypeSpecifier::Void => Ty::Void,
TypeSpecifier::Char => Ty::Char,
TypeSpecifier::SChar => Ty::SChar,
TypeSpecifier::UChar => Ty::UChar,
TypeSpecifier::Integer(int) => Ty::Integer(*int),
TypeSpecifier::Float => Ty::Float,
TypeSpecifier::Double => Ty::Double,
TypeSpecifier::LongDouble => Ty::LongDouble,
TypeSpecifier::Bool => Ty::Bool,
}
}
fn layout_of(ty: Ty) -> TyLayout {
let layout = match ty {
Ty::Void => Layout::size_align(0, 1),
Ty::Char => Layout::size_align(1, 1),
Ty::SChar => Layout::size_align(1, 1),
Ty::UChar => Layout::size_align(1, 1),
Ty::Integer(int) => match int.kind {
parser::ast::IntTyKind::Short => Layout::size_align(2, 2),
parser::ast::IntTyKind::Int => Layout::size_align(4, 4),
parser::ast::IntTyKind::Long => Layout::size_align(8, 8),
parser::ast::IntTyKind::LongLong => Layout::size_align(8, 8),
},
Ty::Float => Layout::size_align(4, 4),
Ty::Double => Layout::size_align(8, 8),
Ty::LongDouble => Layout::size_align(8, 8),
Ty::Bool => Layout::size_align(1, 1),
Ty::Struct(_) => todo!("layout_of struct"),
Ty::Union(_) => todo!("layout_of union"),
Ty::Enum(_) => todo!("layout_of enum"),
Ty::Ptr(_) => Layout::size_align(8, 8),
};
TyLayout { ty, layout }
}

View file

@ -1,45 +1,50 @@
use parser::{Span, Symbol}; use parser::{Span, Symbol};
use super::layout_of; use super::LoweringCx;
use crate::{ use crate::{
ir::{ ir::{
self, BasicBlock, BinKind, Branch, ConstValue, Func, Layout, Operand, Register, self, BasicBlock, BbIdx, BinKind, Branch, ConstValue, Func, Layout, Operand, Register,
RegisterData, Statement, StatementKind, TyLayout, RegisterData, Statement, StatementKind, TyLayout,
}, },
ty::Ty, ty::{Ty, TyKind},
}; };
#[derive(Debug)] #[derive(Debug)]
pub struct FuncBuilder { pub(super) struct FuncBuilder<'a, 'cx> {
pub ir: Func, pub lcx: &'a LoweringCx<'cx>,
current_bb: u32, pub ir: Func<'cx>,
pub current_bb: BbIdx,
} }
impl FuncBuilder { impl<'a, 'cx> FuncBuilder<'a, 'cx> {
pub fn new(name: Symbol, def_span: Span, ret_ty: Ty) -> Self { pub fn new(name: Symbol, def_span: Span, ret_ty: Ty<'cx>, lcx: &'a LoweringCx<'cx>) -> Self {
Self { Self {
ir: Func { ir: Func {
regs: Vec::new(), regs: Vec::new(),
bbs: vec![BasicBlock { bbs: vec![BasicBlock {
statements: Vec::new(), statements: Vec::new(),
term: Branch::Goto(0), term: Branch::Goto(BbIdx(0)),
}], }],
name, name,
def_span, def_span,
ret_ty, ret_ty,
}, },
current_bb: 0, current_bb: BbIdx(0),
lcx,
} }
} }
pub fn new_reg(&mut self, name: Option<Symbol>, tyl: TyLayout) -> Register { pub fn new_reg(&mut self, name: Option<Symbol>, tyl: TyLayout<'cx>) -> Register {
let reg = Register(self.ir.regs.len().try_into().unwrap()); let reg = Register(self.ir.regs.len().try_into().unwrap());
self.ir.regs.push(RegisterData { name, tyl }); self.ir.regs.push(RegisterData { name, tyl });
reg reg
} }
pub fn alloca(&mut self, layout: &Layout, name: Option<Symbol>, span: Span) -> Register { pub fn alloca(&mut self, layout: &Layout, name: Option<Symbol>, span: Span) -> Register {
let reg = self.new_reg(name, layout_of(Ty::Ptr(Box::new(Ty::Void)))); let void_ptr = self
.lcx
.intern_ty(TyKind::Ptr(self.lcx.intern_ty(TyKind::Void)));
let reg = self.new_reg(name, self.lcx.layout_of(void_ptr));
let stmt = Statement { let stmt = Statement {
span, span,
kind: StatementKind::Alloca { kind: StatementKind::Alloca {
@ -48,7 +53,7 @@ impl FuncBuilder {
align: Operand::Const(ConstValue::u64(layout.align)), align: Operand::Const(ConstValue::u64(layout.align)),
}, },
}; };
self.bb_mut().statements.push(stmt); self.cur_bb_mut().statements.push(stmt);
reg reg
} }
@ -58,7 +63,7 @@ impl FuncBuilder {
lhs: Operand, lhs: Operand,
rhs: Operand, rhs: Operand,
span: Span, span: Span,
result_tyl: TyLayout, result_tyl: TyLayout<'cx>,
) -> Register { ) -> Register {
let reg = self.new_reg(None, result_tyl); let reg = self.new_reg(None, result_tyl);
let stmt = StatementKind::BinOp { let stmt = StatementKind::BinOp {
@ -67,13 +72,13 @@ impl FuncBuilder {
rhs, rhs,
result: reg, result: reg,
}; };
self.bb_mut() self.cur_bb_mut()
.statements .statements
.push(Statement { span, kind: stmt }); .push(Statement { span, kind: stmt });
reg reg
} }
pub fn load(&mut self, tyl: TyLayout, ptr_reg: Register, span: Span) -> Register { pub fn load(&mut self, tyl: TyLayout<'cx>, ptr_reg: Register, span: Span) -> Register {
let reg = self.new_reg(None, tyl.clone()); let reg = self.new_reg(None, tyl.clone());
let stmt = StatementKind::Load { let stmt = StatementKind::Load {
result: reg, result: reg,
@ -81,27 +86,27 @@ impl FuncBuilder {
size: Operand::const_u64(tyl.layout.size), size: Operand::const_u64(tyl.layout.size),
align: Operand::const_u64(tyl.layout.align), align: Operand::const_u64(tyl.layout.align),
}; };
self.bb_mut() self.cur_bb_mut()
.statements .statements
.push(Statement { span, kind: stmt }); .push(Statement { span, kind: stmt });
reg reg
} }
pub fn store(&mut self, ptr_reg: Register, rhs: Operand, layout: Layout, span: Span) { pub fn store(&mut self, ptr_reg: Register, rhs: Operand, layout: &Layout, span: Span) {
let stmt = StatementKind::Store { let stmt = StatementKind::Store {
ptr_reg, ptr_reg,
value: rhs, value: rhs,
size: Operand::const_u64(layout.size), size: Operand::const_u64(layout.size),
align: Operand::const_u64(layout.align), align: Operand::const_u64(layout.align),
}; };
self.bb_mut() self.cur_bb_mut()
.statements .statements
.push(Statement { span, kind: stmt }); .push(Statement { span, kind: stmt });
} }
pub fn call( pub fn call(
&mut self, &mut self,
ret_tyl: TyLayout, ret_tyl: TyLayout<'cx>,
func: Operand, func: Operand,
args: Vec<Operand>, args: Vec<Operand>,
span: Span, span: Span,
@ -112,18 +117,30 @@ impl FuncBuilder {
func, func,
args, args,
}; };
self.bb_mut() self.cur_bb_mut()
.statements .statements
.push(Statement { span, kind: stmt }); .push(Statement { span, kind: stmt });
reg reg
} }
pub fn bb_mut(&mut self) -> &mut BasicBlock { pub fn bb_mut(&mut self, bb: BbIdx) -> &mut BasicBlock {
&mut self.ir.bbs[self.current_bb as usize] self.ir.bb_mut(bb)
} }
pub fn finish(mut self) -> Func { pub fn cur_bb_mut(&mut self) -> &mut BasicBlock {
self.bb_mut().term = Branch::Ret(Operand::Const(ConstValue::Void)); &mut self.ir.bbs[self.current_bb.as_usize()]
}
pub fn new_block(&mut self) -> BbIdx {
self.ir.bbs.push(BasicBlock {
statements: vec![],
term: Branch::Goto(BbIdx(0)),
});
BbIdx::from_usize(self.ir.bbs.len() - 1)
}
pub fn finish(mut self) -> Func<'cx> {
self.cur_bb_mut().term = Branch::Ret(Operand::Const(ConstValue::Void));
println!("{}", ir::func_to_string(&self.ir)); println!("{}", ir::func_to_string(&self.ir));

View file

@ -1,10 +1,18 @@
use std::{
hash::{Hash, Hasher},
ops::Deref,
};
use indexmap::IndexMap; use indexmap::IndexMap;
use parser::{ast::IntTy, Symbol}; use parser::{ast::IntTy, Symbol};
use crate::ir::DefId; use crate::ir::DefId;
#[derive(Debug, Clone)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Ty { pub struct Ty<'cx>(&'cx TyKind<'cx>);
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum TyKind<'cx> {
Void, Void,
Char, Char,
SChar, SChar,
@ -14,26 +22,55 @@ pub enum Ty {
Double, Double,
LongDouble, LongDouble,
Bool, Bool,
Ptr(Box<Ty>), Ptr(Ty<'cx>),
Union(UnionTy), Union(UnionTy<'cx>),
Struct(StructTy), Struct(StructTy<'cx>),
Enum(EnumTy), Enum(EnumTy),
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct UnionTy { pub struct UnionTy<'cx> {
pub def_id: DefId, pub def_id: DefId,
pub variants: IndexMap<Symbol, Ty>, pub variants: IndexMap<Symbol, Ty<'cx>>,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct StructTy { pub struct StructTy<'cx> {
pub def_id: DefId, pub def_id: DefId,
pub fields: IndexMap<Symbol, Ty>, pub fields: IndexMap<Symbol, Ty<'cx>>,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct EnumTy { pub struct EnumTy {
pub def_id: DefId, pub def_id: DefId,
pub variants: IndexMap<Symbol, i128>, pub variants: IndexMap<Symbol, i128>,
} }
impl<'cx> Ty<'cx> {
pub fn new_unchecked(kind: &'cx TyKind<'cx>) -> Self {
Self(kind)
}
}
impl<'cx> Deref for Ty<'cx> {
type Target = &'cx TyKind<'cx>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl Hash for UnionTy<'_> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.def_id.hash(state)
}
}
impl Hash for StructTy<'_> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.def_id.hash(state)
}
}
impl Hash for EnumTy {
fn hash<H: Hasher>(&self, state: &mut H) {
self.def_id.hash(state)
}
}

View file

@ -142,7 +142,7 @@ pub enum Stmt {
// --- Types and decls and garbage whatever // --- Types and decls and garbage whatever
// //
#[derive(Debug, DebugPls, Clone, Copy)] #[derive(Debug, DebugPls, Clone, Copy, PartialEq, Eq, Hash)]
pub enum IntTySignedness { pub enum IntTySignedness {
Signed, Signed,
Unsigned, Unsigned,
@ -155,7 +155,7 @@ impl Default for IntTySignedness {
} }
} }
#[derive(Debug, DebugPls, Clone, Copy)] #[derive(Debug, DebugPls, Clone, Copy, PartialEq, Eq, Hash)]
pub enum IntTyKind { pub enum IntTyKind {
Short, Short,
Int, Int,
@ -163,7 +163,7 @@ pub enum IntTyKind {
LongLong, LongLong,
} }
#[derive(Debug, DebugPls, Clone, Copy)] #[derive(Debug, DebugPls, Clone, Copy, PartialEq, Eq, Hash)]
pub struct IntTy { pub struct IntTy {
pub sign: IntTySignedness, pub sign: IntTySignedness,
pub kind: IntTyKind, pub kind: IntTyKind,

View file

@ -15,5 +15,7 @@ fn main() {
printer.translation_unit(&ast).unwrap(); printer.translation_unit(&ast).unwrap();
println!("// END CODE -------------------"); println!("// END CODE -------------------");
let _ = analysis::lower_translation_unit(&ast); let arena = bumpalo::Bump::new();
let _ = analysis::lower_translation_unit(&arena, &ast);
} }