a bunch of stuff mostly

This commit is contained in:
nora 2023-05-22 20:44:18 +02:00
parent 56e7f77a0d
commit b9a2f939c4
29 changed files with 734 additions and 345 deletions

View file

@ -1,157 +0,0 @@
use indexmap::IndexMap;
use lasso::Spur;
use parser::Spanned;
pub type Symbol = Spur;
pub type Ident = Spanned<Symbol>;
pub struct Hir<'hir> {
defs: Vec<Def>,
__: &'hir (),
}
#[derive(Clone, Copy)]
pub struct DefId(u32);
pub enum IntTySignedness {
Signed,
Unsigned,
}
impl Default for IntTySignedness {
fn default() -> Self {
// C defaults to unsigned for integers.
Self::Signed
}
}
pub enum IntTyKind {
Short,
Int,
Long,
LongLong,
}
pub struct IntTy {
pub sign: IntTySignedness,
pub kind: IntTyKind,
}
pub struct Def {
pub name: Ident,
pub def_id: DefId,
pub kind: DefKind,
}
pub enum DefKind {
Union(UnionTy),
Enum(EnumTy),
Struct(StructTy),
}
pub struct UnionTy {
pub def_id: DefId,
pub variants: IndexMap<Symbol, Ty>,
}
pub struct StructTy {
pub def_id: DefId,
pub fields: IndexMap<Symbol, Ty>,
}
pub struct EnumTy {
pub def_id: DefId,
pub variants: IndexMap<Symbol, i128>,
}
pub enum TyKind {
Void,
Char,
SChar,
UChar,
Integer(IntTy),
Float,
Double,
LongDouble,
Bool,
Union(UnionTy),
Struct(StructTy),
Enum(EnumTy),
}
pub struct Ty {
kind: TyKind,
}
pub enum NodeKind {
FunctionDef(FunctionDef),
}
pub struct ExternalDecl;
pub struct FunctionDef {
name: Symbol,
}
pub struct Expr<'hir> {
kind: ExprKind<'hir>,
ty: Ty,
}
pub enum ExprKind<'hir> {
Var(DefId),
Binary(BinaryOp, &'hir Expr<'hir>, &'hir Expr<'hir>),
Unary(UnaryOp, &'hir Expr<'hir>),
Cast(CastExpr<'hir>),
}
pub struct CastExpr<'hir> {
from: Ty,
to: Ty,
expr: &'hir Expr<'hir>,
}
pub enum UnaryOp {
AddrOf,
Deref,
Plus,
Minus,
Tilde,
Bang,
}
#[derive(Debug)]
pub enum ArithOpKind {
Mul,
Div,
Mod,
Add,
Sub,
Shl,
Shr,
BitAnd,
BitXor,
BitOr,
}
#[derive(Debug)]
pub enum ComparisonKind {
Lt,
Gt,
LtEq,
GtEq,
Eq,
Neq,
}
#[derive(Debug)]
pub enum BinaryOp {
Arith(ArithOpKind),
LogicalAnd,
LogicalOr,
Comparison(ComparisonKind),
Comma,
Index, // lhs[rhs]
Assign(Option<ArithOpKind>),
}

View file

