mirror of
https://github.com/Noratrieb/uwucc.git
synced 2026-01-14 16:45:07 +01:00
more
This commit is contained in:
parent
542c0daf6a
commit
86b924f5e3
7 changed files with 171 additions and 67 deletions
|
|
@ -122,6 +122,11 @@ pub enum StatementKind {
|
||||||
rhs: Operand,
|
rhs: Operand,
|
||||||
result: Register,
|
result: Register,
|
||||||
},
|
},
|
||||||
|
UnaryOperation {
|
||||||
|
rhs: Operand,
|
||||||
|
kind: UnaryKind,
|
||||||
|
result: Register,
|
||||||
|
},
|
||||||
PtrOffset {
|
PtrOffset {
|
||||||
result: Register,
|
result: Register,
|
||||||
reg: Register,
|
reg: Register,
|
||||||
|
|
@ -171,6 +176,13 @@ pub enum BinKind {
|
||||||
BitXor,
|
BitXor,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum UnaryKind {
|
||||||
|
Negate,
|
||||||
|
BitNot,
|
||||||
|
LogicalNot,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum ConstValue {
|
pub enum ConstValue {
|
||||||
Void,
|
Void,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use std::fmt::{Display, Formatter, Result, Write};
|
use std::fmt::{Display, Formatter, Result, Write};
|
||||||
|
|
||||||
use super::{BbIdx, BinKind, Branch, ConstValue, Func, Ir, Operand, StatementKind};
|
use super::{BbIdx, BinKind, Branch, ConstValue, Func, Ir, Operand, StatementKind, UnaryKind};
|
||||||
use crate::ir::Register;
|
use crate::ir::Register;
|
||||||
|
|
||||||
pub fn ir_to_string(ir: &Ir<'_>) -> String {
|
pub fn ir_to_string(ir: &Ir<'_>) -> String {
|
||||||
|
|
@ -125,6 +125,17 @@ impl<W: Write> PrettyPrinter<W> {
|
||||||
print_op(lhs),
|
print_op(lhs),
|
||||||
print_op(rhs)
|
print_op(rhs)
|
||||||
),
|
),
|
||||||
|
StatementKind::UnaryOperation { rhs, kind, result } => writeln!(
|
||||||
|
self.out,
|
||||||
|
" {} = {} {}",
|
||||||
|
print_reg(result),
|
||||||
|
match kind {
|
||||||
|
UnaryKind::Negate => "negate",
|
||||||
|
UnaryKind::BitNot => "bitnot",
|
||||||
|
UnaryKind::LogicalNot => "logicalnot",
|
||||||
|
},
|
||||||
|
print_op(rhs)
|
||||||
|
),
|
||||||
StatementKind::PtrOffset {
|
StatementKind::PtrOffset {
|
||||||
result,
|
result,
|
||||||
reg,
|
reg,
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
use rustc_hash::FxHashSet;
|
||||||
|
|
||||||
use super::{Branch, Ir};
|
use super::{Branch, Ir};
|
||||||
use crate::ir::BbIdx;
|
use crate::ir::BbIdx;
|
||||||
|
|
||||||
|
|
@ -5,7 +7,21 @@ pub fn validate(ir: &Ir<'_>) {
|
||||||
for fun in ir.funcs.values() {
|
for fun in ir.funcs.values() {
|
||||||
for (i, bb) in fun.bbs.iter().enumerate() {
|
for (i, bb) in fun.bbs.iter().enumerate() {
|
||||||
if let Branch::Goto(BbIdx(u32::MAX)) = bb.term {
|
if let Branch::Goto(BbIdx(u32::MAX)) = bb.term {
|
||||||
panic!("found dummy term in {} in {}", BbIdx::from_usize(i), fun.name)
|
panic!(
|
||||||
|
"found dummy term in {} in {}",
|
||||||
|
BbIdx::from_usize(i),
|
||||||
|
fun.name
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut reg_names = FxHashSet::default();
|
||||||
|
for reg in &fun.regs {
|
||||||
|
if let Some(name) = reg.name {
|
||||||
|
let is_new = reg_names.insert(name);
|
||||||
|
if !is_new {
|
||||||
|
panic!("register name {name} is used twice");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,20 +2,14 @@ mod builder;
|
||||||
|
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
|
|
||||||
use parser::{
|
use parser::{ast, Span, Symbol};
|
||||||
ast::{
|
|
||||||
self, Atom, DeclAttr, Expr, ExprBinary, ExternalDecl, InitDecl, Stmt, TranslationUnit,
|
|
||||||
TypeSpecifier,
|
|
||||||
},
|
|
||||||
Span, Symbol,
|
|
||||||
};
|
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
|
|
||||||
use self::builder::FuncBuilder;
|
use self::builder::FuncBuilder;
|
||||||
use crate::{
|
use crate::{
|
||||||
ir::{
|
ir::{
|
||||||
self, BbIdx, BinKind, Branch, ConstValue, DefId, Func, Ir, Layout, Operand, Register,
|
self, BbIdx, BinKind, Branch, ConstValue, DefId, Func, Ir, Layout, Operand, Register,
|
||||||
TyLayout,
|
TyLayout, UnaryKind,
|
||||||
},
|
},
|
||||||
ty::{Ty, TyKind},
|
ty::{Ty, TyKind},
|
||||||
Error,
|
Error,
|
||||||
|
|
@ -37,17 +31,17 @@ impl<'cx> LoweringCx<'cx> {
|
||||||
self.next_def_id.set(DefId(def_id.0 + 1));
|
self.next_def_id.set(DefId(def_id.0 + 1));
|
||||||
def_id
|
def_id
|
||||||
}
|
}
|
||||||
fn lower_ty(&self, ty: &TypeSpecifier) -> Ty<'cx> {
|
fn lower_ty(&self, ty: &ast::TypeSpecifier) -> Ty<'cx> {
|
||||||
let kind = match ty {
|
let kind = match ty {
|
||||||
TypeSpecifier::Void => TyKind::Void,
|
ast::TypeSpecifier::Void => TyKind::Void,
|
||||||
TypeSpecifier::Char => TyKind::Char,
|
ast::TypeSpecifier::Char => TyKind::Char,
|
||||||
TypeSpecifier::SChar => TyKind::SChar,
|
ast::TypeSpecifier::SChar => TyKind::SChar,
|
||||||
TypeSpecifier::UChar => TyKind::UChar,
|
ast::TypeSpecifier::UChar => TyKind::UChar,
|
||||||
TypeSpecifier::Integer(int) => TyKind::Integer(*int),
|
ast::TypeSpecifier::Integer(int) => TyKind::Integer(*int),
|
||||||
TypeSpecifier::Float => TyKind::Float,
|
ast::TypeSpecifier::Float => TyKind::Float,
|
||||||
TypeSpecifier::Double => TyKind::Double,
|
ast::TypeSpecifier::Double => TyKind::Double,
|
||||||
TypeSpecifier::LongDouble => TyKind::LongDouble,
|
ast::TypeSpecifier::LongDouble => TyKind::LongDouble,
|
||||||
TypeSpecifier::Bool => TyKind::Bool,
|
ast::TypeSpecifier::Bool => TyKind::Bool,
|
||||||
};
|
};
|
||||||
self.intern_ty(kind)
|
self.intern_ty(kind)
|
||||||
}
|
}
|
||||||
|
|
@ -104,7 +98,7 @@ impl<'cx> LoweringCx<'cx> {
|
||||||
|
|
||||||
pub fn lower_translation_unit<'cx>(
|
pub fn lower_translation_unit<'cx>(
|
||||||
arena: &'cx bumpalo::Bump,
|
arena: &'cx bumpalo::Bump,
|
||||||
ast: &TranslationUnit,
|
ast: &ast::TranslationUnit,
|
||||||
) -> Result<Ir<'cx>, Error> {
|
) -> Result<Ir<'cx>, Error> {
|
||||||
let lcx = LoweringCx {
|
let lcx = LoweringCx {
|
||||||
tys: RefCell::default(),
|
tys: RefCell::default(),
|
||||||
|
|
@ -119,8 +113,8 @@ pub fn lower_translation_unit<'cx>(
|
||||||
|
|
||||||
for (decl, _) in ast {
|
for (decl, _) in ast {
|
||||||
match decl {
|
match decl {
|
||||||
ExternalDecl::Decl(_) => todo!("decl is unsupported"),
|
ast::ExternalDecl::Decl(_) => todo!("decl is unsupported"),
|
||||||
ExternalDecl::FunctionDef(def) => {
|
ast::ExternalDecl::FunctionDef(def) => {
|
||||||
let decl = def.decl.unwrap_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);
|
||||||
|
|
@ -154,7 +148,7 @@ impl<'a, 'cx> FnLoweringCtxt<'a, 'cx> {
|
||||||
self.scopes.iter().rev().find_map(|s| s.get(&ident))
|
self.scopes.iter().rev().find_map(|s| s.get(&ident))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_block(&mut self, body: &[(Stmt, Span)]) -> Result<()> {
|
fn lower_block(&mut self, body: &[(ast::Stmt, Span)]) -> Result<()> {
|
||||||
self.scopes.push(Default::default());
|
self.scopes.push(Default::default());
|
||||||
for (stmt, stmt_span) in body {
|
for (stmt, stmt_span) in body {
|
||||||
self.lower_stmt(stmt, *stmt_span)?;
|
self.lower_stmt(stmt, *stmt_span)?;
|
||||||
|
|
@ -195,16 +189,26 @@ impl<'a, 'cx> FnLoweringCtxt<'a, 'cx> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn expr_as_lvalue(&mut self, expr: &ast::Expr) -> Result<Register> {
|
||||||
|
let ast::Expr::Atom(ast::Atom::Ident((ident, ident_span))) = *expr else {
|
||||||
|
todo!("complex lvalues")
|
||||||
|
};
|
||||||
|
let Some(var) = self.resolve_ident(ident) else {
|
||||||
|
return Err(Error::new(format!("cannot find variable {ident}"), ident_span));
|
||||||
|
};
|
||||||
|
Ok(var.ptr_to)
|
||||||
|
}
|
||||||
|
|
||||||
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) => {
|
ast::Stmt::Decl(decl) => {
|
||||||
self.declare_local(decl, stmt_span)?;
|
self.declare_local(decl, stmt_span)?;
|
||||||
}
|
}
|
||||||
Stmt::Labeled { .. } => todo!("labels are not implemented"),
|
ast::Stmt::Labeled { .. } => todo!("labels are not implemented"),
|
||||||
Stmt::Compound(block) => {
|
ast::Stmt::Compound(block) => {
|
||||||
self.lower_block(block)?;
|
self.lower_block(block)?;
|
||||||
}
|
}
|
||||||
Stmt::If {
|
ast::Stmt::If {
|
||||||
cond,
|
cond,
|
||||||
then: then_body,
|
then: then_body,
|
||||||
otherwise,
|
otherwise,
|
||||||
|
|
@ -237,26 +241,20 @@ impl<'a, 'cx> FnLoweringCtxt<'a, 'cx> {
|
||||||
};
|
};
|
||||||
self.build.current_bb = cont;
|
self.build.current_bb = cont;
|
||||||
}
|
}
|
||||||
Stmt::Switch => todo!(),
|
ast::Stmt::Switch => todo!(),
|
||||||
Stmt::While { cond, body } => todo!(),
|
ast::Stmt::While { .. } => todo!(),
|
||||||
Stmt::For {
|
ast::Stmt::For { .. } => todo!(),
|
||||||
init_decl,
|
ast::Stmt::Goto(_) => todo!(),
|
||||||
init_expr,
|
ast::Stmt::Continue => todo!(),
|
||||||
cond,
|
ast::Stmt::Break => todo!(),
|
||||||
post,
|
ast::Stmt::Return(expr) => {
|
||||||
body,
|
|
||||||
} => todo!(),
|
|
||||||
Stmt::Goto(_) => todo!(),
|
|
||||||
Stmt::Continue => todo!(),
|
|
||||||
Stmt::Break => todo!(),
|
|
||||||
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)?,
|
||||||
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);
|
||||||
}
|
}
|
||||||
Stmt::Expr(ast::Expr::Binary(ast::ExprBinary {
|
ast::Stmt::Expr(ast::Expr::Binary(ast::ExprBinary {
|
||||||
op: ast::BinaryOp::Assign(assign),
|
op: ast::BinaryOp::Assign(assign),
|
||||||
lhs,
|
lhs,
|
||||||
rhs,
|
rhs,
|
||||||
|
|
@ -265,7 +263,7 @@ impl<'a, 'cx> FnLoweringCtxt<'a, 'cx> {
|
||||||
todo!("assign operation");
|
todo!("assign operation");
|
||||||
}
|
}
|
||||||
let rhs = self.lower_expr(&rhs.0, rhs.1)?;
|
let rhs = self.lower_expr(&rhs.0, rhs.1)?;
|
||||||
let (Expr::Atom(ast::Atom::Ident((ident, ident_span))), _) = **lhs else {
|
let (ast::Expr::Atom(ast::Atom::Ident((ident, ident_span))), _) = **lhs else {
|
||||||
todo!("complex assignments")
|
todo!("complex assignments")
|
||||||
};
|
};
|
||||||
let Some(var) = self.resolve_ident(ident) else {
|
let Some(var) = self.resolve_ident(ident) else {
|
||||||
|
|
@ -273,7 +271,7 @@ impl<'a, 'cx> FnLoweringCtxt<'a, 'cx> {
|
||||||
};
|
};
|
||||||
self.build.store(var.ptr_to, rhs, var.tyl.layout, stmt_span);
|
self.build.store(var.ptr_to, rhs, var.tyl.layout, stmt_span);
|
||||||
}
|
}
|
||||||
Stmt::Expr(expr) => {
|
ast::Stmt::Expr(expr) => {
|
||||||
self.lower_expr(expr, stmt_span)?;
|
self.lower_expr(expr, stmt_span)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -283,29 +281,72 @@ impl<'a, 'cx> FnLoweringCtxt<'a, 'cx> {
|
||||||
|
|
||||||
fn lower_expr(&mut self, expr: &ast::Expr, span: Span) -> Result<Operand> {
|
fn lower_expr(&mut self, expr: &ast::Expr, span: Span) -> Result<Operand> {
|
||||||
match expr {
|
match expr {
|
||||||
ast::Expr::Atom(Atom::Char(c)) => Ok(Operand::Const(ConstValue::Int((*c).into()))),
|
ast::Expr::Atom(ast::Atom::Char(c)) => Ok(Operand::Const(ConstValue::Int((*c).into()))),
|
||||||
ast::Expr::Atom(Atom::Int(i)) => Ok(Operand::Const(ConstValue::Int(*i as _))),
|
ast::Expr::Atom(ast::Atom::Int(i)) => Ok(Operand::Const(ConstValue::Int(*i as _))),
|
||||||
ast::Expr::Atom(Atom::Float(_)) => todo!("no floats"),
|
ast::Expr::Atom(ast::Atom::Float(_)) => todo!("no floats"),
|
||||||
ast::Expr::Atom(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 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))
|
||||||
}
|
}
|
||||||
ast::Expr::Atom(Atom::String(_)) => todo!("no string literals"),
|
ast::Expr::Atom(ast::Atom::String(_)) => todo!("no string literals"),
|
||||||
|
ast::Expr::Unary(ast::ExprUnary {
|
||||||
|
op: op @ (ast::UnaryOp::Increment | ast::UnaryOp::Decrement),
|
||||||
|
rhs: rhs_expr,
|
||||||
|
}) => {
|
||||||
|
// First increment/decrement, then return the value.
|
||||||
|
let rhs = self.lower_expr(&rhs_expr.0, rhs_expr.1)?;
|
||||||
|
let lvalue = self.expr_as_lvalue(&rhs_expr.0)?;
|
||||||
|
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))
|
||||||
|
}
|
||||||
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)?;
|
||||||
match unary.op {
|
let kind = match unary.op {
|
||||||
|
ast::UnaryOp::Increment => unreachable!("handled prefix increment above"),
|
||||||
|
ast::UnaryOp::Decrement => unreachable!("handled prefix increment above"),
|
||||||
ast::UnaryOp::AddrOf => todo!("addr of"),
|
ast::UnaryOp::AddrOf => todo!("addr of"),
|
||||||
ast::UnaryOp::Deref => todo!("deref?"),
|
ast::UnaryOp::Deref => todo!("deref?"),
|
||||||
ast::UnaryOp::Plus => todo!("unary plus lol"),
|
ast::UnaryOp::Plus => todo!("unary plus lol"),
|
||||||
ast::UnaryOp::Minus => todo!("unary minus!"),
|
ast::UnaryOp::Minus => UnaryKind::Negate,
|
||||||
ast::UnaryOp::Tilde => todo!("tilde"),
|
ast::UnaryOp::Tilde => UnaryKind::BitNot,
|
||||||
ast::UnaryOp::Bang => todo!("bang bang bang"),
|
ast::UnaryOp::Bang => UnaryKind::LogicalNot,
|
||||||
|
};
|
||||||
|
|
||||||
|
let reg = self.build.unary(
|
||||||
|
kind,
|
||||||
|
rhs,
|
||||||
|
span,
|
||||||
|
self.lcx.layout_of(self.lcx.intern_ty(TyKind::Void)),
|
||||||
|
);
|
||||||
|
Ok(Operand::Reg(reg))
|
||||||
}
|
}
|
||||||
}
|
ast::Expr::Binary(ast::ExprBinary {
|
||||||
ast::Expr::Binary(ExprBinary {
|
|
||||||
lhs,
|
lhs,
|
||||||
rhs,
|
rhs,
|
||||||
op: ast::BinaryOp::Assign(assign),
|
op: ast::BinaryOp::Assign(assign),
|
||||||
|
|
@ -314,13 +355,14 @@ impl<'a, 'cx> FnLoweringCtxt<'a, 'cx> {
|
||||||
todo!("assign operation");
|
todo!("assign operation");
|
||||||
}
|
}
|
||||||
let rhs = self.lower_expr(&rhs.0, rhs.1)?;
|
let rhs = self.lower_expr(&rhs.0, rhs.1)?;
|
||||||
let (Expr::Atom(ast::Atom::Ident((ident, ident_span))), _) = **lhs else {
|
|
||||||
todo!("complex assignments")
|
let ptr_to = self.expr_as_lvalue(&lhs.0)?;
|
||||||
};
|
self.build.store(
|
||||||
let Some(var) = self.resolve_ident(ident) else {
|
ptr_to,
|
||||||
return Err(Error::new(format!("cannot find variable {ident}"), ident_span));
|
rhs,
|
||||||
};
|
self.lcx.layout_of(self.lcx.intern_ty(TyKind::Void)).layout,
|
||||||
self.build.store(var.ptr_to, rhs, var.tyl.layout, span);
|
span,
|
||||||
|
);
|
||||||
Ok(rhs)
|
Ok(rhs)
|
||||||
}
|
}
|
||||||
ast::Expr::Binary(binary) => {
|
ast::Expr::Binary(binary) => {
|
||||||
|
|
@ -363,7 +405,7 @@ impl<'a, 'cx> FnLoweringCtxt<'a, 'cx> {
|
||||||
|
|
||||||
Ok(Operand::Reg(reg))
|
Ok(Operand::Reg(reg))
|
||||||
}
|
}
|
||||||
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)?;
|
||||||
match &postfix.op {
|
match &postfix.op {
|
||||||
ast::PostfixOp::Call(args) => {
|
ast::PostfixOp::Call(args) => {
|
||||||
|
|
@ -397,13 +439,13 @@ struct VariableInfo<'cx> {
|
||||||
def_span: Span,
|
def_span: Span,
|
||||||
tyl: TyLayout<'cx>,
|
tyl: TyLayout<'cx>,
|
||||||
ptr_to: Register,
|
ptr_to: Register,
|
||||||
decl_attr: DeclAttr,
|
decl_attr: ast::DeclAttr,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_func<'cx>(
|
fn lower_func<'cx>(
|
||||||
// may be used later
|
// may be used later
|
||||||
lcx: &LoweringCx<'cx>,
|
lcx: &LoweringCx<'cx>,
|
||||||
body: &[(Stmt, Span)],
|
body: &[(ast::Stmt, Span)],
|
||||||
def_span: Span,
|
def_span: Span,
|
||||||
name: Symbol,
|
name: Symbol,
|
||||||
ret_ty: Ty<'cx>,
|
ret_ty: Ty<'cx>,
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use super::LoweringCx;
|
||||||
use crate::{
|
use crate::{
|
||||||
ir::{
|
ir::{
|
||||||
self, BasicBlock, BbIdx, BinKind, Branch, ConstValue, Func, Layout, Operand, Register,
|
self, BasicBlock, BbIdx, BinKind, Branch, ConstValue, Func, Layout, Operand, Register,
|
||||||
RegisterData, Statement, StatementKind, TyLayout,
|
RegisterData, Statement, StatementKind, TyLayout, UnaryKind,
|
||||||
},
|
},
|
||||||
ty::{Ty, TyKind},
|
ty::{Ty, TyKind},
|
||||||
};
|
};
|
||||||
|
|
@ -85,6 +85,25 @@ impl<'a, 'cx> FuncBuilder<'a, 'cx> {
|
||||||
reg
|
reg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn unary(
|
||||||
|
&mut self,
|
||||||
|
kind: UnaryKind,
|
||||||
|
rhs: Operand,
|
||||||
|
span: Span,
|
||||||
|
result_tyl: TyLayout<'cx>,
|
||||||
|
) -> Register {
|
||||||
|
let reg = self.new_reg(None, result_tyl);
|
||||||
|
let stmt = StatementKind::UnaryOperation {
|
||||||
|
kind,
|
||||||
|
rhs,
|
||||||
|
result: reg,
|
||||||
|
};
|
||||||
|
self.cur_bb_mut()
|
||||||
|
.statements
|
||||||
|
.push(Statement { span, kind: stmt });
|
||||||
|
reg
|
||||||
|
}
|
||||||
|
|
||||||
pub fn load(&mut self, tyl: TyLayout<'cx>, ptr_reg: Register, span: Span) -> Register {
|
pub fn load(&mut self, tyl: TyLayout<'cx>, ptr_reg: Register, span: Span) -> Register {
|
||||||
let reg = self.new_reg(None, tyl.clone());
|
let reg = self.new_reg(None, tyl.clone());
|
||||||
let stmt = StatementKind::Load {
|
let stmt = StatementKind::Load {
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@ pub enum Atom {
|
||||||
|
|
||||||
#[derive(Debug, DebugPls)]
|
#[derive(Debug, DebugPls)]
|
||||||
pub enum UnaryOp {
|
pub enum UnaryOp {
|
||||||
|
Increment,
|
||||||
|
Decrement,
|
||||||
AddrOf,
|
AddrOf,
|
||||||
Deref,
|
Deref,
|
||||||
Plus,
|
Plus,
|
||||||
|
|
|
||||||
|
|
@ -376,6 +376,8 @@ impl<W: Write> PrettyPrinter<W> {
|
||||||
|
|
||||||
fn unary(&mut self, unary: &ExprUnary) -> Result {
|
fn unary(&mut self, unary: &ExprUnary) -> Result {
|
||||||
self.string(match unary.op {
|
self.string(match unary.op {
|
||||||
|
UnaryOp::Increment => "++",
|
||||||
|
UnaryOp::Decrement => "--",
|
||||||
UnaryOp::AddrOf => "&",
|
UnaryOp::AddrOf => "&",
|
||||||
UnaryOp::Deref => "*",
|
UnaryOp::Deref => "*",
|
||||||
UnaryOp::Plus => "+",
|
UnaryOp::Plus => "+",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue