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 def_span: Span,
|
||||
pub ret_ty: Ty<'cx>,
|
||||
/// The amount of function parameters. regs[..arity] are the parameters.
|
||||
pub arity: u32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
|
|
|
|||
|
|
@ -28,8 +28,6 @@ impl<W: Write> PrettyPrinter<W> {
|
|||
}
|
||||
|
||||
pub fn func(&mut self, func: &Func<'_>) -> Result {
|
||||
writeln!(self.out, "def {}() {{", func.name)?;
|
||||
|
||||
let print_reg = |reg: Register| {
|
||||
display_fn(move |f| match func.regs[reg.0 as usize].name {
|
||||
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| {
|
||||
display_fn(move |f| match op {
|
||||
Operand::Const(c) => Display::fmt(&c, f),
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ use std::cell::{Cell, RefCell};
|
|||
|
||||
use parser::{
|
||||
ast::{
|
||||
self, Atom, DeclAttr, Expr, ExprBinary, ExternalDecl, Stmt, TranslationUnit, TypeSpecifier,
|
||||
self, Atom, DeclAttr, Expr, ExprBinary, ExternalDecl, InitDecl, Stmt, TranslationUnit,
|
||||
TypeSpecifier,
|
||||
},
|
||||
Span, Symbol,
|
||||
};
|
||||
|
|
@ -120,16 +121,17 @@ pub fn lower_translation_unit<'cx>(
|
|||
match decl {
|
||||
ExternalDecl::Decl(_) => todo!("decl is unsupported"),
|
||||
ExternalDecl::FunctionDef(def) => {
|
||||
let decl = def.decl.uwnrap_normal();
|
||||
let decl = def.decl.unwrap_normal();
|
||||
let body = &def.body;
|
||||
let ret_ty = lcx.lower_ty(&decl.decl_spec.ty);
|
||||
let func = lower_body(
|
||||
&lcx,
|
||||
body,
|
||||
decl.init_declarators[0].1,
|
||||
decl.init_declarators[0].0.declarator.decl.name().0,
|
||||
ret_ty,
|
||||
)?;
|
||||
|
||||
let (ref declarator, def_span) = decl.init_declarators[0];
|
||||
|
||||
let ast::DirectDeclarator::WithParams { ident, params } = &declarator.declarator.decl else {
|
||||
unreachable!("function def needs withparams declarator");
|
||||
};
|
||||
|
||||
let func = lower_func(&lcx, body, def_span, ident.0, ret_ty, params)?;
|
||||
ir.funcs.insert(lcx.next_def_id(), func);
|
||||
}
|
||||
}
|
||||
|
|
@ -161,37 +163,42 @@ impl<'a, 'cx> FnLoweringCtxt<'a, 'cx> {
|
|||
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<()> {
|
||||
match stmt {
|
||||
Stmt::Decl(decl) => {
|
||||
let decl = decl.uwnrap_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), 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);
|
||||
}
|
||||
}
|
||||
self.declare_local(decl, stmt_span)?;
|
||||
}
|
||||
Stmt::Labeled { .. } => todo!("labels are not implemented"),
|
||||
Stmt::Compound(block) => {
|
||||
|
|
@ -393,20 +400,68 @@ struct VariableInfo<'cx> {
|
|||
decl_attr: DeclAttr,
|
||||
}
|
||||
|
||||
fn lower_body<'cx>(
|
||||
fn lower_func<'cx>(
|
||||
// may be used later
|
||||
lcx: &LoweringCx<'cx>,
|
||||
body: &[(Stmt, Span)],
|
||||
def_span: Span,
|
||||
name: Symbol,
|
||||
ret_ty: Ty<'cx>,
|
||||
params: &[ast::FunctionParamDecl],
|
||||
) -> Result<Func<'cx>, Error> {
|
||||
let mut cx = FnLoweringCtxt {
|
||||
scopes: vec![],
|
||||
build: FuncBuilder::new(name, def_span, ret_ty, lcx),
|
||||
scopes: vec![Default::default()],
|
||||
build: FuncBuilder::new(
|
||||
name,
|
||||
def_span,
|
||||
ret_ty,
|
||||
lcx,
|
||||
params.len().try_into().unwrap(),
|
||||
),
|
||||
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)?;
|
||||
|
||||
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> {
|
||||
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 {
|
||||
ir: Func {
|
||||
regs: Vec::new(),
|
||||
|
|
@ -28,6 +34,7 @@ impl<'a, 'cx> FuncBuilder<'a, 'cx> {
|
|||
name,
|
||||
def_span,
|
||||
ret_ty,
|
||||
arity,
|
||||
},
|
||||
current_bb: BbIdx(0),
|
||||
lcx,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
use std::{
|
||||
fmt::Display,
|
||||
hash::{Hash, Hasher},
|
||||
ops::Deref,
|
||||
};
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use parser::{ast::IntTy, Symbol};
|
||||
use parser::{
|
||||
ast::{IntTy, IntTyKind, IntTySignedness},
|
||||
Symbol,
|
||||
};
|
||||
|
||||
use crate::ir::DefId;
|
||||
|
||||
|
|
@ -74,3 +78,37 @@ impl Hash for EnumTy {
|
|||
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,
|
||||
}
|
||||
|
||||
#[derive(Debug, DebugPls)]
|
||||
#[derive(Debug, DebugPls, Clone)]
|
||||
pub enum TypeSpecifier {
|
||||
Void,
|
||||
Char,
|
||||
|
|
@ -205,7 +205,7 @@ impl DebugPls for DeclAttr {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, DebugPls)]
|
||||
#[derive(Debug, DebugPls, Clone)]
|
||||
pub struct DeclSpec {
|
||||
pub ty: TypeSpecifier,
|
||||
pub attrs: DeclAttr,
|
||||
|
|
@ -229,13 +229,13 @@ pub struct NormalDecl {
|
|||
pub init_declarators: Vec<Spanned<InitDecl>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, DebugPls)]
|
||||
#[derive(Debug, DebugPls, Clone)]
|
||||
pub struct FunctionParamDecl {
|
||||
pub decl_spec: Spanned<DeclSpec>,
|
||||
pub declarator: Spanned<Declarator>,
|
||||
}
|
||||
|
||||
#[derive(Debug, DebugPls)]
|
||||
#[derive(Debug, DebugPls, Clone)]
|
||||
pub enum DirectDeclarator {
|
||||
Ident(Ident),
|
||||
WithParams {
|
||||
|
|
@ -244,7 +244,7 @@ pub enum DirectDeclarator {
|
|||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, DebugPls)]
|
||||
#[derive(Debug, DebugPls, Clone)]
|
||||
pub struct Declarator {
|
||||
pub decl: DirectDeclarator,
|
||||
pub pointer: bool,
|
||||
|
|
@ -265,7 +265,7 @@ pub enum ExternalDecl {
|
|||
pub type TranslationUnit = Vec<Spanned<ExternalDecl>>;
|
||||
|
||||
impl Decl {
|
||||
pub fn uwnrap_normal(&self) -> &NormalDecl {
|
||||
pub fn unwrap_normal(&self) -> &NormalDecl {
|
||||
match self {
|
||||
Decl::Normal(decl) => decl,
|
||||
Decl::StaticAssert => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue