feat(mir):实现寄存器分配和spill/reload及部分优化

tansiping
cy 2 weeks ago
parent 6f30aeb595
commit 20ab603c46

5745
30.txt

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
#pragma once
#include <unordered_map>
#include <initializer_list>
#include <iosfwd>
#include <memory>
@ -150,32 +150,37 @@ struct GlobalInfo {
class Operand {
public:
enum class Kind { Reg, Imm, FrameIndex, Global, Func };
enum class Kind { PhysReg, VirtReg, Imm, FrameIndex, Global, Func };
static Operand Reg(PhysReg reg);
static Operand VirtReg(int index, bool is_float = false);
static Operand Imm(int value);
static Operand Imm64(int64_t value); // 新增:存储 64 位值
static Operand Imm64(int64_t value);
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_; }
PhysReg GetPhysReg() const { return reg_; }
int GetVirtReg() const { return imm_; }
bool IsVirtRegFloat() const { return is_float_; }
int GetImm() const { return imm_; }
int64_t GetImm64() const { return imm64_; } // 新增
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, int64_t imm64);
Operand(Kind kind, PhysReg reg, int imm, const std::string& name);
Operand(Kind kind, int virt_reg, bool is_float);
Kind kind_;
PhysReg reg_;
int imm_;
int64_t imm64_; // 新增
int64_t imm64_;
bool is_float_ = false;
std::string global_name_;
std::string func_name_;
};
@ -186,6 +191,9 @@ class MachineInstr {
Opcode GetOpcode() const { return opcode_; }
const std::vector<Operand>& GetOperands() const { return operands_; }
std::vector<Operand>& GetOperands() { return operands_; }
void SetOperands(std::vector<Operand> operands) { operands_ = std::move(operands); }
private:
Opcode opcode_;
@ -207,6 +215,9 @@ class MachineBasicBlock {
MachineInstr& Append(Opcode opcode,
std::initializer_list<Operand> operands = {});
MachineInstr& InsertBefore(std::vector<MachineInstr>::iterator pos,
Opcode opcode,
std::initializer_list<Operand> operands = {});
private:
std::string name_;
@ -223,6 +234,7 @@ class MachineFunction {
MachineBasicBlock* CreateBlock(const std::string& name);
MachineBasicBlock* GetEntry() { return entry_; }
const MachineBasicBlock* GetEntry() const { return entry_; }
std::vector<std::unique_ptr<MachineBasicBlock>>& GetBlocks() { return blocks_; }
const std::vector<std::unique_ptr<MachineBasicBlock>>& GetBlocks() const { return blocks_; }
// 栈帧管理
@ -235,6 +247,31 @@ class MachineFunction {
void SetFrameSize(int size) { frame_size_ = size; }
int GetLocalVarsSize() const { return local_vars_size_; }
void SetLocalVarsSize(int s) { local_vars_size_ = s; }
// 虚拟寄存器管理
int CreateVirtReg(bool is_float = false);
bool IsVirtRegFloat(int reg) const;
int GetNumVirtRegs() const { return virt_reg_types_.size(); }
const std::vector<bool>& GetVirtRegTypes() const { return virt_reg_types_; }
// 物理寄存器分配结果
void SetPhysRegForVirt(int virt_reg, PhysReg phys_reg);
PhysReg GetPhysRegForVirt(int virt_reg) const;
bool HasPhysRegForVirt(int virt_reg) const;
// 溢出槽管理
int CreateSpillSlot(bool is_float = false);
int GetSpillSlot(int virt_reg) const;
bool HasSpillSlot(int virt_reg) const;
void SetSpillSlot(int virt_reg, int slot);
void SetCalleeSavedOffset(PhysReg reg, int offset);
int GetCalleeSavedOffset(PhysReg reg) const;
// 保存的 callee-saved 寄存器
void AddCalleeSavedReg(PhysReg reg);
const std::vector<PhysReg>& GetCalleeSavedRegs() const { return callee_saved_regs_; }
private:
std::string name_;
MachineBasicBlock* entry_ = nullptr;
@ -242,6 +279,19 @@ class MachineFunction {
std::vector<FrameSlot> frame_slots_;
int frame_size_ = 0;
int local_vars_size_ = 0;
// 虚拟寄存器
int next_virt_reg_ = 0;
std::vector<bool> virt_reg_types_; // true = float, false = int
// 寄存器分配结果
std::vector<PhysReg> virt_to_phys_;
std::vector<int> virt_to_spill_slot_;
// callee-saved 寄存器
std::vector<PhysReg> callee_saved_regs_;
std::unordered_map<PhysReg, int> callee_saved_offsets_;
};
//std::unique_ptr<MachineFunction> LowerToMIR(const ir::Module& module);
void RunRegAlloc(MachineFunction& function);
@ -249,4 +299,5 @@ void RunFrameLowering(MachineFunction& function);
//void PrintAsm(const MachineFunction& function, std::ostream& os);
std::vector<std::unique_ptr<MachineFunction>> LowerToMIR(const ir::Module& module);
void PrintAsm(const std::vector<std::unique_ptr<MachineFunction>>& functions, std::ostream& os);
void RunPeepholeOptimization(MachineFunction& function);
} // namespace mir

272
ir.txt

@ -1,272 +0,0 @@
@MAX = global i32 1000000000
@TWO = global i32 2
@THREE = global i32 3
@FIVE = global i32 5
declare void @putch(i32)
declare void @memset(i32*, i32, i32)
declare i32 @getfarray(float*)
declare float @getfloat()
declare void @putfloat(float)
declare void @putint(i32)
declare void @putfarray(i32, float*)
define float @float_abs(float %x) {
entry:
%0 = alloca float
store float %x, float* %0
%2 = load float, float* %0
%3 = sitofp i32 0 to float
%4 = fcmp olt float %2, %3
br i1 %4, label %L0.if.then, label %L1.if.end
L0.if.then:
%6 = load float, float* %0
%7 = fsub float 0x0, %6
ret float %7
L1.if.end:
%9 = load float, float* %0
ret float %9
}
define float @circle_area(i32 %radius) {
entry:
%0 = alloca i32
store i32 %radius, i32* %0
%2 = load i32, i32* %0
%3 = sitofp i32 %2 to float
%4 = fmul float 0x400921FB60000000, %3
%5 = load i32, i32* %0
%6 = sitofp i32 %5 to float
%7 = fmul float %4, %6
%8 = load i32, i32* %0
%9 = load i32, i32* %0
%10 = mul i32 %8, %9
%11 = sitofp i32 %10 to float
%12 = fmul float %11, 0x400921FB60000000
%13 = fadd float %7, %12
%14 = sitofp i32 2 to float
%15 = fdiv float %13, %14
ret float %15
}
define i32 @float_eq(float %a, float %b) {
entry:
%0 = alloca float
%1 = alloca float
store float %a, float* %0
store float %b, float* %1
%4 = load float, float* %0
%5 = load float, float* %1
%6 = fsub float %4, %5
%7 = call float @float_abs(float %6)
%8 = fcmp olt float %7, 0x3EB0C6F7A0000000
br i1 %8, label %L2.if.then, label %L3.if.else
L2.if.then:
%10 = sitofp i32 1 to float
%11 = fmul float %10, 0x4000000000000000
%12 = sitofp i32 2 to float
%13 = fdiv float %11, %12
%14 = fptosi float %13 to i32
ret i32 %14
L3.if.else:
ret i32 0
L4.if.end:
ret i32 0
}
define void @error() {
entry:
call void @putch(i32 101)
call void @putch(i32 114)
call void @putch(i32 114)
call void @putch(i32 111)
call void @putch(i32 114)
call void @putch(i32 10)
ret void
}
define void @ok() {
entry:
call void @putch(i32 111)
call void @putch(i32 107)
call void @putch(i32 10)
ret void
}
define void @assert(i32 %cond) {
entry:
%0 = alloca i32
store i32 %cond, i32* %0
%2 = load i32, i32* %0
%3 = icmp eq i32 %2, 0
%4 = zext i1 %3 to i32
%5 = icmp ne i32 %4, 0
br i1 %5, label %L5.if.then, label %L6.if.else
L5.if.then:
call void @error()
br label %L7.if.end
L6.if.else:
call void @ok()
br label %L7.if.end
L7.if.end:
ret void
}
define void @assert_not(i32 %cond) {
entry:
%0 = alloca i32
store i32 %cond, i32* %0
%2 = load i32, i32* %0
%3 = icmp ne i32 %2, 0
br i1 %3, label %L8.if.then, label %L9.if.else
L8.if.then:
call void @error()
br label %L10.if.end
L9.if.else:
call void @ok()
br label %L10.if.end
L10.if.end:
ret void
}
define i32 @main() {
entry:
%0 = alloca i32
%1 = alloca i32
%2 = alloca i32
%3 = alloca i32
%4 = alloca float, i32 10
%5 = alloca i32
%6 = alloca float
%7 = alloca float
%8 = alloca float
%9 = call i32 @float_eq(float 0x3FB4000000000000, float 0xC0E01D0000000000)
call void @assert_not(i32 %9)
%11 = call i32 @float_eq(float 0x4057C21FC0000000, float 0x4041475CE0000000)
call void @assert_not(i32 %11)
%13 = call i32 @float_eq(float 0x4041475CE0000000, float 0x4041475CE0000000)
call void @assert(i32 %13)
%15 = fptosi float 0x4016000000000000 to i32
%16 = call float @circle_area(i32 %15)
%17 = load i32, i32* @FIVE
%18 = call float @circle_area(i32 %17)
%19 = call i32 @float_eq(float %16, float %18)
call void @assert(i32 %19)
%21 = call i32 @float_eq(float 0x406D200000000000, float 0x40AFFE0000000000)
call void @assert_not(i32 %21)
%23 = fcmp one float 0x3FF8000000000000, 0x0
br i1 %23, label %L11.if.then, label %L12.if.end
L11.if.then:
call void @ok()
br label %L12.if.end
L12.if.end:
%27 = fcmp oeq float 0x400A666660000000, 0x0
%28 = zext i1 %27 to i32
%29 = icmp eq i32 %28, 0
%30 = zext i1 %29 to i32
%31 = icmp ne i32 %30, 0
br i1 %31, label %L13.if.then, label %L14.if.end
L13.if.then:
call void @ok()
br label %L14.if.end
L14.if.end:
%35 = fcmp one float 0x0, 0x0
%36 = zext i1 %35 to i32
store i32 %36, i32* %0
br i1 %35, label %L15.and.rhs, label %L16.and.end
L15.and.rhs:
%39 = icmp ne i32 3, 0
%40 = zext i1 %39 to i32
store i32 %40, i32* %0
br label %L16.and.end
L16.and.end:
%43 = load i32, i32* %0
%44 = icmp ne i32 %43, 0
br i1 %44, label %L17.if.then, label %L18.if.end
L17.if.then:
call void @error()
br label %L18.if.end
L18.if.end:
%48 = icmp ne i32 0, 0
%49 = zext i1 %48 to i32
store i32 %49, i32* %1
br i1 %48, label %L20.or.end, label %L19.or.rhs
L19.or.rhs:
%52 = fcmp one float 0x3FD3333340000000, 0x0
%53 = zext i1 %52 to i32
store i32 %53, i32* %1
br label %L20.or.end
L20.or.end:
%56 = load i32, i32* %1
%57 = icmp ne i32 %56, 0
br i1 %57, label %L21.if.then, label %L22.if.end
L21.if.then:
call void @ok()
br label %L22.if.end
L22.if.end:
store i32 1, i32* %2
store i32 0, i32* %3
call void @memset(float* %4, i32 0, i32 40)
%64 = getelementptr float, float* %4, i32 0
store float 0x3FF0000000000000, float* %64
%66 = getelementptr float, float* %4, i32 1
store i32 2, float* %66
%68 = getelementptr float, float* %4, i32 0
%69 = call i32 @getfarray(float* %68)
store i32 %69, i32* %5
br label %L23.while.cond
L23.while.cond:
%72 = load i32, i32* %2
%73 = load i32, i32* @MAX
%74 = icmp slt i32 %72, %73
br i1 %74, label %L24.while.body, label %L25.while.end
L24.while.body:
%76 = call float @getfloat()
store float %76, float* %6
%78 = load float, float* %6
%79 = fmul float 0x400921FB60000000, %78
%80 = load float, float* %6
%81 = fmul float %79, %80
store float %81, float* %7
%83 = load float, float* %6
%84 = fptosi float %83 to i32
%85 = call float @circle_area(i32 %84)
store float %85, float* %8
%87 = load i32, i32* %3
%88 = getelementptr float, float* %4, i32 %87
%89 = load float, float* %88
%90 = load float, float* %6
%91 = fadd float %89, %90
%92 = load i32, i32* %3
%93 = getelementptr float, float* %4, i32 %92
store float %91, float* %93
%95 = load float, float* %7
call void @putfloat(float %95)
call void @putch(i32 32)
%98 = load float, float* %8
%99 = fptosi float %98 to i32
call void @putint(i32 %99)
call void @putch(i32 10)
%102 = load i32, i32* %2
%103 = fsub float 0x0, 0x4024000000000000
%104 = fsub float 0x0, %103
%105 = sitofp i32 %102 to float
%106 = fmul float %105, %104
%107 = fptosi float %106 to i32
store i32 %107, i32* %2
%109 = load i32, i32* %3
%110 = add i32 %109, 1
store i32 %110, i32* %3
br label %L23.while.cond
L25.while.end:
%113 = load i32, i32* %5
%114 = getelementptr float, float* %4, i32 0
call void @putfarray(i32 %113, float* %114)
%116 = srem i32 0, 256
%117 = add i32 %116, 256
%118 = srem i32 %117, 256
call void @putint(i32 %118)
call void @putch(i32 10)
ret i32 0
}

@ -1,309 +0,0 @@
.text
.global main
.type main, @function
main:
addi sp, sp, -272
sw ra, 264(sp)
sw s0, 256(sp)
addi a0, sp, -4
li a1, 0
li a2, 32
call
addi a0, sp, -8
li a1, 0
li a2, 32
call
li t2, 1
addi t0, sp, -8
li t1, 0
slli t1, t1, 2
add t0, t0, t1
sw t2, 0(t0)
li t2, 2
addi t0, sp, -8
li t1, 1
slli t1, t1, 2
add t0, t0, t1
sw t2, 0(t0)
li t2, 3
addi t0, sp, -8
li t1, 2
slli t1, t1, 2
add t0, t0, t1
sw t2, 0(t0)
li t2, 4
addi t0, sp, -8
li t1, 3
slli t1, t1, 2
add t0, t0, t1
sw t2, 0(t0)
li t2, 5
addi t0, sp, -8
li t1, 4
slli t1, t1, 2
add t0, t0, t1
sw t2, 0(t0)
li t2, 6
addi t0, sp, -8
li t1, 5
slli t1, t1, 2
add t0, t0, t1
sw t2, 0(t0)
li t2, 7
addi t0, sp, -8
li t1, 6
slli t1, t1, 2
add t0, t0, t1
sw t2, 0(t0)
li t2, 8
addi t0, sp, -8
li t1, 7
slli t1, t1, 2
add t0, t0, t1
sw t2, 0(t0)
addi a0, sp, -44
li a1, 0
li a2, 32
call
li t2, 1
addi t0, sp, -44
li t1, 0
slli t1, t1, 2
add t0, t0, t1
sw t2, 0(t0)
li t2, 2
addi t0, sp, -44
li t1, 1
slli t1, t1, 2
add t0, t0, t1
sw t2, 0(t0)
li t2, 3
addi t0, sp, -44
li t1, 2
slli t1, t1, 2
add t0, t0, t1
sw t2, 0(t0)
li t2, 4
addi t0, sp, -44
li t1, 3
slli t1, t1, 2
add t0, t0, t1
sw t2, 0(t0)
li t2, 5
addi t0, sp, -44
li t1, 4
slli t1, t1, 2
add t0, t0, t1
sw t2, 0(t0)
li t2, 6
addi t0, sp, -44
li t1, 5
slli t1, t1, 2
add t0, t0, t1
sw t2, 0(t0)
li t2, 7
addi t0, sp, -44
li t1, 6
slli t1, t1, 2
add t0, t0, t1
sw t2, 0(t0)
li t2, 8
addi t0, sp, -44
li t1, 7
slli t1, t1, 2
add t0, t0, t1
sw t2, 0(t0)
addi a0, sp, -80
li a1, 0
li a2, 32
call
li t2, 1
addi t0, sp, -80
li t1, 0
slli t1, t1, 2
add t0, t0, t1
sw t2, 0(t0)
li t2, 2
addi t0, sp, -80
li t1, 1
slli t1, t1, 2
add t0, t0, t1
sw t2, 0(t0)
li t2, 3
addi t0, sp, -80
li t1, 2
slli t1, t1, 2
add t0, t0, t1
sw t2, 0(t0)
li t2, 5
addi t0, sp, -80
li t1, 4
slli t1, t1, 2
add t0, t0, t1
sw t2, 0(t0)
li t2, 7
addi t0, sp, -80
li t1, 6
slli t1, t1, 2
add t0, t0, t1
sw t2, 0(t0)
li t2, 8
addi t0, sp, -80
li t1, 7
slli t1, t1, 2
add t0, t0, t1
sw t2, 0(t0)
li t0, 2
li t1, 2
mul t0, t0, t1
sw t0, -112(sp)
li t0, 1
lw t1, -112(sp)
add t0, t0, t1
sw t0, -116(sp)
addi t0, sp, -80
lw t1, -116(sp)
slli t1, t1, 2
add t0, t0, t1
lw t0, 0(t0)
sw t0, -124(sp)
li t0, 2
li t1, 2
mul t0, t0, t1
sw t0, -128(sp)
li t0, 1
lw t1, -128(sp)
add t0, t0, t1
sw t0, -132(sp)
addi t0, sp, -44
lw t1, -132(sp)
slli t1, t1, 2
add t0, t0, t1
lw t0, 0(t0)
sw t0, -140(sp)
addi a0, sp, -108
li a1, 0
li a2, 32
call
lw t2, -124(sp)
addi t0, sp, -108
li t1, 0
slli t1, t1, 2
add t0, t0, t1
sw t2, 0(t0)
lw t2, -140(sp)
addi t0, sp, -108
li t1, 1
slli t1, t1, 2
add t0, t0, t1
sw t2, 0(t0)
li t2, 3
addi t0, sp, -108
li t1, 2
slli t1, t1, 2
add t0, t0, t1
sw t2, 0(t0)
li t2, 4
addi t0, sp, -108
li t1, 3
slli t1, t1, 2
add t0, t0, t1
sw t2, 0(t0)
li t2, 5
addi t0, sp, -108
li t1, 4
slli t1, t1, 2
add t0, t0, t1
sw t2, 0(t0)
li t2, 6
addi t0, sp, -108
li t1, 5
slli t1, t1, 2
add t0, t0, t1
sw t2, 0(t0)
li t2, 7
addi t0, sp, -108
li t1, 6
slli t1, t1, 2
add t0, t0, t1
sw t2, 0(t0)
li t2, 8
addi t0, sp, -108
li t1, 7
slli t1, t1, 2
add t0, t0, t1
sw t2, 0(t0)
li t0, 3
li t1, 2
mul t0, t0, t1
sw t0, -176(sp)
li t0, 1
lw t1, -176(sp)
add t0, t0, t1
sw t0, -180(sp)
addi t0, sp, -108
lw t1, -180(sp)
slli t1, t1, 2
add t0, t0, t1
lw t0, 0(t0)
sw t0, -188(sp)
li t0, 0
li t1, 2
mul t0, t0, t1
sw t0, -192(sp)
li t0, 0
lw t1, -192(sp)
add t0, t0, t1
sw t0, -196(sp)
addi t0, sp, -108
lw t1, -196(sp)
slli t1, t1, 2
add t0, t0, t1
lw t0, 0(t0)
sw t0, -204(sp)
lw t0, -188(sp)
lw t1, -204(sp)
add t0, t0, t1
sw t0, -208(sp)
li t0, 0
li t1, 2
mul t0, t0, t1
sw t0, -212(sp)
li t0, 1
lw t1, -212(sp)
add t0, t0, t1
sw t0, -216(sp)
addi t0, sp, -108
lw t1, -216(sp)
slli t1, t1, 2
add t0, t0, t1
lw t0, 0(t0)
sw t0, -224(sp)
lw t0, -208(sp)
lw t1, -224(sp)
add t0, t0, t1
sw t0, -228(sp)
li t0, 2
li t1, 2
mul t0, t0, t1
sw t0, -232(sp)
li t0, 0
lw t1, -232(sp)
add t0, t0, t1
sw t0, -236(sp)
addi t0, sp, -4
lw t1, -236(sp)
slli t1, t1, 2
add t0, t0, t1
lw t0, 0(t0)
sw t0, -244(sp)
lw t0, -228(sp)
lw t1, -244(sp)
add t0, t0, t1
sw t0, -248(sp)
lw a0, -248(sp)
lw ra, 264(sp)
lw s0, 256(sp)
addi sp, sp, 272
ret
.size main, .-main

@ -59,6 +59,7 @@ int main(int argc, char** argv) {
for (auto& mf : machine_funcs) {
mir::RunRegAlloc(*mf);
mir::RunFrameLowering(*mf);
mir::RunPeepholeOptimization(*mf);
}
mir::PrintAsm(machine_funcs, *out);
}

@ -14,15 +14,19 @@ extern std::vector<mir::GlobalVarInfo> g_globalVars;
namespace mir {
namespace {
const FrameSlot& GetFrameSlot(const MachineFunction& function,
const Operand& operand) {
if (operand.GetKind() != Operand::Kind::FrameIndex) {
throw std::runtime_error(FormatError("mir", "期望 FrameIndex 操作数"));
bool IsFloatPhysReg(PhysReg reg) {
switch (reg) {
case PhysReg::FT0: case PhysReg::FT1: case PhysReg::FT2: case PhysReg::FT3:
case PhysReg::FT4: case PhysReg::FT5: case PhysReg::FT6: case PhysReg::FT7:
case PhysReg::FT8: case PhysReg::FT9: case PhysReg::FT10: case PhysReg::FT11:
case PhysReg::FA0: case PhysReg::FA1: case PhysReg::FA2: case PhysReg::FA3:
case PhysReg::FA4: case PhysReg::FA5: case PhysReg::FA6: case PhysReg::FA7:
case PhysReg::FS0: case PhysReg::FS1:
return true;
default:
return false;
}
return function.GetFrameSlot(operand.GetFrameIndex());
}
// 32位整数加载/存储
void EmitStackLoad(std::ostream& os, PhysReg dst, int offset, PhysReg base = PhysReg::S0) {
if (offset >= -2048 && offset <= 2047) {
@ -94,9 +98,9 @@ void PrintAsmFunction(const MachineFunction& function, std::ostream& os) {
block_names[block_ptr.get()] = block_ptr->GetName();
}
int frame_size = function.GetFrameSize(); // 局部变量区大小(正数)
int local_vars = function.GetLocalVarsSize();
int total_frame = local_vars + 16 ;
//int frame_size = function.GetFrameSize(); // 局部变量区大小(正数)
//int local_vars = function.GetLocalVarsSize();
int total_frame = function.GetFrameSize();
bool prologue_done = false;
for (const auto& block_ptr : function.GetBlocks()) {
@ -111,36 +115,40 @@ void PrintAsmFunction(const MachineFunction& function, std::ostream& os) {
const auto& ops = inst.GetOperands();
// 在入口块的第一条指令前输出序言
// 序言prologue
if (!prologue_done && block.GetName() == "entry") {
// 分配栈帧sp -= total_frame
// 分配栈帧
if (total_frame <= 2047) {
os << " addi sp, sp, -" << total_frame << "\n";
} else {
os << " li t4, -" << total_frame << "\n";
os << " add sp, sp, t4\n";
}
// 保存 ra 和 s0在局部变量区之后即 sp + frame_size 处)
// ra 保存在 sp + frame_size
// s0 保存在 sp + frame_size + 8
int ra_offset = local_vars;
int s0_offset = local_vars + 8;
if (ra_offset <= 2047) {
os << " sd ra, " << ra_offset << "(sp)\n";
} else {
os << " li t4, " << ra_offset << "\n";
os << " add t4, sp, t4\n";
os << " sd ra, 0(t4)\n";
}
if (s0_offset <= 2047) {
os << " sd s0, " << s0_offset << "(sp)\n";
} else {
os << " li t4, " << s0_offset << "\n";
os << " add t4, sp, t4\n";
os << " sd s0, 0(t4)\n";
// 保存 callee-saved 寄存器(包括 ra 和 s0
for (PhysReg reg : function.GetCalleeSavedRegs()) {
int offset = function.GetCalleeSavedOffset(reg);
bool isFloat = (reg >= PhysReg::FT0 && reg <= PhysReg::FT11) ||
(reg >= PhysReg::FA0 && reg <= PhysReg::FA7) ||
(reg == PhysReg::FS0 || reg == PhysReg::FS1);
if (isFloat) {
if (offset <= 2047)
os << " fsw " << PhysRegName(reg) << ", " << offset << "(sp)\n";
else {
os << " li t4, " << offset << "\n";
os << " add t4, sp, t4\n";
os << " fsw " << PhysRegName(reg) << ", 0(t4)\n";
}
} else {
if (offset <= 2047)
os << " sd " << PhysRegName(reg) << ", " << offset << "(sp)\n";
else {
os << " li t4, " << offset << "\n";
os << " add t4, sp, t4\n";
os << " sd " << PhysRegName(reg) << ", 0(t4)\n";
}
}
}
// 建立帧指针
os << " mv s0, sp\n";
prologue_done = true;
}
@ -151,42 +159,42 @@ void PrintAsmFunction(const MachineFunction& function, std::ostream& os) {
break;
case Opcode::MovImm:
os << " li " << PhysRegName(ops.at(0).GetReg()) << ", "
os << " li " << PhysRegName(ops.at(0).GetPhysReg()) << ", "
<< ops.at(1).GetImm() << "\n";
break;
case Opcode::Load: {
if (ops.size() == 2 && ops[1].GetKind() == Operand::Kind::Reg) {
os << " ld " << PhysRegName(ops[0].GetReg()) << ", 0(" << PhysRegName(ops[1].GetReg()) << ")\n";
if (ops.size() == 2 && ops[1].GetKind() == Operand::Kind::PhysReg) {
os << " ld " << PhysRegName(ops[0].GetPhysReg()) << ", 0(" << PhysRegName(ops[1].GetPhysReg()) << ")\n";
} /*else if (ops.size() == 2 && ops[1].GetKind() == Operand::Kind::Imm) {
// 用于调用者 outgoing 存储的占位偏移(将在 Outgoing 中修正)
int offset = ops[1].GetImm(); // 实际偏移 = local_vars + 16 + offset
os << " ld " << PhysRegName(ops[0].GetReg()) << ", " << offset << "(sp)\n";*/
os << " ld " << PhysRegName(ops[0].GetPhysReg()) << ", " << offset << "(sp)\n";*/
else {
int frame_idx = ops[1].GetFrameIndex();
const auto& slot = function.GetFrameSlot(frame_idx);
if (slot.size == 8) EmitStackLoad64(os, ops[0].GetReg(), slot.offset);
else EmitStackLoad(os, ops[0].GetReg(), slot.offset);
if (slot.size == 8) EmitStackLoad64(os, ops[0].GetPhysReg(), slot.offset);
else EmitStackLoad(os, ops[0].GetPhysReg(), slot.offset);
}
break;
}
case Opcode::Store: {
if (ops.size() == 2 && ops[1].GetKind() == Operand::Kind::Reg) {
os << " sd " << PhysRegName(ops[0].GetReg()) << ", 0(" << PhysRegName(ops[1].GetReg()) << ")\n";
if (ops.size() == 2 && ops[1].GetKind() == Operand::Kind::PhysReg) {
os << " sd " << PhysRegName(ops[0].GetPhysReg()) << ", 0(" << PhysRegName(ops[1].GetPhysReg()) << ")\n";
} /*else if (ops.size() == 2 && ops[1].GetKind() == Operand::Kind::Imm) {
int offset = ops[1].GetImm();
// 实际偏移需在 AsmPrinter 中加上 local_vars+16这里简单先直接用 offset动态修正稍复杂
// 临时方案:直接生成 sw t0, offset(sp),但 offset 应为 local_vars+16=?
// 由于 AsmPrinter 中可访问 function.GetLocalVarsSize(),我们计算:
int actual_offset = function.GetLocalVarsSize() + 16 + offset;
if (actual_offset <= 2047) os << " sd " << PhysRegName(ops[0].GetReg()) << ", " << actual_offset << "(sp)\n";
if (actual_offset <= 2047) os << " sd " << PhysRegName(ops[0].GetPhysReg()) << ", " << actual_offset << "(sp)\n";
else { }*/
else {
int frame_idx = ops[1].GetFrameIndex();
const auto& slot = function.GetFrameSlot(frame_idx);
if (slot.size == 8) EmitStackStore64(os, ops[0].GetReg(), slot.offset);
else EmitStackStore(os, ops[0].GetReg(), slot.offset);
if (slot.size == 8) EmitStackStore64(os, ops[0].GetPhysReg(), slot.offset);
else EmitStackStore(os, ops[0].GetPhysReg(), slot.offset);
}
break;
}
@ -200,18 +208,18 @@ void PrintAsmFunction(const MachineFunction& function, std::ostream& os) {
int caller_offset = total_frame + argv_index * 8;
// 加载到 T0
if (caller_offset <= 2047) {
os << " ld " << PhysRegName(ops[0].GetReg()) << ", " << caller_offset << "(s0)\n";
os << " ld " << PhysRegName(ops[0].GetPhysReg()) << ", " << caller_offset << "(s0)\n";
} else {
os << " li t4, " << caller_offset << "\n";
os << " add t4, s0, t4\n";
os << " ld " << PhysRegName(ops[0].GetReg()) << ", 0(t4)\n";
os << " ld " << PhysRegName(ops[0].GetPhysReg()) << ", 0(t4)\n";
}
// 再存入本地槽
const auto& slot = function.GetFrameSlot(dst_slot);
if (slot.size == 8) {
EmitStackStore64(os, ops[0].GetReg(), slot.offset);
EmitStackStore64(os, ops[0].GetPhysReg(), slot.offset);
} else {
EmitStackStore(os, ops[0].GetReg(), slot.offset);
EmitStackStore(os, ops[0].GetPhysReg(), slot.offset);
}
break;
}
@ -223,104 +231,104 @@ void PrintAsmFunction(const MachineFunction& function, std::ostream& os) {
int caller_offset = total_frame + argv_index * 8;
// 使用 s0 保证稳定
if (caller_offset <= 2047) {
os << " flw " << PhysRegName(ops.at(0).GetReg()) << ", " << caller_offset << "(s0)\n";
os << " flw " << PhysRegName(ops.at(0).GetPhysReg()) << ", " << caller_offset << "(s0)\n";
} else {
os << " li t4, " << caller_offset << "\n";
os << " add t4, s0, t4\n";
os << " flw " << PhysRegName(ops.at(0).GetReg()) << ", 0(t4)\n";
os << " flw " << PhysRegName(ops.at(0).GetPhysReg()) << ", 0(t4)\n";
}
const auto& slot = function.GetFrameSlot(dst_slot);
EmitStackStoreFloat(os, ops.at(0).GetReg(), slot.offset);
EmitStackStoreFloat(os, ops.at(0).GetPhysReg(), slot.offset);
break;
}
case Opcode::Add:
os << " add " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< PhysRegName(ops.at(2).GetReg()) << "\n";
os << " add " << PhysRegName(ops.at(0).GetPhysReg()) << ", "
<< PhysRegName(ops.at(1).GetPhysReg()) << ", "
<< PhysRegName(ops.at(2).GetPhysReg()) << "\n";
break;
case Opcode::Addi:
os << " addi " << PhysRegName(ops[0].GetReg()) << ", "
<< PhysRegName(ops[1].GetReg()) << ", "
os << " addi " << PhysRegName(ops[0].GetPhysReg()) << ", "
<< PhysRegName(ops[1].GetPhysReg()) << ", "
<< ops[2].GetImm() << "\n";
break;
case Opcode::Sub:
os << " sub " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< PhysRegName(ops.at(2).GetReg()) << "\n";
os << " sub " << PhysRegName(ops.at(0).GetPhysReg()) << ", "
<< PhysRegName(ops.at(1).GetPhysReg()) << ", "
<< PhysRegName(ops.at(2).GetPhysReg()) << "\n";
break;
case Opcode::Mul: {
if (ops.size() > 2 && ops.at(2).GetKind() == Operand::Kind::Imm) {
os << " mul " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
os << " mul " << PhysRegName(ops.at(0).GetPhysReg()) << ", "
<< PhysRegName(ops.at(1).GetPhysReg()) << ", "
<< ops.at(2).GetImm() << "\n";
} else {
os << " mul " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< PhysRegName(ops.at(2).GetReg()) << "\n";
os << " mul " << PhysRegName(ops.at(0).GetPhysReg()) << ", "
<< PhysRegName(ops.at(1).GetPhysReg()) << ", "
<< PhysRegName(ops.at(2).GetPhysReg()) << "\n";
}
break;
}
case Opcode::Div:
os << " div " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< PhysRegName(ops.at(2).GetReg()) << "\n";
os << " div " << PhysRegName(ops.at(0).GetPhysReg()) << ", "
<< PhysRegName(ops.at(1).GetPhysReg()) << ", "
<< PhysRegName(ops.at(2).GetPhysReg()) << "\n";
break;
case Opcode::Rem:
os << " rem " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< PhysRegName(ops.at(2).GetReg()) << "\n";
os << " rem " << PhysRegName(ops.at(0).GetPhysReg()) << ", "
<< PhysRegName(ops.at(1).GetPhysReg()) << ", "
<< PhysRegName(ops.at(2).GetPhysReg()) << "\n";
break;
case Opcode::Slt:
os << " slt " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< PhysRegName(ops.at(2).GetReg()) << "\n";
os << " slt " << PhysRegName(ops.at(0).GetPhysReg()) << ", "
<< PhysRegName(ops.at(1).GetPhysReg()) << ", "
<< PhysRegName(ops.at(2).GetPhysReg()) << "\n";
break;
case Opcode::Slti:
os << " slti " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
os << " slti " << PhysRegName(ops.at(0).GetPhysReg()) << ", "
<< PhysRegName(ops.at(1).GetPhysReg()) << ", "
<< ops.at(2).GetImm() << "\n";
break;
case Opcode::Sltu:
os << " sltu " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
<< PhysRegName(ops.at(2).GetReg()) << "\n";
os << " sltu " << PhysRegName(ops.at(0).GetPhysReg()) << ", "
<< PhysRegName(ops.at(1).GetPhysReg()) << ", "
<< PhysRegName(ops.at(2).GetPhysReg()) << "\n";
break;
case Opcode::Sltiu:
os << " sltiu " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
os << " sltiu " << PhysRegName(ops.at(0).GetPhysReg()) << ", "
<< PhysRegName(ops.at(1).GetPhysReg()) << ", "
<< ops.at(2).GetImm() << "\n";
break;
case Opcode::Xori:
os << " xori " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
os << " xori " << PhysRegName(ops.at(0).GetPhysReg()) << ", "
<< PhysRegName(ops.at(1).GetPhysReg()) << ", "
<< ops.at(2).GetImm() << "\n";
break;
case Opcode::LoadGlobalAddr: {
std::string global_name = ops.at(1).GetGlobalName();
os << " la " << PhysRegName(ops.at(0).GetReg()) << ", " << global_name << "\n";
os << " la " << PhysRegName(ops.at(0).GetPhysReg()) << ", " << global_name << "\n";
break;
}
case Opcode::LoadGlobal:
// 全局变量加载 - 使用 lw32位
os << " lw " << PhysRegName(ops.at(0).GetReg()) << ", 0("
<< PhysRegName(ops.at(1).GetReg()) << ")\n";
os << " lw " << PhysRegName(ops.at(0).GetPhysReg()) << ", 0("
<< PhysRegName(ops.at(1).GetPhysReg()) << ")\n";
break;
case Opcode::StoreGlobal: {
std::string global_name = ops.at(1).GetGlobalName();
os << " la t1, " << global_name << "\n";
os << " sw " << PhysRegName(ops.at(0).GetReg()) << ", 0(t1)\n";
os << " sw " << PhysRegName(ops.at(0).GetPhysReg()) << ", 0(t1)\n";
break;
}
@ -329,12 +337,12 @@ void PrintAsmFunction(const MachineFunction& function, std::ostream& os) {
case Opcode::LoadIndirect:
// 间接加载 - 使用 lw32位
os << " lw " << PhysRegName(ops.at(0).GetReg()) << ", 0("
<< PhysRegName(ops.at(1).GetReg()) << ")\n";
os << " lw " << PhysRegName(ops.at(0).GetPhysReg()) << ", 0("
<< PhysRegName(ops.at(1).GetPhysReg()) << ")\n";
break;
case Opcode::LoadIndirectFloat:
os << " flw " << PhysRegName(ops[0].GetReg()) << ", 0("
<< PhysRegName(ops[1].GetReg()) << ")\n";
os << " flw " << PhysRegName(ops[0].GetPhysReg()) << ", 0("
<< PhysRegName(ops[1].GetPhysReg()) << ")\n";
break;
case Opcode::Call: {
std::string func_name = "memset"; // 默认值
@ -350,62 +358,58 @@ void PrintAsmFunction(const MachineFunction& function, std::ostream& os) {
const auto& slot = function.GetFrameSlot(frame_idx);
// 计算地址64 位offset 是正数
if (slot.offset <= 2047) {
os << " addi " << PhysRegName(ops.at(0).GetReg()) << ", s0, " << slot.offset << "\n";
os << " addi " << PhysRegName(ops.at(0).GetPhysReg()) << ", s0, " << slot.offset << "\n";
} else {
os << " li " << PhysRegName(ops.at(0).GetReg()) << ", " << slot.offset << "\n";
os << " add " << PhysRegName(ops.at(0).GetReg()) << ", s0, "
<< PhysRegName(ops.at(0).GetReg()) << "\n";
os << " li " << PhysRegName(ops.at(0).GetPhysReg()) << ", " << slot.offset << "\n";
os << " add " << PhysRegName(ops.at(0).GetPhysReg()) << ", s0, "
<< PhysRegName(ops.at(0).GetPhysReg()) << "\n";
}
break;
}
case Opcode::Slli:
os << " slli " << PhysRegName(ops.at(0).GetReg()) << ", "
<< PhysRegName(ops.at(1).GetReg()) << ", "
os << " slli " << PhysRegName(ops.at(0).GetPhysReg()) << ", "
<< PhysRegName(ops.at(1).GetPhysReg()) << ", "
<< ops.at(2).GetImm() << "\n";
break;
case Opcode::StoreIndirect:
// 间接存储 - 使用 sw32位
os << " sw " << PhysRegName(ops.at(0).GetReg()) << ", 0("
<< PhysRegName(ops.at(1).GetReg()) << ")\n";
os << " sw " << PhysRegName(ops.at(0).GetPhysReg()) << ", 0("
<< PhysRegName(ops.at(1).GetPhysReg()) << ")\n";
break;
case Opcode::StoreIndirectFloat:
os << " fsw " << PhysRegName(ops[0].GetReg()) << ", 0("
<< PhysRegName(ops[1].GetReg()) << ")\n";
break;
case Opcode::Ret:{
// 恢复 ra 和 s0
int ra_offset = local_vars;
int s0_offset = local_vars + 8;
if (ra_offset <= 2047) {
os << " ld ra, " << ra_offset << "(s0)\n";
} else {
os << " li t3, " << ra_offset << "\n";
os << " add t3, s0, t3\n";
os << " ld ra, 0(t3)\n";
}
// 恢复 sp
if (total_frame <= 2047) {
os << " addi sp, s0, " << total_frame << "\n";
} else {
os << " li t3, " << total_frame << "\n";
os << " add sp, s0, t3\n";
}
if (s0_offset <= 2047) {
os << " ld s0, " << s0_offset << "(s0)\n";
} else {
os << " li t3, " << s0_offset << "\n";
os << " add t3, s0, t3\n";
os << " ld s0, 0(t3)\n";
}
os << " ret\n";
os << " fsw " << PhysRegName(ops[0].GetPhysReg()) << ", 0("
<< PhysRegName(ops[1].GetPhysReg()) << ")\n";
break;
case Opcode::Ret: {
int total_frame = function.GetFrameSize();
// 1. 恢复除 ra 和 s0 以外的 callee-saved 寄存器
for (PhysReg reg : function.GetCalleeSavedRegs()) {
if (reg == PhysReg::RA || reg == PhysReg::S0) continue;
int offset = function.GetCalleeSavedOffset(reg);
bool isFloat = IsFloatPhysReg(reg);
if (isFloat) {
EmitStackLoadFloat(os, reg, offset, PhysReg::S0);
} else {
EmitStackLoad64(os, reg, offset, PhysReg::S0);
}
}
// 2. 恢复 ra
int ra_offset = function.GetCalleeSavedOffset(PhysReg::RA);
EmitStackLoad64(os, PhysReg::RA, ra_offset, PhysReg::S0);
// 3. 恢复 sp
if (total_frame <= 2047) {
os << " addi sp, s0, " << total_frame << "\n";
} else {
os << " li t3, " << total_frame << "\n";
os << " add sp, s0, t3\n";
}
// 4. 恢复 s0
int s0_offset = function.GetCalleeSavedOffset(PhysReg::S0);
EmitStackLoad64(os, PhysReg::S0, s0_offset, PhysReg::S0);
os << " ret\n";
break;
}
case Opcode::Br: {
@ -426,7 +430,7 @@ void PrintAsmFunction(const MachineFunction& function, std::ostream& os) {
// 生成一个唯一的本地标签作为跳板
static int condbr_id = 0;
std::string temp_label = ".L_condbr_" + std::to_string(condbr_id++);
os << " bnez " << PhysRegName(ops[0].GetReg()) << ", " << temp_label << "\n";
os << " bnez " << PhysRegName(ops[0].GetPhysReg()) << ", " << temp_label << "\n";
os << " j " << false_it->second << "\n";
os << temp_label << ":\n";
os << " j " << true_it->second << "\n";
@ -435,91 +439,91 @@ void PrintAsmFunction(const MachineFunction& function, std::ostream& os) {
// 浮点运算
case Opcode::FAdd:
os << " fadd.s " << PhysRegName(ops[0].GetReg()) << ", "
<< PhysRegName(ops[1].GetReg()) << ", "
<< PhysRegName(ops[2].GetReg()) << "\n";
os << " fadd.s " << PhysRegName(ops[0].GetPhysReg()) << ", "
<< PhysRegName(ops[1].GetPhysReg()) << ", "
<< PhysRegName(ops[2].GetPhysReg()) << "\n";
break;
case Opcode::FSub:
os << " fsub.s " << PhysRegName(ops[0].GetReg()) << ", "
<< PhysRegName(ops[1].GetReg()) << ", "
<< PhysRegName(ops[2].GetReg()) << "\n";
os << " fsub.s " << PhysRegName(ops[0].GetPhysReg()) << ", "
<< PhysRegName(ops[1].GetPhysReg()) << ", "
<< PhysRegName(ops[2].GetPhysReg()) << "\n";
break;
case Opcode::FMul:
os << " fmul.s " << PhysRegName(ops[0].GetReg()) << ", "
<< PhysRegName(ops[1].GetReg()) << ", "
<< PhysRegName(ops[2].GetReg()) << "\n";
os << " fmul.s " << PhysRegName(ops[0].GetPhysReg()) << ", "
<< PhysRegName(ops[1].GetPhysReg()) << ", "
<< PhysRegName(ops[2].GetPhysReg()) << "\n";
break;
case Opcode::FDiv:
os << " fdiv.s " << PhysRegName(ops[0].GetReg()) << ", "
<< PhysRegName(ops[1].GetReg()) << ", "
<< PhysRegName(ops[2].GetReg()) << "\n";
os << " fdiv.s " << PhysRegName(ops[0].GetPhysReg()) << ", "
<< PhysRegName(ops[1].GetPhysReg()) << ", "
<< PhysRegName(ops[2].GetPhysReg()) << "\n";
break;
case Opcode::FEq:
os << " feq.s " << PhysRegName(ops[0].GetReg()) << ", "
<< PhysRegName(ops[1].GetReg()) << ", "
<< PhysRegName(ops[2].GetReg()) << "\n";
os << " feq.s " << PhysRegName(ops[0].GetPhysReg()) << ", "
<< PhysRegName(ops[1].GetPhysReg()) << ", "
<< PhysRegName(ops[2].GetPhysReg()) << "\n";
break;
case Opcode::FLt:
os << " flt.s " << PhysRegName(ops[0].GetReg()) << ", "
<< PhysRegName(ops[1].GetReg()) << ", "
<< PhysRegName(ops[2].GetReg()) << "\n";
os << " flt.s " << PhysRegName(ops[0].GetPhysReg()) << ", "
<< PhysRegName(ops[1].GetPhysReg()) << ", "
<< PhysRegName(ops[2].GetPhysReg()) << "\n";
break;
case Opcode::FLe:
os << " fle.s " << PhysRegName(ops[0].GetReg()) << ", "
<< PhysRegName(ops[1].GetReg()) << ", "
<< PhysRegName(ops[2].GetReg()) << "\n";
os << " fle.s " << PhysRegName(ops[0].GetPhysReg()) << ", "
<< PhysRegName(ops[1].GetPhysReg()) << ", "
<< PhysRegName(ops[2].GetPhysReg()) << "\n";
break;
case Opcode::FMov:
os << " fmv.s " << PhysRegName(ops[0].GetReg()) << ", "
<< PhysRegName(ops[1].GetReg()) << "\n";
os << " fmv.s " << PhysRegName(ops[0].GetPhysReg()) << ", "
<< PhysRegName(ops[1].GetPhysReg()) << "\n";
break;
case Opcode::FMovWX:
os << " fmv.w.x " << PhysRegName(ops[0].GetReg()) << ", "
<< PhysRegName(ops[1].GetReg()) << "\n";
os << " fmv.w.x " << PhysRegName(ops[0].GetPhysReg()) << ", "
<< PhysRegName(ops[1].GetPhysReg()) << "\n";
break;
case Opcode::FMovXW:
os << " fmv.x.w " << PhysRegName(ops[0].GetReg()) << ", "
<< PhysRegName(ops[1].GetReg()) << "\n";
os << " fmv.x.w " << PhysRegName(ops[0].GetPhysReg()) << ", "
<< PhysRegName(ops[1].GetPhysReg()) << "\n";
break;
case Opcode::SIToFP:
os << " fcvt.s.w " << PhysRegName(ops[0].GetReg()) << ", "
<< PhysRegName(ops[1].GetReg()) << "\n";
os << " fcvt.s.w " << PhysRegName(ops[0].GetPhysReg()) << ", "
<< PhysRegName(ops[1].GetPhysReg()) << "\n";
break;
case Opcode::FPToSI:
os << " fcvt.w.s " << PhysRegName(ops[0].GetReg()) << ", "
<< PhysRegName(ops[1].GetReg()) << ", rtz\n";
os << " fcvt.w.s " << PhysRegName(ops[0].GetPhysReg()) << ", "
<< PhysRegName(ops[1].GetPhysReg()) << ", rtz\n";
break;
case Opcode::LoadFloat:
if (ops.size() == 2 && ops[1].GetKind() == Operand::Kind::Reg) {
os << " flw " << PhysRegName(ops[0].GetReg()) << ", 0("
<< PhysRegName(ops[1].GetReg()) << ")\n";
if (ops.size() == 2 && ops[1].GetKind() == Operand::Kind::PhysReg) {
os << " flw " << PhysRegName(ops[0].GetPhysReg()) << ", 0("
<< PhysRegName(ops[1].GetPhysReg()) << ")\n";
} else {
int frame_idx = ops[1].GetFrameIndex();
const auto& slot = function.GetFrameSlot(frame_idx);
EmitStackLoadFloat(os, ops[0].GetReg(), slot.offset);
EmitStackLoadFloat(os, ops[0].GetPhysReg(), slot.offset);
}
break;
case Opcode::StoreFloat:
if (ops.size() == 2 && ops[1].GetKind() == Operand::Kind::Reg) {
os << " fsw " << PhysRegName(ops[0].GetReg()) << ", 0("
<< PhysRegName(ops[1].GetReg()) << ")\n";
if (ops.size() == 2 && ops[1].GetKind() == Operand::Kind::PhysReg) {
os << " fsw " << PhysRegName(ops[0].GetPhysReg()) << ", 0("
<< PhysRegName(ops[1].GetPhysReg()) << ")\n";
} else {
int frame_idx = ops[1].GetFrameIndex();
const auto& slot = function.GetFrameSlot(frame_idx);
EmitStackStoreFloat(os, ops[0].GetReg(), slot.offset);
EmitStackStoreFloat(os, ops[0].GetPhysReg(), slot.offset);
}
break;

@ -8,6 +8,7 @@ add_library(mir_core STATIC
RegAlloc.cpp
FrameLowering.cpp
AsmPrinter.cpp
Peephole.cpp
)
target_link_libraries(mir_core PUBLIC

@ -1,5 +1,5 @@
#include "mir/MIR.h"
#include <algorithm>
#include <stdexcept>
#include <vector>
@ -15,35 +15,58 @@ int AlignTo(int value, int align) {
} // namespace
void RunFrameLowering(MachineFunction& function) {
auto& saved = const_cast<std::vector<PhysReg>&>(function.GetCalleeSavedRegs());
auto has_reg = [&](PhysReg r) {
return std::find(saved.begin(), saved.end(), r) != saved.end();
};
if (!has_reg(PhysReg::RA)) saved.push_back(PhysReg::RA);
if (!has_reg(PhysReg::S0)) saved.push_back(PhysReg::S0);
int cursor = 0;
const auto& slots = function.GetFrameSlots();
std::vector<FrameSlot> newSlots;
// 为每个栈槽分配偏移
for (const auto& slot : slots) {
// 1. 为每个现有栈槽分配偏移(包括局部变量、溢出槽)
for (const auto& slot : function.GetFrameSlots()) {
int align = slot.size;
cursor = AlignTo(cursor, align);
function.GetFrameSlot(slot.index).offset = cursor;
FrameSlot newSlot = slot;
newSlot.offset = cursor;
newSlots.push_back(newSlot);
cursor += slot.size;
}
// 局部变量区按 16 字节对齐
int local_vars_size = AlignTo(cursor, 16);
function.SetLocalVarsSize(local_vars_size);
// 总帧大小 = 局部变量区 + 16保存 ra 和 s0
function.SetFrameSize(local_vars_size + 16);
// 插入 Prologue/Epilogue 占位符(原逻辑)
auto& insts = function.GetEntry()->GetInstructions();
std::vector<MachineInstr> lowered;
lowered.emplace_back(Opcode::Prologue);
for (const auto& inst : insts) {
if (inst.GetOpcode() == Opcode::Ret) {
lowered.emplace_back(Opcode::Epilogue);
}
lowered.push_back(inst);
// 2. 为 callee-saved 寄存器分配空间(先计算需要保存的寄存器)
const auto& savedRegs = function.GetCalleeSavedRegs();
int savedSize = 0;
for (PhysReg reg : savedRegs) {
bool isFloat = (reg >= PhysReg::FT0 && reg <= PhysReg::FT11) ||
(reg >= PhysReg::FA0 && reg <= PhysReg::FA7) ||
(reg == PhysReg::FS0 || reg == PhysReg::FS1);
savedSize += isFloat ? 4 : 8;
}
// 3. 总帧大小 = 局部变量区 + callee-saved 区 + 对齐
int calleeSavedArea = AlignTo(savedSize, 8);
cursor = AlignTo(cursor, 16); // 局部变量区对齐
int localVarsSize = cursor;
function.SetLocalVarsSize(localVarsSize);
int totalFrame = localVarsSize + calleeSavedArea;
function.SetFrameSize(totalFrame);
// 4. 记录每个 callee-saved 寄存器的偏移(相对于 sp
int offset = localVarsSize;
for (PhysReg reg : savedRegs) {
bool isFloat = (reg >= PhysReg::FT0 && reg <= PhysReg::FT11) ||
(reg >= PhysReg::FA0 && reg <= PhysReg::FA7) ||
(reg == PhysReg::FS0 || reg == PhysReg::FS1);
int size = isFloat ? 4 : 8;
function.SetCalleeSavedOffset(reg, offset);
offset += size;
}
const_cast<std::vector<FrameSlot>&>(function.GetFrameSlots()).clear();
for (auto& slot : newSlots) {
const_cast<std::vector<FrameSlot>&>(function.GetFrameSlots()).push_back(slot);
}
insts = std::move(lowered);
}
} // namespace mir

@ -13,4 +13,11 @@ MachineInstr& MachineBasicBlock::Append(Opcode opcode,
return instructions_.back();
}
MachineInstr& MachineBasicBlock::InsertBefore(std::vector<MachineInstr>::iterator pos,
Opcode opcode,
std::initializer_list<Operand> operands) {
auto it = instructions_.insert(pos, MachineInstr(opcode, std::vector<Operand>(operands)));
return *it;
}
} // namespace mir

@ -2,6 +2,7 @@
#include <stdexcept>
#include <utility>
#include <algorithm>
#include "utils/Log.h"
@ -39,4 +40,85 @@ const FrameSlot& MachineFunction::GetFrameSlot(int index) const {
return frame_slots_[index];
}
// 虚拟寄存器管理
int MachineFunction::CreateVirtReg(bool is_float) {
int reg = next_virt_reg_++;
virt_reg_types_.push_back(is_float);
virt_to_phys_.push_back(PhysReg::ZERO);
virt_to_spill_slot_.push_back(-1);
return reg;
}
bool MachineFunction::IsVirtRegFloat(int reg) const {
if (reg < 0 || reg >= static_cast<int>(virt_reg_types_.size())) {
throw std::runtime_error(FormatError("mir", "非法 VirtReg"));
}
return virt_reg_types_[reg];
}
// 物理寄存器分配结果
void MachineFunction::SetPhysRegForVirt(int virt_reg, PhysReg phys_reg) {
if (virt_reg < 0 || virt_reg >= static_cast<int>(virt_to_phys_.size())) {
throw std::runtime_error(FormatError("mir", "非法 VirtReg"));
}
virt_to_phys_[virt_reg] = phys_reg;
}
PhysReg MachineFunction::GetPhysRegForVirt(int virt_reg) const {
if (virt_reg < 0 || virt_reg >= static_cast<int>(virt_to_phys_.size())) {
throw std::runtime_error(FormatError("mir", "非法 VirtReg"));
}
return virt_to_phys_[virt_reg];
}
bool MachineFunction::HasPhysRegForVirt(int virt_reg) const {
if (virt_reg < 0 || virt_reg >= static_cast<int>(virt_to_phys_.size())) {
return false;
}
return virt_to_phys_[virt_reg] != PhysReg::ZERO;
}
// 溢出槽管理
int MachineFunction::CreateSpillSlot(bool is_float) {
return CreateFrameIndex(is_float ? 8 : 4);
}
int MachineFunction::GetSpillSlot(int virt_reg) const {
if (virt_reg < 0 || virt_reg >= static_cast<int>(virt_to_spill_slot_.size())) {
throw std::runtime_error(FormatError("mir", "非法 VirtReg"));
}
return virt_to_spill_slot_[virt_reg];
}
bool MachineFunction::HasSpillSlot(int virt_reg) const {
if (virt_reg < 0 || virt_reg >= static_cast<int>(virt_to_spill_slot_.size())) {
return false;
}
return virt_to_spill_slot_[virt_reg] != -1;
}
void MachineFunction::SetSpillSlot(int virt_reg, int slot) {
if (virt_reg < 0 || virt_reg >= static_cast<int>(virt_to_spill_slot_.size())) {
throw std::runtime_error(FormatError("mir", "非法 VirtReg"));
}
virt_to_spill_slot_[virt_reg] = slot;
}
// callee-saved 寄存器
void MachineFunction::AddCalleeSavedReg(PhysReg reg) {
if (std::find(callee_saved_regs_.begin(), callee_saved_regs_.end(), reg) == callee_saved_regs_.end()) {
callee_saved_regs_.push_back(reg);
}
}
void MachineFunction::SetCalleeSavedOffset(PhysReg reg, int offset) {
callee_saved_offsets_[reg] = offset;
}
int MachineFunction::GetCalleeSavedOffset(PhysReg reg) const {
auto it = callee_saved_offsets_.find(reg);
if (it == callee_saved_offsets_.end()) {
throw std::runtime_error(FormatError("mir", "找不到 callee-saved 寄存器的偏移"));
}
return it->second;
}
} // namespace mir

@ -1,6 +1,7 @@
#include "mir/MIR.h"
#include <utility>
#include <stdexcept>
namespace mir {
@ -8,11 +9,16 @@ Operand::Operand(Kind kind, PhysReg reg, int imm)
: kind_(kind), reg_(reg), imm_(imm) {}
Operand::Operand(Kind kind, PhysReg reg, int64_t imm64)
: kind_(kind), reg_(PhysReg::ZERO), imm_(0), imm64_(imm64) {}
// 新增构造函数
Operand::Operand(Kind kind, PhysReg reg, int imm, const std::string& name)
: kind_(kind), reg_(reg), imm_(imm), global_name_(name) {}
Operand::Operand(Kind kind, int virt_reg, bool is_float)
: kind_(kind), reg_(PhysReg::ZERO), imm_(virt_reg), is_float_(is_float) {}
Operand Operand::Reg(PhysReg reg) { return Operand(Kind::Reg, reg, 0); }
Operand Operand::Reg(PhysReg reg) { return Operand(Kind::PhysReg, reg, 0); }
Operand Operand::VirtReg(int index, bool is_float) {
return Operand(Kind::VirtReg, index, is_float);
}
Operand Operand::Imm(int value) {
return Operand(Kind::Imm, PhysReg::ZERO, value);
@ -24,7 +30,6 @@ Operand Operand::FrameIndex(int index) {
return Operand(Kind::FrameIndex, PhysReg::ZERO, index);
}
// 新增
Operand Operand::Global(const std::string& name) {
return Operand(Kind::Global, PhysReg::ZERO, 0, name);
}

@ -0,0 +1,65 @@
// Peephole.cpp - 保守优化版(仅启用安全规则)
#include "mir/MIR.h"
#include <algorithm>
#include <vector>
#include <cstdint>
namespace mir {
namespace {
// 判断两个地址操作数是否指向同一内存位置(考虑栈槽和物理寄存器)
bool SameAddr(const Operand& a, const Operand& b) {
if (a.GetKind() != b.GetKind()) return false;
if (a.GetKind() == Operand::Kind::PhysReg)
return a.GetPhysReg() == b.GetPhysReg();
if (a.GetKind() == Operand::Kind::FrameIndex)
return a.GetFrameIndex() == b.GetFrameIndex();
return false;
}
// 规则2消除死存储连续两次存储到同一地址删除第一次
// 例如: sw t0, addr; sw t1, addr -> 仅保留第二次存储
bool EliminateDeadStore(std::vector<MachineInstr>& instrs) {
bool changed = false;
for (size_t i = 0; i + 1 < instrs.size(); ) {
auto& inst1 = instrs[i];
auto& inst2 = instrs[i+1];
Opcode op1 = inst1.GetOpcode();
Opcode op2 = inst2.GetOpcode();
bool is_store1 = (op1 == Opcode::Store || op1 == Opcode::StoreFloat);
bool is_store2 = (op2 == Opcode::Store || op2 == Opcode::StoreFloat);
if (is_store1 && is_store2) {
const auto& ops1 = inst1.GetOperands();
const auto& ops2 = inst2.GetOperands();
// 两个存储操作数至少都有两个操作数 [value, addr]
if (ops1.size() >= 2 && ops2.size() >= 2 &&
SameAddr(ops1[1], ops2[1])) {
// 第一次存储被第二次覆盖,删除第一次
instrs.erase(instrs.begin() + i);
changed = true;
continue; // 重新检查当前位置
}
}
++i;
}
return changed;
}
} // anonymous namespace
void RunPeepholeOptimization(MachineFunction& function) {
bool overallChanged = true;
while (overallChanged) {
overallChanged = false;
for (auto& blockPtr : function.GetBlocks()) {
auto& instrs = blockPtr->GetInstructions();
bool changed = false;
// 启用死存储消除
changed |= EliminateDeadStore(instrs);
// changed |= EliminateRedundantStoreLoad(instrs);
if (changed)
overallChanged = true;
}
}
}
} // namespace mir

@ -1,91 +1,344 @@
// RegAlloc.cpp - 修复版
#include "mir/MIR.h"
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stdexcept>
#include "utils/Log.h"
namespace mir {
namespace {
bool IsAllowedReg(PhysReg reg) {
switch (reg) {
// 临时寄存器
case PhysReg::T0:
case PhysReg::T1:
case PhysReg::T2:
case PhysReg::T3:
case PhysReg::T4:
case PhysReg::T5:
case PhysReg::T6:
// 参数/返回值寄存器
case PhysReg::A0:
case PhysReg::A1:
case PhysReg::A2:
case PhysReg::A3:
case PhysReg::A4:
case PhysReg::A5:
case PhysReg::A6:
case PhysReg::A7:
// 保存寄存器
case PhysReg::S0:
case PhysReg::S1:
case PhysReg::S2:
case PhysReg::S3:
case PhysReg::S4:
case PhysReg::S5:
case PhysReg::S6:
case PhysReg::S7:
case PhysReg::S8:
case PhysReg::S9:
case PhysReg::S10:
case PhysReg::S11:
// 特殊寄存器
case PhysReg::ZERO:
case PhysReg::RA:
case PhysReg::SP:
case PhysReg::GP:
case PhysReg::TP:
case PhysReg::FT0:
case PhysReg::FT1:
case PhysReg::FT2:
case PhysReg::FT3:
case PhysReg::FT4:
case PhysReg::FT5:
case PhysReg::FT6:
case PhysReg::FT7:
case PhysReg::FT8:
case PhysReg::FT9:
case PhysReg::FT10:
case PhysReg::FT11:
// 浮点保存寄存器
case PhysReg::FS0:
case PhysReg::FS1:
// 浮点参数寄存器
case PhysReg::FA0:
case PhysReg::FA1:
case PhysReg::FA2:
case PhysReg::FA3:
case PhysReg::FA4:
case PhysReg::FA5:
case PhysReg::FA6:
case PhysReg::FA7:
return true;
}
return false;
// ---------- 物理寄存器集合(排除临时寄存器)----------
std::vector<PhysReg> GetAllocatableIntRegs() {
return {
PhysReg::T0, PhysReg::T1, PhysReg::T2, PhysReg::T3,
// T4, T5 保留为临时寄存器,不分配
PhysReg::T6,
PhysReg::A0, PhysReg::A1, PhysReg::A2, PhysReg::A3,
PhysReg::A4, PhysReg::A5, PhysReg::A6, PhysReg::A7,
PhysReg::S1, PhysReg::S2, PhysReg::S3, PhysReg::S4,
PhysReg::S5, PhysReg::S6, PhysReg::S7, PhysReg::S8,
PhysReg::S9, PhysReg::S10, PhysReg::S11
};
}
} // namespace
std::vector<PhysReg> GetAllocatableFloatRegs() {
return {
PhysReg::FT0, PhysReg::FT1, PhysReg::FT2, PhysReg::FT3,
PhysReg::FT4, PhysReg::FT5, PhysReg::FT6, PhysReg::FT7,
// FT8, FT9 保留为临时寄存器
PhysReg::FT10, PhysReg::FT11,
PhysReg::FA0, PhysReg::FA1, PhysReg::FA2, PhysReg::FA3,
PhysReg::FA4, PhysReg::FA5, PhysReg::FA6, PhysReg::FA7,
PhysReg::FS0, PhysReg::FS1
};
}
void RunRegAlloc(MachineFunction& function) {
// 修复GetEntry() 返回指针,使用 ->
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", "寄存器分配失败"));
}
bool IsCallerSaved(PhysReg reg) {
if (reg >= PhysReg::T0 && reg <= PhysReg::T6) return true;
if (reg >= PhysReg::A0 && reg <= PhysReg::A7) return true;
if (reg >= PhysReg::FT0 && reg <= PhysReg::FT11) return true;
if (reg >= PhysReg::FA0 && reg <= PhysReg::FA7) return true;
return false;
}
// 临时寄存器(分配时排除)
const PhysReg kIntTempLoad = PhysReg::T4; // 整数加载临时
const PhysReg kIntTempStore = PhysReg::T5; // 整数存储临时
const PhysReg kFloatTempLoad = PhysReg::FT8; // 浮点加载临时
const PhysReg kFloatTempStore = PhysReg::FT9; // 浮点存储临时
// 活跃区间(扩展,预计算跨调用标志)
struct LiveInterval {
int vreg;
int start;
int end;
bool is_float;
bool crosses_call;
LiveInterval(int r, int s, int e, bool f, bool cc = false)
: vreg(r), start(s), end(e), is_float(f), crosses_call(cc) {}
bool operator<(const LiveInterval& other) const { return start < other.start; }
};
// 收集指令位置及Call信息
struct InstrInfo {
MachineInstr* instr;
int pos;
bool is_call;
};
std::vector<InstrInfo> CollectInstructions(MachineFunction& func) {
std::vector<InstrInfo> result;
int pos = 0;
for (auto& block : func.GetBlocks()) {
for (auto& instr : block->GetInstructions()) {
result.push_back({&instr, pos++, instr.GetOpcode() == Opcode::Call});
}
}
return result;
}
// 计算活跃区间同时记录是否跨越Call
void ComputeLiveIntervals(MachineFunction& func,
std::vector<LiveInterval>& intervals,
std::vector<int>& call_positions) {
std::map<int, int> first_def, last_use;
auto instrs = CollectInstructions(func);
call_positions.clear();
for (const auto& info : instrs) {
if (info.is_call)
call_positions.push_back(info.pos);
}
for (const auto& info : instrs) {
const auto& ops = info.instr->GetOperands();
// 定义点:通常第一个操作数为写(简化处理)
if (!ops.empty() && ops[0].GetKind() == Operand::Kind::VirtReg) {
int vreg = ops[0].GetVirtReg();
if (first_def.find(vreg) == first_def.end())
first_def[vreg] = info.pos;
}
// 使用点
for (size_t i = 0; i < ops.size(); ++i) {
if (ops[i].GetKind() == Operand::Kind::VirtReg) {
int vreg = ops[i].GetVirtReg();
last_use[vreg] = info.pos;
}
}
}
// 构建区间并判断是否跨越Call
for (int vreg = 0; vreg < func.GetNumVirtRegs(); ++vreg) {
int s = 0, e = 0;
auto def_it = first_def.find(vreg);
auto use_it = last_use.find(vreg);
if (def_it == first_def.end()) {
s = 0;
e = (use_it != last_use.end()) ? use_it->second : 0;
} else {
s = def_it->second;
e = (use_it != last_use.end()) ? use_it->second : s;
}
bool crosses = false;
for (int pos : call_positions) {
if (pos > s && pos < e) { crosses = true; break; }
}
intervals.emplace_back(vreg, s, e, func.IsVirtRegFloat(vreg), crosses);
}
}
std::sort(intervals.begin(), intervals.end());
}
// 线性扫描分配(分离整数/浮点活跃列表)
void LinearScanRegisterAllocation(MachineFunction& func,
const std::vector<LiveInterval>& intervals,
const std::vector<int>& call_positions) {
auto all_int = GetAllocatableIntRegs();
auto all_float = GetAllocatableFloatRegs();
std::vector<PhysReg> free_int = all_int;
std::vector<PhysReg> free_float = all_float;
struct ActiveInterval {
LiveInterval interval;
PhysReg reg;
ActiveInterval(LiveInterval i, PhysReg r) : interval(i), reg(r) {}
};
std::vector<ActiveInterval> active_int, active_float;
for (const auto& interval : intervals) {
auto& active_list = interval.is_float ? active_float : active_int;
auto& free_list = interval.is_float ? free_float : free_int;
// 1. 移除已过期的活跃区间
auto it = active_list.begin();
while (it != active_list.end()) {
if (it->interval.end < interval.start) {
free_list.push_back(it->reg);
it = active_list.erase(it);
} else {
++it;
}
}
// 2. 确定可用寄存器(考虑跨调用约束)
std::vector<PhysReg> eligible;
for (PhysReg r : free_list) {
if (interval.crosses_call && IsCallerSaved(r))
continue;
eligible.push_back(r);
}
if (!eligible.empty()) {
// 分配第一个可用寄存器
PhysReg reg = eligible.front();
free_list.erase(std::find(free_list.begin(), free_list.end(), reg));
func.SetPhysRegForVirt(interval.vreg, reg);
active_list.emplace_back(interval, reg);
// 记录 callee-saved 寄存器
if (!interval.is_float && reg >= PhysReg::S1 && reg <= PhysReg::S11)
func.AddCalleeSavedReg(reg);
if (interval.is_float && (reg == PhysReg::FS0 || reg == PhysReg::FS1))
func.AddCalleeSavedReg(reg);
} else {
// 无可用寄存器,需要溢出:选择结束点最远的活跃区间
auto spill_candidate = active_list.end();
int farthest_end = -1;
for (auto it2 = active_list.begin(); it2 != active_list.end(); ++it2) {
if (it2->interval.end > farthest_end) {
farthest_end = it2->interval.end;
spill_candidate = it2;
}
}
if (spill_candidate != active_list.end() && spill_candidate->interval.end > interval.end) {
// 溢出旧区间,将其寄存器转给新区间
PhysReg reg = spill_candidate->reg;
// 清除被溢出区间的物理映射
func.SetPhysRegForVirt(spill_candidate->interval.vreg, PhysReg::ZERO);
func.SetSpillSlot(spill_candidate->interval.vreg,
func.CreateSpillSlot(spill_candidate->interval.is_float));
active_list.erase(spill_candidate);
// 分配寄存器给当前区间
func.SetPhysRegForVirt(interval.vreg, reg);
active_list.emplace_back(interval, reg);
// 记录 callee-saved
if (!interval.is_float && reg >= PhysReg::S1 && reg <= PhysReg::S11)
func.AddCalleeSavedReg(reg);
if (interval.is_float && (reg == PhysReg::FS0 || reg == PhysReg::FS1))
func.AddCalleeSavedReg(reg);
} else {
// 溢出当前区间
func.SetSpillSlot(interval.vreg,
func.CreateSpillSlot(interval.is_float));
// 不分配物理寄存器,保持 ZERO
}
}
}
}
// 插入溢出代码(使用两个不同的临时寄存器,避免冲突)
// RegAlloc.cpp - 修复 InsertSpillReload
void InsertSpillReload(MachineFunction& func) {
for (auto& block : func.GetBlocks()) {
auto& instrs = block->GetInstructions();
// 使用索引遍历,避免迭代器失效
for (size_t idx = 0; idx < instrs.size(); ++idx) {
auto& instr = instrs[idx];
auto& ops = instr.GetOperands();
// 第一遍:替换有物理寄存器的虚拟寄存器
for (size_t i = 0; i < ops.size(); ++i) {
if (ops[i].GetKind() == Operand::Kind::VirtReg) {
int vreg = ops[i].GetVirtReg();
if (func.HasPhysRegForVirt(vreg)) {
const_cast<Operand&>(ops[i]) = Operand::Reg(func.GetPhysRegForVirt(vreg));
}
}
}
}
// 第二遍:处理溢出(使用新的指令列表)
std::vector<MachineInstr> new_instrs;
for (size_t idx = 0; idx < instrs.size(); ++idx) {
auto& instr = instrs[idx];
auto& ops = instr.GetOperands();
bool is_store = (instr.GetOpcode() == Opcode::Store ||
instr.GetOpcode() == Opcode::StoreFloat);
bool is_call = (instr.GetOpcode() == Opcode::Call);
bool is_ret = (instr.GetOpcode() == Opcode::Ret);
// 收集需要加载的操作数(读操作)
std::vector<std::pair<size_t, int>> reads;
// 收集需要存储的操作数(写操作)
std::vector<std::pair<size_t, int>> writes;
for (size_t i = 0; i < ops.size(); ++i) {
if (ops[i].GetKind() == Operand::Kind::VirtReg) {
int vreg = ops[i].GetVirtReg();
if (func.HasSpillSlot(vreg)) {
bool is_write = (i == 0 && !is_store && !is_call && !is_ret);
if (is_write) {
writes.push_back({i, vreg});
} else {
reads.push_back({i, vreg});
}
}
}
}
// 为每个读操作插入 load 指令
for (auto& read : reads) {
int vreg = read.second;
int slot = func.GetSpillSlot(vreg);
bool is_float = func.IsVirtRegFloat(vreg);
PhysReg temp = is_float ? kFloatTempLoad : kIntTempLoad;
auto load_op = is_float ? Opcode::LoadFloat : Opcode::Load;
new_instrs.emplace_back(load_op,
std::vector<Operand>{Operand::Reg(temp), Operand::FrameIndex(slot)});
}
// 复制当前指令,并替换操作数
MachineInstr new_instr = instr;
auto& new_ops = const_cast<std::vector<Operand>&>(new_instr.GetOperands());
for (auto& read : reads) {
int vreg = read.second;
bool is_float = func.IsVirtRegFloat(vreg);
PhysReg temp = is_float ? kFloatTempLoad : kIntTempLoad;
new_ops[read.first] = Operand::Reg(temp);
}
for (auto& write : writes) {
int vreg = write.second;
bool is_float = func.IsVirtRegFloat(vreg);
PhysReg temp = is_float ? kFloatTempStore : kIntTempStore;
new_ops[write.first] = Operand::Reg(temp);
}
new_instrs.push_back(new_instr);
// 为每个写操作插入 store 指令
for (auto& write : writes) {
int vreg = write.second;
int slot = func.GetSpillSlot(vreg);
bool is_float = func.IsVirtRegFloat(vreg);
PhysReg temp = is_float ? kFloatTempStore : kIntTempStore;
auto store_op = is_float ? Opcode::StoreFloat : Opcode::Store;
new_instrs.emplace_back(store_op,
std::vector<Operand>{Operand::Reg(temp), Operand::FrameIndex(slot)});
}
}
// 替换指令列表
instrs = std::move(new_instrs);
}
}
} // namespace
void RunRegAlloc(MachineFunction& function) {
if (function.GetNumVirtRegs() == 0)
return;
// 1. 计算活跃区间和 Call 位置
std::vector<LiveInterval> intervals;
std::vector<int> call_positions;
ComputeLiveIntervals(function, intervals, call_positions);
// 2. 线性扫描分配
LinearScanRegisterAllocation(function, intervals, call_positions);
// 3. 插入溢出代码
InsertSpillReload(function);
RunPeepholeOptimization(function);
}
} // namespace mir
} // namespace mir
Loading…
Cancel
Save