diff --git a/include/ir/IR.h b/include/ir/IR.h index c49b931..b9424b1 100644 --- a/include/ir/IR.h +++ b/include/ir/IR.h @@ -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_; diff --git a/include/mir/MIR.h b/include/mir/MIR.h index 4dfe142..44018a5 100644 --- a/include/mir/MIR.h +++ b/include/mir/MIR.h @@ -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 { diff --git a/output.ll b/output.ll new file mode 100644 index 0000000..8766b64 --- /dev/null +++ b/output.ll @@ -0,0 +1,5 @@ +define i32 @main() { +entry: + ret i32 42 +} + diff --git a/parse_tree.txt b/parse_tree.txt new file mode 100644 index 0000000..3c5e64b --- /dev/null +++ b/parse_tree.txt @@ -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: diff --git a/scripts/mir_test.sh b/scripts/mir_test.sh old mode 100644 new mode 100755 diff --git a/scripts/mir_test1.sh b/scripts/mir_test1.sh index 4da40dc..ce3868f 100755 --- a/scripts/mir_test1.sh +++ b/scripts/mir_test1.sh @@ -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 "" diff --git a/scripts/verify_mir_asm.sh b/scripts/verify_mir_asm.sh index f9cb092..b8c0c3a 100755 --- a/scripts/verify_mir_asm.sh +++ b/scripts/verify_mir_asm.sh @@ -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 [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 \ No newline at end of file +#pragma once + +#include +#include +#include +#include +#include + +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 arrayValues; + std::vector 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 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 operands = {}); + + Opcode GetOpcode() const { return opcode_; } + const std::vector& GetOperands() const { return operands_; } + + private: + Opcode opcode_; + std::vector 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& GetInstructions() { return instructions_; } + const std::vector& GetInstructions() const { return instructions_; } + + MachineInstr& Append(Opcode opcode, + std::initializer_list operands = {}); + + private: + std::string name_; + std::vector 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>& GetBlocks() const { return blocks_; } + + // 栈帧管理 + int CreateFrameIndex(int size = 4); + FrameSlot& GetFrameSlot(int index); + const FrameSlot& GetFrameSlot(int index) const; + const std::vector& 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> blocks_; + std::vector frame_slots_; + int frame_size_ = 0; +}; +//std::unique_ptr LowerToMIR(const ir::Module& module); +void RunRegAlloc(MachineFunction& function); +void RunFrameLowering(MachineFunction& function); +//void PrintAsm(const MachineFunction& function, std::ostream& os); +std::vector> LowerToMIR(const ir::Module& module); +void PrintAsm(const std::vector>& functions, std::ostream& os); +} // namespace mir \ No newline at end of file diff --git a/src/ir/IRBuilder.cpp b/src/ir/IRBuilder.cpp index 49060c0..304bd00 100644 --- a/src/ir/IRBuilder.cpp +++ b/src/ir/IRBuilder.cpp @@ -231,7 +231,7 @@ ZExtInst* IRBuilder::CreateZExt(Value* val, const std::string& name) { } return insert_block_->Append(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(val, name); } - +*/ void IRBuilder::CreateMemsetZero(Value* ptr, int num_elements, Context& ctx, Module& mod) { if (!insert_block_) { throw std::runtime_error(FormatError("ir", "IRBuilder 未设置插入点")); diff --git a/src/ir/IRPrinter.cpp b/src/ir/IRPrinter.cpp index 8867dfc..05f3b52 100644 --- a/src/ir/IRPrinter.cpp +++ b/src/ir/IRPrinter.cpp @@ -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(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; } + */ } } } diff --git a/src/ir/Instruction.cpp b/src/ir/Instruction.cpp index 8475546..224039f 100644 --- a/src/ir/Instruction.cpp +++ b/src/ir/Instruction.cpp @@ -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(), "") { diff --git a/src/irgen/IRGenExp.cpp b/src/irgen/IRGenExp.cpp index 224e606..5d00798 100644 --- a/src/irgen/IRGenExp.cpp +++ b/src/irgen/IRGenExp.cpp @@ -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; diff --git a/src/mir/AsmPrinter.cpp b/src/mir/AsmPrinter.cpp index c7a988d..344f11e 100644 --- a/src/mir/AsmPrinter.cpp +++ b/src/mir/AsmPrinter.cpp @@ -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(" diff --git a/src/mir/Lowering.cpp b/src/mir/Lowering.cpp index ca44e42..4b4c822 100644 --- a/src/mir/Lowering.cpp +++ b/src/mir/Lowering.cpp @@ -279,12 +279,61 @@ void LowerInstructionToBlock(const ir::Instruction& inst, MachineFunction& funct case ir::Opcode::Call: { auto& call = static_cast(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(static_cast(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(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(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 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(static_cast(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()) { diff --git a/test.s b/test.s new file mode 100644 index 0000000..1278898 --- /dev/null +++ b/test.s @@ -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 + diff --git a/test.sy b/test.sy new file mode 100644 index 0000000..dbff730 --- /dev/null +++ b/test.sy @@ -0,0 +1 @@ +int main() { return 42; }