Search code examples
compiler-constructionmipslocal-variables

MIPS Compiler local variables


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!


Solution

  • 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