Skip to content

Commit

Permalink
完成了一半函数传参
Browse files Browse the repository at this point in the history
  • Loading branch information
夏廷轩 committed May 25, 2024
1 parent 1297a5b commit e641ec9
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 29 deletions.
135 changes: 107 additions & 28 deletions src/gen_asm.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
//! 根据内存形式 Koopa IR 生成汇编
use std::fmt::write;
use std::{fs::File, io::Write};

use crate::ds_for_asm::check_i12;
Expand All @@ -7,7 +8,7 @@ use crate::ds_for_asm::UserKind;
use koopa::ir::*;
pub trait GenerateAsm {
type GenerateResult;
fn generate(&self, output: &mut File) -> Self::GenerateResult;
fn generate(&self, output: &mut File, program_info: &Program) -> Self::GenerateResult;
}

fn get_reg(
Expand Down Expand Up @@ -46,53 +47,110 @@ fn free_reg(func_data: &koopa::ir::FunctionData, func_info: &mut GenerateAsmInfo
}
}

fn store_by_offset(output: &mut File, func_info: &mut GenerateAsmInfo, reg: &str, offset: i32) {
if check_i12(offset) {
writeln!(output, " sw {}, {}(sp)", reg, offset).unwrap();
} else {
let reg_addr = func_info.get_reg_i32(output, offset);
writeln!(output, " add {}, sp, {}", reg_addr, reg_addr).unwrap();
writeln!(output, " sw {}, 0({})", reg, reg_addr).unwrap();
func_info.free_reg(UserKind::Tmpi32(offset));
}
}

fn load_by_offset(output: &mut File, func_info: &mut GenerateAsmInfo, reg: &str, offset: i32) {
if check_i12(offset) {
writeln!(output, " lw {}, {}(sp)", reg, offset).unwrap();
} else {
let reg_addr = func_info.get_reg_i32(output, offset);
writeln!(output, " add {}, sp, {}", reg_addr, reg_addr).unwrap();
writeln!(output, " lw {}, 0({})", reg, reg_addr).unwrap();
func_info.free_reg(UserKind::Tmpi32(offset));
}
}

/// 为Program实现GenerateAsm trait
impl GenerateAsm for Program {
type GenerateResult = ();
fn generate(&self, output: &mut File) {
writeln!(output, " .text").unwrap();
fn generate(&self, output: &mut File, program_info: &Program) {
// 遍历函数列表
for &func in self.func_layout() {
self.func(func).generate(output);
self.func(func).generate(output, program_info);
}
}
}

/// 为FunctionData实现GenerateAsm trait
impl GenerateAsm for koopa::ir::FunctionData {
type GenerateResult = ();
fn generate(&self, output: &mut File) {
fn generate(&self, output: &mut File, program_info: &Program) {
//跳过声明
if self.layout().entry_bb().is_none() {
return;
}

writeln!(output, " .text").unwrap();
writeln!(output, " .globl {}", &self.name()[1..]).unwrap();
writeln!(output, "{}:", &self.name()[1..]).unwrap();

let mut func_info = GenerateAsmInfo::new();

//计算栈大小
let mut ra_size = 0; //ra大小 0 or 4
let mut local_var_size = 0; //局部变量空间大小
let mut param_size = 0; //参数空间大小
/*
_______
ra
-------
局部区域
-------
参数区域
_______
*/

//计算各部分大小
for (&bb, node) in self.layout().bbs() {
for &inst in node.insts().keys() {
let value_data = self.dfg().value(inst);
let value_type = value_data.ty();
if let ValueKind::Call(call_inst) = value_data.kind() {
let mut now_params_size = 0;
let mut now_params_cnt = 0;
ra_size = 4; //有函数调用,需要保存ra
for &param in call_inst.args() {
now_params_cnt += 1;
if now_params_cnt > 8 {
now_params_size += self.dfg().value(param).ty().size() as i32;
}
}
if now_params_size > param_size {
param_size = now_params_size;
}
}
if value_type.is_unit() {
//没有返回值,不需要分配栈空间
continue;
}
func_info.stack_size += value_type.size() as i32;
local_var_size += value_type.size() as i32;
}
}

//对齐16
//计算sp偏移量并对齐16
func_info.stack_size = ra_size + local_var_size + param_size;
func_info.stack_size = (func_info.stack_size + 15) & !15; //check?

//移动栈指针
func_info.set_sp(output);

//为每个元素分配栈偏移量
let mut now_stack_offset = 0;
//计算ra偏移量,是否保存ra是由ra_size决定的
let ra_offset = local_var_size + param_size;
if ra_size > 0 {
//保存ra
store_by_offset(output, &mut func_info, "ra", ra_offset);
}

//为每个元素分配栈偏移量,从参数区域正上方开始
let mut now_stack_offset = param_size;

// 遍历基本块列表
for (&bb, node) in self.layout().bbs() {
Expand All @@ -108,6 +166,34 @@ impl GenerateAsm for koopa::ir::FunctionData {
let value_data = self.dfg().value(inst);
// 访问指令
match value_data.kind() {
ValueKind::Call(call_inst) => {
let mut now_params_offset = 0;
for (i, &param) in call_inst.args().iter().enumerate() {
let reg_param = get_reg(output, self, &mut func_info, param);
if i <= 7 {
//参数个数小于等于8个,存在a0-a7
writeln!(output, " mv a{}, {}", i, reg_param).unwrap();
} else {
//存栈上
store_by_offset(
output,
&mut func_info,
&reg_param,
now_params_offset,
);

now_params_offset += self.dfg().value(param).ty().size() as i32;
}
free_reg(self, &mut func_info, param);
}

writeln!(
output,
" call {}",
&(program_info.func(call_inst.callee()).name())[1..]
)
.unwrap();
}
ValueKind::Branch(br_inst) => {
let cond = br_inst.cond();
let true_bb_name = self.dfg().bb(br_inst.true_bb()).name().clone().unwrap();
Expand Down Expand Up @@ -147,7 +233,14 @@ impl GenerateAsm for koopa::ir::FunctionData {
}
None => {}
}

if ra_size > 0 {
//恢复ra
let addr_reg = func_info.get_reg_i32(output, ra_offset);
writeln!(output, " li {}, {}", addr_reg, ra_offset).unwrap();
writeln!(output, " add {}, sp, {}", addr_reg, addr_reg).unwrap();
writeln!(output, " lw ra, 0({})", addr_reg).unwrap();
func_info.free_reg(UserKind::Tmpi32(ra_offset));
}
func_info.reset_sp(output);
writeln!(output, " ret").unwrap();
}
Expand All @@ -163,14 +256,7 @@ impl GenerateAsm for koopa::ir::FunctionData {
let offset = *func_info.name_to_offset.get(&addr).unwrap();
let reg_ret = get_reg(output, self, &mut func_info, inst);

if check_i12(offset) {
writeln!(output, " lw {}, {}(sp)", reg_ret, offset).unwrap();
} else {
let reg_addr = func_info.get_reg_i32(output, offset);
writeln!(output, " add {}, sp, {}", reg_addr, reg_addr).unwrap();
writeln!(output, " lw {}, 0({})", reg_ret, reg_addr).unwrap();
func_info.free_reg(UserKind::Tmpi32(offset));
}
load_by_offset(output, &mut func_info, &reg_ret, offset);

func_info.new_var(output, inst, now_stack_offset);
now_stack_offset += value_data.ty().size() as i32;
Expand All @@ -183,14 +269,7 @@ impl GenerateAsm for koopa::ir::FunctionData {
let value = store_inst.value();
let reg_val = get_reg(output, self, &mut func_info, value);

if (check_i12(offset)) {
writeln!(output, " sw {}, {}(sp)", reg_val, offset).unwrap();
} else {
let reg_addr = func_info.get_reg_i32(output, offset);
writeln!(output, " add {}, sp, {}", reg_addr, reg_addr).unwrap();
writeln!(output, " sw {}, 0({})", reg_val, reg_addr).unwrap();
func_info.free_reg(UserKind::Tmpi32(offset));
}
store_by_offset(output, &mut func_info, &reg_val, offset);

free_reg(self, &mut func_info, value);
}
Expand Down
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ fn main() -> Result<()> {
println!("{}", my_koppa_ir);
let driver = koopa::front::Driver::from(my_koppa_ir);
let program = driver.generate_program().unwrap();
program.generate(&mut output_file);
program.generate(&mut output_file, &program);
}
}
_ => {
Expand Down

0 comments on commit e641ec9

Please sign in to comment.