mirror of
https://github.com/Noratrieb/uwucc.git
synced 2026-01-14 16:45:07 +01:00
intern
This commit is contained in:
parent
d3846e3357
commit
77e18126e7
9 changed files with 312 additions and 129 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -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",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -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"] }
|
||||||
|
|
|
||||||
|
|
@ -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 }
|
||||||
|
|
|
||||||
|
|
@ -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))?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 }
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue