[backend]修复了一个栈管理问题

This commit is contained in:
Lixuanwang
2025-07-30 20:40:56 +08:00
parent 8e94f89931
commit 03b62b138f
4 changed files with 66 additions and 90 deletions

View File

@@ -165,10 +165,6 @@ void RISCv64RegAlloc::handleCallingConvention() {
*/
void RISCv64RegAlloc::eliminateFrameIndices() {
StackFrameInfo& frame_info = MFunc->getFrameInfo();
// 初始偏移量为保存ra和s0留出空间。
// 假设序言是 addi sp, sp, -stack_size; sd ra, stack_size-8(sp); sd s0, stack_size-16(sp);
int current_offset = 16;
Function* F = MFunc->getFunc();
RISCv64ISel* isel = MFunc->getISel();
@@ -190,12 +186,15 @@ void RISCv64RegAlloc::eliminateFrameIndices() {
}
}
// 处理局部变量
// 遍历AllocaInst来计算局部变量所需的总空间
// [关键修改] 为局部变量分配空间时起始点必须考虑为ra, s0以及所有callee-saved寄存器预留的空间。
// 布局顺序为: [s0/ra, 16字节] -> [callee-saved, callee_saved_size字节] -> [局部变量...]
int local_var_offset = 16 + frame_info.callee_saved_size;
int locals_start_offset = local_var_offset; // 记录局部变量区域的起始点,用于计算总大小
// 处理局部变量 (AllocaInst)
for (auto& bb : F->getBasicBlocks()) {
for (auto& inst : bb->getInstructions()) {
if (auto alloca = dynamic_cast<AllocaInst*>(inst.get())) {
// 获取Alloca指令指向的类型 (例如 alloca i32* 中,获取 i32)
Type* allocated_type = alloca->getType()->as<PointerType>()->getBaseType();
int size = getTypeSizeInBytes(allocated_type);
@@ -203,14 +202,17 @@ void RISCv64RegAlloc::eliminateFrameIndices() {
size = (size + 7) & ~7;
if (size == 0) size = 8; // 至少分配8字节
current_offset += size;
local_var_offset += size;
unsigned alloca_vreg = isel->getVReg(alloca);
// 局部变量使用相对于s0的负向偏移
frame_info.alloca_offsets[alloca_vreg] = -current_offset;
frame_info.alloca_offsets[alloca_vreg] = -local_var_offset;
}
}
}
frame_info.locals_size = current_offset;
// [修复] 正确计算并设置locals_size
// 它只应该包含由AllocaInst分配的局部变量的总大小。
frame_info.locals_size = local_var_offset - locals_start_offset;
// 遍历所有机器指令,将伪指令展开为真实指令
for (auto& mbb : MFunc->getBlocks()) {