Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clobbering of outer function return values during nested function calls #3

Open
dylanjtuttle opened this issue Sep 28, 2022 · 0 comments
Labels
bug Something isn't working code gen Issue regarding the code generation stage of compilation

Comments

@dylanjtuttle
Copy link
Owner

When nesting multiple function calls, instructions seem to occur in a strange and difficult to explain order, sometimes causing the return values of some of the functions to be mysteriously discarded.

Minimum Reproducible Example:

func main() returns void {
    int x = add1(return1());
    printf("{}", x);
}

func return1() returns int {
    return 1;
}

func add1(int x) returns int {
    return x + 1;
}

Output:

1

Generated assembly code:

        str     w0, [sp, 0]
        bl      return11
        mov     w9, w0
        mov     w0, w9
        bl      add11
        bl      return11
        adrp    x0, L1@PAGE
        add     x0, x0, L1@PAGEOFF
        ldr     w9, [sp, 0]
        str     w9, [sp, -32]!
        bl      _printf
        add     sp, sp, 32

Let's break this down:

Working as expected

  • str w0, [sp, 0] - Variable x is declared and the initial value of zero is placed in its location on the stack, sp + 0
  • bl return11 - Function return1 is called
  • mov w9, w0 - Value returned from return1 is moved to a temporary register (w9)
  • mov w0, w9 - The value in w9 is moved back into w0, as it is the first and only argument passed into add1
  • bl add11 - Function add1 is called, passing result from return1 in

Where things get weird

  • bl return11 - Function return1 is called again for some reason, overwriting the return value from add1 with its own
  • The format string "%d" is moved into x0:
adrp    x0, L1@PAGE
add     x0, x0, L1@PAGEOFF
  • ldr w9, [sp, 0] - The value of variable x is loaded into w9. Note that x had not been updated to contain the result of the nested function call, and even if it had been, it would contain the wrong value because of the second call to return1.
  • The incorrect value of x is stored on the stack to be passed into printf, which is then called, printing 1 to the console:
str     w9, [sp, -32]!
bl      _printf
add     sp, sp, 32

This must be caused by the code generation for function calls, assignments, or possibly both.

@dylanjtuttle dylanjtuttle added bug Something isn't working code gen Issue regarding the code generation stage of compilation labels Sep 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working code gen Issue regarding the code generation stage of compilation
Projects
None yet
Development

No branches or pull requests

1 participant