mirror of
https://github.com/Noratrieb/uwucc.git
synced 2026-01-14 16:45:07 +01:00
build
This commit is contained in:
parent
8bf9849641
commit
d3846e3357
5 changed files with 265 additions and 133 deletions
|
|
@ -43,6 +43,12 @@ use crate::ty::Ty;
|
||||||
pub struct DefId(u32);
|
pub struct DefId(u32);
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct TyLayout {
|
||||||
|
pub ty: Ty,
|
||||||
|
pub layout: Layout,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct Layout {
|
pub struct Layout {
|
||||||
pub size: u64,
|
pub size: u64,
|
||||||
pub align: u64,
|
pub align: u64,
|
||||||
|
|
@ -69,6 +75,7 @@ pub struct BasicBlock {
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct RegisterData {
|
pub struct RegisterData {
|
||||||
|
pub tyl: TyLayout,
|
||||||
pub name: Option<Symbol>,
|
pub name: Option<Symbol>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -111,6 +118,11 @@ pub enum StatementKind {
|
||||||
reg: Register,
|
reg: Register,
|
||||||
amount: Operand,
|
amount: Operand,
|
||||||
},
|
},
|
||||||
|
Call {
|
||||||
|
result: Register,
|
||||||
|
func: Operand,
|
||||||
|
args: Vec<Operand>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
|
|
||||||
|
|
@ -123,6 +123,22 @@ impl<W: Write> PrettyPrinter<W> {
|
||||||
print_reg(reg),
|
print_reg(reg),
|
||||||
print_op(amount)
|
print_op(amount)
|
||||||
),
|
),
|
||||||
|
StatementKind::Call {
|
||||||
|
result,
|
||||||
|
func,
|
||||||
|
ref args,
|
||||||
|
} => {
|
||||||
|
writeln!(
|
||||||
|
self.out,
|
||||||
|
" {} = call {} ({})",
|
||||||
|
print_reg(result),
|
||||||
|
print_op(func),
|
||||||
|
args.iter()
|
||||||
|
.map(|arg| print_op(*arg).to_string())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ")
|
||||||
|
)
|
||||||
|
}
|
||||||
}?;
|
}?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
|
mod builder;
|
||||||
|
|
||||||
use parser::{
|
use parser::{
|
||||||
ast::{self, Atom, DeclAttr, Expr, ExternalDecl, Stmt, TranslationUnit, TypeSpecifier},
|
ast::{self, Atom, DeclAttr, Expr, ExternalDecl, Stmt, TranslationUnit, TypeSpecifier},
|
||||||
Span, Symbol,
|
Span, Symbol,
|
||||||
};
|
};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
|
use self::builder::FuncBuilder;
|
||||||
use crate::{
|
use crate::{
|
||||||
ir::{
|
ir::{BinKind, ConstValue, Func, Ir, Layout, Operand, Register, TyLayout},
|
||||||
self, BasicBlock, BinKind, Branch, ConstValue, Func, Ir, Layout, Operand, Register,
|
|
||||||
RegisterData, Statement, StatementKind,
|
|
||||||
},
|
|
||||||
ty::Ty,
|
ty::Ty,
|
||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
@ -44,8 +44,7 @@ pub fn lower_translation_unit(ast: &TranslationUnit) -> Result<Ir, Error> {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct FnLoweringCtxt {
|
struct FnLoweringCtxt {
|
||||||
scopes: Vec<FxHashMap<Symbol, VariableInfo>>,
|
scopes: Vec<FxHashMap<Symbol, VariableInfo>>,
|
||||||
ir: Func,
|
build: FuncBuilder,
|
||||||
current_bb: u32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FnLoweringCtxt {
|
impl FnLoweringCtxt {
|
||||||
|
|
@ -53,24 +52,77 @@ impl FnLoweringCtxt {
|
||||||
self.scopes.iter().rev().find_map(|s| s.get(&ident))
|
self.scopes.iter().rev().find_map(|s| s.get(&ident))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_reg(&mut self, name: Option<Symbol>) -> Register {
|
fn lower_body(&mut self, body: &[(Stmt, Span)]) -> Result<()> {
|
||||||
let reg = Register(self.ir.regs.len().try_into().unwrap());
|
for (stmt, stmt_span) in body {
|
||||||
self.ir.regs.push(RegisterData { name });
|
self.lower_stmt(stmt, *stmt_span)?;
|
||||||
reg
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloca(&mut self, layout: &Layout, name: Option<Symbol>, span: Span) -> Register {
|
fn lower_stmt(&mut self, stmt: &ast::Stmt, stmt_span: Span) -> Result<()> {
|
||||||
let reg = self.new_reg(name);
|
match stmt {
|
||||||
let stmt = Statement {
|
Stmt::Decl(decl) => {
|
||||||
span,
|
let decl = decl.uwnrap_normal();
|
||||||
kind: StatementKind::Alloca {
|
let ty = lower_ty(&decl.decl_spec.ty);
|
||||||
reg,
|
let decl_attr = decl.decl_spec.attrs;
|
||||||
size: Operand::Const(ConstValue::u64(layout.size)),
|
|
||||||
align: Operand::Const(ConstValue::u64(layout.align)),
|
for (var, def_span) in &decl.init_declarators {
|
||||||
},
|
let tyl = layout_of(ty.clone());
|
||||||
|
let (name, _) = 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,
|
||||||
};
|
};
|
||||||
self.bb_mut().statements.push(stmt);
|
self.scopes.last_mut().unwrap().insert(name, variable_info);
|
||||||
reg
|
}
|
||||||
|
}
|
||||||
|
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(ast::Expr::Binary(ast::ExprBinary {
|
||||||
|
op: ast::BinaryOp::Assign(assign),
|
||||||
|
lhs,
|
||||||
|
rhs,
|
||||||
|
})) => {
|
||||||
|
if assign.is_some() {
|
||||||
|
todo!("assign operation");
|
||||||
|
}
|
||||||
|
let rhs = self.lower_expr(&rhs.0, rhs.1)?;
|
||||||
|
let (Expr::Atom(ast::Atom::Ident((ident, ident_span))), _) = **lhs else {
|
||||||
|
todo!("complex assignments")
|
||||||
|
};
|
||||||
|
let Some(var) = self.resolve_ident(ident) else {
|
||||||
|
return Err(Error::new(format!("cannot find variable {ident}"), ident_span));
|
||||||
|
};
|
||||||
|
self.build.store(var.ptr_to, rhs, var.tyl.layout, stmt_span);
|
||||||
|
}
|
||||||
|
Stmt::Expr(expr) => {
|
||||||
|
self.lower_expr(expr, stmt_span)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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> {
|
||||||
|
|
@ -108,35 +160,40 @@ impl FnLoweringCtxt {
|
||||||
ast::BinaryOp::Assign(_) => todo!("no assign"),
|
ast::BinaryOp::Assign(_) => todo!("no assign"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let reg = self.new_reg(None);
|
let reg = self.build.binary(kind, lhs, rhs, span, layout_of(Ty::Void));
|
||||||
let stmt = StatementKind::BinOp {
|
|
||||||
kind,
|
|
||||||
lhs,
|
|
||||||
rhs,
|
|
||||||
result: reg,
|
|
||||||
};
|
|
||||||
self.bb_mut()
|
|
||||||
.statements
|
|
||||||
.push(Statement { span, kind: stmt });
|
|
||||||
|
|
||||||
Ok(Operand::Reg(reg))
|
Ok(Operand::Reg(reg))
|
||||||
}
|
}
|
||||||
Expr::Postfix(_) => todo!(),
|
Expr::Postfix(postfix) => {
|
||||||
}
|
let lhs = self.lower_expr(&postfix.lhs.0, postfix.lhs.1)?;
|
||||||
}
|
match &postfix.op {
|
||||||
|
ast::PostfixOp::Call(args) => {
|
||||||
|
let args = args
|
||||||
|
.iter()
|
||||||
|
.map(|(arg, sp)| self.lower_expr(arg, *sp))
|
||||||
|
.collect::<Result<_, _>>()?;
|
||||||
|
|
||||||
fn bb_mut(&mut self) -> &mut BasicBlock {
|
let reg = self.build.call(layout_of(Ty::Void), lhs, args, span);
|
||||||
&mut self.ir.bbs[self.current_bb as usize]
|
Ok(Operand::Reg(reg))
|
||||||
|
}
|
||||||
|
ast::PostfixOp::Member(_) => todo!("member expr"),
|
||||||
|
ast::PostfixOp::ArrowMember(_) => todo!("arrow member expr"),
|
||||||
|
ast::PostfixOp::Increment => {
|
||||||
|
todo!("gotta have lvalues")
|
||||||
|
}
|
||||||
|
ast::PostfixOp::Decrement => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct VariableInfo {
|
struct VariableInfo {
|
||||||
def_span: Span,
|
def_span: Span,
|
||||||
ty: Ty,
|
tyl: TyLayout,
|
||||||
ptr_to: Register,
|
ptr_to: Register,
|
||||||
decl_attr: DeclAttr,
|
decl_attr: DeclAttr,
|
||||||
layout: Layout,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_body(
|
fn lower_body(
|
||||||
|
|
@ -149,100 +206,12 @@ fn lower_body(
|
||||||
) -> Result<Func, Error> {
|
) -> Result<Func, Error> {
|
||||||
let mut cx: FnLoweringCtxt = FnLoweringCtxt {
|
let mut cx: FnLoweringCtxt = FnLoweringCtxt {
|
||||||
scopes: vec![FxHashMap::default()],
|
scopes: vec![FxHashMap::default()],
|
||||||
ir: Func {
|
build: FuncBuilder::new(name, def_span, ret_ty),
|
||||||
regs: Vec::new(),
|
|
||||||
bbs: vec![BasicBlock {
|
|
||||||
statements: Vec::new(),
|
|
||||||
term: Branch::Goto(0),
|
|
||||||
}],
|
|
||||||
name,
|
|
||||||
def_span,
|
|
||||||
ret_ty,
|
|
||||||
},
|
|
||||||
current_bb: 0,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for (stmt, stmt_span) in body {
|
cx.lower_body(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 {
|
Ok(cx.build.finish())
|
||||||
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(ast::Expr::Binary(ast::ExprBinary {
|
|
||||||
op: ast::BinaryOp::Assign(assign),
|
|
||||||
lhs,
|
|
||||||
rhs,
|
|
||||||
})) => {
|
|
||||||
if assign.is_some() {
|
|
||||||
todo!("assign operation");
|
|
||||||
}
|
|
||||||
let rhs = cx.lower_expr(&rhs.0, rhs.1)?;
|
|
||||||
let (Expr::Atom(ast::Atom::Ident((ident, ident_span))), _) = **lhs else {
|
|
||||||
todo!("complex assignments")
|
|
||||||
};
|
|
||||||
let Some(var) = cx.resolve_ident(ident) else {
|
|
||||||
return Err(Error::new(format!("cannot find variable {ident}"), ident_span));
|
|
||||||
};
|
|
||||||
let stmt = StatementKind::Store {
|
|
||||||
ptr_reg: var.ptr_to,
|
|
||||||
value: rhs,
|
|
||||||
size: Operand::const_u64(var.layout.size),
|
|
||||||
align: Operand::const_u64(var.layout.align),
|
|
||||||
};
|
|
||||||
cx.bb_mut().statements.push(Statement {
|
|
||||||
span: *stmt_span,
|
|
||||||
kind: stmt,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Stmt::Expr(expr) => {
|
|
||||||
cx.lower_expr(expr, *stmt_span)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cx.bb_mut().term = Branch::Ret(Operand::Const(ConstValue::Void));
|
|
||||||
|
|
||||||
dbg!(&cx);
|
|
||||||
|
|
||||||
println!("{}", ir::func_to_string(&cx.ir));
|
|
||||||
|
|
||||||
Ok(cx.ir)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_ty(ty: &TypeSpecifier) -> Ty {
|
fn lower_ty(ty: &TypeSpecifier) -> Ty {
|
||||||
|
|
@ -259,8 +228,8 @@ fn lower_ty(ty: &TypeSpecifier) -> Ty {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout_of(ty: &Ty) -> Layout {
|
fn layout_of(ty: Ty) -> TyLayout {
|
||||||
match ty {
|
let layout = match ty {
|
||||||
Ty::Void => Layout::size_align(0, 1),
|
Ty::Void => Layout::size_align(0, 1),
|
||||||
Ty::Char => Layout::size_align(1, 1),
|
Ty::Char => Layout::size_align(1, 1),
|
||||||
Ty::SChar => Layout::size_align(1, 1),
|
Ty::SChar => Layout::size_align(1, 1),
|
||||||
|
|
@ -278,5 +247,7 @@ fn layout_of(ty: &Ty) -> Layout {
|
||||||
Ty::Struct(_) => todo!("layout_of struct"),
|
Ty::Struct(_) => todo!("layout_of struct"),
|
||||||
Ty::Union(_) => todo!("layout_of union"),
|
Ty::Union(_) => todo!("layout_of union"),
|
||||||
Ty::Enum(_) => todo!("layout_of enum"),
|
Ty::Enum(_) => todo!("layout_of enum"),
|
||||||
}
|
Ty::Ptr(_) => Layout::size_align(8, 8),
|
||||||
|
};
|
||||||
|
TyLayout { ty, layout }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
132
analysis/src/lower/builder.rs
Normal file
132
analysis/src/lower/builder.rs
Normal file
|
|
@ -0,0 +1,132 @@
|
||||||
|
use parser::{Span, Symbol};
|
||||||
|
|
||||||
|
use super::layout_of;
|
||||||
|
use crate::{
|
||||||
|
ir::{
|
||||||
|
self, BasicBlock, BinKind, Branch, ConstValue, Func, Layout, Operand, Register,
|
||||||
|
RegisterData, Statement, StatementKind, TyLayout,
|
||||||
|
},
|
||||||
|
ty::Ty,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct FuncBuilder {
|
||||||
|
pub ir: Func,
|
||||||
|
current_bb: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FuncBuilder {
|
||||||
|
pub fn new(name: Symbol, def_span: Span, ret_ty: Ty) -> Self {
|
||||||
|
Self {
|
||||||
|
ir: Func {
|
||||||
|
regs: Vec::new(),
|
||||||
|
bbs: vec![BasicBlock {
|
||||||
|
statements: Vec::new(),
|
||||||
|
term: Branch::Goto(0),
|
||||||
|
}],
|
||||||
|
name,
|
||||||
|
def_span,
|
||||||
|
ret_ty,
|
||||||
|
},
|
||||||
|
current_bb: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_reg(&mut self, name: Option<Symbol>, tyl: TyLayout) -> Register {
|
||||||
|
let reg = Register(self.ir.regs.len().try_into().unwrap());
|
||||||
|
self.ir.regs.push(RegisterData { name, tyl });
|
||||||
|
reg
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn alloca(&mut self, layout: &Layout, name: Option<Symbol>, span: Span) -> Register {
|
||||||
|
let reg = self.new_reg(name, layout_of(Ty::Ptr(Box::new(Ty::Void))));
|
||||||
|
let stmt = Statement {
|
||||||
|
span,
|
||||||
|
kind: StatementKind::Alloca {
|
||||||
|
reg,
|
||||||
|
size: Operand::Const(ConstValue::u64(layout.size)),
|
||||||
|
align: Operand::Const(ConstValue::u64(layout.align)),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
self.bb_mut().statements.push(stmt);
|
||||||
|
reg
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn binary(
|
||||||
|
&mut self,
|
||||||
|
kind: BinKind,
|
||||||
|
lhs: Operand,
|
||||||
|
rhs: Operand,
|
||||||
|
span: Span,
|
||||||
|
result_tyl: TyLayout,
|
||||||
|
) -> Register {
|
||||||
|
let reg = self.new_reg(None, result_tyl);
|
||||||
|
let stmt = StatementKind::BinOp {
|
||||||
|
kind,
|
||||||
|
lhs,
|
||||||
|
rhs,
|
||||||
|
result: reg,
|
||||||
|
};
|
||||||
|
self.bb_mut()
|
||||||
|
.statements
|
||||||
|
.push(Statement { span, kind: stmt });
|
||||||
|
reg
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load(&mut self, tyl: TyLayout, ptr_reg: Register, span: Span) -> Register {
|
||||||
|
let reg = self.new_reg(None, tyl.clone());
|
||||||
|
let stmt = StatementKind::Load {
|
||||||
|
result: reg,
|
||||||
|
ptr_reg,
|
||||||
|
size: Operand::const_u64(tyl.layout.size),
|
||||||
|
align: Operand::const_u64(tyl.layout.align),
|
||||||
|
};
|
||||||
|
self.bb_mut()
|
||||||
|
.statements
|
||||||
|
.push(Statement { span, kind: stmt });
|
||||||
|
reg
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn store(&mut self, ptr_reg: Register, rhs: Operand, layout: Layout, span: Span) {
|
||||||
|
let stmt = StatementKind::Store {
|
||||||
|
ptr_reg,
|
||||||
|
value: rhs,
|
||||||
|
size: Operand::const_u64(layout.size),
|
||||||
|
align: Operand::const_u64(layout.align),
|
||||||
|
};
|
||||||
|
self.bb_mut()
|
||||||
|
.statements
|
||||||
|
.push(Statement { span, kind: stmt });
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn call(
|
||||||
|
&mut self,
|
||||||
|
ret_tyl: TyLayout,
|
||||||
|
func: Operand,
|
||||||
|
args: Vec<Operand>,
|
||||||
|
span: Span,
|
||||||
|
) -> Register {
|
||||||
|
let reg = self.new_reg(None, ret_tyl);
|
||||||
|
let stmt = StatementKind::Call {
|
||||||
|
result: reg,
|
||||||
|
func,
|
||||||
|
args,
|
||||||
|
};
|
||||||
|
self.bb_mut()
|
||||||
|
.statements
|
||||||
|
.push(Statement { span, kind: stmt });
|
||||||
|
reg
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bb_mut(&mut self) -> &mut BasicBlock {
|
||||||
|
&mut self.ir.bbs[self.current_bb as usize]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn finish(mut self) -> Func {
|
||||||
|
self.bb_mut().term = Branch::Ret(Operand::Const(ConstValue::Void));
|
||||||
|
|
||||||
|
println!("{}", ir::func_to_string(&self.ir));
|
||||||
|
|
||||||
|
self.ir
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -14,6 +14,7 @@ pub enum Ty {
|
||||||
Double,
|
Double,
|
||||||
LongDouble,
|
LongDouble,
|
||||||
Bool,
|
Bool,
|
||||||
|
Ptr(Box<Ty>),
|
||||||
Union(UnionTy),
|
Union(UnionTy),
|
||||||
Struct(StructTy),
|
Struct(StructTy),
|
||||||
Enum(EnumTy),
|
Enum(EnumTy),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue