diff --git a/.gitignore b/.gitignore index 53075fa..8bf0773 100644 --- a/.gitignore +++ b/.gitignore @@ -73,4 +73,5 @@ test/test_result/ # mxr # ========================= result.txt -build.sh \ No newline at end of file +build.sh +gdb.sh \ No newline at end of file diff --git a/include/mir/MIR.h b/include/mir/MIR.h index 47b8959..67ef476 100644 --- a/include/mir/MIR.h +++ b/include/mir/MIR.h @@ -19,41 +19,161 @@ class MIRContext { MIRContext& DefaultContext(); -enum class PhysReg { W0, W8, W9, X29, X30, SP }; +enum class PhysReg { + //W0, W8, W9, X29, X30, SP + // 32位通用寄存器 + W0, W1, W2, W3, W4, W5, W6, W7, // 参数传递/临时 + W8, W9, // 临时寄存器(当前主要使用) + W10, W11, W12, W13, W14, W15, // 临时寄存器(扩展) + W16, W17, // intra-procedure-call 临时 + W18, // 平台预留 + W19, W20, W21, W22, W23, W24, // 被调用者保存(扩展用) + W25, W26, W27, W28, // 被调用者保存 + W29, // 帧指针 (FP) + W30, // 链接寄存器 (LR) + + // 64位版本 + X0, X1, X2, X3, X4, X5, X6, X7, + X8, X9, X10, X11, X12, X13, X14, X15, + X16, X17, X18, + X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, + X29, // FP + X30, // LR + + // 浮点寄存器 (32位) + S0, S1, S2, S3, S4, S5, S6, S7, + S8, S9, S10, S11, S12, S13, S14, S15, + S16, S17, S18, S19, S20, S21, S22, S23, + S24, S25, S26, S27, S28, S29, S30, S31, + + // 特殊寄存器 + SP, // 栈指针 + ZR, // 零寄存器 +}; const char* PhysRegName(PhysReg reg); +// ========== 条件码枚举(用于 BCond 指令)========== +enum class CondCode { + EQ, // 相等 (equal) + NE, // 不等 (not equal) + CS, // 进位设置 (carry set) / 无符号大于等于 + CC, // 进位清除 (carry clear) / 无符号小于 + MI, // 负数 (minus) + PL, // 非负数 (plus) + VS, // 溢出 (overflow set) + VC, // 无溢出 (overflow clear) + HI, // 无符号大于 (higher) + LS, // 无符号小于等于 (lower or same) + GE, // 有符号大于等于 (greater or equal) + LT, // 有符号小于 (less than) + GT, // 有符号大于 (greater than) + LE, // 有符号小于等于 (less or equal) + AL, // 总是 (always) +}; + +const char* CondCodeName(CondCode cc); + +// ========== MIR 指令操作码枚举 ========== enum class Opcode { - Prologue, - Epilogue, - MovImm, - LoadStack, - StoreStack, - AddRR, - Ret, + // ---------- 栈帧相关 ---------- + Prologue, // 函数序言(伪指令) + Epilogue, // 函数尾声(伪指令) + + // ---------- 数据传输 ---------- + MovImm, // 立即数移动到寄存器: MOV w8, #imm + MovReg, // 寄存器之间移动: MOV w8, w9 + LoadStack, // 从栈槽加载: LDR w8, [sp, #offset] + StoreStack, // 存储到栈槽: STR w8, [sp, #offset] + LoadStackPair,// 成对加载: LDP x29, x30, [sp], #16 + StoreStackPair,// 成对存储: STP x29, x30, [sp, #-16]! + + // ---------- 整数算术运算 ---------- + AddRR, // 加法: ADD w8, w8, w9 + AddRI, // 加法(立即数): ADD w8, w8, #imm + SubRR, // 减法: SUB w8, w8, w9 + SubRI, // 减法(立即数): SUB w8, w8, #imm + MulRR, // 乘法: MUL w8, w8, w9 + SDivRR, // 有符号除法: SDIV w8, w8, w9 + UDivRR, // 无符号除法: UDIV w8, w8, w9 + + // ---------- 浮点算术运算 ---------- + FAddRR, // 浮点加法: FADD s0, s0, s1 + FSubRR, // 浮点减法: FSUB s0, s0, s1 + FMulRR, // 浮点乘法: FMUL s0, s0, s1 + FDivRR, // 浮点除法: FDIV s0, s0, s1 + + // ---------- 比较运算 ---------- + CmpRR, // 比较(寄存器): CMP w8, w9 + CmpRI, // 比较(立即数): CMP w8, #imm + FCmpRR, // 浮点比较: FCMP s0, s1 + + // ---------- 类型转换 ---------- + SIToFP, // 有符号整数转浮点: SCVTF s0, w0 + FPToSI, // 浮点转有符号整数: FCVTZS w0, s0 + ZExt, // 零扩展(i1 -> i32): AND w8, w8, #1 + + // ---------- 控制流 ---------- + B, // 无条件跳转: B label + BCond, // 条件跳转: B.EQ label, B.NE label, B.GT label 等 + Call, // 函数调用: BL target + Ret, // 函数返回: RET + + // ---------- 逻辑运算 ---------- + AndRR, // 按位与: AND w8, w8, w9 + OrRR, // 按位或: ORR w8, w8, w9 + EorRR, // 按位异或: EOR w8, w8, w9 + LslRR, // 逻辑左移: LSL w8, w8, w9 + LsrRR, // 逻辑右移: LSR w8, w8, w9 + AsrRR, // 算术右移: ASR w8, w8, w9 + + // ---------- 特殊 ---------- + Nop, // 空操作: NOP + Label, // 内联标签,不生成实际指令,仅输出标签名 + + // 添加 + Movk, // movk Rd, #imm16, lsl #shift + + // 添加 + LoadStackAddr, // 将栈帧地址加载到寄存器 (add xd, sp, #offset) + + // 用于全局变量地址计算 + Adrp, // ADRP Xd, label + AddLabel, // ADD Xd, Xn, :lo12:label + + // 新增 + Sxtw, // 符号扩展字到双字:sxtw Xd, Wn }; +// ========== 操作数类 ========== class Operand { public: - enum class Kind { Reg, Imm, FrameIndex }; + enum class Kind { Reg, Imm, FrameIndex, Cond, Label }; static Operand Reg(PhysReg reg); static Operand Imm(int value); static Operand FrameIndex(int index); + static Operand Cond(CondCode cc); + static Operand Label(const std::string& label); Kind GetKind() const { return kind_; } PhysReg GetReg() const { return reg_; } int GetImm() const { return imm_; } int GetFrameIndex() const { return imm_; } + CondCode GetCondCode() const { return cc_; } + const std::string& GetLabel() const { return label_; } private: - Operand(Kind kind, PhysReg reg, int imm); + Operand(Kind kind, PhysReg reg, int imm, CondCode cc, const std::string& label); Kind kind_; PhysReg reg_; int imm_; + CondCode cc_; + std::string label_; }; +// ========== MIR 指令类 ========== class MachineInstr { public: MachineInstr(Opcode opcode, std::vector operands = {}); @@ -66,12 +186,14 @@ class MachineInstr { std::vector operands_; }; +// ========== 栈槽结构 ========== struct FrameSlot { int index = 0; int size = 4; int offset = 0; }; +// ========== MIR 基本块 ========== class MachineBasicBlock { public: explicit MachineBasicBlock(std::string name); @@ -82,38 +204,133 @@ class MachineBasicBlock { MachineInstr& Append(Opcode opcode, std::initializer_list operands = {}); + MachineInstr& Append(Opcode opcode, std::vector operands); + + // 控制流信息 + std::vector& GetSuccessors() { return successors_; } + const std::vector& GetSuccessors() const { return successors_; } + void AddSuccessor(MachineBasicBlock* succ) { successors_.push_back(succ); } private: std::string name_; std::vector instructions_; + std::vector successors_; }; +// ========== MIR 函数 ========== class MachineFunction { public: explicit MachineFunction(std::string name); const std::string& GetName() const { return name_; } + + // 基本块管理 MachineBasicBlock& GetEntry() { return entry_; } const MachineBasicBlock& GetEntry() const { return entry_; } + std::vector>& GetBasicBlocks() { + return basic_blocks_; + } + const std::vector>& GetBasicBlocks() const { + return basic_blocks_; + } + + void AddBasicBlock(std::unique_ptr bb) { + basic_blocks_.push_back(std::move(bb)); + } + + // 栈槽管理 int CreateFrameIndex(int size = 4); FrameSlot& GetFrameSlot(int index); const FrameSlot& GetFrameSlot(int index) const; + std::vector& GetFrameSlots() { return frame_slots_; } 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_; + std::vector> basic_blocks_; std::vector frame_slots_; int frame_size_ = 0; }; -std::unique_ptr LowerToMIR(const ir::Module& module); +// ========== MIR 模块 ========== +class MachineModule { + public: + MachineModule() = default; + + // 添加 MachineFunction + void AddFunction(std::unique_ptr func) { + functions_.push_back(std::move(func)); + } + + // 获取所有函数 + const std::vector>& GetFunctions() const { + return functions_; + } + + std::vector>& GetFunctions() { + return functions_; + } + + // 根据名称查找函数 + MachineFunction* GetFunction(const std::string& name) { + for (auto& func : functions_) { + if (func->GetName() == name) { + return func.get(); + } + } + return nullptr; + } + + const MachineFunction* GetFunction(const std::string& name) const { + for (const auto& func : functions_) { + if (func->GetName() == name) { + return func.get(); + } + } + return nullptr; + } + + struct GlobalDecl { + std::string name; + int size; // 字节大小 + int alignment; // 对齐要求(通常为 4 或 8) + bool is_zero_init; // 是否为零初始化 + bool has_init_data; // 是否包含初始化数据(用于标量常量) + uint64_t init_data; // 初始化数据(≤8字节) + // 构造函数,默认零初始化 + GlobalDecl(const std::string& n, int sz, int align, bool zero = true, + bool has_data = false, uint64_t data = 0) + : name(n), size(sz), alignment(align), is_zero_init(zero), + has_init_data(has_data), init_data(data) {} + }; + + void AddGlobal(const std::string& name, int size, int alignment, + bool is_zero_init = true, + bool has_init_data = false, uint64_t init_data = 0) { + globals_.emplace_back(name, size, alignment, is_zero_init, + has_init_data, init_data); + } + const std::vector& GetGlobals() const { return globals_; } + + private: + std::vector> functions_; + std::vector globals_; +}; + +// ========== 后端流程函数 ========== +/* std::unique_ptr LowerToMIR(const ir::Module& module); void RunRegAlloc(MachineFunction& function); void RunFrameLowering(MachineFunction& function); -void PrintAsm(const MachineFunction& function, std::ostream& os); +void PrintAsm(const MachineFunction& function, std::ostream& os); */ +std::unique_ptr LowerToMIR(const ir::Module& module); +void RunRegAlloc(MachineModule& module); +void RunFrameLowering(MachineModule& module); +void PrintAsm(const MachineModule& module, std::ostream& os); } // namespace mir diff --git a/scripts/test_compiler.sh b/scripts/test_compiler.sh index ac98f68..ba6363f 100755 --- a/scripts/test_compiler.sh +++ b/scripts/test_compiler.sh @@ -69,7 +69,7 @@ for test_dir in "${TEST_DIRS[@]}"; do stem=${base%.sy} case "$(basename "$test_dir")" in functional) - out_dir="$RESULT_BASE_DIR/function/ir" + out_dir="$RESULT_BASE_DIR/functional/ir" ;; performance) out_dir="$RESULT_BASE_DIR/performance/ir" diff --git a/scripts/test_mir.sh b/scripts/test_mir.sh new file mode 100755 index 0000000..821cb01 --- /dev/null +++ b/scripts/test_mir.sh @@ -0,0 +1,167 @@ +#!/bin/bash + +# 测试脚本(支持动态输出目录) +# 用法: ./run_tests.sh [--verbose] [--mode <模式>] [<单个测试文件>] +# 模式: parse-tree, ir, asm, run (默认 run) + +COMPILER="./build/bin/compiler" +TEST_SCRIPT="./scripts/verify_asm.sh" +TEST_DIR="test/test_case" +RESULT_FILE="result.txt" +VERBOSE=0 +MODE="run" # 默认模式为完整测试 + +# 解析参数 +while [[ $# -gt 0 ]]; do + case "$1" in + --verbose|-v) + VERBOSE=1 + shift + ;; + --mode) + MODE="$2" + shift 2 + ;; + --emit-parse-tree) + MODE="parse-tree" + shift + ;; + --emit-ir) + MODE="ir" + shift + ;; + --emit-asm) + MODE="asm" + shift + ;; + --run) + MODE="run" + shift + ;; + -*) + echo "未知选项: $1" + exit 1 + ;; + *) + # 非选项参数视为测试文件 + SINGLE_FILE="$1" + shift + ;; + esac +done + +# 检查编译器是否存在 +if [ ! -f "$COMPILER" ]; then + echo "错误: 编译器未找到于 $COMPILER" + echo "请先完成项目构建 (cmake 和 make)" + exit 1 +fi + +# 如果是 run 模式,检查测试脚本是否存在 +if [ "$MODE" = "run" ] && [ ! -f "$TEST_SCRIPT" ]; then + echo "错误: 测试脚本未找到于 $TEST_SCRIPT" + exit 1 +fi + +# 如果指定了单个文件,检查文件是否存在 +if [ -n "$SINGLE_FILE" ] && [ ! -f "$SINGLE_FILE" ]; then + echo "错误: 文件 $SINGLE_FILE 不存在" + exit 1 +fi + +# 清空(或创建)结果文件 +> "$RESULT_FILE" + +# 计数器 +total=0 +passed=0 +failed=0 + +echo "开始测试 (模式: $MODE)..." +echo "输出将保存到 $RESULT_FILE" +echo "------------------------" + +# 确定测试文件列表 +if [ -n "$SINGLE_FILE" ]; then + TEST_FILES=("$SINGLE_FILE") +else + mapfile -t TEST_FILES < <(find "$TEST_DIR" -type f -name "*.sy" | sort) +fi + +# 根据模式执行测试 +for file in "${TEST_FILES[@]}"; do + ((total++)) + if [ $VERBOSE -eq 1 ]; then + echo "测试文件: $file" + else + echo -n "测试 $file ... " + fi + + echo "========== $file ==========" >> "$RESULT_FILE" + + # 根据模式构建命令 + case "$MODE" in + parse-tree) + cmd="$COMPILER --emit-parse-tree \"$file\"" + ;; + ir) + cmd="$COMPILER --emit-ir \"$file\"" + ;; + asm) + cmd="$COMPILER --emit-asm \"$file\"" + ;; + run) + # 根据输入文件所在子目录确定输出目录 + # 提取 test/test_case/ 之后的子目录名(functional 或 performance) + rel_path="${file#$TEST_DIR/}" + subdir=$(echo "$rel_path" | cut -d'/' -f1) + if [[ "$subdir" != "functional" && "$subdir" != "performance" ]]; then + echo "警告: 未知子目录 $subdir,使用默认输出目录" >> "$RESULT_FILE" + out_dir="test/test_result/asm" + else + out_dir="test/test_result/$subdir/asm" + fi + cmd="$TEST_SCRIPT \"$file\" \"$out_dir\" --run" + ;; + *) + echo "未知模式: $MODE" >&2 + exit 1 + ;; + esac + + if [ $VERBOSE -eq 1 ]; then + eval "$cmd" 2>&1 | tee -a "$RESULT_FILE" + result=${PIPESTATUS[0]} + else + eval "$cmd" >> "$RESULT_FILE" 2>&1 + result=$? + fi + + echo "" >> "$RESULT_FILE" + + if [ $result -eq 0 ]; then + if [ $VERBOSE -eq 0 ]; then + echo "通过" + fi + ((passed++)) + else + if [ $VERBOSE -eq 0 ]; then + echo "失败" + else + echo ">>> 测试失败: $file" + fi + ((failed++)) + fi +done + +echo "------------------------" +echo "总计: $total" +echo "通过: $passed" +echo "失败: $failed" +echo "详细输出已保存至 $RESULT_FILE" + +if [ $failed -gt 0 ]; then + exit 1 +else + exit 0 +fi \ No newline at end of file diff --git a/scripts/verify_asm.sh b/scripts/verify_asm.sh index a4b8ae2..c96cb65 100755 --- a/scripts/verify_asm.sh +++ b/scripts/verify_asm.sh @@ -52,7 +52,8 @@ expected_file="$input_dir/$stem.out" "$compiler" --emit-asm "$input" > "$asm_file" echo "汇编已生成: $asm_file" -aarch64-linux-gnu-gcc "$asm_file" -o "$exe" +# 静态链接 +aarch64-linux-gnu-gcc -no-pie "$asm_file" -L./sylib -lsysy -static -o "$exe" echo "可执行文件已生成: $exe" if [[ "$run_exec" == true ]]; then @@ -83,7 +84,7 @@ if [[ "$run_exec" == true ]]; then } > "$actual_file" if [[ -f "$expected_file" ]]; then - if diff -u "$expected_file" "$actual_file"; then + if diff -w -u "$expected_file" "$actual_file"; then echo "输出匹配: $expected_file" else echo "输出不匹配: $expected_file" >&2 diff --git a/src/ir/Type.cpp b/src/ir/Type.cpp index 792ff54..f53e6ec 100644 --- a/src/ir/Type.cpp +++ b/src/ir/Type.cpp @@ -14,6 +14,7 @@ size_t Type::Size() const { case Kind::PtrInt32: return 8; // 假设 64 位指针 case Kind::PtrFloat: return 8; case Kind::Label: return 8; // 标签地址大小(指针大小) + case Kind::PtrInt1: return 8; // 指向 i1 的指针大小 default: return 0; // 派生类应重写 } } diff --git a/src/main.cpp b/src/main.cpp index 88ed747..c54f087 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -46,13 +46,17 @@ int main(int argc, char** argv) { } if (opts.emit_asm) { - auto machine_func = mir::LowerToMIR(*module); - mir::RunRegAlloc(*machine_func); - mir::RunFrameLowering(*machine_func); + //auto machine_func = mir::LowerToMIR(*module); + auto machine_module = mir::LowerToMIR(*module); + //mir::RunRegAlloc(*machine_func); + mir::RunRegAlloc(*machine_module); + //mir::RunFrameLowering(*machine_func); + mir::RunFrameLowering(*machine_module); if (need_blank_line) { std::cout << "\n"; } - mir::PrintAsm(*machine_func, std::cout); + //mir::PrintAsm(*machine_func, std::cout); + mir::PrintAsm(*machine_module, std::cout); } #else if (opts.emit_ir || opts.emit_asm) { diff --git a/src/mir/AsmPrinter.cpp b/src/mir/AsmPrinter.cpp index 4d1f65f..b5d04f7 100644 --- a/src/mir/AsmPrinter.cpp +++ b/src/mir/AsmPrinter.cpp @@ -2,12 +2,24 @@ #include #include +#include #include "utils/Log.h" +//#define DEBUG_Asm + +#ifdef DEBUG_Asm +#include +#define DEBUG_MSG(msg) std::cerr << "[Asm Debug] " << msg << std::endl +#else +#define DEBUG_MSG(msg) +#endif + namespace mir { namespace { +static void PrintLoadImm64(std::ostream& os, PhysReg reg, uint64_t imm); + const FrameSlot& GetFrameSlot(const MachineFunction& function, const Operand& operand) { if (operand.GetKind() != Operand::Kind::FrameIndex) { @@ -16,63 +28,458 @@ const FrameSlot& GetFrameSlot(const MachineFunction& function, return function.GetFrameSlot(operand.GetFrameIndex()); } -void PrintStackAccess(std::ostream& os, const char* mnemonic, PhysReg reg, - int offset) { - os << " " << mnemonic << " " << PhysRegName(reg) << ", [x29, #" << offset - << "]\n"; +void PrintStackAccess(std::ostream& os, const char* insn, PhysReg reg, int64_t offset) { + // offset 通常是负数,例如 -8, -24, -40 等 + if (offset >= -256 && offset <= 255) { + os << " " << insn << " " << PhysRegName(reg) << ", [x29, #" << offset << "]\n"; + return; + } + + // 大偏移量:用 x16 计算 x29 + offset,然后间接访问 + os << " mov x16, x29\n"; + + int64_t abs_offset = (offset >= 0) ? offset : -offset; + if (abs_offset <= 4095) { + if (offset >= 0) { + os << " add x16, x16, #" << offset << "\n"; + } else { + os << " sub x16, x16, #" << abs_offset << "\n"; + } + } else { + // 分解大偏移量 + PrintLoadImm64(os, PhysReg::X17, abs_offset); + if (offset >= 0) { + os << " add x16, x16, x17\n"; + } else { + os << " sub x16, x16, x17\n"; + } + } + + os << " " << insn << " " << PhysRegName(reg) << ", [x16]\n"; } -} // namespace +// 打印单个操作数 +void PrintOperand(std::ostream& os, const Operand& op) { + switch (op.GetKind()) { + case Operand::Kind::Reg: + os << PhysRegName(op.GetReg()); + break; + case Operand::Kind::Imm: + os << "#" << op.GetImm(); + break; + case Operand::Kind::FrameIndex: + os << "[sp, #" << op.GetFrameIndex() << "]"; + break; + case Operand::Kind::Cond: + os << CondCodeName(op.GetCondCode()); + break; + case Operand::Kind::Label: + DEBUG_MSG("label is" << op.GetLabel()); + os << op.GetLabel(); + break; + } +} -void PrintAsm(const MachineFunction& function, std::ostream& os) { - os << ".text\n"; - os << ".global " << function.GetName() << "\n"; - os << ".type " << function.GetName() << ", %function\n"; - os << function.GetName() << ":\n"; +// 判断立即数是否可作为 AArch64 ADD/SUB 指令的 12 位立即数(可左移 0 或 12 位) +static bool IsLegalAddSubImm(int64_t imm) { + if (imm < 0) imm = -imm; // 取绝对值,因为移位规则对称 + if (imm <= 4095) return true; // 0-4095 直接合法 + if ((imm & 0xFFF) == 0 && imm <= 4095 * 4096) return true; // 4096 的倍数且 ≤ 16773120 + return false; +} + +// 在匿名命名空间添加辅助函数 +static void PrintLoadImm64(std::ostream& os, PhysReg reg, uint64_t imm) { + // 输出 movz + movk 序列 + uint16_t part0 = imm & 0xFFFF; + uint16_t part1 = (imm >> 16) & 0xFFFF; + uint16_t part2 = (imm >> 32) & 0xFFFF; + uint16_t part3 = (imm >> 48) & 0xFFFF; + + os << " movz " << PhysRegName(reg) << ", #" << part0; + if (part1 != 0 || part2 != 0 || part3 != 0) { + os << ", lsl #0"; + } + os << "\n"; + + if (part1 != 0) { + os << " movk " << PhysRegName(reg) << ", #" << part1 << ", lsl #16\n"; + } + if (part2 != 0) { + os << " movk " << PhysRegName(reg) << ", #" << part2 << ", lsl #32\n"; + } + if (part3 != 0) { + os << " movk " << PhysRegName(reg) << ", #" << part3 << ", lsl #48\n"; + } +} - for (const auto& inst : function.GetEntry().GetInstructions()) { - const auto& ops = inst.GetOperands(); - switch (inst.GetOpcode()) { - case Opcode::Prologue: - os << " stp x29, x30, [sp, #-16]!\n"; - os << " mov x29, sp\n"; - if (function.GetFrameSize() > 0) { - os << " sub sp, sp, #" << function.GetFrameSize() << "\n"; +// 打印单条指令 +void PrintInstruction(std::ostream& os, const MachineInstr& instr, + const MachineFunction& function) { + const auto& ops = instr.GetOperands(); + + switch (instr.GetOpcode()) { + case Opcode::Prologue: + os << " stp x29, x30, [sp, #-16]!\n"; + os << " mov x29, sp\n"; + if (function.GetFrameSize() > 0) { + int64_t size = function.GetFrameSize(); + if (IsLegalAddSubImm(size)) { + os << " sub sp, sp, #" << size << "\n"; + } else { + PrintLoadImm64(os, PhysReg::X16, size); + os << " sub sp, sp, x16\n"; } - break; - case Opcode::Epilogue: - if (function.GetFrameSize() > 0) { - os << " add sp, sp, #" << function.GetFrameSize() << "\n"; + } + break; + case Opcode::Epilogue: + if (function.GetFrameSize() > 0) { + int64_t size = function.GetFrameSize(); + if (IsLegalAddSubImm(size)) { + os << " add sp, sp, #" << size << "\n"; + } else { + PrintLoadImm64(os, PhysReg::X16, size); + os << " add sp, sp, x16\n"; } - os << " ldp x29, x30, [sp], #16\n"; - break; - case Opcode::MovImm: - os << " mov " << PhysRegName(ops.at(0).GetReg()) << ", #" - << ops.at(1).GetImm() << "\n"; - break; - case Opcode::LoadStack: { - const auto& slot = GetFrameSlot(function, ops.at(1)); - PrintStackAccess(os, "ldur", ops.at(0).GetReg(), slot.offset); - break; } - case Opcode::StoreStack: { + os << " ldp x29, x30, [sp], #16\n"; + break; + case Opcode::MovImm: + os << " mov " << PhysRegName(ops.at(0).GetReg()) << ", #" + << ops.at(1).GetImm() << "\n"; + break; + case Opcode::MovReg: + os << " mov " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << "\n"; + break; + case Opcode::StoreStack: { + // 检查第二个操作数的类型 + if (ops.size() >= 2 && ops.at(1).GetKind() == Operand::Kind::FrameIndex) { + // 存储到栈槽 const auto& slot = GetFrameSlot(function, ops.at(1)); PrintStackAccess(os, "stur", ops.at(0).GetReg(), slot.offset); - break; + } else if (ops.size() >= 2 && ops.at(1).GetKind() == Operand::Kind::Reg) { + // 间接存储:存储到寄存器指向的地址 + // STR W9, [X8] + os << " str " << PhysRegName(ops.at(0).GetReg()) << ", [" + << PhysRegName(ops.at(1).GetReg()) << "]\n"; + } else { + throw std::runtime_error("StoreStack: 无效的操作数类型"); + } + break; + } + case Opcode::LoadStack: { + // 检查第二个操作数的类型 + if (ops.size() >= 2 && ops.at(1).GetKind() == Operand::Kind::FrameIndex) { + // 从栈槽加载 + const auto& slot = GetFrameSlot(function, ops.at(1)); + PrintStackAccess(os, "ldur", ops.at(0).GetReg(), slot.offset); + } else if (ops.size() >= 2 && ops.at(1).GetKind() == Operand::Kind::Reg) { + // 间接加载:从寄存器指向的地址加载 + // LDR W9, [X8] + os << " ldr " << PhysRegName(ops.at(0).GetReg()) << ", [" + << PhysRegName(ops.at(1).GetReg()) << "]\n"; + } else { + throw std::runtime_error("LoadStack: 无效的操作数类型"); + } + break; + } + case Opcode::StoreStackPair: + // stp x29, x30, [sp, #-16]! + os << " stp " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", [sp"; + if (ops.size() > 2 && ops.at(2).GetKind() == Operand::Kind::Imm) { + int offset = ops.at(2).GetImm(); + os << ", #" << offset; } - case Opcode::AddRR: + os << "]!\n"; // 注意添加 ! 表示 pre-index + break; + case Opcode::LoadStackPair: + // ldp x29, x30, [sp], #16 + os << " ldp " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", [sp]"; + if (ops.size() > 2 && ops.at(2).GetKind() == Operand::Kind::Imm) { + int offset = ops.at(2).GetImm(); + os << ", #" << offset; + } + os << "\n"; + break; + case Opcode::AddRR: + os << " add " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::AddRI: + os << " add " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", #" + << ops.at(2).GetImm() << "\n"; + break; + case Opcode::SubRR: + os << " sub " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::SubRI: + os << " sub " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", #" + << ops.at(2).GetImm() << "\n"; + break; + case Opcode::MulRR: + os << " mul " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::SDivRR: + os << " sdiv " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::UDivRR: + os << " udiv " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::FAddRR: + os << " fadd " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::FSubRR: + os << " fsub " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::FMulRR: + os << " fmul " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::FDivRR: + os << " fdiv " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::CmpRR: + os << " cmp " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << "\n"; + break; + case Opcode::CmpRI: + os << " cmp " << PhysRegName(ops.at(0).GetReg()) << ", #" + << ops.at(1).GetImm() << "\n"; + break; + case Opcode::FCmpRR: + os << " fcmp " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << "\n"; + break; + case Opcode::SIToFP: + os << " scvtf " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << "\n"; + break; + case Opcode::FPToSI: + os << " fcvtzs " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << "\n"; + break; + case Opcode::ZExt: + os << " and " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", #1\n"; + break; + case Opcode::AndRR: + os << " and " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::OrRR: + os << " orr " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::EorRR: + os << " eor " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::LslRR: + os << " lsl " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::LsrRR: + os << " lsr " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::AsrRR: + os << " asr " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << ", " + << PhysRegName(ops.at(2).GetReg()) << "\n"; + break; + case Opcode::B: + os << " b "; + PrintOperand(os, ops.at(0)); + os << "\n"; + break; + case Opcode::BCond: + os << " b."; + PrintOperand(os, ops.at(0)); + os << " "; + PrintOperand(os, ops.at(1)); + os << "\n"; + break; + case Opcode::Call: + os << " bl "; + PrintOperand(os, ops.at(0)); + os << "\n"; + break; + case Opcode::Ret: + os << " ret\n"; + break; + case Opcode::Nop: + os << " nop\n"; + break; + case Opcode::Label: + os << ops.at(0).GetLabel() << ":\n"; + break; + case Opcode::Movk: + os << " movk " << PhysRegName(ops.at(0).GetReg()) << ", #" + << ops.at(1).GetImm() << ", lsl #" << ops.at(2).GetImm() << "\n"; + break; + case Opcode::LoadStackAddr: { + const FrameSlot& slot = GetFrameSlot(function, ops.at(1)); + int64_t offset = slot.offset; // 负值,如 -8 + PhysReg dst = ops.at(0).GetReg(); + + auto tryEmitSimple = [&]() -> bool { + if (offset >= 0 && offset <= 4095) { + os << " add " << PhysRegName(dst) << ", x29, #" << offset << "\n"; + return true; + } else if (offset < 0 && offset >= -4095) { + os << " sub " << PhysRegName(dst) << ", x29, #" << (-offset) << "\n"; + return true; + } + return false; + }; + + if (tryEmitSimple()) break; + + // 复杂偏移 + uint64_t absOffset = (offset >= 0) ? offset : -offset; + PrintLoadImm64(os, PhysReg::X16, absOffset); + if (offset >= 0) { + os << " add " << PhysRegName(dst) << ", x29, x16\n"; + } else { + os << " sub " << PhysRegName(dst) << ", x29, x16\n"; + } + break; + } + case Opcode::Adrp: { + // adrp Xd, label + os << " adrp " << PhysRegName(ops.at(0).GetReg()) << ", " + << ops.at(1).GetLabel() << "\n"; + break; + } + case Opcode::AddLabel: { + // add Xd, Xn, :lo12:label os << " add " << PhysRegName(ops.at(0).GetReg()) << ", " - << PhysRegName(ops.at(1).GetReg()) << ", " - << PhysRegName(ops.at(2).GetReg()) << "\n"; + << PhysRegName(ops.at(1).GetReg()) << ", :lo12:" + << ops.at(2).GetLabel() << "\n"; break; - case Opcode::Ret: - os << " ret\n"; + } + case Opcode::Sxtw: + os << " sxtw " << PhysRegName(ops.at(0).GetReg()) << ", " + << PhysRegName(ops.at(1).GetReg()) << "\n"; + break; + default: + os << " // unknown instruction\n"; break; + } +} + +// 打印单个函数(单函数版本) +void PrintAsm(const MachineFunction& function, std::ostream& os) { + // 输出函数标签 + os << ".text\n"; + os << ".global " << function.GetName() << "\n"; + os << ".type " << function.GetName() << ", %function\n"; + os << function.GetName() << ":\n"; + + // 计算栈帧大小 + int frameSize = function.GetFrameSize(); + + // 输出每个基本块 + const auto& blocks = function.GetBasicBlocks(); + bool firstBlock = true; + + for (const auto& bb : blocks) { + DEBUG_MSG("block"); + // 输出基本块标签(非第一个基本块) + if (!firstBlock) { + os << bb->GetName() << ":\n"; + } + firstBlock = false; + + // 输出基本块中的指令 + for (const auto& inst : bb->GetInstructions()) { + DEBUG_MSG("inst"); + PrintInstruction(os, inst, function); + } + } + + os << ".size " << function.GetName() << ", .-" << function.GetName() << "\n"; +} + +} // namespace + +// 打印模块(模块版本) +void PrintAsm(const MachineModule& module, std::ostream& os) { + // 输出文件头 + os << ".arch armv8-a\n"; + + // 输出数据段:全局变量 + const auto& globals = module.GetGlobals(); + if (!globals.empty()) { + os << "\n.data\n"; + for (const auto& g : globals) { + os << ".global " << g.name << "\n"; + os << ".type " << g.name << ", %object\n"; + os << ".align " << g.alignment << "\n"; + os << g.name << ":\n"; + if (g.is_zero_init) { + os << " .zero " << g.size << "\n"; + } else if (g.has_init_data) { + if (g.size == 4) { + os << " .word " << static_cast(g.init_data) << "\n"; + } else if (g.size == 8) { + os << " .quad " << g.init_data << "\n"; + } else { + // 暂不支持的标量大小,回退为零初始化 + os << " .zero " << g.size << " // unhandled init size\n"; + } + } else { + // 有初始值但无法提取(例如数组、结构体) + os << " .zero " << g.size << " // unhandled initializer\n"; + } + os << ".size " << g.name << ", " << g.size << "\n\n"; } } - os << ".size " << function.GetName() << ", .-" << function.GetName() - << "\n"; + static const std::set externalFuncs = { + "getint", "getch", "getarray", "putint", "putch", "putarray", "puts", + "_sysy_starttime", "_sysy_stoptime", "starttime", "stoptime", + "getfloat", "putfloat", "getfarray", "putfarray", "memset", + "sysy_alloc_i32", "sysy_alloc_f32", "sysy_free_i32", "sysy_free_f32", + "sysy_zero_i32", "sysy_zero_f32" + }; + DEBUG_MSG("module"); + // 遍历所有函数,输出汇编 + for (const auto& func : module.GetFunctions()) { + + if (externalFuncs.count(func->GetName())) { + continue; // 跳过库函数桩 + } + DEBUG_MSG("func"); + PrintAsm(*func, os); + os << "\n"; + } } -} // namespace mir +} // namespace mir \ No newline at end of file diff --git a/src/mir/FrameLowering.cpp b/src/mir/FrameLowering.cpp index 679ab68..86cd502 100644 --- a/src/mir/FrameLowering.cpp +++ b/src/mir/FrameLowering.cpp @@ -5,6 +5,15 @@ #include "utils/Log.h" +//#define DEBUG_Frame + +#ifdef DEBUG_Frame +#include +#define DEBUG_MSG(msg) std::cerr << "[Frame Debug] " << msg << std::endl +#else +#define DEBUG_MSG(msg) +#endif + namespace mir { namespace { @@ -15,31 +24,49 @@ int AlignTo(int value, int align) { } // namespace void RunFrameLowering(MachineFunction& function) { + DEBUG_MSG("function RunFrameLowering"); int cursor = 0; - for (const auto& slot : function.GetFrameSlots()) { - cursor += slot.size; - if (-cursor < -256) { - throw std::runtime_error(FormatError("mir", "暂不支持过大的栈帧")); - } - } - - cursor = 0; for (const auto& slot : function.GetFrameSlots()) { cursor += slot.size; function.GetFrameSlot(slot.index).offset = -cursor; } function.SetFrameSize(AlignTo(cursor, 16)); - auto& insts = function.GetEntry().GetInstructions(); - std::vector lowered; - lowered.emplace_back(Opcode::Prologue); - for (const auto& inst : insts) { - if (inst.GetOpcode() == Opcode::Ret) { - lowered.emplace_back(Opcode::Epilogue); + // 基本块 + const auto& blocks = function.GetBasicBlocks(); + bool firstBlock = true; + + for (const auto& bb : blocks) { + DEBUG_MSG("block"); + auto& insts = bb->GetInstructions(); + std::vector lowered; + // 输出基本块标签(非第一个基本块) + if (firstBlock) { + DEBUG_MSG("empalace Prologue"); + lowered.emplace_back(Opcode::Prologue); + } + firstBlock = false; + + // 输出基本块中的指令 + for (const auto& inst : insts) { + DEBUG_MSG("inst"); + if (inst.GetOpcode() == Opcode::Ret) { + DEBUG_MSG("empalace Epilogue"); + lowered.emplace_back(Opcode::Epilogue); + } + lowered.push_back(inst); } - lowered.push_back(inst); + insts = std::move(lowered); + } +} + +// 模块版本的栈帧布局 +void RunFrameLowering(MachineModule& module) { + // 对模块中的每个函数执行栈帧布局 + DEBUG_MSG("module RunFrameLowering"); + for (auto& func : module.GetFunctions()) { + RunFrameLowering(*func); } - insts = std::move(lowered); } -} // namespace mir +} // namespace mir \ No newline at end of file diff --git a/src/mir/Lowering.cpp b/src/mir/Lowering.cpp index 9a18396..0817fbb 100644 --- a/src/mir/Lowering.cpp +++ b/src/mir/Lowering.cpp @@ -2,122 +2,1374 @@ #include #include +#include #include "ir/IR.h" #include "utils/Log.h" +//#define DEBUG_Lower + +#ifdef DEBUG_Lower +#include +#define DEBUG_MSG(msg) std::cerr << "[Lower Debug] " << msg << std::endl +#else +#define DEBUG_MSG(msg) ((void)0) +#endif + namespace mir { namespace { using ValueSlotMap = std::unordered_map; +inline bool IsInt32Type(const ir::Type* type) { + return type && type->IsInt32() && type->Size() == 4; +} + +static uint32_t FloatToBits(float f) { + uint32_t bits; + memcpy(&bits, &f, sizeof(bits)); + return bits; +} + +// 获取类型大小(字节) +int GetTypeSize(const ir::Type* type) { + if (!type) return 4; + size_t size = type->Size(); + return size > 0 ? static_cast(size) : 4; +} + +// 将 IR 整数比较谓词转换为 ARMv8 条件码 +CondCode IcmpToCondCode(ir::IcmpInst::Predicate pred) { + switch (pred) { + case ir::IcmpInst::Predicate::EQ: return CondCode::EQ; + case ir::IcmpInst::Predicate::NE: return CondCode::NE; + case ir::IcmpInst::Predicate::LT: return CondCode::LT; + case ir::IcmpInst::Predicate::GT: return CondCode::GT; + case ir::IcmpInst::Predicate::LE: return CondCode::LE; + case ir::IcmpInst::Predicate::GE: return CondCode::GE; + default: return CondCode::AL; + } +} + +// 将 IR 浮点比较谓词转换为 ARMv8 条件码 +CondCode FcmpToCondCode(ir::FcmpInst::Predicate pred, bool& isOrdered) { + isOrdered = true; + switch (pred) { + case ir::FcmpInst::Predicate::OEQ: return CondCode::EQ; + case ir::FcmpInst::Predicate::ONE: return CondCode::NE; + case ir::FcmpInst::Predicate::OLT: return CondCode::LT; + case ir::FcmpInst::Predicate::OGT: return CondCode::GT; + case ir::FcmpInst::Predicate::OLE: return CondCode::LE; + case ir::FcmpInst::Predicate::OGE: return CondCode::GE; + case ir::FcmpInst::Predicate::UEQ: isOrdered = false; return CondCode::EQ; + case ir::FcmpInst::Predicate::UNE: isOrdered = false; return CondCode::NE; + case ir::FcmpInst::Predicate::ULT: isOrdered = false; return CondCode::LT; + case ir::FcmpInst::Predicate::UGT: isOrdered = false; return CondCode::GT; + case ir::FcmpInst::Predicate::ULE: isOrdered = false; return CondCode::LE; + case ir::FcmpInst::Predicate::UGE: isOrdered = false; return CondCode::GE; + default: return CondCode::AL; + } +} + +// 获取基本块的标签名(用于汇编输出) +std::string GetBlockLabel(const ir::BasicBlock* bb) { + if (!bb || !bb->GetParent()) { + return ".Lunknown"; + } + // 格式:.L函数名_基本块名 + std::string funcName = bb->GetParent()->GetName(); + std::string blockName = bb->GetName(); + + // 如果基本块没有名字,使用地址作为标识 + if (blockName.empty()) { + blockName = std::to_string(reinterpret_cast(bb)); + } + + return ".L" + funcName + "_" + blockName; +} + +// 获取数组类型的维度信息 +static const ir::ArrayType* GetArrayType(const ir::Type* type) { + if (type->IsArray()) { + return static_cast(type); + } + return nullptr; +} + +static std::vector GetArrayStrides(const ir::ArrayType* arrayType) { + std::vector strides; + const std::vector& dims = arrayType->GetDimensions(); + int stride = 4; // 元素大小(int/float 是 4 字节) + + // 从最后一维向前计算步长 + for (int i = dims.size() - 1; i >= 0; --i) { + strides.insert(strides.begin(), stride); + stride *= dims[i]; + } + return strides; +} + +// 在 Lowering.cpp 中添加辅助函数 +const ir::Value* GetOperand(const ir::Instruction& inst, size_t index) { + if (index < inst.GetNumOperands()) { + return inst.GetOperand(index); + } + return nullptr; +} + +const ir::BasicBlock* GetBasicBlockOperand(const ir::Instruction& inst, size_t index) { + const ir::Value* operand = GetOperand(inst, index); + if (operand) { + return dynamic_cast(operand); + } + return nullptr; +} + void EmitValueToReg(const ir::Value* value, PhysReg target, - const ValueSlotMap& slots, MachineBasicBlock& block) { + const ValueSlotMap& slots, MachineBasicBlock& block, + MachineFunction& function) { + // 处理整数常量 + if (value == nullptr) { + DEBUG_MSG( "EmitValueToReg called with null value\n"); + } + + // 辅助函数:判断32位立即数是否可用单条 movz/movn 编码 + auto isLegalMovImm = [](uint32_t imm) -> bool { + // 检查是否可以通过 movz 或 movn 表示(16位立即数,可左移0/16/32/48位) + // 对于32位寄存器,只考虑 lsl 0 或 16 + if ((imm & 0xFFFF) == imm) return true; // 低16位,lsl #0 + if ((imm & 0xFFFF0000) == imm) return true; // 高16位,lsl #16 + // 可选:检查 movn 情况(~imm 满足上述条件),为了简单可不做,直接返回 false + return false; + }; + if (auto* constant = dynamic_cast(value)) { - block.Append(Opcode::MovImm, - {Operand::Reg(target), Operand::Imm(constant->GetValue())}); + uint32_t imm = static_cast(constant->GetValue()); + + // 如果目标是浮点寄存器,将 imm 位模式解释为 float 并加载 + if (target >= PhysReg::S0 && target <= PhysReg::S7) { + auto it = slots.find(value); + int slot; + if (it == slots.end()) { + slot = function.CreateFrameIndex(4); + // 将 imm 写入栈槽(与 ConstantFloat 相同方式) + if (isLegalMovImm(imm)) { + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W10), Operand::Imm(static_cast(imm))}); + } else { + uint16_t low = imm & 0xFFFF; + uint16_t high = (imm >> 16) & 0xFFFF; + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W10), Operand::Imm(low)}); + if (high != 0) { + block.Append(Opcode::Movk, {Operand::Reg(PhysReg::W10), Operand::Imm(high), Operand::Imm(16)}); + } + } + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W10), Operand::FrameIndex(slot)}); + const_cast(slots).emplace(value, slot); + } else { + slot = it->second; + } + // 从栈槽加载到浮点目标寄存器 + block.Append(Opcode::LoadStack, {Operand::Reg(target), Operand::FrameIndex(slot)}); + return; + } + + if (isLegalMovImm(imm)) { + block.Append(Opcode::MovImm, + {Operand::Reg(target), Operand::Imm(static_cast(imm))}); + } else { + // 分解为 movz (低16位) + movk (高16位) + uint16_t low = imm & 0xFFFF; + uint16_t high = (imm >> 16) & 0xFFFF; + block.Append(Opcode::MovImm, + {Operand::Reg(target), Operand::Imm(low)}); // 先加载低16位 + if (high != 0) { + // 使用 Movk 指令写入高16位 + block.Append(Opcode::Movk, + {Operand::Reg(target), Operand::Imm(high), Operand::Imm(16)}); + } + } + return; + } + // 处理浮点常量 + if (auto* fconstant = dynamic_cast(value)) { + // 检查是否已经为这个常量分配了栈槽 + auto it = slots.find(value); + int slot; + if (it == slots.end()) { + DEBUG_MSG("Value not found: " << value->GetName()); + // 输出所有 slots 的键名用于调试 + for (auto& p : slots) { + DEBUG_MSG(" Slot key: " << p.first->GetName()); + } + // 分配新的栈槽 + slot = function.CreateFrameIndex(4); + // 将浮点常量存储到栈槽 + float fval = fconstant->GetValue(); + uint32_t int_val = FloatToBits(fval); + + // 同样需要对 int_val 进行大立即数分解 + if (isLegalMovImm(int_val)) { + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W10), Operand::Imm(static_cast(int_val))}); + } else { + uint16_t low = int_val & 0xFFFF; + uint16_t high = (int_val >> 16) & 0xFFFF; + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W10), Operand::Imm(low)}); + if (high != 0) { + block.Append(Opcode::Movk, {Operand::Reg(PhysReg::W10), Operand::Imm(high), Operand::Imm(16)}); + } + } + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W10), Operand::FrameIndex(slot)}); + const_cast(slots).emplace(value, slot); + } else { + slot = it->second; + } + + // 从栈槽加载到目标寄存器 + block.Append(Opcode::LoadStack, {Operand::Reg(target), Operand::FrameIndex(slot)}); return; } + // 处理零常量 + if (dynamic_cast(value) || + dynamic_cast(value)) { + // 如果目标是浮点寄存器,必须通过栈槽加载 0.0f 的位模式 + if (target >= PhysReg::S0 && target <= PhysReg::S7) { + auto it = slots.find(value); + int slot; + if (it == slots.end()) { + slot = function.CreateFrameIndex(4); + // 写入 0 + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W10), Operand::Imm(0)}); + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W10), Operand::FrameIndex(slot)}); + const_cast(slots).emplace(value, slot); + } else { + slot = it->second; + } + // 加载到浮点寄存器 + block.Append(Opcode::LoadStack, {Operand::Reg(target), Operand::FrameIndex(slot)}); + return; + } + // 原有的整数/指针零常量处理保持不变 + block.Append(Opcode::MovImm, {Operand::Reg(target), Operand::Imm(0)}); + return; + } + + // ========== 处理全局变量 ========== + if (auto* global = dynamic_cast(value)) { + // 如果目标是 32 位寄存器,升级为对应的 64 位寄存器 + PhysReg addrTarget = target; + if (target >= PhysReg::W0 && target <= PhysReg::W30) { + // 映射 Wn → Xn + addrTarget = static_cast( + static_cast(target) - static_cast(PhysReg::W0) + static_cast(PhysReg::X0)); + } + // 现在 addrTarget 一定是 64 位寄存器 + block.Append(Opcode::Adrp, {Operand::Reg(addrTarget), Operand::Label(global->GetName())}); + block.Append(Opcode::AddLabel, {Operand::Reg(addrTarget), Operand::Reg(addrTarget), Operand::Label(global->GetName())}); + return; + } + + // ========== 处理从栈槽加载的值 ========== auto it = slots.find(value); if (it == slots.end()) { + // 使用值的地址作为调试信息 + std::string valueName = value->GetName(); + if (valueName.empty()) { + valueName = "(anonymous at " + std::to_string(reinterpret_cast(value)) + ")"; + } + DEBUG_MSG("Value not found: " << valueName); + // 输出所有 slots 的键名用于调试 + for (auto& p : slots) { + std::string slotName = p.first->GetName(); + if (slotName.empty()) { + slotName = "(anonymous at " + std::to_string(reinterpret_cast(p.first)) + ")"; + } + DEBUG_MSG(" Slot key: " << slotName); + } throw std::runtime_error( - FormatError("mir", "找不到值对应的栈槽: " + value->GetName())); + FormatError("mir", "找不到值对应的栈槽: " + valueName)); } - block.Append(Opcode::LoadStack, - {Operand::Reg(target), Operand::FrameIndex(it->second)}); + PhysReg actualTarget = target; + const ir::Type* ty = value->GetType().get(); + bool isPointer = ty->IsPtrInt32() || ty->IsPtrFloat() || ty->IsPtrInt1() + || ty->IsArray(); // 数组类型在地址上下文中视为指针 + + // 若非指针类型且目标是 64 位寄存器,降级为对应的 32 位寄存器(自动零扩展) + if (!isPointer && target >= PhysReg::X0 && target <= PhysReg::X30) { + actualTarget = static_cast( + static_cast(target) - static_cast(PhysReg::X0) + static_cast(PhysReg::W0)); } -void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, - ValueSlotMap& slots) { - auto& block = function.GetEntry(); +block.Append(Opcode::LoadStack, + {Operand::Reg(actualTarget), Operand::FrameIndex(it->second)}); +} +void LowerInstruction(const ir::Instruction& inst, MachineFunction& function, + ValueSlotMap& slots, MachineBasicBlock& block, + std::unordered_map& blockMap) { + //auto& block = function.GetEntry(); + DEBUG_MSG("Processing instruction: " << inst.GetName() + << " (opcode: " << static_cast(inst.GetOpcode()) << ")"); switch (inst.GetOpcode()) { case ir::Opcode::Alloca: { - slots.emplace(&inst, function.CreateFrameIndex()); - return; + // alloca 返回一个指针,我们需要为该指针分配一个栈槽(存放地址值) + int ptrSlot = function.CreateFrameIndex(8); // 指针占8字节 + // 为数组数据分配实际栈空间 + int arraySlot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + + // 将数组基地址(sp + arraySlot_offset)加载到 x8 + block.Append(Opcode::LoadStackAddr, + {Operand::Reg(PhysReg::X8), Operand::FrameIndex(arraySlot)}); + // 将地址存储到指针槽 + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::X8), Operand::FrameIndex(ptrSlot)}); + + // 将 alloca 指令映射到指针槽,后续使用 alloca 值即获得地址 + slots.emplace(&inst, ptrSlot); + return; } case ir::Opcode::Store: { - auto& store = static_cast(inst); - auto dst = slots.find(store.GetPtr()); - if (dst == slots.end()) { - throw std::runtime_error( - FormatError("mir", "暂不支持对非栈变量地址进行写入")); + auto& store = static_cast(inst); + const ir::Value* ptr = store.GetPtr(); + const ir::Value* val = store.GetValue(); + + // 处理全局变量作为存储目标 + if (auto* global = dynamic_cast(ptr)) { + // 生成全局变量地址到 x8 + block.Append(Opcode::Adrp, {Operand::Reg(PhysReg::X8), Operand::Label(global->GetName())}); + block.Append(Opcode::AddLabel, {Operand::Reg(PhysReg::X8), Operand::Reg(PhysReg::X8), Operand::Label(global->GetName())}); + // 加载要存储的值到 w9 + EmitValueToReg(val, PhysReg::W9, slots, block, function); + // 间接存储:str w9, [x8] + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W9), Operand::Reg(PhysReg::X8)}); + return; + } + + auto dstIt = slots.find(ptr); + if (dstIt == slots.end()) { + // 指针不在 slots 中(例如直接来自函数参数的指针) + // 计算指针地址到 x8 + EmitValueToReg(ptr, PhysReg::X8, slots, block, function); + // 加载要存储的值到 w9 + EmitValueToReg(val, PhysReg::W9, slots, block, function); + // 使用 StoreStack 的寄存器间接形式(str w9, [x8]) + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::W9), Operand::Reg(PhysReg::X8)}); + } else { + // 指针在 slots 中(alloca 或 gep 的结果),从指针槽加载地址到 x8 + block.Append(Opcode::LoadStack, + {Operand::Reg(PhysReg::X8), Operand::FrameIndex(dstIt->second)}); + // 加载要存储的值到 w9 + EmitValueToReg(val, PhysReg::W9, slots, block, function); + // 间接存储 + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::W9), Operand::Reg(PhysReg::X8)}); + } + return; + } + case ir::Opcode::Load: { + auto& load = static_cast(inst); + const ir::Value* ptr = load.GetPtr(); + int dstSlot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + + // 处理全局变量作为加载源 + if (auto* global = dynamic_cast(ptr)) { + // 生成全局变量地址到 x8 + block.Append(Opcode::Adrp, {Operand::Reg(PhysReg::X8), Operand::Label(global->GetName())}); + block.Append(Opcode::AddLabel, {Operand::Reg(PhysReg::X8), Operand::Reg(PhysReg::X8), Operand::Label(global->GetName())}); + // 间接加载到 w9 + block.Append(Opcode::LoadStack, {Operand::Reg(PhysReg::W9), Operand::Reg(PhysReg::X8)}); + // 存储结果到栈槽 + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W9), Operand::FrameIndex(dstSlot)}); + slots.emplace(&inst, dstSlot); + return; + } + + auto srcIt = slots.find(ptr); + if (srcIt == slots.end()) { + // 指针不在 slots 中,计算地址到 x8 + EmitValueToReg(ptr, PhysReg::X8, slots, block, function); + // 间接加载到 w9 + block.Append(Opcode::LoadStack, + {Operand::Reg(PhysReg::W9), Operand::Reg(PhysReg::X8)}); + } else { + // 从指针槽加载地址到 x8 + block.Append(Opcode::LoadStack, + {Operand::Reg(PhysReg::X8), Operand::FrameIndex(srcIt->second)}); + // 间接加载到 w9 + block.Append(Opcode::LoadStack, + {Operand::Reg(PhysReg::W9), Operand::Reg(PhysReg::X8)}); + } + // 将加载的值存入结果槽 + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::W9), Operand::FrameIndex(dstSlot)}); + slots.emplace(&inst, dstSlot); + return; + } + case ir::Opcode::Add: { + auto& bin = static_cast(inst); + const ir::Type* lhsTy = bin.GetLhs()->GetType().get(); + const ir::Type* rhsTy = bin.GetRhs()->GetType().get(); + const ir::Type* resultTy = inst.GetType().get(); + + // 指针判断:指令结果类型是指针,或者任一操作数是指针(指针算术) + bool isPointer = (lhsTy->IsPtrInt32() || lhsTy->IsPtrFloat() || lhsTy->IsPtrInt1() || lhsTy->IsArray()) || + (rhsTy->IsPtrInt32() || rhsTy->IsPtrFloat() || rhsTy->IsPtrInt1() || rhsTy->IsArray()) || + resultTy->IsPtrInt32() || resultTy->IsPtrFloat() || resultTy->IsPtrInt1() || resultTy->IsArray(); + + // 判断是否为纯 32 位有符号整数加法(需要提升为 64 位以避免溢出) + bool isI32 = !isPointer && IsInt32Type(lhsTy) && IsInt32Type(rhsTy) && IsInt32Type(resultTy); + + int slotSize = isPointer ? 8 : 4; + int dst_slot = function.CreateFrameIndex(slotSize); + + PhysReg lhsReg, rhsReg, dstReg; + if (isI32) { + // 使用 64 位寄存器,先符号扩展 + lhsReg = PhysReg::X8; + rhsReg = PhysReg::X9; + dstReg = PhysReg::X8; + + EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block, function); + block.Append(Opcode::Sxtw, {Operand::Reg(PhysReg::X8), Operand::Reg(PhysReg::W8)}); + + EmitValueToReg(bin.GetRhs(), PhysReg::W9, slots, block, function); + block.Append(Opcode::Sxtw, {Operand::Reg(PhysReg::X9), Operand::Reg(PhysReg::W9)}); + } else { + lhsReg = isPointer ? PhysReg::X8 : PhysReg::W8; + rhsReg = isPointer ? PhysReg::X9 : PhysReg::W9; + dstReg = isPointer ? PhysReg::X8 : PhysReg::W8; + EmitValueToReg(bin.GetLhs(), lhsReg, slots, block, function); + EmitValueToReg(bin.GetRhs(), rhsReg, slots, block, function); } - EmitValueToReg(store.GetValue(), PhysReg::W8, slots, block); - block.Append(Opcode::StoreStack, - {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst->second)}); + + block.Append(Opcode::AddRR, {Operand::Reg(dstReg), Operand::Reg(lhsReg), Operand::Reg(rhsReg)}); + + if (isI32) { + // 结果在 X8 中,只需存储低 32 位(W8) + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + } else { + block.Append(Opcode::StoreStack, {Operand::Reg(dstReg), Operand::FrameIndex(dst_slot)}); + } + slots.emplace(&inst, dst_slot); return; } - case ir::Opcode::Load: { - auto& load = static_cast(inst); - auto src = slots.find(load.GetPtr()); - if (src == slots.end()) { - throw std::runtime_error( - FormatError("mir", "暂不支持对非栈变量地址进行读取")); - } - int dst_slot = function.CreateFrameIndex(); - block.Append(Opcode::LoadStack, - {Operand::Reg(PhysReg::W8), Operand::FrameIndex(src->second)}); - block.Append(Opcode::StoreStack, - {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + + case ir::Opcode::Sub: { + auto& bin = static_cast(inst); + // 如果两个操作数都是浮点类型,则使用浮点减法 + if (bin.GetLhs()->GetType()->IsFloat() && bin.GetRhs()->GetType()->IsFloat()) { + int dst_slot = function.CreateFrameIndex(4); + EmitValueToReg(bin.GetLhs(), PhysReg::S0, slots, block, function); + EmitValueToReg(bin.GetRhs(), PhysReg::S1, slots, block, function); + block.Append(Opcode::FSubRR, {Operand::Reg(PhysReg::S0), Operand::Reg(PhysReg::S0), Operand::Reg(PhysReg::S1)}); + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::S0), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + const ir::Type* lhsTy = bin.GetLhs()->GetType().get(); + const ir::Type* rhsTy = bin.GetRhs()->GetType().get(); + const ir::Type* resultTy = inst.GetType().get(); + + bool isPointer = (lhsTy->IsPtrInt32() || lhsTy->IsPtrFloat() || lhsTy->IsPtrInt1() || lhsTy->IsArray()) || + (rhsTy->IsPtrInt32() || rhsTy->IsPtrFloat() || rhsTy->IsPtrInt1() || rhsTy->IsArray()) || + resultTy->IsPtrInt32() || resultTy->IsPtrFloat() || resultTy->IsPtrInt1() || resultTy->IsArray(); + + bool isI32 = !isPointer && IsInt32Type(lhsTy) && IsInt32Type(rhsTy) && IsInt32Type(resultTy); + + int slotSize = isPointer ? 8 : 4; + int dst_slot = function.CreateFrameIndex(slotSize); + + PhysReg lhsReg, rhsReg, dstReg; + if (isI32) { + lhsReg = PhysReg::X8; + rhsReg = PhysReg::X9; + dstReg = PhysReg::X8; + + EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block, function); + block.Append(Opcode::Sxtw, {Operand::Reg(PhysReg::X8), Operand::Reg(PhysReg::W8)}); + + EmitValueToReg(bin.GetRhs(), PhysReg::W9, slots, block, function); + block.Append(Opcode::Sxtw, {Operand::Reg(PhysReg::X9), Operand::Reg(PhysReg::W9)}); + } else { + lhsReg = isPointer ? PhysReg::X8 : PhysReg::W8; + rhsReg = isPointer ? PhysReg::X9 : PhysReg::W9; + dstReg = isPointer ? PhysReg::X8 : PhysReg::W8; + EmitValueToReg(bin.GetLhs(), lhsReg, slots, block, function); + EmitValueToReg(bin.GetRhs(), rhsReg, slots, block, function); + } + + block.Append(Opcode::SubRR, {Operand::Reg(dstReg), Operand::Reg(lhsReg), Operand::Reg(rhsReg)}); + + if (isI32) { + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + } else { + block.Append(Opcode::StoreStack, {Operand::Reg(dstReg), Operand::FrameIndex(dst_slot)}); + } slots.emplace(&inst, dst_slot); return; } - case ir::Opcode::Add: { + + case ir::Opcode::Mul: { auto& bin = static_cast(inst); - int dst_slot = function.CreateFrameIndex(); - EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block); - EmitValueToReg(bin.GetRhs(), PhysReg::W9, slots, block); - block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::W8), - Operand::Reg(PhysReg::W8), - Operand::Reg(PhysReg::W9)}); - block.Append(Opcode::StoreStack, - {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + const ir::Type* lhsTy = bin.GetLhs()->GetType().get(); + const ir::Type* rhsTy = bin.GetRhs()->GetType().get(); + const ir::Type* resultTy = inst.GetType().get(); + + // 乘法一般不涉及指针,但保留判断 + bool isPointer = (lhsTy->IsPtrInt32() || lhsTy->IsPtrFloat() || lhsTy->IsPtrInt1()) || + (rhsTy->IsPtrInt32() || rhsTy->IsPtrFloat() || rhsTy->IsPtrInt1()) || + resultTy->IsPtrInt32() || resultTy->IsPtrFloat() || resultTy->IsPtrInt1(); + + bool isI32 = !isPointer && IsInt32Type(lhsTy) && IsInt32Type(rhsTy) && IsInt32Type(resultTy); + + int slotSize = isPointer ? 8 : 4; + int dst_slot = function.CreateFrameIndex(slotSize); + + PhysReg lhsReg, rhsReg, dstReg; + if (isI32) { + lhsReg = PhysReg::X8; + rhsReg = PhysReg::X9; + dstReg = PhysReg::X8; + + EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block, function); + block.Append(Opcode::Sxtw, {Operand::Reg(PhysReg::X8), Operand::Reg(PhysReg::W8)}); + + EmitValueToReg(bin.GetRhs(), PhysReg::W9, slots, block, function); + block.Append(Opcode::Sxtw, {Operand::Reg(PhysReg::X9), Operand::Reg(PhysReg::W9)}); + } else { + lhsReg = isPointer ? PhysReg::X8 : PhysReg::W8; + rhsReg = isPointer ? PhysReg::X9 : PhysReg::W9; + dstReg = isPointer ? PhysReg::X8 : PhysReg::W8; + EmitValueToReg(bin.GetLhs(), lhsReg, slots, block, function); + EmitValueToReg(bin.GetRhs(), rhsReg, slots, block, function); + } + + block.Append(Opcode::MulRR, {Operand::Reg(dstReg), Operand::Reg(lhsReg), Operand::Reg(rhsReg)}); + + if (isI32) { + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + } else { + block.Append(Opcode::StoreStack, {Operand::Reg(dstReg), Operand::FrameIndex(dst_slot)}); + } + slots.emplace(&inst, dst_slot); + return; + } + + case ir::Opcode::Div: { + auto& bin = static_cast(inst); + const ir::Type* lhsTy = bin.GetLhs()->GetType().get(); + const ir::Type* rhsTy = bin.GetRhs()->GetType().get(); + const ir::Type* resultTy = inst.GetType().get(); + + bool isPointer = (lhsTy->IsPtrInt32() || lhsTy->IsPtrFloat() || lhsTy->IsPtrInt1()) || + (rhsTy->IsPtrInt32() || rhsTy->IsPtrFloat() || rhsTy->IsPtrInt1()) || + resultTy->IsPtrInt32() || resultTy->IsPtrFloat() || resultTy->IsPtrInt1(); + + bool isI32 = !isPointer && IsInt32Type(lhsTy) && IsInt32Type(rhsTy) && IsInt32Type(resultTy); + + int slotSize = isPointer ? 8 : 4; + int dst_slot = function.CreateFrameIndex(slotSize); + + PhysReg lhsReg, rhsReg, dstReg; + if (isI32) { + lhsReg = PhysReg::X8; + rhsReg = PhysReg::X9; + dstReg = PhysReg::X8; + + EmitValueToReg(bin.GetLhs(), PhysReg::W8, slots, block, function); + block.Append(Opcode::Sxtw, {Operand::Reg(PhysReg::X8), Operand::Reg(PhysReg::W8)}); + + EmitValueToReg(bin.GetRhs(), PhysReg::W9, slots, block, function); + block.Append(Opcode::Sxtw, {Operand::Reg(PhysReg::X9), Operand::Reg(PhysReg::W9)}); + } else { + lhsReg = isPointer ? PhysReg::X8 : PhysReg::W8; + rhsReg = isPointer ? PhysReg::X9 : PhysReg::W9; + dstReg = isPointer ? PhysReg::X8 : PhysReg::W8; + EmitValueToReg(bin.GetLhs(), lhsReg, slots, block, function); + EmitValueToReg(bin.GetRhs(), rhsReg, slots, block, function); + } + + block.Append(Opcode::SDivRR, {Operand::Reg(dstReg), Operand::Reg(lhsReg), Operand::Reg(rhsReg)}); + + if (isI32) { + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + } else { + block.Append(Opcode::StoreStack, {Operand::Reg(dstReg), Operand::FrameIndex(dst_slot)}); + } + slots.emplace(&inst, dst_slot); + return; + } + + case ir::Opcode::Mod: { + // Mod 指令:a % b = a - (a / b) * b + // 我们直接复用提升策略:使用 64 位运算 + const ir::Value* lhs = inst.GetOperand(0); + const ir::Value* rhs = inst.GetOperand(1); + const ir::Type* lhsTy = lhs->GetType().get(); + const ir::Type* rhsTy = rhs->GetType().get(); + const ir::Type* resultTy = inst.GetType().get(); + + bool isI32 = IsInt32Type(lhsTy) && IsInt32Type(rhsTy) && IsInt32Type(resultTy); + + int dst_slot = function.CreateFrameIndex(4); // 结果总是 32 位 + if (isI32) { + // 加载并扩展 lhs + EmitValueToReg(lhs, PhysReg::W8, slots, block, function); + block.Append(Opcode::Sxtw, {Operand::Reg(PhysReg::X8), Operand::Reg(PhysReg::W8)}); + // 加载并扩展 rhs + EmitValueToReg(rhs, PhysReg::W9, slots, block, function); + block.Append(Opcode::Sxtw, {Operand::Reg(PhysReg::X9), Operand::Reg(PhysReg::W9)}); + + // X10 = X8 / X9 + block.Append(Opcode::SDivRR, {Operand::Reg(PhysReg::X10), Operand::Reg(PhysReg::X8), Operand::Reg(PhysReg::X9)}); + // X10 = X10 * X9 + block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::X10), Operand::Reg(PhysReg::X10), Operand::Reg(PhysReg::X9)}); + // X8 = X8 - X10 + block.Append(Opcode::SubRR, {Operand::Reg(PhysReg::X8), Operand::Reg(PhysReg::X8), Operand::Reg(PhysReg::X10)}); + // 存储低 32 位 + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + } else { + // 原有逻辑(假设不会用于指针或 64 位整数) + EmitValueToReg(lhs, PhysReg::W8, slots, block, function); + EmitValueToReg(rhs, PhysReg::W9, slots, block, function); + block.Append(Opcode::SDivRR, {Operand::Reg(PhysReg::W10), Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::W9)}); + block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::W10), Operand::Reg(PhysReg::W10), Operand::Reg(PhysReg::W9)}); + block.Append(Opcode::SubRR, {Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::W10)}); + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + } slots.emplace(&inst, dst_slot); return; } case ir::Opcode::Ret: { auto& ret = static_cast(inst); - EmitValueToReg(ret.GetValue(), PhysReg::W0, slots, block); + const ir::Value* retVal = ret.GetValue(); + if (retVal != nullptr) { + const ir::Type* retType = retVal->GetType().get(); + PhysReg retReg = PhysReg::W0; // 默认整数返回值 + if (retType->IsFloat()) { + retReg = PhysReg::S0; + } else if (retType->IsPtrInt32() || retType->IsPtrFloat() || retType->IsPtrInt1()) { + retReg = PhysReg::X0; + } else { + retReg = PhysReg::W0; + } + EmitValueToReg(retVal, retReg, slots, block, function); + } block.Append(Opcode::Ret); return; } - case ir::Opcode::Sub: - case ir::Opcode::Mul: - throw std::runtime_error(FormatError("mir", "暂不支持该二元运算")); - } + case ir::Opcode::FAdd: { + auto& bin = static_cast(inst); + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); // 分配结果栈槽 + // 浮点值加载到 S0, S1(使用浮点寄存器) + EmitValueToReg(bin.GetLhs(), PhysReg::S0, slots, block, function); + EmitValueToReg(bin.GetRhs(), PhysReg::S1, slots, block, function); + block.Append(Opcode::FAddRR, {Operand::Reg(PhysReg::S0), + Operand::Reg(PhysReg::S0), + Operand::Reg(PhysReg::S1)}); + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::S0), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + case ir::Opcode::FSub: { + auto& bin = static_cast(inst); + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); // 分配结果栈槽 + // 浮点值加载到 S0, S1(使用浮点寄存器) + EmitValueToReg(bin.GetLhs(), PhysReg::S0, slots, block, function); + EmitValueToReg(bin.GetRhs(), PhysReg::S1, slots, block, function); + block.Append(Opcode::FSubRR, {Operand::Reg(PhysReg::S0), + Operand::Reg(PhysReg::S0), + Operand::Reg(PhysReg::S1)}); + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::S0), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + case ir::Opcode::FMul: { + auto& bin = static_cast(inst); + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); // 分配结果栈槽 + // 浮点值加载到 S0, S1(使用浮点寄存器) + EmitValueToReg(bin.GetLhs(), PhysReg::S0, slots, block, function); + EmitValueToReg(bin.GetRhs(), PhysReg::S1, slots, block, function); + block.Append(Opcode::FMulRR, {Operand::Reg(PhysReg::S0), + Operand::Reg(PhysReg::S0), + Operand::Reg(PhysReg::S1)}); + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::S0), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + case ir::Opcode::FDiv: { + auto& bin = static_cast(inst); + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); // 分配结果栈槽 + // 浮点值加载到 S0, S1(使用浮点寄存器) + EmitValueToReg(bin.GetLhs(), PhysReg::S0, slots, block, function); + EmitValueToReg(bin.GetRhs(), PhysReg::S1, slots, block, function); + block.Append(Opcode::FDivRR, {Operand::Reg(PhysReg::S0), + Operand::Reg(PhysReg::S0), + Operand::Reg(PhysReg::S1)}); + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::S0), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + // ========== 整数比较指令(修正版)========== + case ir::Opcode::Icmp: { + auto& icmp = static_cast(inst); + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + + EmitValueToReg(icmp.GetLhs(), PhysReg::W8, slots, block, function); + EmitValueToReg(icmp.GetRhs(), PhysReg::W9, slots, block, function); + + block.Append(Opcode::CmpRR, {Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::W9)}); + CondCode cc = IcmpToCondCode(icmp.GetPredicate()); + + // 使用 CSET 模式 + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(1)}); + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W9), Operand::Imm(0)}); + + std::string true_label = ".L_cset_true_" + std::to_string(reinterpret_cast(&icmp)); + std::string end_label = ".L_cset_end_" + std::to_string(reinterpret_cast(&icmp)); + + block.Append(Opcode::BCond, {Operand::Cond(cc), Operand::Label(true_label)}); + block.Append(Opcode::MovReg, {Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::W9)}); + block.Append(Opcode::B, {Operand::Label(end_label)}); + block.Append(Opcode::Label, {Operand::Label(true_label)}); + block.Append(Opcode::Label, {Operand::Label(end_label)}); + + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + // ========== 浮点比较指令 ========== + case ir::Opcode::FCmp: { + auto& fcmp = static_cast(inst); + int dst_slot = function.CreateFrameIndex(4); // 结果是 i1(4字节) - throw std::runtime_error(FormatError("mir", "暂不支持该 IR 指令")); -} + // 1. 加载浮点操作数并比较 + EmitValueToReg(fcmp.GetLhs(), PhysReg::S0, slots, block, function); + EmitValueToReg(fcmp.GetRhs(), PhysReg::S1, slots, block, function); + block.Append(Opcode::FCmpRR, {Operand::Reg(PhysReg::S0), Operand::Reg(PhysReg::S1)}); -} // namespace + // 2. 获取有序/无序标志和条件码 + bool isOrdered; + CondCode cc = FcmpToCondCode(fcmp.GetPredicate(), isOrdered); -std::unique_ptr LowerToMIR(const ir::Module& module) { - DefaultContext(); + // 3. 结果预设为 0 + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(0)}); - if (module.GetFunctions().size() != 1) { - throw std::runtime_error(FormatError("mir", "暂不支持多个函数")); - } + // 4. 生成标签 + std::string set1_label = ".L_fcset_true_" + std::to_string(reinterpret_cast(&fcmp)); + std::string end_label = ".L_fcset_end_" + std::to_string(reinterpret_cast(&fcmp)); - const auto& func = *module.GetFunctions().front(); - if (func.GetName() != "main") { - throw std::runtime_error(FormatError("mir", "暂不支持非 main 函数")); + // 5. 处理 NaN 情况 + if (isOrdered) { + // 有序比较:如果无序 (V=1) → 直接结束(结果为 0) + block.Append(Opcode::BCond, {Operand::Cond(CondCode::VS), Operand::Label(end_label)}); + } else { + // 无序比较:如果无序 (V=1) → 结果置 1 + block.Append(Opcode::BCond, {Operand::Cond(CondCode::VS), Operand::Label(set1_label)}); + } + // 6. 正常条件跳转 + block.Append(Opcode::BCond, {Operand::Cond(cc), Operand::Label(set1_label)}); + + // 7. 无条件到结束 + block.Append(Opcode::B, {Operand::Label(end_label)}); + + // 8. 置 1 标签 + block.Append(Opcode::Label, {Operand::Label(set1_label)}); + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W8), Operand::Imm(1)}); + + // 9. 结束标签并存储结果 + block.Append(Opcode::Label, {Operand::Label(end_label)}); + block.Append(Opcode::StoreStack, {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + // ========== 跳转指令(使用标签操作数)========== + case ir::Opcode::Br: { + DEBUG_MSG("Processing Br"); + auto& br = static_cast(inst); + + if (br.IsConditional()) { + // 条件跳转 + EmitValueToReg(br.GetCondition(), PhysReg::W8, slots, block, function); + block.Append(Opcode::CmpRI, {Operand::Reg(PhysReg::W8), Operand::Imm(0)}); + + std::string trueLabel = GetBlockLabel(br.GetTrueTarget()); + std::string falseLabel = GetBlockLabel(br.GetFalseTarget()); + + block.Append(Opcode::BCond, {Operand::Cond(CondCode::NE), Operand::Label(trueLabel)}); + block.Append(Opcode::B, {Operand::Label(falseLabel)}); + } else { + // 无条件跳转 + std::string targetLabel = GetBlockLabel(br.GetTarget()); + block.Append(Opcode::B, {Operand::Label(targetLabel)}); + } + return; + } + case ir::Opcode::CondBr: { + DEBUG_MSG("Processing CondBr"); + auto& br = static_cast(inst); + + // 条件跳转处理 + EmitValueToReg(br.GetCondition(), PhysReg::W8, slots, block, function); + block.Append(Opcode::CmpRI, {Operand::Reg(PhysReg::W8), Operand::Imm(0)}); + + std::string trueLabel = GetBlockLabel(br.GetTrueTarget()); + std::string falseLabel = GetBlockLabel(br.GetFalseTarget()); + + block.Append(Opcode::BCond, {Operand::Cond(CondCode::NE), Operand::Label(trueLabel)}); + block.Append(Opcode::B, {Operand::Label(falseLabel)}); + return; + } + // ========== 函数调用 ========== + case ir::Opcode::Call: { + auto& call = static_cast(inst); + const ir::Function* callee = call.GetCallee(); + const std::string& calleeName = callee->GetName(); + + // 分配结果栈槽(如果有返回值) + int dst_slot = -1; + if (!inst.GetType()->IsVoid()) { + dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + } + + // 按照 ARM64 调用约定传递参数 + const auto& args = call.GetArgs(); + size_t intArgCount = 0; + size_t fpArgCount = 0; + + for (size_t i = 0; i < args.size(); ++i) { + const auto* arg = args[i]; + const ir::Type* argType = arg->GetType().get(); + + if (argType->IsFloat()) { + // 浮点参数 + PhysReg reg = static_cast(static_cast(PhysReg::S0) + fpArgCount); + EmitValueToReg(arg, reg, slots, block, function); + fpArgCount++; + } else if (argType->IsPtrInt32() || argType->IsPtrFloat() || argType->IsPtrInt1()) { + // 指针参数 → X 寄存器(占用一个整数参数槽) + PhysReg reg = static_cast(static_cast(PhysReg::X0) + intArgCount); + EmitValueToReg(arg, reg, slots, block, function); + intArgCount++; + } else { + // 普通整数 → W 寄存器 + PhysReg reg = static_cast(static_cast(PhysReg::W0) + intArgCount); + EmitValueToReg(arg, reg, slots, block, function); + intArgCount++; + } + } + + // 生成调用指令 + //block.Append(Opcode::Call, {Operand::Imm(0)}); // 实际需要传递函数名 + block.Append(Opcode::Call, {Operand::Label(calleeName)}); + // 保存返回值 + if (dst_slot != -1) { + const ir::Type* retType = inst.GetType().get(); + PhysReg srcReg = PhysReg::W0; + if (retType->IsFloat()) { + srcReg = PhysReg::S0; + } else if (retType->IsPtrInt32() || retType->IsPtrFloat() || retType->IsPtrInt1()) { + srcReg = PhysReg::X0; + } else { + srcReg = PhysReg::W0; + } + block.Append(Opcode::StoreStack, + {Operand::Reg(srcReg), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + } + return; + } + // ========== 类型转换指令 ========== + case ir::Opcode::ZExt: { + auto& zext = static_cast(inst); + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + + // 加载源值到 w8 + EmitValueToReg(zext.GetValue(), PhysReg::W8, slots, block, function); + + // 零扩展:i1 -> i32,直接存储即可(因为 i1 已经是 0 或 1) + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + case ir::Opcode::SIToFP: { + auto& sitofp = static_cast(inst); + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + + // 加载整数到 w8 + EmitValueToReg(sitofp.GetValue(), PhysReg::W8, slots, block, function); + + // 整数转浮点:SCVTF s0, w8 + block.Append(Opcode::SIToFP, {Operand::Reg(PhysReg::S0), Operand::Reg(PhysReg::W8)}); + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::S0), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + case ir::Opcode::FPToSI: { + auto& fptosi = static_cast(inst); + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + + // 加载浮点数到 s0 + EmitValueToReg(fptosi.GetValue(), PhysReg::S0, slots, block, function); + + // 浮点转整数:FCVTZS w8, s0 + block.Append(Opcode::FPToSI, {Operand::Reg(PhysReg::W8), Operand::Reg(PhysReg::S0)}); + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + case ir::Opcode::GEP: { + auto& gep = static_cast(inst); + + DEBUG_MSG("Processing GEP instruction: " << inst.GetName()); + + // GEP 返回指针类型,在 ARM64 上指针是 8 字节 + int dst_slot = function.CreateFrameIndex(8); + + // 获取基地址(数组的起始地址) + ir::Value* base = gep.GetBase(); + const auto& indices = gep.GetIndices(); + + std::string baseName = base->GetName().empty() ? "unnamed" : base->GetName(); + DEBUG_MSG("Base value: " << baseName); + DEBUG_MSG("Number of indices: " << indices.size()); + + // 打印索引值 + for (size_t idx_i = 0; idx_i < indices.size(); ++idx_i) { + if (auto* const_int = dynamic_cast(indices[idx_i])) { + DEBUG_MSG(" Index[" << idx_i << "] = " << const_int->GetValue() << " (constant)"); + } else { + DEBUG_MSG(" Index[" << idx_i << "] = variable"); + } + } + + // 加载基地址到 x8 + EmitValueToReg(base, PhysReg::X8, slots, block, function); + + if (indices.empty()) { + DEBUG_MSG("No indices, storing base address directly"); + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::X8), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + + // 获取基地址类型 + const ir::Type* baseType = base->GetType().get(); + DEBUG_MSG("Base type kind: " << static_cast(baseType->GetKind())); + + // 关键修改:对于数组指针类型,第一个索引是多余的,应该跳过 + size_t start_index = 0; + if (baseType->IsPtrInt32() || baseType->IsPtrFloat() || baseType->IsPtrInt1()) { + // 对于指针类型,第一个索引是偏移量,不能跳过 + DEBUG_MSG("Base is pointer type, using all indices for pointer arithmetic"); + start_index = 0; + } else if (baseType->IsArray()) { + // 对于数组类型(非指针),第一个索引是多余的 + // 因为 base 已经是数组本身,不需要再解引用 + DEBUG_MSG("Base is array type, skipping first index (array decay)"); + start_index = 1; + } + + // 如果基地址是数组类型,需要处理多维数组 + if (baseType->IsArray()) { + DEBUG_MSG("Base is array type, processing multi-dimensional array"); + const ir::ArrayType* arrayType = static_cast(baseType); + const std::vector& dims = arrayType->GetDimensions(); + + DEBUG_MSG("Array dimensions: "); + for (size_t i = 0; i < dims.size(); ++i) { + DEBUG_MSG(" dim[" << i << "] = " << dims[i]); + } + + // 正确计算每个维度的步长 + std::vector strides(dims.size()); + int element_size = 4; // 元素大小(int/float 是 4 字节) + for (int i = dims.size() - 1; i >= 0; --i) { + if (i == static_cast(dims.size()) - 1) { + strides[i] = element_size; + DEBUG_MSG("strides[" << i << "] = " << strides[i] << " (element size)"); + } else { + strides[i] = strides[i + 1] * dims[i + 1]; + DEBUG_MSG("strides[" << i << "] = " << strides[i+1] << " * " << dims[i+1] + << " = " << strides[i]); + } + } + + // 计算总偏移,跳过第一个索引 + size_t numIndices = indices.size(); + size_t effective_indices = numIndices - start_index; + if (effective_indices > dims.size()) { + DEBUG_MSG("Warning: effective indices (" << effective_indices << ") > dims.size() (" + << dims.size() << "), truncating"); + effective_indices = dims.size(); + } + + DEBUG_MSG("Using " << effective_indices << " effective indices (starting from " << start_index << ")"); + + // 加载当前地址到 x9 作为偏移量累加器 + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::X9), Operand::Imm(0)}); + + // 用于调试的静态偏移计算 + int debug_offset = 0; + + for (size_t i = 0; i < effective_indices; ++i) { + size_t idx_pos = start_index + i; + int index_value = 0; + if (auto* const_int = dynamic_cast(indices[idx_pos])) { + index_value = const_int->GetValue(); + DEBUG_MSG("Index[" << idx_pos << "] = " << index_value << " (constant)"); + debug_offset += index_value * strides[i]; + DEBUG_MSG(" Contribution = " << index_value << " * " << strides[i] + << " = " << (index_value * strides[i])); + DEBUG_MSG(" Running offset = " << debug_offset); + } else { + DEBUG_MSG("Index[" << idx_pos << "] = variable"); + } + + // 加载当前索引到 x10 + EmitValueToReg(indices[idx_pos], PhysReg::X10, slots, block, function); + + // 乘以步长 + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::X11), Operand::Imm(strides[i])}); + block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::X10), + Operand::Reg(PhysReg::X10), + Operand::Reg(PhysReg::X11)}); + + // 累加到偏移量 + block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X9), + Operand::Reg(PhysReg::X9), + Operand::Reg(PhysReg::X10)}); + } + + DEBUG_MSG("Total computed offset = " << debug_offset); + + // 最终地址 = base + offset + block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X8), + Operand::Reg(PhysReg::X8), + Operand::Reg(PhysReg::X9)}); + + // 存储计算出的地址 + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::X8), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + DEBUG_MSG("Array GEP completed, result stored in slot " << dst_slot); + return; + } + + // 其他情况的处理... + DEBUG_MSG("Base is other type, using simple handling"); + if (indices.size() >= 1) { + EmitValueToReg(indices[0], PhysReg::X9, slots, block, function); + + // 乘以元素大小(默认 4 字节) + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::X10), Operand::Imm(4)}); + block.Append(Opcode::MulRR, {Operand::Reg(PhysReg::X9), + Operand::Reg(PhysReg::X9), + Operand::Reg(PhysReg::X10)}); + + block.Append(Opcode::AddRR, {Operand::Reg(PhysReg::X8), + Operand::Reg(PhysReg::X8), + Operand::Reg(PhysReg::X9)}); + } + + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::X8), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + DEBUG_MSG("Simple GEP completed"); + return; + } + // 处理 Trunc 指令 + case ir::Opcode::Trunc: { + auto& inst_ref = static_cast(inst); + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + + // 假设 Trunc 指令有 GetValue() 方法 + // 如果没有,需要通过操作数列表获取 + const ir::Value* src_val = nullptr; + if (inst.GetNumOperands() > 0) { + src_val = inst.GetOperand(0); + } + if (src_val) { + EmitValueToReg(src_val, PhysReg::W8, slots, block, function); + } + + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + // 处理 And 指令 + case ir::Opcode::And: { + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + + const ir::Value* lhs = nullptr; + const ir::Value* rhs = nullptr; + if (inst.GetNumOperands() >= 2) { + lhs = inst.GetOperand(0); + rhs = inst.GetOperand(1); + } + + if (lhs && rhs) { + EmitValueToReg(lhs, PhysReg::W8, slots, block, function); + EmitValueToReg(rhs, PhysReg::W9, slots, block, function); + block.Append(Opcode::AndRR, {Operand::Reg(PhysReg::W8), + Operand::Reg(PhysReg::W8), + Operand::Reg(PhysReg::W9)}); + } + + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + // 处理 Or 指令 + case ir::Opcode::Or: { + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + + const ir::Value* lhs = nullptr; + const ir::Value* rhs = nullptr; + if (inst.GetNumOperands() >= 2) { + lhs = inst.GetOperand(0); + rhs = inst.GetOperand(1); + } + + if (lhs && rhs) { + EmitValueToReg(lhs, PhysReg::W8, slots, block, function); + EmitValueToReg(rhs, PhysReg::W9, slots, block, function); + block.Append(Opcode::OrRR, {Operand::Reg(PhysReg::W8), + Operand::Reg(PhysReg::W8), + Operand::Reg(PhysReg::W9)}); + } + + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + // 处理 Not 指令 + case ir::Opcode::Not: { + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + + const ir::Value* src_val = nullptr; + if (inst.GetNumOperands() > 0) { + src_val = inst.GetOperand(0); + } + + if (src_val) { + EmitValueToReg(src_val, PhysReg::W8, slots, block, function); + // NOT = XOR with -1 + block.Append(Opcode::MovImm, {Operand::Reg(PhysReg::W9), Operand::Imm(-1)}); + block.Append(Opcode::EorRR, {Operand::Reg(PhysReg::W8), + Operand::Reg(PhysReg::W8), + Operand::Reg(PhysReg::W9)}); + } + + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::W8), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + // 处理 FPExt(浮点扩展) + case ir::Opcode::FPExt: { + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + + const ir::Value* src_val = nullptr; + if (inst.GetNumOperands() > 0) { + src_val = inst.GetOperand(0); + } + + if (src_val) { + EmitValueToReg(src_val, PhysReg::S0, slots, block, function); + } + + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::S0), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + // 处理 FPTrunc(浮点截断) + case ir::Opcode::FPTrunc: { + int dst_slot = function.CreateFrameIndex(GetTypeSize(inst.GetType().get())); + + const ir::Value* src_val = nullptr; + if (inst.GetNumOperands() > 0) { + src_val = inst.GetOperand(0); + } + + if (src_val) { + EmitValueToReg(src_val, PhysReg::S0, slots, block, function); + } + + block.Append(Opcode::StoreStack, + {Operand::Reg(PhysReg::S0), Operand::FrameIndex(dst_slot)}); + slots.emplace(&inst, dst_slot); + return; + } + default: + DEBUG_MSG("Unhandled opcode: " << static_cast(inst.GetOpcode()) + << " for instruction: " << inst.GetName()); + throw std::runtime_error(FormatError("mir", "暂不支持该 IR 指令,opcode: " + + std::to_string(static_cast(inst.GetOpcode())))); + //throw std::runtime_error(FormatError("mir", "暂不支持该 IR 指令")); + //throw std::runtime_error(FormatError("mir", "暂不支持该 IR 指令,opcode: " + // + std::to_string(static_cast(inst.GetOpcode())))); } +} + +} // namespace +// 辅助函数,将单个 IR 函数转换为 MachineFunction +std::unique_ptr LowerFunction(const ir::Function& func) { auto machine_func = std::make_unique(func.GetName()); ValueSlotMap slots; - const auto* entry = func.GetEntry(); - if (!entry) { - throw std::runtime_error(FormatError("mir", "IR 函数缺少入口基本块")); + + // 存储参数信息,稍后处理 + struct ParamInfo { + const ir::Value* arg; + int slot; + bool isFloat; + bool isPointer; + }; + std::vector paramInfos; + + // 为函数参数分配栈槽 + for (const auto& arg : func.GetArguments()) { + int slot = machine_func->CreateFrameIndex(GetTypeSize(arg->GetType().get())); + slots.emplace(arg.get(), slot); + bool isFloat = arg->GetType()->IsFloat(); + bool isPointer = arg->GetType()->IsPtrInt32() || arg->GetType()->IsPtrFloat() || arg->GetType()->IsPtrInt1(); + paramInfos.push_back({arg.get(), slot, isFloat, isPointer}); + } + + // IR 基本块到 MIR 基本块的映射 + std::unordered_map blockMap; + + // 第一遍:为每个 IR 基本块创建 MIR 基本块 + std::string func_name = func.GetName(); + for (const auto& bb : func.GetBlocks()) { + // 格式: .L函数名_基本块名 + auto mirBB = std::make_unique(".L" + func_name + "_" + bb->GetName()); + blockMap[bb.get()] = mirBB.get(); + machine_func->AddBasicBlock(std::move(mirBB)); + } + + // 在入口基本块的开头添加参数加载指令 + if (!func.GetBlocks().empty()) { + MachineBasicBlock* entryBB = blockMap[func.GetEntry()]; + if (entryBB) { + size_t intArgIdx = 0; + size_t fpArgIdx = 0; + + for (const auto& param : paramInfos) { + if (param.isFloat) { + if (fpArgIdx < 8) { + PhysReg reg = static_cast(static_cast(PhysReg::S0) + fpArgIdx); + entryBB->Append(Opcode::StoreStack, + {Operand::Reg(reg), Operand::FrameIndex(param.slot)}); + } + fpArgIdx++; + } else if (param.isPointer) { + if (intArgIdx < 8) { + PhysReg reg = static_cast(static_cast(PhysReg::X0) + intArgIdx); + entryBB->Append(Opcode::StoreStack, {Operand::Reg(reg), Operand::FrameIndex(param.slot)}); + } + intArgIdx++; + } else { + if (intArgIdx < 8) { + PhysReg reg = static_cast(static_cast(PhysReg::W0) + intArgIdx); + entryBB->Append(Opcode::StoreStack, + {Operand::Reg(reg), Operand::FrameIndex(param.slot)}); + } + intArgIdx++; + } + } + } + } + + // 第二遍:遍历每个基本块,转换指令 + for (const auto& bb : func.GetBlocks()) { + MachineBasicBlock* mirBB = blockMap[bb.get()]; + if (!mirBB) { + throw std::runtime_error(FormatError("mir", "找不到基本块对应的 MIR 基本块")); + } + + for (const auto& inst : bb->GetInstructions()) { + LowerInstruction(*inst, *machine_func, slots, *mirBB, blockMap); + } } + return machine_func; +} - for (const auto& inst : entry->GetInstructions()) { - LowerInstruction(*inst, *machine_func, slots); +std::unique_ptr LowerToMIR(const ir::Module& module) { + DefaultContext(); + + auto machine_module = std::make_unique(); + + // 收集全局变量信息 + for (const auto& global : module.GetGlobals()) { + int size = GetTypeSize(global->GetType().get()); + int alignment = global->GetType()->Alignment(); + bool is_zero_init = !global->HasInitializer(); + bool has_init_data = false; + uint64_t init_data = 0; + + if (!is_zero_init) { + const auto& init = global->GetInitializer(); + // 简单处理:只支持单个元素的标量初始化(float 或 int) + if (init.size() == 1) { + if (auto* cf = dynamic_cast(init[0])) { + float fval = cf->GetValue(); + uint32_t bits; + memcpy(&bits, &fval, sizeof(bits)); + init_data = bits; + has_init_data = true; + } else if (auto* ci = dynamic_cast(init[0])) { + init_data = static_cast(ci->GetValue()); + has_init_data = true; + } + } + } + machine_module->AddGlobal(global->GetName(), size, alignment, + is_zero_init, has_init_data, init_data); } - return machine_func; + std::vector globals; + // 处理全局变量 + for (const auto& global : module.GetGlobals()) { + // 为全局变量在数据段分配空间 + // 这里需要扩展 MachineModule 来支持全局变量 + DEBUG_MSG("Global variable: " << global->GetName()); + globals.push_back(global.get()); + } + + // 遍历模块中的所有函数 + for (const auto& func : module.GetFunctions()) { + try { + auto machine_func = LowerFunction(*func); + machine_module->AddFunction(std::move(machine_func)); + } catch (const std::runtime_error& e) { + // 记录错误但继续处理其他函数 + throw std::runtime_error(FormatError("mir", "转换函数失败: " + func->GetName() + " - " + e.what())); + } + } + + if (machine_module->GetFunctions().empty()) { + throw std::runtime_error(FormatError("mir", "模块中没有成功转换的函数")); + } + + return machine_module; } -} // namespace mir +} // namespace mir \ No newline at end of file diff --git a/src/mir/MIRBasicBlock.cpp b/src/mir/MIRBasicBlock.cpp index d42b4b3..ab0dd57 100644 --- a/src/mir/MIRBasicBlock.cpp +++ b/src/mir/MIRBasicBlock.cpp @@ -9,7 +9,8 @@ MachineBasicBlock::MachineBasicBlock(std::string name) MachineInstr& MachineBasicBlock::Append(Opcode opcode, std::initializer_list operands) { - instructions_.emplace_back(opcode, std::vector(operands)); + //instructions_.emplace_back(opcode, std::vector(operands)); + instructions_.emplace_back(opcode, std::move(operands)); return instructions_.back(); } diff --git a/src/mir/MIRInstr.cpp b/src/mir/MIRInstr.cpp index 0a21a03..1959b5c 100644 --- a/src/mir/MIRInstr.cpp +++ b/src/mir/MIRInstr.cpp @@ -4,17 +4,25 @@ namespace mir { -Operand::Operand(Kind kind, PhysReg reg, int imm) - : kind_(kind), reg_(reg), imm_(imm) {} +Operand::Operand(Kind kind, PhysReg reg, int imm, CondCode cc, const std::string& label) + : kind_(kind), reg_(reg), imm_(imm), cc_(cc), label_(label) {} -Operand Operand::Reg(PhysReg reg) { return Operand(Kind::Reg, reg, 0); } +Operand Operand::Reg(PhysReg reg) { return Operand(Kind::Reg, reg, 0, CondCode::EQ, ""); } Operand Operand::Imm(int value) { - return Operand(Kind::Imm, PhysReg::W0, value); + return Operand(Kind::Imm, PhysReg::W0, value, CondCode::EQ, ""); } Operand Operand::FrameIndex(int index) { - return Operand(Kind::FrameIndex, PhysReg::W0, index); + return Operand(Kind::FrameIndex, PhysReg::W0, index, CondCode::EQ, ""); +} + +Operand Operand::Cond(CondCode cc) { + return Operand(Kind::Cond, PhysReg::W0, 0, cc, ""); +} + +Operand Operand::Label(const std::string& label) { + return Operand(Kind::Label, PhysReg::W0, 0, CondCode::EQ, label); } MachineInstr::MachineInstr(Opcode opcode, std::vector operands) diff --git a/src/mir/RegAlloc.cpp b/src/mir/RegAlloc.cpp index 5dc5d2b..19f6f51 100644 --- a/src/mir/RegAlloc.cpp +++ b/src/mir/RegAlloc.cpp @@ -12,8 +12,8 @@ bool IsAllowedReg(PhysReg reg) { case PhysReg::W0: case PhysReg::W8: case PhysReg::W9: - case PhysReg::X29: - case PhysReg::X30: + case PhysReg::X29: //FP = X29 帧指针 + case PhysReg::X30: //LR = X30 链接寄存器 case PhysReg::SP: return true; } @@ -22,15 +22,61 @@ bool IsAllowedReg(PhysReg reg) { } // namespace +//void RunRegAlloc(MachineFunction& function) { +// for (const auto& inst : function.GetEntry().GetInstructions()) { +// for (const auto& operand : inst.GetOperands()) { +// if (operand.GetKind() == Operand::Kind::Reg && +// !IsAllowedReg(operand.GetReg())) { +// throw std::runtime_error(FormatError("mir", "寄存器分配失败")); +// } +// } +// } +//} + +// 单函数版本的寄存器分配(原有逻辑) void RunRegAlloc(MachineFunction& function) { - for (const auto& inst : function.GetEntry().GetInstructions()) { - for (const auto& operand : inst.GetOperands()) { - if (operand.GetKind() == Operand::Kind::Reg && - !IsAllowedReg(operand.GetReg())) { - throw std::runtime_error(FormatError("mir", "寄存器分配失败")); + // 当前仅执行最小一致性检查,不实现真实寄存器分配 + // Lab3 阶段保持栈槽模型,不需要真实寄存器分配 + + // 检查每个基本块中的指令 + for (auto& bb : function.GetBasicBlocks()) { + for (auto& instr : bb->GetInstructions()) { + // 检查指令的操作数是否有效 + for (const auto& operand : instr.GetOperands()) { + switch (operand.GetKind()) { + case Operand::Kind::Reg: + // 寄存器操作数:检查是否在允许的范围内 + // 当前使用固定寄存器 w0, w8, w9, s0, s1 等 + break; + case Operand::Kind::FrameIndex: + // 栈槽索引:检查是否有效 + if (operand.GetFrameIndex() < 0 || + operand.GetFrameIndex() >= static_cast(function.GetFrameSlots().size())) { + throw std::runtime_error( + FormatError("regalloc", "无效的栈槽索引: " + + std::to_string(operand.GetFrameIndex()))); + } + break; + case Operand::Kind::Imm: + case Operand::Kind::Cond: + case Operand::Kind::Label: + // 立即数、条件码、标签不需要检查 + break; + } } } } + + // 注意:Lab3 阶段不实现真实寄存器分配 + // 所有值仍然使用栈槽模型,寄存器仅作为临时计算使用 +} + +// 模块版本的寄存器分配 +void RunRegAlloc(MachineModule& module) { + // 对模块中的每个函数执行寄存器分配 + for (auto& func : module.GetFunctions()) { + RunRegAlloc(*func); + } } } // namespace mir diff --git a/src/mir/Register.cpp b/src/mir/Register.cpp index 7530470..772322e 100644 --- a/src/mir/Register.cpp +++ b/src/mir/Register.cpp @@ -8,20 +8,111 @@ namespace mir { const char* PhysRegName(PhysReg reg) { switch (reg) { - case PhysReg::W0: - return "w0"; - case PhysReg::W8: - return "w8"; - case PhysReg::W9: - return "w9"; - case PhysReg::X29: - return "x29"; - case PhysReg::X30: - return "x30"; - case PhysReg::SP: - return "sp"; + // 32位寄存器 + case PhysReg::W0: return "w0"; + case PhysReg::W1: return "w1"; + case PhysReg::W2: return "w2"; + case PhysReg::W3: return "w3"; + case PhysReg::W4: return "w4"; + case PhysReg::W5: return "w5"; + case PhysReg::W6: return "w6"; + case PhysReg::W7: return "w7"; + case PhysReg::W8: return "w8"; + case PhysReg::W9: return "w9"; + case PhysReg::W10: return "w10"; + case PhysReg::W11: return "w11"; + case PhysReg::W12: return "w12"; + case PhysReg::W13: return "w13"; + case PhysReg::W14: return "w14"; + case PhysReg::W15: return "w15"; + case PhysReg::W16: return "w16"; // 添加 + case PhysReg::W17: return "w17"; // 添加 + case PhysReg::W18: return "w18"; // 添加 + case PhysReg::W19: return "w19"; // 添加 + case PhysReg::W20: return "w20"; // 添加 + case PhysReg::W21: return "w21"; // 添加 + case PhysReg::W22: return "w22"; // 添加 + case PhysReg::W23: return "w23"; // 添加 + case PhysReg::W24: return "w24"; // 添加 + case PhysReg::W25: return "w25"; // 添加 + case PhysReg::W26: return "w26"; // 添加 + case PhysReg::W27: return "w27"; // 添加 + case PhysReg::W28: return "w28"; // 添加 + case PhysReg::W29: return "w29"; + case PhysReg::W30: return "w30"; + + // 64位寄存器 + case PhysReg::X0: return "x0"; + case PhysReg::X1: return "x1"; + case PhysReg::X2: return "x2"; + case PhysReg::X3: return "x3"; + case PhysReg::X4: return "x4"; + case PhysReg::X5: return "x5"; + case PhysReg::X6: return "x6"; + case PhysReg::X7: return "x7"; + case PhysReg::X8: return "x8"; + case PhysReg::X9: return "x9"; + case PhysReg::X10: return "x10"; // 添加 + case PhysReg::X11: return "x11"; // 添加 + case PhysReg::X12: return "x12"; // 添加 + case PhysReg::X13: return "x13"; // 添加 + case PhysReg::X14: return "x14"; // 添加 + case PhysReg::X15: return "x15"; // 添加 + case PhysReg::X16: return "x16"; // 添加 + case PhysReg::X17: return "x17"; // 添加 + case PhysReg::X18: return "x18"; // 添加 + case PhysReg::X19: return "x19"; // 添加 + case PhysReg::X20: return "x20"; // 添加 + case PhysReg::X21: return "x21"; // 添加 + case PhysReg::X22: return "x22"; // 添加 + case PhysReg::X23: return "x23"; // 添加 + case PhysReg::X24: return "x24"; // 添加 + case PhysReg::X25: return "x25"; // 添加 + case PhysReg::X26: return "x26"; // 添加 + case PhysReg::X27: return "x27"; // 添加 + case PhysReg::X28: return "x28"; // 添加 + case PhysReg::X29: return "x29"; + case PhysReg::X30: return "x30"; + + // 浮点寄存器 + case PhysReg::S0: return "s0"; + case PhysReg::S1: return "s1"; + case PhysReg::S2: return "s2"; + case PhysReg::S3: return "s3"; + case PhysReg::S4: return "s4"; + case PhysReg::S5: return "s5"; + case PhysReg::S6: return "s6"; + case PhysReg::S7: return "s7"; + + // 特殊寄存器 + case PhysReg::SP: return "sp"; + case PhysReg::ZR: return "xzr"; + + default: return "unknown"; } throw std::runtime_error(FormatError("mir", "未知物理寄存器")); } +const char* CondCodeName(CondCode cc) { + switch (cc) { + case CondCode::EQ: return "eq"; + case CondCode::NE: return "ne"; + case CondCode::CS: return "cs"; + case CondCode::CC: return "cc"; + case CondCode::MI: return "mi"; + case CondCode::PL: return "pl"; + case CondCode::VS: return "vs"; + case CondCode::VC: return "vc"; + case CondCode::HI: return "hi"; + case CondCode::LS: return "ls"; + case CondCode::GE: return "ge"; + case CondCode::LT: return "lt"; + case CondCode::GT: return "gt"; + case CondCode::LE: return "le"; + case CondCode::AL: return "al"; + default: return "unknown"; + } + throw std::runtime_error(FormatError("mir", "未知条件码")); +} + } // namespace mir diff --git a/sylib/README.md b/sylib/README.md new file mode 100644 index 0000000..b77e61d --- /dev/null +++ b/sylib/README.md @@ -0,0 +1,5 @@ +编译libsysy.a +``` +aarch64-linux-gnu-gcc -c sylib.c -o sylib.o +aarch64-linux-gnu-ar rcs libsysy.a sylib.o +``` \ No newline at end of file diff --git a/test/test_case/performance/if-combine3.out b/test/test_case/performance/if-combine3.out index da3038d..c08cdd5 100644 --- a/test/test_case/performance/if-combine3.out +++ b/test/test_case/performance/if-combine3.out @@ -1,2 +1,2 @@ 60255 -0 \ No newline at end of file +0 diff --git a/test/test_case/performance/large_loop_array_2.out b/test/test_case/performance/large_loop_array_2.out index 9aea9e0..aa47d0d 100644 --- a/test/test_case/performance/large_loop_array_2.out +++ b/test/test_case/performance/large_loop_array_2.out @@ -1,2 +1,2 @@ 0 -0 \ No newline at end of file +0 diff --git a/test/test_case/performance/vector_mul3.out b/test/test_case/performance/vector_mul3.out index 8fc524f..30c8612 100644 --- a/test/test_case/performance/vector_mul3.out +++ b/test/test_case/performance/vector_mul3.out @@ -1,2 +1,2 @@ 1 -0 \ No newline at end of file +0