feat(ir,backend,frontend): Support for and revise ir array param generate
This commit is contained in:
+121
-7
@@ -1,6 +1,6 @@
|
||||
use std::{collections::BTreeMap, vec};
|
||||
|
||||
use crate::{ir::types::{CmpOp, Function, IRInstr, IRType, MoveRValue, UnaryOp, Variable, VariableOrIntLit, VariableType}, sema::{analyzer::Analyzer as SemaAnalyzer, hir::{HirBlockStmt, HirBreakStmt, HirCompileUnit, HirContinueStmt, HirExpr, HirExprValue, HirFuncDeclStmt, HirGlobalDeclStmt, HirIfElseBranch, HirIfStmt, HirReturnStmt, HirStatement, HirVarDeclStmt, HirWhileStmt}, symbol::{FunctionId, SymbolId}}};
|
||||
use crate::{ir::types::{BinaryOp as IRBinaryOp, CmpOp, Function, IRInstr, IRType, MoveRValue, UnaryOp, Variable, VariableOrIntLit, VariableType}, sema::{analyzer::Analyzer as SemaAnalyzer, hir::{HirBlockStmt, HirBreakStmt, HirCompileUnit, HirContinueStmt, HirExpr, HirExprValue, HirForInit, HirForStmt, HirFuncDeclStmt, HirGlobalDeclStmt, HirIfElseBranch, HirIfStmt, HirReturnStmt, HirStatement, HirVarDeclStmt, HirWhileStmt}, symbol::{FunctionId, SymbolId}}};
|
||||
use crate::ast::types::BinaryOp as AstBinaryOp;
|
||||
use crate::ast::types::UnaryOp as AstUnaryOp;
|
||||
pub struct Generator<'a> {
|
||||
@@ -64,11 +64,24 @@ impl<'a> Generator<'a> {
|
||||
|
||||
fn generate_var_decl(&mut self, var_decl: HirVarDeclStmt, is_global: bool) -> Vec<IRInstr> {
|
||||
let mut instrs = vec![];
|
||||
let var_type = if is_global { VariableType::Global } else { VariableType::Local };
|
||||
for value in var_decl.values {
|
||||
let var_type = if is_global { VariableType::Global } else { VariableType::Local };
|
||||
let var = self.var_manager.declare_symbol(value.symbol, var_type, self.sema.get_symbol_type(value.symbol).into());
|
||||
if is_global {
|
||||
instrs.push(IRInstr::Declare(var));
|
||||
} else if let Some(init) = value.value {
|
||||
self.current_exit_label.push(None);
|
||||
let (init_instrs, init_var) = match self.generate_expr(init) {
|
||||
Some(res) => res,
|
||||
None => {
|
||||
self.current_exit_label.pop();
|
||||
continue;
|
||||
}
|
||||
};
|
||||
self.current_exit_label.pop();
|
||||
let target = self.var_manager.get_symbol(value.symbol).unwrap();
|
||||
instrs.extend(init_instrs);
|
||||
instrs.push(IRInstr::Move(target, MoveRValue::Var(init_var.unwrap())));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,6 +138,7 @@ impl<'a> Generator<'a> {
|
||||
Return(return_stmt) => self.generate_return_stmt(return_stmt),
|
||||
If(if_stmt) => self.generate_if_stmt(if_stmt),
|
||||
While(while_stmt) => self.generate_while_stmt(while_stmt),
|
||||
For(for_stmt) => self.generate_for_stmt(for_stmt),
|
||||
Break(break_stmt) => self.generate_break_stmt(break_stmt),
|
||||
Continue(continue_stmt) => self.generate_continue_stmt(continue_stmt),
|
||||
Block(block_stmt) => {
|
||||
@@ -193,6 +207,69 @@ impl<'a> Generator<'a> {
|
||||
instrs.push(IRInstr::Label(exit_label));
|
||||
instrs
|
||||
}
|
||||
fn generate_for_stmt(&mut self, for_stmt: HirForStmt) -> Vec<IRInstr> {
|
||||
let mut instrs = vec![];
|
||||
let cond_label = self.request_label();
|
||||
let body_label = self.request_label();
|
||||
let update_label = self.request_label();
|
||||
let exit_label = self.request_label();
|
||||
|
||||
if let Some(init) = for_stmt.init {
|
||||
match init {
|
||||
HirForInit::Expr(init) => {
|
||||
self.current_exit_label.push(None);
|
||||
let (init_instrs, _) = match self.generate_expr(init) {
|
||||
Some(res) => res,
|
||||
None => {
|
||||
self.current_exit_label.pop();
|
||||
return vec![];
|
||||
}
|
||||
};
|
||||
self.current_exit_label.pop();
|
||||
instrs.extend(init_instrs);
|
||||
}
|
||||
HirForInit::VarDecl(var_decl) => {
|
||||
instrs.extend(self.generate_var_decl(var_decl, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
instrs.push(IRInstr::Label(cond_label));
|
||||
if let Some(condition) = for_stmt.condition {
|
||||
self.current_exit_label.push(Some((body_label, exit_label)));
|
||||
let (cond_instrs, _) = match self.generate_expr(condition) {
|
||||
Some(res) => res,
|
||||
None => {
|
||||
self.current_exit_label.pop();
|
||||
return vec![];
|
||||
}
|
||||
};
|
||||
self.current_exit_label.pop();
|
||||
instrs.extend(cond_instrs);
|
||||
}
|
||||
|
||||
instrs.push(IRInstr::Label(body_label));
|
||||
self.while_exit_label.push((update_label, exit_label));
|
||||
instrs.extend(self.generate_block_stmt(for_stmt.body));
|
||||
self.while_exit_label.pop();
|
||||
|
||||
instrs.push(IRInstr::Label(update_label));
|
||||
if let Some(update) = for_stmt.update {
|
||||
self.current_exit_label.push(None);
|
||||
let (update_instrs, _) = match self.generate_expr(update) {
|
||||
Some(res) => res,
|
||||
None => {
|
||||
self.current_exit_label.pop();
|
||||
return vec![];
|
||||
}
|
||||
};
|
||||
self.current_exit_label.pop();
|
||||
instrs.extend(update_instrs);
|
||||
}
|
||||
instrs.push(IRInstr::Goto(cond_label));
|
||||
instrs.push(IRInstr::Label(exit_label));
|
||||
instrs
|
||||
}
|
||||
fn generate_if_stmt(&mut self, if_stmt: HirIfStmt) -> Vec<IRInstr> {
|
||||
let mut instrs = vec![];
|
||||
let then_label = self.request_label();
|
||||
@@ -274,9 +351,13 @@ impl<'a> Generator<'a> {
|
||||
HirExprValue::Var(symbol) => {
|
||||
let var = self.var_manager.get_symbol(symbol).unwrap();
|
||||
if var.data_type.is_array() {
|
||||
let ptr_ty = var.data_type.decay_to_ptr().unwrap();
|
||||
let dest = self.var_manager.declare_temp(ptr_ty);
|
||||
(vec![IRInstr::Move(dest.clone(), MoveRValue::Var(var))], Some(dest))
|
||||
if var.data_type.is_array_param() {
|
||||
(vec![], Some(var))
|
||||
} else {
|
||||
let ptr_ty = var.data_type.decay_to_ptr().unwrap();
|
||||
let dest = self.var_manager.declare_temp(ptr_ty);
|
||||
(vec![IRInstr::Move(dest.clone(), MoveRValue::Var(var))], Some(dest))
|
||||
}
|
||||
} else {
|
||||
(vec![], Some(var))
|
||||
}
|
||||
@@ -372,6 +453,35 @@ impl<'a> Generator<'a> {
|
||||
};
|
||||
(instrs, Some(dest_var))
|
||||
},
|
||||
HirExprValue::IncDec { op, operand, is_prefix } => {
|
||||
let result_ty: IRType = expr.ty.clone().into();
|
||||
let (mut instrs, target, is_addr) = self.generate_lvalue(*operand)?;
|
||||
let old_var = self.var_manager.declare_temp(result_ty.clone());
|
||||
if is_addr {
|
||||
instrs.push(IRInstr::Load(old_var.clone(), target.clone()));
|
||||
} else {
|
||||
instrs.push(IRInstr::Move(old_var.clone(), MoveRValue::Var(target.clone())));
|
||||
}
|
||||
|
||||
let one = self.var_manager.declare_temp(result_ty.clone());
|
||||
instrs.push(IRInstr::Move(one.clone(), MoveRValue::ConstInt(1)));
|
||||
let new_var = self.var_manager.declare_temp(result_ty.clone());
|
||||
let ir_op = match op {
|
||||
crate::ast::types::IncDecOp::Inc => IRBinaryOp::Add,
|
||||
crate::ast::types::IncDecOp::Dec => IRBinaryOp::Sub,
|
||||
};
|
||||
instrs.push(IRInstr::Binary(new_var.clone(), old_var.clone(), ir_op, one));
|
||||
if is_addr {
|
||||
instrs.push(IRInstr::Store(target, new_var.clone()));
|
||||
} else {
|
||||
instrs.push(IRInstr::Move(target, MoveRValue::Var(new_var.clone())));
|
||||
}
|
||||
if is_prefix {
|
||||
(instrs, Some(new_var))
|
||||
} else {
|
||||
(instrs, Some(old_var))
|
||||
}
|
||||
},
|
||||
HirExprValue::BinaryOp { lhs, op, rhs } => {
|
||||
// +--------+-------------------------+-------------------------+-------------------------+
|
||||
// | parent | (true_exit, false_exit) | (true_exit, false_exit) | (true_exit, false_exit) |
|
||||
@@ -564,8 +674,12 @@ impl<'a> Generator<'a> {
|
||||
HirExprValue::Var(symbol) => {
|
||||
let var = self.var_manager.get_symbol(symbol).unwrap();
|
||||
if var.data_type.is_array() {
|
||||
let ptr = self.var_manager.declare_temp(var.data_type.decay_to_ptr().unwrap());
|
||||
(vec![IRInstr::Move(ptr.clone(), MoveRValue::Var(var))], ptr)
|
||||
if var.data_type.is_array_param() {
|
||||
(vec![], var)
|
||||
} else {
|
||||
let ptr = self.var_manager.declare_temp(var.data_type.decay_to_ptr().unwrap());
|
||||
(vec![IRInstr::Move(ptr.clone(), MoveRValue::Var(var))], ptr)
|
||||
}
|
||||
} else {
|
||||
(vec![], var)
|
||||
}
|
||||
|
||||
+17
-1
@@ -86,6 +86,10 @@ impl IRType {
|
||||
matches!(self, IRType::Array(_, _))
|
||||
}
|
||||
|
||||
pub fn is_array_param(&self) -> bool {
|
||||
matches!(self, IRType::Array(_, dims) if dims.first().is_some_and(|dim| *dim == 0))
|
||||
}
|
||||
|
||||
pub fn decay_to_ptr(&self) -> Option<IRType> {
|
||||
match self {
|
||||
IRType::Array(elem, dims) => {
|
||||
@@ -236,6 +240,18 @@ impl Variable {
|
||||
_ => format!("{} {}", self.data_type, self),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_typed_string_with_type(&self, ty: &IRType) -> String {
|
||||
match ty {
|
||||
IRType::Array(_, _) => {
|
||||
let (base_type, dims) = ty.base_type_and_dims();
|
||||
let dims_str = dims.iter().map(|dim| format!("[{}]", dim)).collect::<Vec<_>>().join("");
|
||||
format!("{} {}{}", base_type, self, dims_str)
|
||||
}
|
||||
IRType::Ptr(_) => format!("{}* {}", ty.scalar_base_type(), self),
|
||||
_ => format!("{} {}", ty, self),
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Function {
|
||||
@@ -247,7 +263,7 @@ pub struct Function {
|
||||
impl Function {
|
||||
pub fn to_call_string(&self, args: &Vec<Variable>) -> String {
|
||||
assert!(args.len() == self.parameter_types.len());
|
||||
let args_str = args.iter().zip(self.parameter_types.iter()).map(|(arg, param)| format!("{} {}", param, arg)).collect::<Vec<_>>().join(", ");
|
||||
let args_str = args.iter().zip(self.parameter_types.iter()).map(|(arg, param)| arg.to_typed_string_with_type(param)).collect::<Vec<_>>().join(", ");
|
||||
format!("{} @{}({})", self.return_type, self.name, args_str)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user