mirror of
https://github.com/Noratrieb/uwucc.git
synced 2026-01-14 16:45:07 +01:00
tyl
This commit is contained in:
parent
86b924f5e3
commit
ffd3dad040
2 changed files with 73 additions and 64 deletions
|
|
@ -2,7 +2,10 @@ mod builder;
|
||||||
|
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
|
|
||||||
use parser::{ast, Span, Symbol};
|
use parser::{
|
||||||
|
ast::{self, IntTy, IntTyKind, IntTySignedness},
|
||||||
|
Span, Symbol,
|
||||||
|
};
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
|
|
||||||
use self::builder::FuncBuilder;
|
use self::builder::FuncBuilder;
|
||||||
|
|
@ -144,6 +147,14 @@ struct FnLoweringCtxt<'a, 'cx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'cx> FnLoweringCtxt<'a, 'cx> {
|
impl<'a, 'cx> FnLoweringCtxt<'a, 'cx> {
|
||||||
|
fn dummy_tyl(&self) -> TyLayout<'cx> {
|
||||||
|
self.ty_layout(TyKind::Void)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ty_layout(&self, ty_kind: TyKind<'cx>) -> TyLayout<'cx> {
|
||||||
|
self.lcx.layout_of(self.lcx.intern_ty(ty_kind))
|
||||||
|
}
|
||||||
|
|
||||||
fn resolve_ident(&self, ident: Symbol) -> Option<&VariableInfo<'cx>> {
|
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))
|
||||||
}
|
}
|
||||||
|
|
@ -183,7 +194,7 @@ impl<'a, 'cx> FnLoweringCtxt<'a, 'cx> {
|
||||||
}
|
}
|
||||||
if let Some((init, init_span)) = &var.init {
|
if let Some((init, init_span)) = &var.init {
|
||||||
let init = self.lower_expr(init, *init_span)?;
|
let init = self.lower_expr(init, *init_span)?;
|
||||||
self.build.store(ptr_to, init, tyl.layout, *init_span);
|
self.build.store(ptr_to, init.0, tyl.layout, *init_span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -235,7 +246,7 @@ impl<'a, 'cx> FnLoweringCtxt<'a, 'cx> {
|
||||||
None => cont,
|
None => cont,
|
||||||
};
|
};
|
||||||
self.build.bb_mut(pred).term = Branch::Switch {
|
self.build.bb_mut(pred).term = Branch::Switch {
|
||||||
cond,
|
cond: cond.0,
|
||||||
yes: then,
|
yes: then,
|
||||||
no: false_branch,
|
no: false_branch,
|
||||||
};
|
};
|
||||||
|
|
@ -249,7 +260,7 @@ impl<'a, 'cx> FnLoweringCtxt<'a, 'cx> {
|
||||||
ast::Stmt::Break => todo!(),
|
ast::Stmt::Break => todo!(),
|
||||||
ast::Stmt::Return(expr) => {
|
ast::Stmt::Return(expr) => {
|
||||||
let ret = match expr {
|
let ret = match expr {
|
||||||
Some(expr) => self.lower_expr(&expr.0, expr.1)?,
|
Some(expr) => self.lower_expr(&expr.0, expr.1)?.0,
|
||||||
None => Operand::Const(ConstValue::Void),
|
None => Operand::Const(ConstValue::Void),
|
||||||
};
|
};
|
||||||
self.build.cur_bb_mut().term = Branch::Ret(ret);
|
self.build.cur_bb_mut().term = Branch::Ret(ret);
|
||||||
|
|
@ -269,7 +280,8 @@ impl<'a, 'cx> FnLoweringCtxt<'a, 'cx> {
|
||||||
let Some(var) = self.resolve_ident(ident) else {
|
let Some(var) = self.resolve_ident(ident) else {
|
||||||
return Err(Error::new(format!("cannot find variable {ident}"), ident_span));
|
return Err(Error::new(format!("cannot find variable {ident}"), ident_span));
|
||||||
};
|
};
|
||||||
self.build.store(var.ptr_to, rhs, var.tyl.layout, stmt_span);
|
self.build
|
||||||
|
.store(var.ptr_to, rhs.0, var.tyl.layout, stmt_span);
|
||||||
}
|
}
|
||||||
ast::Stmt::Expr(expr) => {
|
ast::Stmt::Expr(expr) => {
|
||||||
self.lower_expr(expr, stmt_span)?;
|
self.lower_expr(expr, stmt_span)?;
|
||||||
|
|
@ -279,17 +291,27 @@ impl<'a, 'cx> FnLoweringCtxt<'a, 'cx> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_expr(&mut self, expr: &ast::Expr, span: Span) -> Result<Operand> {
|
fn lower_expr(&mut self, expr: &ast::Expr, span: Span) -> Result<(Operand, TyLayout<'cx>)> {
|
||||||
match expr {
|
match expr {
|
||||||
ast::Expr::Atom(ast::Atom::Char(c)) => Ok(Operand::Const(ConstValue::Int((*c).into()))),
|
ast::Expr::Atom(ast::Atom::Char(c)) => Ok((
|
||||||
ast::Expr::Atom(ast::Atom::Int(i)) => Ok(Operand::Const(ConstValue::Int(*i as _))),
|
Operand::Const(ConstValue::Int((*c).into())),
|
||||||
|
self.ty_layout(TyKind::Char),
|
||||||
|
)),
|
||||||
|
ast::Expr::Atom(ast::Atom::Int(i)) => Ok((
|
||||||
|
Operand::Const(ConstValue::Int(*i as _)),
|
||||||
|
self.ty_layout(TyKind::Integer(IntTy {
|
||||||
|
sign: IntTySignedness::Signed,
|
||||||
|
kind: IntTyKind::Int,
|
||||||
|
})),
|
||||||
|
)),
|
||||||
ast::Expr::Atom(ast::Atom::Float(_)) => todo!("no floats"),
|
ast::Expr::Atom(ast::Atom::Float(_)) => todo!("no floats"),
|
||||||
ast::Expr::Atom(ast::Atom::Ident((ident, ident_span))) => {
|
ast::Expr::Atom(ast::Atom::Ident((ident, ident_span))) => {
|
||||||
let Some(var) = self.resolve_ident(*ident) else {
|
let Some(var) = self.resolve_ident(*ident) else {
|
||||||
return Err(Error::new(format!("cannot find variable {ident}"), *ident_span));
|
return Err(Error::new(format!("cannot find variable {ident}"), *ident_span));
|
||||||
};
|
};
|
||||||
|
let tyl = var.tyl;
|
||||||
let op = self.build.load(var.tyl, var.ptr_to, span);
|
let op = self.build.load(var.tyl, var.ptr_to, span);
|
||||||
Ok(Operand::Reg(op))
|
Ok((Operand::Reg(op), tyl))
|
||||||
}
|
}
|
||||||
ast::Expr::Atom(ast::Atom::String(_)) => todo!("no string literals"),
|
ast::Expr::Atom(ast::Atom::String(_)) => todo!("no string literals"),
|
||||||
ast::Expr::Unary(ast::ExprUnary {
|
ast::Expr::Unary(ast::ExprUnary {
|
||||||
|
|
@ -297,33 +319,29 @@ impl<'a, 'cx> FnLoweringCtxt<'a, 'cx> {
|
||||||
rhs: rhs_expr,
|
rhs: rhs_expr,
|
||||||
}) => {
|
}) => {
|
||||||
// First increment/decrement, then return the value.
|
// First increment/decrement, then return the value.
|
||||||
let rhs = self.lower_expr(&rhs_expr.0, rhs_expr.1)?;
|
let (rhs, rhs_tyl) = self.lower_expr(&rhs_expr.0, rhs_expr.1)?;
|
||||||
let lvalue = self.expr_as_lvalue(&rhs_expr.0)?;
|
let is_incr = matches!(op, ast::UnaryOp::Increment);
|
||||||
let bin_kind = if let ast::UnaryOp::Increment = op {
|
|
||||||
BinKind::Add
|
|
||||||
} else {
|
|
||||||
BinKind::Sub
|
|
||||||
};
|
|
||||||
let lhs = self.build.load(
|
|
||||||
self.lcx.layout_of(self.lcx.intern_ty(TyKind::Void)),
|
|
||||||
lvalue,
|
|
||||||
span,
|
|
||||||
);
|
|
||||||
let result = self.build.binary(
|
|
||||||
bin_kind,
|
|
||||||
Operand::Reg(lhs),
|
|
||||||
rhs,
|
|
||||||
span,
|
|
||||||
self.lcx.layout_of(self.lcx.intern_ty(TyKind::Void)),
|
|
||||||
);
|
|
||||||
self.build.store(
|
|
||||||
lhs,
|
|
||||||
rhs,
|
|
||||||
self.lcx.layout_of(self.lcx.intern_ty(TyKind::Void)).layout,
|
|
||||||
span,
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(Operand::Reg(result))
|
if !rhs_tyl.ty.is_integral() {
|
||||||
|
return Err(Error::new(
|
||||||
|
format!(
|
||||||
|
"cannot {} {}",
|
||||||
|
if is_incr { "increment" } else { "decrement" },
|
||||||
|
rhs_tyl.ty
|
||||||
|
),
|
||||||
|
rhs_expr.1,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let lvalue = self.expr_as_lvalue(&rhs_expr.0)?;
|
||||||
|
let bin_kind = if is_incr { BinKind::Add } else { BinKind::Sub };
|
||||||
|
let lhs = self.build.load(self.dummy_tyl(), lvalue, span);
|
||||||
|
let result =
|
||||||
|
self.build
|
||||||
|
.binary(bin_kind, Operand::Reg(lhs), rhs, span, self.dummy_tyl());
|
||||||
|
self.build.store(lhs, rhs, self.dummy_tyl().layout, span);
|
||||||
|
|
||||||
|
Ok((Operand::Reg(result), self.dummy_tyl()))
|
||||||
}
|
}
|
||||||
ast::Expr::Unary(unary) => {
|
ast::Expr::Unary(unary) => {
|
||||||
let rhs = self.lower_expr(&unary.rhs.0, unary.rhs.1)?;
|
let rhs = self.lower_expr(&unary.rhs.0, unary.rhs.1)?;
|
||||||
|
|
@ -338,13 +356,8 @@ impl<'a, 'cx> FnLoweringCtxt<'a, 'cx> {
|
||||||
ast::UnaryOp::Bang => UnaryKind::LogicalNot,
|
ast::UnaryOp::Bang => UnaryKind::LogicalNot,
|
||||||
};
|
};
|
||||||
|
|
||||||
let reg = self.build.unary(
|
let reg = self.build.unary(kind, rhs.0, span, self.dummy_tyl());
|
||||||
kind,
|
Ok((Operand::Reg(reg), self.dummy_tyl()))
|
||||||
rhs,
|
|
||||||
span,
|
|
||||||
self.lcx.layout_of(self.lcx.intern_ty(TyKind::Void)),
|
|
||||||
);
|
|
||||||
Ok(Operand::Reg(reg))
|
|
||||||
}
|
}
|
||||||
ast::Expr::Binary(ast::ExprBinary {
|
ast::Expr::Binary(ast::ExprBinary {
|
||||||
lhs,
|
lhs,
|
||||||
|
|
@ -357,12 +370,8 @@ impl<'a, 'cx> FnLoweringCtxt<'a, 'cx> {
|
||||||
let rhs = self.lower_expr(&rhs.0, rhs.1)?;
|
let rhs = self.lower_expr(&rhs.0, rhs.1)?;
|
||||||
|
|
||||||
let ptr_to = self.expr_as_lvalue(&lhs.0)?;
|
let ptr_to = self.expr_as_lvalue(&lhs.0)?;
|
||||||
self.build.store(
|
self.build
|
||||||
ptr_to,
|
.store(ptr_to, rhs.0, self.dummy_tyl().layout, span);
|
||||||
rhs,
|
|
||||||
self.lcx.layout_of(self.lcx.intern_ty(TyKind::Void)).layout,
|
|
||||||
span,
|
|
||||||
);
|
|
||||||
Ok(rhs)
|
Ok(rhs)
|
||||||
}
|
}
|
||||||
ast::Expr::Binary(binary) => {
|
ast::Expr::Binary(binary) => {
|
||||||
|
|
@ -395,15 +404,11 @@ impl<'a, 'cx> FnLoweringCtxt<'a, 'cx> {
|
||||||
ast::BinaryOp::Assign(_) => unreachable!("assign handled above"),
|
ast::BinaryOp::Assign(_) => unreachable!("assign handled above"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let reg = self.build.binary(
|
let reg = self
|
||||||
kind,
|
.build
|
||||||
lhs,
|
.binary(kind, lhs.0, rhs.0, span, self.dummy_tyl());
|
||||||
rhs,
|
|
||||||
span,
|
|
||||||
self.lcx.layout_of(self.lcx.intern_ty(TyKind::Void)),
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(Operand::Reg(reg))
|
Ok((Operand::Reg(reg), self.dummy_tyl()))
|
||||||
}
|
}
|
||||||
ast::Expr::Postfix(postfix) => {
|
ast::Expr::Postfix(postfix) => {
|
||||||
let lhs = self.lower_expr(&postfix.lhs.0, postfix.lhs.1)?;
|
let lhs = self.lower_expr(&postfix.lhs.0, postfix.lhs.1)?;
|
||||||
|
|
@ -411,16 +416,11 @@ impl<'a, 'cx> FnLoweringCtxt<'a, 'cx> {
|
||||||
ast::PostfixOp::Call(args) => {
|
ast::PostfixOp::Call(args) => {
|
||||||
let args = args
|
let args = args
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(arg, sp)| self.lower_expr(arg, *sp))
|
.map(|(arg, sp)| self.lower_expr(arg, *sp).map(|o| o.0))
|
||||||
.collect::<Result<_, _>>()?;
|
.collect::<Result<_, _>>()?;
|
||||||
|
|
||||||
let reg = self.build.call(
|
let reg = self.build.call(self.dummy_tyl(), lhs.0, args, span);
|
||||||
self.lcx.layout_of(self.lcx.intern_ty(TyKind::Void)),
|
Ok((Operand::Reg(reg), self.dummy_tyl()))
|
||||||
lhs,
|
|
||||||
args,
|
|
||||||
span,
|
|
||||||
);
|
|
||||||
Ok(Operand::Reg(reg))
|
|
||||||
}
|
}
|
||||||
ast::PostfixOp::Member(_) => todo!("member expr"),
|
ast::PostfixOp::Member(_) => todo!("member expr"),
|
||||||
ast::PostfixOp::ArrowMember(_) => todo!("arrow member expr"),
|
ast::PostfixOp::ArrowMember(_) => todo!("arrow member expr"),
|
||||||
|
|
|
||||||
|
|
@ -112,3 +112,12 @@ impl Display for Ty<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'cx> Ty<'cx> {
|
||||||
|
pub fn is_integral(self) -> bool {
|
||||||
|
matches!(
|
||||||
|
*self,
|
||||||
|
TyKind::Char | TyKind::SChar | TyKind::UChar | TyKind::Integer(_)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue