mirror of
https://github.com/Noratrieb/uwucc.git
synced 2026-01-14 16:45:07 +01:00
param
This commit is contained in:
parent
c84fdfaf3a
commit
542c0daf6a
6 changed files with 160 additions and 50 deletions
|
|
@ -69,6 +69,8 @@ pub struct Func<'cx> {
|
||||||
pub name: Symbol,
|
pub name: Symbol,
|
||||||
pub def_span: Span,
|
pub def_span: Span,
|
||||||
pub ret_ty: Ty<'cx>,
|
pub ret_ty: Ty<'cx>,
|
||||||
|
/// The amount of function parameters. regs[..arity] are the parameters.
|
||||||
|
pub arity: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,6 @@ impl<W: Write> PrettyPrinter<W> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn func(&mut self, func: &Func<'_>) -> Result {
|
pub fn func(&mut self, func: &Func<'_>) -> Result {
|
||||||
writeln!(self.out, "def {}() {{", func.name)?;
|
|
||||||
|
|
||||||
let print_reg = |reg: Register| {
|
let print_reg = |reg: Register| {
|
||||||
display_fn(move |f| match func.regs[reg.0 as usize].name {
|
display_fn(move |f| match func.regs[reg.0 as usize].name {
|
||||||
None => write!(f, "%{}", reg.0),
|
None => write!(f, "%{}", reg.0),
|
||||||
|
|
@ -37,6 +35,16 @@ impl<W: Write> PrettyPrinter<W> {
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
write!(self.out, "def {}(", func.name)?;
|
||||||
|
for param in 0..func.arity {
|
||||||
|
let reg = &func.regs[param as usize];
|
||||||
|
write!(self.out, "{} {}", reg.tyl.ty, print_reg(Register(param)))?;
|
||||||
|
if (param + 1) != func.arity {
|
||||||
|
write!(self.out, ", ")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
writeln!(self.out, ") {{",)?;
|
||||||
|
|
||||||
let print_op = |op: Operand| {
|
let print_op = |op: Operand| {
|
||||||
display_fn(move |f| match op {
|
display_fn(move |f| match op {
|
||||||
Operand::Const(c) => Display::fmt(&c, f),
|
Operand::Const(c) => Display::fmt(&c, f),
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,8 @@ use std::cell::{Cell, RefCell};
|
||||||
|
|
||||||
use parser::{
|
use parser::{
|
||||||
ast::{
|
ast::{
|
||||||
self, Atom, DeclAttr, Expr, ExprBinary, ExternalDecl, Stmt, TranslationUnit, TypeSpecifier,
|
self, Atom, DeclAttr, Expr, ExprBinary, ExternalDecl, InitDecl, Stmt, TranslationUnit,
|
||||||
|
TypeSpecifier,
|
||||||
},
|
},
|
||||||
Span, Symbol,
|
Span, Symbol,
|
||||||
};
|
};
|
||||||
|
|
@ -120,16 +121,17 @@ pub fn lower_translation_unit<'cx>(
|
||||||
match decl {
|
match decl {
|
||||||
ExternalDecl::Decl(_) => todo!("decl is unsupported"),
|
ExternalDecl::Decl(_) => todo!("decl is unsupported"),
|
||||||
ExternalDecl::FunctionDef(def) => {
|
ExternalDecl::FunctionDef(def) => {
|
||||||
let decl = def.decl.uwnrap_normal();
|
let decl = def.decl.unwrap_normal();
|
||||||
let body = &def.body;
|
let body = &def.body;
|
||||||
let ret_ty = lcx.lower_ty(&decl.decl_spec.ty);
|
let ret_ty = lcx.lower_ty(&decl.decl_spec.ty);
|
||||||
let func = lower_body(
|
|
||||||
&lcx,
|
let (ref declarator, def_span) = decl.init_declarators[0];
|
||||||
body,
|
|
||||||
decl.init_declarators[0].1,
|
let ast::DirectDeclarator::WithParams { ident, params } = &declarator.declarator.decl else {
|
||||||
decl.init_declarators[0].0.declarator.decl.name().0,
|
unreachable!("function def needs withparams declarator");
|
||||||
ret_ty,
|
};
|
||||||
)?;
|
|
||||||
|
let func = lower_func(&lcx, body, def_span, ident.0, ret_ty, params)?;
|
||||||
ir.funcs.insert(lcx.next_def_id(), func);
|
ir.funcs.insert(lcx.next_def_id(), func);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -161,37 +163,42 @@ impl<'a, 'cx> FnLoweringCtxt<'a, 'cx> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn declare_local(&mut self, decl: &ast::Decl, span: Span) -> Result<()> {
|
||||||
|
let decl = decl.unwrap_normal();
|
||||||
|
let ty = self.lcx.lower_ty(&decl.decl_spec.ty);
|
||||||
|
let decl_attr = decl.decl_spec.attrs;
|
||||||
|
|
||||||
|
for (var, def_span) in &decl.init_declarators {
|
||||||
|
let tyl = self.lcx.layout_of(ty);
|
||||||
|
let (name, name_span) = var.declarator.decl.name();
|
||||||
|
let ptr_to = self.build.alloca(tyl.layout, Some(name), span);
|
||||||
|
|
||||||
|
let variable_info = VariableInfo {
|
||||||
|
def_span: *def_span,
|
||||||
|
ptr_to,
|
||||||
|
decl_attr,
|
||||||
|
tyl: tyl.clone(),
|
||||||
|
};
|
||||||
|
let predeclared = self.scopes.last_mut().unwrap().insert(name, variable_info);
|
||||||
|
if let Some(predeclared) = predeclared {
|
||||||
|
return Err(Error::new(
|
||||||
|
format!("variable {name} has already been declared"),
|
||||||
|
name_span,
|
||||||
|
)
|
||||||
|
.note_spanned("already declared here", predeclared.def_span));
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn lower_stmt(&mut self, stmt: &ast::Stmt, stmt_span: Span) -> Result<()> {
|
fn lower_stmt(&mut self, stmt: &ast::Stmt, stmt_span: Span) -> Result<()> {
|
||||||
match stmt {
|
match stmt {
|
||||||
Stmt::Decl(decl) => {
|
Stmt::Decl(decl) => {
|
||||||
let decl = decl.uwnrap_normal();
|
self.declare_local(decl, stmt_span)?;
|
||||||
let ty = self.lcx.lower_ty(&decl.decl_spec.ty);
|
|
||||||
let decl_attr = decl.decl_spec.attrs;
|
|
||||||
|
|
||||||
for (var, def_span) in &decl.init_declarators {
|
|
||||||
let tyl = self.lcx.layout_of(ty);
|
|
||||||
let (name, name_span) = var.declarator.decl.name();
|
|
||||||
let ptr_to = self.build.alloca(tyl.layout, Some(name), stmt_span);
|
|
||||||
|
|
||||||
let variable_info = VariableInfo {
|
|
||||||
def_span: *def_span,
|
|
||||||
ptr_to,
|
|
||||||
decl_attr,
|
|
||||||
tyl: tyl.clone(),
|
|
||||||
};
|
|
||||||
let predeclared = self.scopes.last_mut().unwrap().insert(name, variable_info);
|
|
||||||
if let Some(predeclared) = predeclared {
|
|
||||||
return Err(Error::new(
|
|
||||||
format!("variable {name} has already been declared"),
|
|
||||||
name_span,
|
|
||||||
)
|
|
||||||
.note_spanned("already declared here", predeclared.def_span));
|
|
||||||
}
|
|
||||||
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(block) => {
|
Stmt::Compound(block) => {
|
||||||
|
|
@ -393,20 +400,68 @@ struct VariableInfo<'cx> {
|
||||||
decl_attr: DeclAttr,
|
decl_attr: DeclAttr,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_body<'cx>(
|
fn lower_func<'cx>(
|
||||||
// may be used later
|
// may be used later
|
||||||
lcx: &LoweringCx<'cx>,
|
lcx: &LoweringCx<'cx>,
|
||||||
body: &[(Stmt, Span)],
|
body: &[(Stmt, Span)],
|
||||||
def_span: Span,
|
def_span: Span,
|
||||||
name: Symbol,
|
name: Symbol,
|
||||||
ret_ty: Ty<'cx>,
|
ret_ty: Ty<'cx>,
|
||||||
|
params: &[ast::FunctionParamDecl],
|
||||||
) -> Result<Func<'cx>, Error> {
|
) -> Result<Func<'cx>, Error> {
|
||||||
let mut cx = FnLoweringCtxt {
|
let mut cx = FnLoweringCtxt {
|
||||||
scopes: vec![],
|
scopes: vec![Default::default()],
|
||||||
build: FuncBuilder::new(name, def_span, ret_ty, lcx),
|
build: FuncBuilder::new(
|
||||||
|
name,
|
||||||
|
def_span,
|
||||||
|
ret_ty,
|
||||||
|
lcx,
|
||||||
|
params.len().try_into().unwrap(),
|
||||||
|
),
|
||||||
lcx,
|
lcx,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
for param in params {
|
||||||
|
let decl_spec = ¶m.decl_spec.0;
|
||||||
|
let ty = lcx.lower_ty(&decl_spec.ty);
|
||||||
|
let tyl = lcx.layout_of(ty);
|
||||||
|
// Create all the parameter registers.
|
||||||
|
let _ = cx
|
||||||
|
.build
|
||||||
|
.new_reg(Some(param.declarator.0.decl.name().0), tyl);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i, param) in params.iter().enumerate() {
|
||||||
|
// For every param, we create an allocation and store the register into it.
|
||||||
|
let param_reg_data = &cx.build.ir.regs[i];
|
||||||
|
let name = param.declarator.0.decl.name().0;
|
||||||
|
|
||||||
|
let decl_spec = ¶m.decl_spec.0;
|
||||||
|
let decl_attr = decl_spec.attrs;
|
||||||
|
let tyl = param_reg_data.tyl;
|
||||||
|
let span = param.declarator.1;
|
||||||
|
|
||||||
|
let alloca_name = Symbol::intern(&format!("{}.local", name));
|
||||||
|
let ptr_to = cx.build.alloca(tyl.layout, Some(alloca_name), span);
|
||||||
|
|
||||||
|
let variable_info = VariableInfo {
|
||||||
|
def_span: span,
|
||||||
|
ptr_to,
|
||||||
|
decl_attr,
|
||||||
|
tyl,
|
||||||
|
};
|
||||||
|
let predeclared = cx.scopes.last_mut().unwrap().insert(name, variable_info);
|
||||||
|
if let Some(predeclared) = predeclared {
|
||||||
|
return Err(
|
||||||
|
Error::new(format!("parameter {name} has already been declared"), span)
|
||||||
|
.note_spanned("already declared here", predeclared.def_span),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
cx.build
|
||||||
|
.store(ptr_to, Operand::Reg(Register(i as _)), tyl.layout, span);
|
||||||
|
}
|
||||||
|
|
||||||
cx.lower_block(body)?;
|
cx.lower_block(body)?;
|
||||||
|
|
||||||
if let Branch::Goto(BbIdx(u32::MAX)) = cx.build.cur_bb_mut().term {
|
if let Branch::Goto(BbIdx(u32::MAX)) = cx.build.cur_bb_mut().term {
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,13 @@ pub(super) struct FuncBuilder<'a, 'cx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'cx> FuncBuilder<'a, 'cx> {
|
impl<'a, 'cx> FuncBuilder<'a, 'cx> {
|
||||||
pub fn new(name: Symbol, def_span: Span, ret_ty: Ty<'cx>, lcx: &'a LoweringCx<'cx>) -> Self {
|
pub fn new(
|
||||||
|
name: Symbol,
|
||||||
|
def_span: Span,
|
||||||
|
ret_ty: Ty<'cx>,
|
||||||
|
lcx: &'a LoweringCx<'cx>,
|
||||||
|
arity: u32,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
ir: Func {
|
ir: Func {
|
||||||
regs: Vec::new(),
|
regs: Vec::new(),
|
||||||
|
|
@ -28,6 +34,7 @@ impl<'a, 'cx> FuncBuilder<'a, 'cx> {
|
||||||
name,
|
name,
|
||||||
def_span,
|
def_span,
|
||||||
ret_ty,
|
ret_ty,
|
||||||
|
arity,
|
||||||
},
|
},
|
||||||
current_bb: BbIdx(0),
|
current_bb: BbIdx(0),
|
||||||
lcx,
|
lcx,
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,14 @@
|
||||||
use std::{
|
use std::{
|
||||||
|
fmt::Display,
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
ops::Deref,
|
ops::Deref,
|
||||||
};
|
};
|
||||||
|
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use parser::{ast::IntTy, Symbol};
|
use parser::{
|
||||||
|
ast::{IntTy, IntTyKind, IntTySignedness},
|
||||||
|
Symbol,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::ir::DefId;
|
use crate::ir::DefId;
|
||||||
|
|
||||||
|
|
@ -74,3 +78,37 @@ impl Hash for EnumTy {
|
||||||
self.def_id.hash(state)
|
self.def_id.hash(state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Display for Ty<'_> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match **self {
|
||||||
|
TyKind::Void => f.write_str("void"),
|
||||||
|
TyKind::Char => f.write_str("char"),
|
||||||
|
TyKind::SChar => f.write_str("signed char"),
|
||||||
|
TyKind::UChar => f.write_str("unsigned char"),
|
||||||
|
TyKind::Integer(int) => {
|
||||||
|
match int.sign {
|
||||||
|
IntTySignedness::Signed => f.write_str("signed "),
|
||||||
|
IntTySignedness::Unsigned => f.write_str("unsigned "),
|
||||||
|
}?;
|
||||||
|
match int.kind {
|
||||||
|
IntTyKind::Short => f.write_str("short"),
|
||||||
|
IntTyKind::Int => f.write_str("int"),
|
||||||
|
IntTyKind::Long => f.write_str("long"),
|
||||||
|
IntTyKind::LongLong => f.write_str("long long"),
|
||||||
|
}?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
TyKind::Float => f.write_str("float"),
|
||||||
|
TyKind::Double => f.write_str("double"),
|
||||||
|
TyKind::LongDouble => f.write_str("long double"),
|
||||||
|
TyKind::Bool => f.write_str("_Bool"),
|
||||||
|
TyKind::Ptr(ty) => {
|
||||||
|
write!(f, "{ty}*")
|
||||||
|
}
|
||||||
|
TyKind::Union(_) => todo!(),
|
||||||
|
TyKind::Struct(_) => todo!(),
|
||||||
|
TyKind::Enum(_) => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -169,7 +169,7 @@ pub struct IntTy {
|
||||||
pub kind: IntTyKind,
|
pub kind: IntTyKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, DebugPls)]
|
#[derive(Debug, DebugPls, Clone)]
|
||||||
pub enum TypeSpecifier {
|
pub enum TypeSpecifier {
|
||||||
Void,
|
Void,
|
||||||
Char,
|
Char,
|
||||||
|
|
@ -205,7 +205,7 @@ impl DebugPls for DeclAttr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, DebugPls)]
|
#[derive(Debug, DebugPls, Clone)]
|
||||||
pub struct DeclSpec {
|
pub struct DeclSpec {
|
||||||
pub ty: TypeSpecifier,
|
pub ty: TypeSpecifier,
|
||||||
pub attrs: DeclAttr,
|
pub attrs: DeclAttr,
|
||||||
|
|
@ -229,13 +229,13 @@ pub struct NormalDecl {
|
||||||
pub init_declarators: Vec<Spanned<InitDecl>>,
|
pub init_declarators: Vec<Spanned<InitDecl>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, DebugPls)]
|
#[derive(Debug, DebugPls, Clone)]
|
||||||
pub struct FunctionParamDecl {
|
pub struct FunctionParamDecl {
|
||||||
pub decl_spec: Spanned<DeclSpec>,
|
pub decl_spec: Spanned<DeclSpec>,
|
||||||
pub declarator: Spanned<Declarator>,
|
pub declarator: Spanned<Declarator>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, DebugPls)]
|
#[derive(Debug, DebugPls, Clone)]
|
||||||
pub enum DirectDeclarator {
|
pub enum DirectDeclarator {
|
||||||
Ident(Ident),
|
Ident(Ident),
|
||||||
WithParams {
|
WithParams {
|
||||||
|
|
@ -244,7 +244,7 @@ pub enum DirectDeclarator {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, DebugPls)]
|
#[derive(Debug, DebugPls, Clone)]
|
||||||
pub struct Declarator {
|
pub struct Declarator {
|
||||||
pub decl: DirectDeclarator,
|
pub decl: DirectDeclarator,
|
||||||
pub pointer: bool,
|
pub pointer: bool,
|
||||||
|
|
@ -265,7 +265,7 @@ pub enum ExternalDecl {
|
||||||
pub type TranslationUnit = Vec<Spanned<ExternalDecl>>;
|
pub type TranslationUnit = Vec<Spanned<ExternalDecl>>;
|
||||||
|
|
||||||
impl Decl {
|
impl Decl {
|
||||||
pub fn uwnrap_normal(&self) -> &NormalDecl {
|
pub fn unwrap_normal(&self) -> &NormalDecl {
|
||||||
match self {
|
match self {
|
||||||
Decl::Normal(decl) => decl,
|
Decl::Normal(decl) => decl,
|
||||||
Decl::StaticAssert => {
|
Decl::StaticAssert => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue