15
Procedures – Generating the Code Lecture 21 Mon, Apr 4, 2005

Procedures – Generating the Code Lecture 21 Mon, Apr 4, 2005

Embed Size (px)

Citation preview

Page 1: Procedures – Generating the Code Lecture 21 Mon, Apr 4, 2005

Procedures – Generating the Code

Lecture 21

Mon, Apr 4, 2005

Page 2: Procedures – Generating the Code Lecture 21 Mon, Apr 4, 2005

Code for a FUNC Syntax Tree

The code generated by a FUNC syntax tree should output the text

.text

.globl _fname

.def _fname; .scl 2; .type 32; .endef

_fname:

which the assembler uses to define the function name _fname.

Page 3: Procedures – Generating the Code Lecture 21 Mon, Apr 4, 2005

Code for a FUNC Syntax Tree

A FUNC syntax tree must also Save the old base pointer. Save the old stack pointer. Create the local block.

The code should bepush %ebp # Save base ptr

mov %esp,%ebp # Save stack ptr

sub $n,%esp # n bytes for locals

Page 4: Procedures – Generating the Code Lecture 21 Mon, Apr 4, 2005

Code for a FEND Syntax Tree

The code generated by a FEND syntax tree should Restore the old stack pointer (thereby clearing the

local block). Restore the old base pointer. Return to the calling function.

The code should bemov %ebp,%esp # Restore stack ptrpop %ebp # Restore base ptrret # Return

Page 5: Procedures – Generating the Code Lecture 21 Mon, Apr 4, 2005

Code for a RET Syntax Tree

The code for a return is similar to the code for the end of a function, except There is a return value. The block level should not be changed.

If the return value is an integer, it should be placed in register eax. Why not push it onto the stack?

If the return value is a double, it should be placed (or left) in FPU register st(0).

Page 6: Procedures – Generating the Code Lecture 21 Mon, Apr 4, 2005

Code for a CALL Syntax Tree

Function calls are a bit more complicated since we must process the LIST tree.

We must push onto the stack each parameter in the LIST tree.

If we do a pre-order traversal, pushing as we go, in which order will the parameters be pushed?

Page 7: Procedures – Generating the Code Lecture 21 Mon, Apr 4, 2005

Code for a CALL Syntax Tree

First, we must distinguish the three cases: No parameter. One parameter. More than one parameter.

What distinguishes the case of no parameter?

What distinguishes the case of exactly one parameter?

Anything else must be more than one parameter and will be handled recursively.

Page 8: Procedures – Generating the Code Lecture 21 Mon, Apr 4, 2005

Code for a CALL Syntax Tree

If the right subtree is null, then there is no parameter.

If the right subtree is not a LIST tree, then it must be an expression tree representing one parameter. Push that parameter onto the runtime stack.

If the right subtree is a LIST tree, then call on generateNodeCode() to handle it under the LIST case.

Page 9: Procedures – Generating the Code Lecture 21 Mon, Apr 4, 2005

Code for a CALL Syntax Tree

Incidentally, the CALL node may be either unary or binary.

It is listed in the Utility class as binary. Therefore, when a CALL tree is printed, we

will get the warning “attempted to print a null tree.”

We may ignore it or we can prevent it by making CALL a special case.

Page 10: Procedures – Generating the Code Lecture 21 Mon, Apr 4, 2005

Code for a LIST Syntax Tree

While processing the parameter list, we must count the total number of bytes used by the parameters.

Call this paramBlockSize. Before processing any parameters,

The current value of paramBlockSize should be pushed onto a stack since a parameter list may include a function call itself.

paramBlockSize should be set to 0.

Page 11: Procedures – Generating the Code Lecture 21 Mon, Apr 4, 2005

Code for a LIST Syntax Tree

In the LIST case, we simply do right-to-left pre-order traversal of the tree, pushing the parameters as we go.

Each parameter is an expression, so we must call on traverseTree() to do a left-to-right post-order traversal of the expression tree.

Page 12: Procedures – Generating the Code Lecture 21 Mon, Apr 4, 2005

Pseudocode for the LIST Case

Call traverseTree() to handle the right subtree as an expression tree. Push the value onto the runtime stack.

If the left subtree is a LIST tree, then Call generateNodeCode() to handle it

recursively as a LIST tree. (Recursive case) Else

Call traverseTree() to handle it as an expression tree. (Non-recursive case) Push the value onto the runtime stack.

Page 13: Procedures – Generating the Code Lecture 21 Mon, Apr 4, 2005

Code for a CALL Syntax Tree

Now, back to the CALL case. We still have to

Do the call instruction Clear the parameters off the stack. Pass the return value back.

The call instruction is of the form

call _fname The name is stored in the left subtree.

Page 14: Procedures – Generating the Code Lecture 21 Mon, Apr 4, 2005

Code for a CALL Syntax Tree

To “clear” the parameters off the stack, we simply move the stack pointer. Add to the stack pointer the number of bytes

occupied by the parameters. That value has been stored on the special stack

designated for that purpose. Pop the number off the stack. Use it to adjust the stack pointer.

Page 15: Procedures – Generating the Code Lecture 21 Mon, Apr 4, 2005

Code for a CALL Syntax Tree

If the return value is a double, it is already in st(0), where it belongs.

If it is a int, then it is on the stack and must be popped into eax.