A MiniDream program must generate code for method calls that occur in two different contexts:
The techniques for handling both are similar.
The following is the only legal method call statement in MiniDream:
out.writeint(expr)
To generate code for this call, you first generate code to evaluate expr
.
After evaluating expr
, emit a call instruction to invoke the writeint function in the MiniDream standard library, followed by an instruction to remove the parameter from the stack:
call writeint
addl $4, %esp
For example, consider the following MiniDream fragment:
out.writeint(x + 3)
Here’s the code your compiler might generate:
pushl x # from IdExpr
pushl $3 # from IntLitExpr
popl %ebx # now, BinOpExpr
popl %eax
addl %ebx, %eax
pushl %eax
# Now, from CallStmt, perform the call and clean up the stack
call writeint
addl $4, %esp
The following is the only legal method call that may occur in an expression in MiniDream:
in.readint()
Generating code for this call is much the same as for a call statement. The difference is that, after the call completes, you must push the return value onto the stack, to be used in the expression evaluation.
The C calling convention specifies that the called function leaves its return value in the EAX register. Thus, in visitCallExpr
, you might emit code like this:
call readint
pushl %eax
For example, consider the following Dream fragment:
x := in.readint()
Here’s the code your compiler might generate:
# From visitCallExpr, perform the call
call readint
pushl %eax
# Now, from visitAssignStmt...
popl _x