feat(ir,backend,frontend): Support for and revise ir array param generate

This commit is contained in:
2026-06-07 22:26:23 +08:00
parent 55636e07af
commit b7c2924e8b
11 changed files with 508 additions and 67 deletions
+121 -7
View File
@@ -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
View File
@@ -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)
}