【发布时间】:2015-07-23 16:26:47
【问题描述】:
我正在编写一个 tinyc 编译器,它可以转换为 MIPS 程序集。我被困在如何实现局部变量处理的问题上。下面的例子让人很难想出一个合适的解决方案:
int* funcA() {
int a = 3;
return &a;
}
int main() {
return *(funcA());
}
通常您会在堆栈上创建局部变量。所以在这种情况下,'int a' 将在堆栈上创建。问题是最后我们要返回 'a' 的地址,而不是 &a 的值。但是在我们离开 'funcA()' 的那一刻,我们将堆栈重置为旧状态,最后我们返回的指针不再有效,以后可能会显示为必杀技。
我的第一次尝试是使用寄存器来处理所有事情,但是使用 &-Operator 我们将其转换为如下内容:
.globl funcA
funcA:
addiu $sp, $sp, -4 # save return address
sw $ra, ($sp)
addiu $sp, $sp, -4 # save the reg we will use for further processing
sw $s0, ($sp)
addiu $t0, $zero, 3 # $t0 = a and add 3
la $s0, ($t0)
la $t0, ($s0)
sw $t1, ($t0) # crashes here
la $v0, ($t1) # put the result in $v0
lw $s0, ($sp)
addiu $sp, $sp, 4 # restore the stack
lw $ra, ($sp)
addiu $sp, $sp, 4
jr $ra # jump back
它会在标记的行中崩溃,因为目标寄存器没有地址来存储某些东西。一种想法是为每个局部变量创建一个数据段,但这会产生开销,并且不适用于递归函数。
有没有人有适当的解决方案来处理局部变量,尤其是当你从局部变量返回地址而不是值时?
感谢任何帮助!
【问题讨论】:
-
我认为您遇到的第一个问题是您从一个错误的 C 示例开始。您将遇到与尝试在 MIPS 中实现 C 代码相同的问题...将
int a放在堆栈上并返回指向它的指针。例如,mingw32-gcc 编译器会警告您int* funcA()- 警告:函数返回局部变量的地址。 -
哇哦,非常感谢!这个问题让我睡不着觉,解决起来很简单!
-
我很高兴它有帮助 - 我没有意识到这是您正在寻找的解决方案。我将其添加为答案。
标签: compiler-construction mips local-variables