2
votes

I'm writing a tinyc Compiler which translates into MIPS assembly. I'm stuck with the question how to implement the local variable handling. The following example makes it hard to think of a proper solution:

int* funcA() {
    int a = 3;
    return &a;
}

int main() {
    return *(funcA());
}

Normally you would create the local variable on the stack. So in this case 'int a' would be created on the stack. The problem is that in the end we want to return the address of 'a' and not the value with &a. But in the moment we leave 'funcA()' we reset the stack to the old state and the pointer we return in the end is not valid anymore and could show later into nirvana.

My first attempt was to handle everything with registers, but with the &-Operator we translate it to something like this:

    .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

It would crash in the marked line because the destination register doesn't have an address to store something. One idea is to to create a datasegment for every local variable, but that would be a overhead and it wouldn't work with recursive functions.

Does anyone have a proper solution how to handle local variables especially if you return an address from a local variable and not a value?

Any help is appreciated!

1
I think the first issue you have is that you are starting with a faulty C example. You will have the same problem with the C code that you do in trying to implement it in MIPS... putting int a on the stack and returning a pointer to it. For example, the mingw32-gcc compiler will warn you about your int* funcA() - warning: function returns address of local variable. - embedded_guy
Oh wow, thank you very much! The question didn't let me sleep and the solution was so easy! - Rooky
I'm glad it helped - and I didn't realize that was the solution you were looking for. I will add it as an answer. - embedded_guy

1 Answers

2
votes

The primary issue that you are running into is that the example C you are starting with is not good code. The same issue with trying to implement the code in MIPS exists in the original, C code. You should never create a local variable within a function and try to return its address. That local variable could be held in a register or on the stack and its data will probably be wiped out.

For an example, I wrote this bit of code in C to illustrate and compiled it with mingw32-gcc:

int* funcA()
{
    int a = 3;
    return &a;
}

int main (void)
{
    int * myPointer;

    myPointer = funcA();

    return 0;
}

The compiler produces this warning:

warning: function returns address of local variable