@ -1,57 +1,135 @@
/// A low level IR used for codegen.
///
///
/// The following expression is lowered to the following IR:
///
///
/// ```c
/// int i = 0;
/// long l = 1;
/// int y = ((int)&i)+l;
/// if (true) {
/// i = 1;
/// } else {
/// i = 2;
/// }
/// yeet(i);
/// ```
///
///
/// ```c
/// int _0; // i
/// long _1; // l
/// int *_2; // tmp &i
/// int _3; // tmp (int)&i
/// int _4; // tmp l (implicit cast to int)
/// int _5; // y
///
/// _0 = Const(0)
/// _1 = Const(1)
/// _2 = AddrOf(_0)
/// _3 = Cast(Ptr, Int, _2)
/// _4 = Cast(Long, Int, _1)
/// _5 = _3 + _4
/// bb0:
/// %0 = alloca 4, 4
/// store _0, 0
/// %1 = alloca 8, 8
/// store %1, 1
/// branch true, bb1, bb2
/// bb1:
/// store %0, 1
/// branch bb3
/// bb2:
/// store %0, 2
/// branch bb3
/// bb3:
/// %val = load %0
/// call yeet(%val)
/// ```
use parser::{Span, Symbol};
use rustc_hash::FxHashMap;
use parser::Span;
use crate::ty::Ty;
use crate::hir::Ty;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct DefId(u32);
struct Body {
locals: Vec<LocalDecl>,
statements: Vec<Statement>,
#[derive(Debug, Clone)]
pub struct Layout {
pub size: u64,
pub align: u64,
}
struct LocalDecl {
pub ty: Ty,
pub struct Ir {
pub funcs: FxHashMap<DefId, Func>,
}
struct Statement {
#[derive(Debug, Clone)]
pub struct Func {
pub bbs: Vec<BasicBlock>,
pub def_span: Span,
pub ret_ty: Ty,
}
#[derive(Debug, Clone)]
pub struct BasicBlock {
pub regs: Vec<RegisterData>,
pub statements: Vec<Statement>,
pub term: Branch,
}
#[derive(Debug, Clone)]
pub struct RegisterData {
pub name: Option<Symbol>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Register(pub u32);
#[derive(Debug, Clone)]
pub struct Statement {
pub span: Span,
pub kind: StatementKind,
}
enum StatementKind {
Assign(LValue, RValue),
#[derive(Debug, Clone)]
pub enum StatementKind {
Alloca {
reg: Register,
size: Operand,
align: Operand,
},
Store {
ptr_reg: Register,
size: Operand,
align: Operand,
},
Load {
result: Register,
ptr_reg: Register,
size: Operand,
align: Operand,
},
Arith {
kind: ArithKind,
lhs: Register,
rhs: Register,
result: Register,
},
Comp {
kind: CompKind,
lhs: Register,
rhs: Register,
result: Register,
},
PtrOffset {
reg: Register,
amount: Operand,
},
}
enum RValue {
BinOp(BinOpKind, Operand),
Const,
#[derive(Debug, Clone)]
pub enum Operand {
Reg(Register),
Const(ConstValue),
}
enum BinOpKind {
#[derive(Debug, Clone)]
pub enum Branch {
Goto(u32),
Switch {
cond: Option<RValue>,
yes: u32,
no: u32,
},
}
#[derive(Debug, Clone)]
pub enum ArithKind {
Add,
Sub,
Mul,
@ -59,8 +137,35 @@ enum BinOpKind {
Mod,
}
enum Operand {
Local(usize),
#[derive(Debug, Clone)]
pub enum CompKind {
Eq,
Neq,
Gt,
Geq,
Lt,
Leq,
}
enum LValue {}
#[derive(Debug, Clone)]
pub enum RValue {
Register(u32),
Constant(ConstValue),
}
#[derive(Debug, Clone)]
pub enum ConstValue {
Int(u128),
}
impl Layout {
pub fn size_align(size: u64, align: u64) -> Self {
Self { size, align }
}
}
impl ConstValue {
pub fn u64(int: u64) -> Self {
Self::Int(int.into())
}
}

View file

@ -1,6 +1,20 @@
#![allow(dead_code)] // TODO: no
#![warn(rust_2018_idioms)]
mod hir;
mod ir;
mod lower;
mod ty;
pub use lower::lower_translation_unit;
use parser::Span;
pub struct Error {
msg: String,
span: Span,
}
impl Error {
pub fn new(msg: String, span: Span) -> Self {
Self { msg, span }
}
}

View file

@ -1,85 +1,180 @@
use parser::{ast, Span};
use parser::{
ast::{DeclAttr, ExternalDecl, Stmt, TranslationUnit, TypeSpecifier},
Span, Symbol,
};
use rustc_hash::FxHashMap;
use crate::hir::{self, DefId, Symbol};
use crate::{
ir::{
BasicBlock, Branch, ConstValue, Func, Ir, Layout, Operand, Register, RegisterData,
Statement, StatementKind,
},
ty::Ty,
Error,
};
pub struct LowerCtx<'hir> {
hir_symbol_intern: lasso::Rodeo,
hir_arena: &'hir bumpalo::Bump,
global_symbols: FxHashMap<Symbol, &'hir hir::ExternalDecl>,
scope: Scope,
}
struct LoweringCx {}
struct Scope {
parent: Option<Box<Scope>>,
variables: FxHashMap<Symbol, DefId>,
}
pub fn lower_translation_unit(ast: &TranslationUnit) -> Result<Ir, Error> {
let mut lcx = LoweringCx {};
impl Scope {
fn new() -> Self {
Self {
parent: None,
variables: FxHashMap::default(),
}
}
fn insert(&mut self, symbol: Symbol, def_id: DefId) {
self.variables.insert(symbol, def_id);
}
fn enter_new(&mut self) {
let new = Self::new();
let this = std::mem::replace(self, new);
self.parent = Some(Box::new(this));
}
fn leave(&mut self) {
let old = std::mem::replace(self, Self::new());
let parent = old.parent.expect("parent not found when leaving scope");
*self = *parent;
}
fn lookup(&self, sym: Symbol) -> Option<DefId> {
self.variables
.get(&sym)
.copied()
.or_else(|| self.parent.as_ref().and_then(|parent| parent.lookup(sym)))
}
}
impl<'hir> LowerCtx<'hir> {
pub fn lower_translation_unit(&mut self, unit: &ast::TranslationUnit) -> hir::Hir<'hir> {
for _decl in unit {}
todo!()
}
fn lower_decl(&mut self, decl: &ast::ExternalDecl, span: Span) -> hir::ExternalDecl {
for (decl, _) in ast {
match decl {
ast::ExternalDecl::Decl(_) => todo!(),
ast::ExternalDecl::FunctionDef(def) => {
let _fn_def = self.lower_function_def(def, span);
hir::ExternalDecl
ExternalDecl::Decl(_) => todo!("decl is unsupported"),
ExternalDecl::FunctionDef(def) => {
let decl = def.decl.uwnrap_normal();
let body = &def.body;
let ret_ty = lower_ty(&decl.decl_spec.ty);
lower_body(&mut lcx, body, decl.init_declarators[0].1, ret_ty)?;
}
}
}
fn lower_function_def(&mut self, def: &ast::FunctionDef, _span: Span) -> hir::FunctionDef {
let decl = def.decl.uwnrap_normal();
let (init_declarator, _declarator_span) = decl
.init_declarators
.get(0)
.expect("single init declarator in function definition");
let declarator = &init_declarator.declarator;
todo!()
}
let ((name_ident, _name_span), _param_decls) = declarator.decl.unwrap_with_params();
#[derive(Debug)]
struct FnLoweringCtxt {
scopes: Vec<FxHashMap<Symbol, VariableInfo>>,
ir: Func,
current_bb: u32,
}
let name_sym = self.hir_symbol_intern.get_or_intern(name_ident);
impl FnLoweringCtxt {
fn alloca(&mut self, layout: &Layout, name: Option<Symbol>, span: Span) -> Register {
let bb = self.bb_mut();
let reg = Register(bb.regs.len().try_into().unwrap());
bb.regs.push(RegisterData { name });
let stmt = Statement {
span,
kind: StatementKind::Alloca {
reg,
size: Operand::Const(ConstValue::u64(layout.size)),
align: Operand::Const(ConstValue::u64(layout.align)),
},
};
bb.statements.push(stmt);
reg
}
if self.global_symbols.contains_key(&name_sym) {
panic!("function declarated twice! return this error properly! lol!")
}
todo!()
fn bb_mut(&mut self) -> &mut BasicBlock {
&mut self.ir.bbs[self.current_bb as usize]
}
}
#[derive(Debug)]
struct VariableInfo {
def_span: Span,
ty: Ty,
ptr_to: Register,
decl_attr: DeclAttr,
layout: Layout,
}
fn lower_body(
// may be used later
_lcx: &mut LoweringCx,
body: &[(Stmt, Span)],
def_span: Span,
ret_ty: Ty,
) -> Result<Func, Error> {
let mut cx: FnLoweringCtxt = FnLoweringCtxt {
scopes: vec![FxHashMap::default()],
ir: Func {
bbs: vec![BasicBlock {
regs: Vec::new(),
statements: Vec::new(),
term: Branch::Goto(0),
}],
def_span,
ret_ty,
},
current_bb: 0,
};
for (stmt, stmt_span) in body {
match stmt {
Stmt::Decl(decl) => {
let decl = decl.uwnrap_normal();
let ty = lower_ty(&decl.decl_spec.ty);
let decl_attr = decl.decl_spec.attrs;
for (var, def_span) in &decl.init_declarators {
let layout = layout_of(&ty);
let (name, _) = var.declarator.decl.name();
let ptr_to = cx.alloca(&layout, Some(name), *stmt_span);
let variable_info = VariableInfo {
def_span: *def_span,
ty: ty.clone(),
ptr_to,
decl_attr,
layout,
};
cx.scopes.last_mut().unwrap().insert(name, variable_info);
}
}
Stmt::Labeled { .. } => todo!("labels are not implemented"),
Stmt::Compound(_) => todo!("blocks are not implemented"),
Stmt::If {
cond,
then,
otherwise,
} => todo!(),
Stmt::Switch => todo!(),
Stmt::While { cond, body } => todo!(),
Stmt::For {
init_decl,
init_expr,
cond,
post,
body,
} => todo!(),
Stmt::Goto(_) => todo!(),
Stmt::Continue => todo!(),
Stmt::Break => todo!(),
Stmt::Return(_) => todo!(),
Stmt::Expr(_) => todo!(),
}
}
dbg!(&cx);
Ok(cx.ir)
}
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) -> 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"),
}
}

38
analysis/src/ty.rs Normal file
View file

@ -0,0 +1,38 @@
use indexmap::IndexMap;
use parser::{ast::IntTy, Symbol};
use crate::ir::DefId;
#[derive(Debug, Clone)]
pub enum Ty {
Void,
Char,
SChar,
UChar,
Integer(IntTy),
Float,
Double,
LongDouble,
Bool,
Union(UnionTy),
Struct(StructTy),
Enum(EnumTy),
}
#[derive(Debug, Clone)]
pub struct UnionTy {
pub def_id: DefId,
pub variants: IndexMap<Symbol, Ty>,
}
#[derive(Debug, Clone)]
pub struct StructTy {
pub def_id: DefId,
pub fields: IndexMap<Symbol, Ty>,
}
#[derive(Debug, Clone)]
pub struct EnumTy {
pub def_id: DefId,
pub variants: IndexMap<Symbol, i128>,
}