Do void functions truly need to return 0?

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Do void functions truly need to return 0?

ibeckermayer
According to the book:
"
- VM functions corresponding to void Jack methods and functions must return the constant 0 as their return value.
- When translating a do sub statement where sub is a void method or function, the caller of the corresponding VM function must pop (and ignore) the returned value (which is always the constant 0).
"

The latter bullet point makes sense to me, since it simplifies our system if we can assume that every function returns a value and then just handle this one edge case where that value is meaningless.

However what I'm uncertain of still is whether returning the constant 0 on void functions is strictly necessary. I've walked through several scenarios and it appears to me as though this is a superfluous requirement -- if we don't push a 0 onto the stack before returning from a void function, we'll just end up with some junk value being returned (i.e. our saved THAT, or some now out of scope LCL variable, or something else). But so long as we pop that junk (the latter bullet point), it seems as though it shouldn't matter whether its 0 or anything else.

Is there some edge case or aspect of the Jack or VM semantics or mechanics that I'm not accounting for that makes this line of reasoning untrue? Or is returning 0 from void functions truly just an aesthetic touch?
Reply | Threaded
Open this post in threaded view
|

Re: Do void functions truly need to return 0?

WBahn
Administrator
It doesn't matter whether it is a zero or something other than zero, but you must push something onto the stack since the caller is going to pop something. If your void function doesn't push something onto the stack, then when the caller pops the return value (which doesn't exist) it will corrupt the stack.
Reply | Threaded
Open this post in threaded view
|

Re: Do void functions truly need to return 0?

ibeckermayer
I recognize that the "0" is irrelevant, but what I'm asking is whether I actually need to explicitly push anything additional onto the stack before a void return.

For example, say I have a dummy function like

function void Foo() {
    return
}

which gets called from main

function void main() {
    do Foo()
}

That gets compiled to a

call main.Foo 0

which internally pushes the return-address and various pointers onto the stack (figure 8.5) and then goes to main.Foo. If main.Foo is compiled as just

function main.Foo 0
// push constant 0 omitted
return

That return statement gets assembled to a relatively complex set of operations (figure 8.5 again). If you walk through that logic, it will wind up returning "saved THAT" (from figure 8.4).

One can walk through various other scenarios, and see that you might end up with some other random value that was on top of the stack when the void function returned, or one of the local variables, etc, but since it doesn't matter what value is returned.

So my argument is that the `push constant 0` is superfluous, we don't need to do that in order to return from a void function without breaking our system. OTOH, I can imagine that I'm confused on some aspect of the mechanics, or that there is an edge case that I'm not accounting for.

Reply | Threaded
Open this post in threaded view
|

Re: Do void functions truly need to return 0?

WBahn
Administrator
If you don't push anything on the stack, then your stack pointer will be in the same position it was when the function was called. If you then pop something off the stack and discard it, you will be popping off something that the calling function had placed on the stack before it called the function that just returned, thus corrupting the stack.

Keep in mind that any time you change the stack pointer you are effectively pushing or popping things to and from the stack. If your return implementation always adjusts the stack pointer to make the stack have one more item on it than before the function is called, then your called function HAS pushed one item onto the stack regardless of whether you set that value to something specific or whether it is just whatever junk happened to be there. I think this is what you are talking about doing.