mirror of
https://github.com/Noratrieb/uwucc.git
synced 2026-01-15 17:15:10 +01:00
a bunch of stuff mostly
This commit is contained in:
parent
56e7f77a0d
commit
b9a2f939c4
29 changed files with 734 additions and 345 deletions
|
|
@ -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>),
|
||||
}
|
||||
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
38
analysis/src/ty.rs
Normal 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>,
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue