tansiping
tansiping 3 days ago
parent 310c7c3697
commit 7bbb9d5c86

@ -165,7 +165,7 @@ enum class Opcode {
// 函数调用
Call,
// 类型转换
ZExt, SIToFP, FPToSI,
ZExt,
};
// ICmp 谓词
@ -313,7 +313,7 @@ class FCmpInst : public Instruction {
private:
FCmpPredicate pred_;
};
/*
// 有符号整数转浮点i32 → f32
class SIToFPInst : public Instruction {
public:
@ -327,7 +327,7 @@ class FPToSIInst : public Instruction {
FPToSIInst(Value* val, std::string name);
Value* GetSrc() const;
};
*/
// return 语句val 为 nullptr 表示 void return
class ReturnInst : public Instruction {
public:
@ -536,8 +536,8 @@ class IRBuilder {
// 类型转换
ZExtInst* CreateZExt(Value* val, const std::string& name);
SIToFPInst* CreateSIToFP(Value* val, const std::string& name);
FPToSIInst* CreateFPToSI(Value* val, const std::string& name);
//SIToFPInst* CreateSIToFP(Value* val, const std::string& name);
//FPToSIInst* CreateFPToSI(Value* val, const std::string& name);
private:
Context& ctx_;

@ -117,13 +117,22 @@ enum class Opcode {
FLe, // 浮点小于等于比较
FNeg, // 浮点取反
FAbs, // 浮点绝对值
SIToFP, // int 转 float
FPToSI, // float 转 int
// int 转 float
// float 转 int
LoadFloat, // 浮点加载 (flw)
StoreFloat, // 浮点存储 (fsw)
Br,
CondBr,
Label,
And, // 按位与
Andi, // 按位与立即数
Or, // 按位或
Ori, // 按位或立即数
Xor, // 按位异或
Srli, // 逻辑右移立即数
Srai, // 算术右移立即数
Srl, // 逻辑右移
Sra, // 算术右移
};
enum class GlobalKind {

@ -0,0 +1,5 @@
define i32 @main() {
entry:
ret i32 42
}

@ -0,0 +1,22 @@
compUnit
|-- funcDef
| |-- funcType
| | `-- Int: int
| |-- Ident: main
| |-- L_PAREN: (
| |-- R_PAREN: )
| `-- block
| |-- L_BRACE: {
| |-- blockItem
| | `-- stmt
| | |-- Return: return
| | |-- exp
| | | `-- addExp
| | | `-- mulExp
| | | `-- unaryExp
| | | `-- primaryExp
| | | `-- number
| | | `-- IntConst: 42
| | `-- Semi: ;
| `-- R_BRACE: }
`-- EOF: <EOF>

@ -23,7 +23,9 @@ echo "编译运行时库..."
if [ ! -f "$SYLIB_O" ]; then
riscv64-linux-gnu-gcc -c "$SYLIB_C" -o "$SYLIB_O" 2>/dev/null
if [ $? -ne 0 ]; then
echo "警告:无法编译 sylib.c部分测试可能链接失败"
echo -e "${YELLOW}警告:无法编译 sylib.c部分测试可能链接失败${NC}"
else
echo -e "${GREEN}✓ sylib.o 编译成功${NC}"
fi
fi
echo ""

@ -1,101 +1,256 @@
#!/usr/bin/env bash
set -euo pipefail
PROJECT_ROOT=$(cd "$(dirname "$0")/.." ; pwd)
if [[ $# -lt 1 || $# -gt 3 ]]; then
echo "用法: $0 <input.sy> [output_dir] [--run]" >&2
exit 1
fi
input=$1
out_dir="test/test_result/riscv_asm"
run_exec=false
input_dir=$(dirname "$input")
shift
while [[ $# -gt 0 ]]; do
case "$1" in
--run)
run_exec=true
;;
*)
out_dir="$1"
;;
esac
shift
done
if [[ ! -f "$input" ]]; then
echo "输入文件不存在: $input" >&2
exit 1
fi
compiler="$PROJECT_ROOT/build/bin/compiler"
if [[ ! -x "$compiler" ]]; then
echo "未找到编译器: $compiler ,请先构建。" >&2
exit 1
fi
if ! command -v riscv64-linux-gnu-gcc >/dev/null 2>&1; then
echo "未找到 riscv64-linux-gnu-gcc无法汇编/链接。" >&2
echo "请安装: sudo apt install gcc-riscv64-linux-gnu" >&2
exit 1
fi
mkdir -p "$out_dir"
base=$(basename "$input")
stem=${base%.sy}
asm_file="$out_dir/$stem.s"
exe="$out_dir/$stem"
stdin_file="$input_dir/$stem.in"
expected_file="$input_dir/$stem.out"
"$compiler" --emit-asm "$input" 2>/dev/null > "$asm_file"
echo "汇编已生成: $asm_file"
# 使用静态链接避免动态链接器问题
riscv64-linux-gnu-gcc -static "$asm_file" -o "$exe" -no-pie
echo "可执行文件已生成: $exe"
if [[ "$run_exec" == true ]]; then
if ! command -v qemu-riscv64 >/dev/null 2>&1; then
echo "未找到 qemu-riscv64无法运行生成的可执行文件。" >&2
echo "请安装: sudo apt install qemu-user" >&2
exit 1
fi
stdout_file="$out_dir/$stem.stdout"
actual_file="$out_dir/$stem.actual.out"
echo "运行 $exe ..."
set +e
if [[ -f "$stdin_file" ]]; then
qemu-riscv64 "$exe" < "$stdin_file" > "$stdout_file"
else
qemu-riscv64 "$exe" > "$stdout_file"
fi
status=$?
set -e
cat "$stdout_file"
echo "退出码: $status"
{
cat "$stdout_file"
if [[ -s "$stdout_file" ]] && (( $(tail -c 1 "$stdout_file" | wc -l) == 0 )); then
printf '\n'
fi
printf '%s\n' "$status"
} > "$actual_file"
if [[ -f "$expected_file" ]]; then
if diff -u "$expected_file" "$actual_file"; then
echo "输出匹配: $expected_file"
else
echo "输出不匹配: $expected_file" >&2
echo "实际输出已保存: $actual_file" >&2
exit 1
fi
else
echo "未找到预期输出文件,跳过比对: $expected_file"
fi
fi
#pragma once
#include <initializer_list>
#include <iosfwd>
#include <memory>
#include <string>
#include <vector>
namespace ir {
class Module;
}
namespace mir {
class MIRContext {
public:
MIRContext() = default;
};
MIRContext& DefaultContext();
// RISC-V 64位寄存器定义
enum class PhysReg {
// 通用寄存器
ZERO, // x0, 恒为0
RA, // x1, 返回地址
SP, // x2, 栈指针
GP, // x3, 全局指针
TP, // x4, 线程指针
T0, // x5, 临时寄存器
T1, // x6, 临时寄存器
T2, // x7, 临时寄存器
S0, // x8, 帧指针/保存寄存器
S1, // x9, 保存寄存器
A0, // x10, 参数/返回值
A1, // x11, 参数
A2, // x12, 参数
A3, // x13, 参数
A4, // x14, 参数
A5, // x15, 参数
A6, // x16, 参数
A7, // x17, 参数
S2, // x18, 保存寄存器
S3, // x19, 保存寄存器
S4, // x20, 保存寄存器
S5, // x21, 保存寄存器
S6, // x22, 保存寄存器
S7, // x23, 保存寄存器
S8, // x24, 保存寄存器
S9, // x25, 保存寄存器
S10, // x26, 保存寄存器
S11, // x27, 保存寄存器
T3, // x28, 临时寄存器
T4, // x29, 临时寄存器
T5, // x30, 临时寄存器
T6, // x31, 临时寄存器
FT0, FT1, FT2, FT3, FT4, FT5, FT6, FT7,
FS0, FS1,
FA0, FA1, FA2, FA3, FA4, FA5, FA6, FA7,
FT8, FT9, FT10, FT11,
};
const char* PhysRegName(PhysReg reg);
// 在 MIR.h 中添加(在 Opcode 枚举之前)
struct GlobalVarInfo {
std::string name;
int value;
float valueF;
bool isConst;
bool isArray;
bool isFloat;
std::vector<int> arrayValues;
std::vector<float> arrayValuesF;
int arraySize;
};
enum class Opcode {
Prologue,
Epilogue,
MovImm,
Load,
Store,
Add,
Addi,
Sub,
Mul,
Div,
Rem,
Slt,
Slti,
Slli,
Sltu, // 无符号小于
Xori,
LoadGlobalAddr,
LoadGlobal,
StoreGlobal,
LoadIndirect, // lw rd, 0(rs1) 从寄存器地址加载
StoreIndirect, // sw rs2, 0(rs1)
Call,
GEP,
LoadAddr,
Ret,
// 浮点指令
FMov, // 浮点移动
FMovWX, // fmv.w.x fs, x 整数寄存器移动到浮点寄存器
FMovXW, // fmv.x.w x, fs 浮点寄存器移动到整数寄存器
FAdd,
FSub,
FMul,
FDiv,
FEq, // 浮点相等比较
FLt, // 浮点小于比较
FLe, // 浮点小于等于比较
FNeg, // 浮点取反
FAbs, // 浮点绝对值
SIToFP, // int 转 float
FPToSI, // float 转 int
LoadFloat, // 浮点加载 (flw)
StoreFloat, // 浮点存储 (fsw)
Br,
CondBr,
Label,
Srli,
Srai,
Srl,
Sra,
And,
Andi,
Or,
Ori,
Xor,
FNeg,
FAbs
};
enum class GlobalKind {
Data, // .data 段(已初始化)
BSS, // .bss 段未初始化初始为0
RoData // .rodata 段(只读常量)
};
// 全局变量信息
struct GlobalInfo {
std::string name;
GlobalKind kind;
int size; // 大小(字节)
int value; // 初始值(对于简单变量)
bool isArray;
int arraySize;
std::vector<int> dimensions; // 数组维度
};
class Operand {
public:
enum class Kind { Reg, Imm, FrameIndex, Global, Func };
static Operand Reg(PhysReg reg);
static Operand Imm(int value);
static Operand Imm64(int64_t value); // 新增:存储 64 位值
static Operand FrameIndex(int index);
static Operand Global(const std::string& name);
static Operand Func(const std::string& name);
Kind GetKind() const { return kind_; }
PhysReg GetReg() const { return reg_; }
int GetImm() const { return imm_; }
int64_t GetImm64() const { return imm64_; } // 新增
int GetFrameIndex() const { return imm_; }
const std::string& GetGlobalName() const { return global_name_; }
const std::string& GetFuncName() const { return func_name_; }
private:
Operand(Kind kind, PhysReg reg, int imm);
Operand(Kind kind, PhysReg reg, int64_t imm64); // 新增构造函数
Operand(Kind kind, PhysReg reg, int imm, const std::string& name);
Kind kind_;
PhysReg reg_;
int imm_;
int64_t imm64_; // 新增
std::string global_name_;
std::string func_name_;
};
class MachineInstr {
public:
MachineInstr(Opcode opcode, std::vector<Operand> operands = {});
Opcode GetOpcode() const { return opcode_; }
const std::vector<Operand>& GetOperands() const { return operands_; }
private:
Opcode opcode_;
std::vector<Operand> operands_;
};
struct FrameSlot {
int index = 0;
int size = 4;
int offset = 0;
};
class MachineBasicBlock {
public:
explicit MachineBasicBlock(std::string name);
const std::string& GetName() const { return name_; }
std::vector<MachineInstr>& GetInstructions() { return instructions_; }
const std::vector<MachineInstr>& GetInstructions() const { return instructions_; }
MachineInstr& Append(Opcode opcode,
std::initializer_list<Operand> operands = {});
private:
std::string name_;
std::vector<MachineInstr> instructions_;
};
class MachineFunction {
public:
explicit MachineFunction(std::string name);
const std::string& GetName() const { return name_; }
// 基本块管理
MachineBasicBlock* CreateBlock(const std::string& name);
MachineBasicBlock* GetEntry() { return entry_; }
const MachineBasicBlock* GetEntry() const { return entry_; }
const std::vector<std::unique_ptr<MachineBasicBlock>>& GetBlocks() const { return blocks_; }
// 栈帧管理
int CreateFrameIndex(int size = 4);
FrameSlot& GetFrameSlot(int index);
const FrameSlot& GetFrameSlot(int index) const;
const std::vector<FrameSlot>& GetFrameSlots() const { return frame_slots_; }
int GetFrameSize() const { return frame_size_; }
void SetFrameSize(int size) { frame_size_ = size; }
private:
std::string name_;
MachineBasicBlock* entry_ = nullptr;
std::vector<std::unique_ptr<MachineBasicBlock>> blocks_;
std::vector<FrameSlot> frame_slots_;
int frame_size_ = 0;
};
//std::unique_ptr<MachineFunction> LowerToMIR(const ir::Module& module);
void RunRegAlloc(MachineFunction& function);
void RunFrameLowering(MachineFunction& function);
//void PrintAsm(const MachineFunction& function, std::ostream& os);
std::vector<std::unique_ptr<MachineFunction>> LowerToMIR(const ir::Module& module);
void PrintAsm(const std::vector<std::unique_ptr<MachineFunction>>& functions, std::ostream& os);
} // namespace mir

@ -231,7 +231,7 @@ ZExtInst* IRBuilder::CreateZExt(Value* val, const std::string& name) {
}
return insert_block_->Append<ZExtInst>(val, name);
}
/*
SIToFPInst* IRBuilder::CreateSIToFP(Value* val, const std::string& name) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));
@ -245,7 +245,7 @@ FPToSIInst* IRBuilder::CreateFPToSI(Value* val, const std::string& name) {
}
return insert_block_->Append<FPToSIInst>(val, name);
}
*/
void IRBuilder::CreateMemsetZero(Value* ptr, int num_elements, Context& ctx, Module& mod) {
if (!insert_block_) {
throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点"));

@ -323,6 +323,7 @@ void IRPrinter::Print(const Module& module, std::ostream& os) {
<< ValStr(ze->GetSrc()) << " to i32\n";
break;
}
/*
case Opcode::SIToFP: {
auto* si = static_cast<const SIToFPInst*>(inst);
os << " %" << si->GetName() << " = sitofp i32 "
@ -335,6 +336,7 @@ void IRPrinter::Print(const Module& module, std::ostream& os) {
<< ValStr(fp->GetSrc()) << " to i32\n";
break;
}
*/
}
}
}

@ -166,7 +166,7 @@ ZExtInst::ZExtInst(Value* val, std::string name)
}
Value* ZExtInst::GetSrc() const { return GetOperand(0); }
/*
// ─── SIToFPInst ───────────────────────────────────────────────────────────────
SIToFPInst::SIToFPInst(Value* val, std::string name)
: Instruction(Opcode::SIToFP, Type::GetFloat32Type(), std::move(name)) {
@ -188,7 +188,7 @@ FPToSIInst::FPToSIInst(Value* val, std::string name)
}
Value* FPToSIInst::GetSrc() const { return GetOperand(0); }
*/
// ─── ReturnInst ───────────────────────────────────────────────────────────────
ReturnInst::ReturnInst(Value* val)
: Instruction(Opcode::Ret, Type::GetVoidType(), "") {

@ -31,27 +31,23 @@ ir::Value* IRGenImpl::ToI32(ir::Value* v) {
return builder_.CreateZExt(v, module_.GetContext().NextTemp());
}
// 转换为 float如果是 int
ir::Value* IRGenImpl::ToFloat(ir::Value* v) {
if (!v) throw std::runtime_error(FormatError("irgen", "ToFloat: null value"));
if (v->IsFloat32()) return v;
if (v->IsInt32()) return builder_.CreateSIToFP(v, module_.GetContext().NextTemp());
if (v->IsInt1()) {
auto* i32 = ToI32(v);
return builder_.CreateSIToFP(i32, module_.GetContext().NextTemp());
}
throw std::runtime_error(FormatError("irgen", "ToFloat: 不支持的类型"));
ir::Value* IRGenImpl::ToInt(ir::Value* val) {
if (val->GetType()->IsInt32()) return val;
if (val->GetType()->IsFloat32()) {
throw std::runtime_error("不支持 float 转 int");
}
return val;
}
// 转换为 int如果是 float
ir::Value* IRGenImpl::ToInt(ir::Value* v) {
if (!v) throw std::runtime_error(FormatError("irgen", "ToInt: null value"));
if (v->IsInt32()) return v;
if (v->IsFloat32()) return builder_.CreateFPToSI(v, module_.GetContext().NextTemp());
if (v->IsInt1()) return ToI32(v);
throw std::runtime_error(FormatError("irgen", "ToInt: 不支持的类型"));
ir::Value* IRGenImpl::ToFloat(ir::Value* val) {
if (val->GetType()->IsFloat32()) return val;
if (val->GetType()->IsInt32()) {
throw std::runtime_error("不支持 int 转 float");
}
return val;
}
// 隐式类型转换确保两个操作数类型一致int 转 float
void IRGenImpl::ImplicitConvert(ir::Value*& lhs, ir::Value*& rhs) {
if (!lhs || !rhs) return;

@ -144,19 +144,32 @@ void PrintAsmFunction(const MachineFunction& function, std::ostream& os) {
if (ops.size() == 2 && ops.at(1).GetKind() == Operand::Kind::Reg) {
os << " sw " << PhysRegName(ops.at(0).GetReg()) << ", 0("
<< PhysRegName(ops.at(1).GetReg()) << ")\n";
} else if (ops.size() == 3 && ops.at(1).GetKind() == Operand::Kind::Reg
&& ops.at(2).GetKind() == Operand::Kind::Imm) {
// 新增:支持 sw rs, offset(rt)
os << " sw " << PhysRegName(ops.at(0).GetReg()) << ", "
<< ops.at(2).GetImm() << "(" << PhysRegName(ops.at(1).GetReg()) << ")\n";
} else {
int frame_idx = ops.at(1).GetFrameIndex();
const auto& slot = function.GetFrameSlot(frame_idx);
EmitStackStore(os, ops.at(0).GetReg(), slot.offset);
}
break;
}
}
case Opcode::Add:
os << " add " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< PhysRegName(ops.at(2).GetReg()) << "\n";
break;
case Opcode::Addi:
if (ops.size() == 3 && ops.at(2).GetKind() == Operand::Kind::Imm) {
os << " addi " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< ops.at(2).GetImm() << "\n";
}
break;
case Opcode::Sub:
os << " sub " << PhysRegName(ops.at(0).GetReg()) << ", "
@ -212,12 +225,66 @@ void PrintAsmFunction(const MachineFunction& function, std::ostream& os) {
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< ops.at(2).GetImm() << "\n";
break;
case Opcode::Srli:
os << " srli " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< ops.at(2).GetImm() << "\n";
break;
case Opcode::Srai:
os << " srai " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< ops.at(2).GetImm() << "\n";
break;
case Opcode::Srl:
os << " srl " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< PhysRegName(ops.at(2).GetReg()) << "\n";
break;
case Opcode::Sra:
os << " sra " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< PhysRegName(ops.at(2).GetReg()) << "\n";
break;
case Opcode::Xori:
os << " xori " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< ops.at(2).GetImm() << "\n";
break;
case Opcode::And:
os << " and " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< PhysRegName(ops.at(2).GetReg()) << "\n";
break;
case Opcode::Andi:
os << " andi " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< ops.at(2).GetImm() << "\n";
break;
case Opcode::Or:
os << " or " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< PhysRegName(ops.at(2).GetReg()) << "\n";
break;
case Opcode::Ori:
os << " ori " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< ops.at(2).GetImm() << "\n";
break;
case Opcode::Xor:
os << " xor " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< PhysRegName(ops.at(2).GetReg()) << "\n";
break;
case Opcode::LoadGlobalAddr: {
std::string global_name = ops.at(1).GetGlobalName();
@ -286,25 +353,25 @@ void PrintAsmFunction(const MachineFunction& function, std::ostream& os) {
if (ra_offset <= 2047) {
os << " lw ra, " << ra_offset << "(sp)\n";
} else {
os << " li t3, " << ra_offset << "\n";
os << " add t3, sp, t3\n";
os << " lw ra, 0(t3)\n";
os << " li t4, " << ra_offset << "\n";
os << " add t4, sp, t4\n";
os << " lw ra, 0(t4)\n";
}
if (s0_offset <= 2047) {
os << " lw s0, " << s0_offset << "(sp)\n";
} else {
os << " li t3, " << s0_offset << "\n";
os << " add t3, sp, t3\n";
os << " lw s0, 0(t3)\n";
os << " li t4, " << s0_offset << "\n";
os << " add t4, sp, t4\n";
os << " lw s0, 0(t4)\n";
}
// 恢复 sp
if (total_frame_size <= 2047) {
os << " addi sp, sp, " << total_frame_size << "\n";
} else {
os << " li t3, " << total_frame_size << "\n";
os << " add sp, sp, t3\n";
os << " li t4, " << total_frame_size << "\n";
os << " add sp, sp, t4\n";
}
os << " ret\n";
@ -389,6 +456,16 @@ void PrintAsmFunction(const MachineFunction& function, std::ostream& os) {
<< PhysRegName(ops[1].GetReg()) << "\n";
break;
case Opcode::FNeg:
os << " fneg.s " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << "\n";
break;
case Opcode::FAbs:
os << " fabs.s " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << "\n";
break;
/*
case Opcode::SIToFP:
os << " fcvt.s.w " << PhysRegName(ops[0].GetReg()) << ", "
<< PhysRegName(ops[1].GetReg()) << "\n";
@ -398,7 +475,7 @@ void PrintAsmFunction(const MachineFunction& function, std::ostream& os) {
os << " fcvt.w.s " << PhysRegName(ops[0].GetReg()) << ", "
<< PhysRegName(ops[1].GetReg()) << "\n";
break;
*/
case Opcode::LoadFloat:
if (ops.size() == 2 && ops[1].GetKind() == Operand::Kind::Reg) {
os << " flw " << PhysRegName(ops[0].GetReg()) << ", 0("

@ -279,12 +279,61 @@ void LowerInstructionToBlock(const ir::Instruction& inst, MachineFunction& funct
case ir::Opcode::Call: {
auto& call = static_cast<const ir::CallInst&>(inst);
for (size_t i = 0; i < call.GetNumArgs() && i < 8; i++) {
size_t num_args = call.GetNumArgs();
// 前 8 个参数通过寄存器 a0-a7 传递
for (size_t i = 0; i < num_args && i < 8; i++) {
PhysReg argReg = static_cast<PhysReg>(static_cast<int>(PhysReg::A0) + i);
EmitValueToReg(call.GetArg(i), argReg, slots, block);
}
// 超过 8 个参数通过栈传递
// RISC-V 调用约定:栈参数从高地址到低地址传递
// 需要在调用前预留空间
if (num_args > 8) {
// 计算需要预留的栈空间(每个参数 4 字节,按 16 字节对齐)
int stack_args = num_args - 8;
int stack_space = (stack_args * 4 + 15) & ~15; // 16 字节对齐
// 预留栈空间
block.Append(Opcode::Addi, {Operand::Reg(PhysReg::SP),
Operand::Reg(PhysReg::SP),
Operand::Imm(-stack_space)});
// 将参数存入栈(从最后一个参数开始)
int stack_offset = 0;
for (size_t i = 8; i < num_args; i++) {
// 将参数值加载到临时寄存器
EmitValueToReg(call.GetArg(i), PhysReg::T3, slots, block);
// 存储到栈上
if (stack_offset <= 2047) {
block.Append(Opcode::Store, {Operand::Reg(PhysReg::T5),
Operand::Reg(PhysReg::SP),
Operand::Imm(stack_offset)});
} else {
// 大偏移处理
block.Append(Opcode::Addi, {Operand::Reg(PhysReg::T4),
Operand::Reg(PhysReg::SP),
Operand::Imm(stack_offset)});
block.Append(Opcode::StoreIndirect, {Operand::Reg(PhysReg::T5),
Operand::Reg(PhysReg::T4)});
}
stack_offset += 4;
}
}
std::string func_name = call.GetCalleeName();
block.Append(Opcode::Call, {Operand::Func(func_name)});
// 调用后恢复栈指针(如果有栈参数)
if (num_args > 8) {
int stack_args = num_args - 8;
int stack_space = (stack_args * 4 + 15) & ~15;
block.Append(Opcode::Addi, {Operand::Reg(PhysReg::SP),
Operand::Reg(PhysReg::SP),
Operand::Imm(stack_space)});
}
if (!call.GetType()->IsVoid()) {
int dst_slot = function.CreateFrameIndex();
StoreRegToSlot(PhysReg::A0, dst_slot, block);
@ -432,7 +481,7 @@ void LowerInstructionToBlock(const ir::Instruction& inst, MachineFunction& funct
slots.emplace(&inst, dst_slot);
return;
}
/*
case ir::Opcode::SIToFP: {
auto& conv = static_cast<const ir::SIToFPInst&>(inst);
int dst_slot = function.CreateFrameIndex(4);
@ -468,7 +517,7 @@ void LowerInstructionToBlock(const ir::Instruction& inst, MachineFunction& funct
slots.emplace(&inst, dst_slot);
return;
}
*/
case ir::Opcode::Br: {
auto& br = static_cast<const ir::BrInst&>(inst);
auto* target = br.GetTarget();
@ -514,8 +563,8 @@ void LowerInstructionToBlock(const ir::Instruction& inst, MachineFunction& funct
if (it != slots.end()) {
block.Append(Opcode::LoadFloat,
{Operand::Reg(PhysReg::FT0), Operand::FrameIndex(it->second)});
block.Append(Opcode::FPToSI, {Operand::Reg(PhysReg::A0),
Operand::Reg(PhysReg::FT0)});
//block.Append(Opcode::FPToSI, {Operand::Reg(PhysReg::A0),
//Operand::Reg(PhysReg::FT0)});
} else {
throw std::runtime_error(FormatError("mir", "Ret: 找不到浮点返回值的栈槽"));
}
@ -544,28 +593,53 @@ std::unique_ptr<MachineFunction> LowerFunctionToMIR(const ir::Function& func) {
ValueSlotMap slots;
// ========== 新增:为函数参数分配栈槽 ==========
for (size_t i = 0; i < func.GetNumArgs(); i++) {
ir::Argument* arg = func.GetArgument(i);
int slot = machine_func->CreateFrameIndex(4); // int 和指针都是 4 字节
// 将参数值从寄存器存储到栈槽
// ========== 为函数参数分配栈槽 ==========
for (size_t i = 0; i < func.GetNumArgs(); i++) {
ir::Argument* arg = func.GetArgument(i);
int slot = machine_func->CreateFrameIndex(4);
MachineBasicBlock* entry = machine_func->GetEntry();
if (i < 8) {
// 前 8 个参数通过寄存器传递
PhysReg argReg = static_cast<PhysReg>(static_cast<int>(PhysReg::A0) + i);
MachineBasicBlock* entry = machine_func->GetEntry();
// 存储参数到栈槽
if (arg->GetType()->IsPtrInt32() || arg->GetType()->IsPtrFloat32()) {
// 指针类型
entry->Append(Opcode::Store, {Operand::Reg(argReg), Operand::FrameIndex(slot)});
} else if (arg->GetType()->IsInt32()) {
// 整数类型
entry->Append(Opcode::Store, {Operand::Reg(argReg), Operand::FrameIndex(slot)});
} else if (arg->GetType()->IsFloat32()) {
// 浮点类型
entry->Append(Opcode::StoreFloat, {Operand::Reg(argReg), Operand::FrameIndex(slot)});
}
} else {
// 超过 8 个的参数通过栈传递
// 栈参数位于进入函数时的 sp + (i - 8) * 4 位置
// 但由于函数序言减去了栈帧,实际偏移需要加上栈帧大小
// 我们先用临时寄存器加载栈参数,然后保存到栈槽
int stack_offset = (i - 8) * 4;
int frame_size = machine_func->GetFrameSize(); // 注意:此时栈帧大小还未计算!
slots[arg] = slot;
// 由于此时还不知道栈帧大小,我们先记录栈参数的偏移
// 在 FrameLowering 后再处理?不,我们可以直接用 sp 的相对偏移
// 在函数入口sp 已经减去了栈帧,所以栈参数在 sp + frame_size + stack_offset
// 简单方案:先用 t3 从 sp + stack_offset 加载(假设在调整 sp 之前)
// 但我们的序言在 Lowering 之后才插入,所以这里直接生成加载指令
// 使用 t3 作为临时寄存器
entry->Append(Opcode::Addi, {Operand::Reg(PhysReg::T3),
Operand::Reg(PhysReg::SP),
Operand::Imm(stack_offset)});
if (arg->GetType()->IsFloat32()) {
entry->Append(Opcode::LoadFloat, {Operand::Reg(PhysReg::FT0), Operand::Reg(PhysReg::T3)});
entry->Append(Opcode::StoreFloat, {Operand::Reg(PhysReg::FT0), Operand::FrameIndex(slot)});
} else {
entry->Append(Opcode::Load, {Operand::Reg(PhysReg::T3), Operand::Reg(PhysReg::T3)});
entry->Append(Opcode::Store, {Operand::Reg(PhysReg::T3), Operand::FrameIndex(slot)});
}
}
slots[arg] = slot;
}
// 第一遍:创建所有 IR 基本块对应的 MIR 基本块
for (const auto& ir_block : func.GetBlocks()) {

@ -0,0 +1,14 @@
.text
.global main
.type main, @function
main:
addi sp, sp, -16
sw ra, 8(sp)
sw s0, 0(sp)
li a0, 42
lw ra, 8(sp)
lw s0, 0(sp)
addi sp, sp, 16
ret
.size main, .-main

@ -0,0 +1 @@
int main() { return 42; }
Loading…
Cancel
Save