cpsc 388 – compiler design and construction code generation

58
CPSC 388 – Compiler Design and Construction Code Generation

Upload: william-hopkins

Post on 05-Jan-2016

216 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: CPSC 388 – Compiler Design and Construction Code Generation

CPSC 388 – Compiler Design and Construction

Code Generation

Page 2: CPSC 388 – Compiler Design and Construction Code Generation

Code Generation Global Variables Functions (entry and exit) Statements Expressions

Assume only scalar variables, no arrays (you figure out arrays)

Generate MIPS assembly code for Spim http://pages.cs.wisc.edu/~larus/spim.html

Page 3: CPSC 388 – Compiler Design and Construction Code Generation

Spim Interpreter

spim –file <name> <name> is the name file containing

MIPS assembly code Program will run, giving output and

errors to screen Also has graphical interface

Page 4: CPSC 388 – Compiler Design and Construction Code Generation

Some Spim Registers

Register Purpose$sp Stack pointer

$fp Frame pointer

$ra Return address

$v0, $a0 Used for output and return value

$t0-$t7 temporaries

Page 5: CPSC 388 – Compiler Design and Construction Code Generation

Helps for Generating Assembly Code Constants Used

SP, FP, RA, V0, A0, T0, T1, TRUE, FALSE Methods Used

generate(opcode, arg1, arg2, arg3)generateIndexed(opcode,R1,R2,offset)genPush(R1)genPop(R1)String nextLabel()genLabel(label)

Page 6: CPSC 388 – Compiler Design and Construction Code Generation

Global Variables

For each global variable, v:.data

.align 2 # align on word boundary

_v: .space N N is the size of the variable in bytes

int: 4 bytes arrays: 4*(size of array)

Page 7: CPSC 388 – Compiler Design and Construction Code Generation

Global Variable Example Give source code

int x;

int y[10]; Generate code

.data

.align 2

_x: .space 4

.data

.align 2

_y: .space 40

Page 8: CPSC 388 – Compiler Design and Construction Code Generation

Code Generation for Functions

For each Function Function preamble Function entry (setup AR) Function body (function’s statements) Function exit (restore stack, return to

caller)

Page 9: CPSC 388 – Compiler Design and Construction Code Generation

Function Preamble

For the main function generate:.text

.globl main

main: All other functions:

.text

_<fName>: Where <fname> is the function name

Page 10: CPSC 388 – Compiler Design and Construction Code Generation

Function Entry

Caller’sAR

parameters

<- FP

<- SP

Caller’sAR

parameters

<- FP

<- SP

return addControl link

Space forLocal vars

NewAR

Page 11: CPSC 388 – Compiler Design and Construction Code Generation

Function Entry Steps Push RA

sw $ra, 0($sp)subu $sp, $sp, 4

Push CLsw $fp, 0($sp)subu $sp, $sp, 4

Set FPaddu $fp, $sp, <size of params +8>

Push space for local varssubu $sp, $sp, <size of locals in bytes>

Page 12: CPSC 388 – Compiler Design and Construction Code Generation

Function Body

No need for code from DeclListNode Call codeGen() for statement nodes in

StmtListNode

FnBodyNode

DeclListNode StmtListNode

Page 13: CPSC 388 – Compiler Design and Construction Code Generation

Function Exit Pop AR Jump to RA field

lw $ra, -<paramsize>($fp)

move $t0, $fp

lw $fp, -<paramsize+4>($fp)

move $sp, $t0

jr $ra Caller’sAR

parameters

<- FP

<- SP

return addControl link

Space forLocal vars

NewAR

Page 14: CPSC 388 – Compiler Design and Construction Code Generation

Function Returns Return statement End of function

Two ways to handle this Generate return code once and have

return statements jump to this code (op code is ‘b’ for branch)

Generate return code for each return statement and end of function

Page 15: CPSC 388 – Compiler Design and Construction Code Generation

Return Statement’s value

Return statements can return a a value from an ExpNode

ExpNodes will push values onto the stack

Return statement should pop the top of stack and place return value in register V0 before the rest of return code

Page 16: CPSC 388 – Compiler Design and Construction Code Generation

Statements Write a different codeGen() method for

each kind of statement in AST Hard to debug assembly code Alternate method:

Write codeGen() for the WriteIntStmtNode and WriteStrStmtNode classes first (maybe one method)

Test codeGen() for other kinds of statements and expressions by writing a c- program that computes and prints a value.

Page 17: CPSC 388 – Compiler Design and Construction Code Generation

Write Statement Call codeGen for expression being printed

Leaves value on top of stack (if int) Leaves address on top of stack (if String)

Pop top of stack into A0 (register used for output)

Set register V0 to 1 of int 4 if String

Generate: syscall

Page 18: CPSC 388 – Compiler Design and Construction Code Generation

Write Statement Example

myExp.codeGen();

genPop(A0);

if ( type is int)

generate(“li”,V0,1);

else if (type is String)

generate(“li”,V0,4);

generate(“syscall”);

Page 19: CPSC 388 – Compiler Design and Construction Code Generation

If Statement

Two Methods for Generating code Numeric Method Control-Flow Method

IfStmtNode

DeclListNode StmtListNodeExpNode

Page 20: CPSC 388 – Compiler Design and Construction Code Generation

Numeric Method for If Statements

Evaluate the condition, leave value on stack

Pop top of stack into register T0 Jump to FalseLabel if T0==FALSE Code for statement list FalseLabel:

Note: Every Label in assembly code must be unique! I’m Using FalseLabel but the actual label is generated usinggenLabel()

Page 21: CPSC 388 – Compiler Design and Construction Code Generation

You Try It

Write the actual code needed for IfStmtNode

What is the form for IfElseStmtNode?

What is the form for WhileStmtNode?

Page 22: CPSC 388 – Compiler Design and Construction Code Generation

Return Stmt

Call codeGen() for expNode child(leaves result value on stack)

Pop value off stack into V0 Generate code for actual return

Pop AR Jump to address in RA

ReturnStmtNode

ExpNode

ReturnStmtNode

Page 23: CPSC 388 – Compiler Design and Construction Code Generation

Read Statement

Code:li $v0, 5syscall

Loads special value 5 into register V0, then does syscall. 5 tells syscall to read in an integer and store it back in V0 Need to write code to copy value from V0 back into address

represented by ExpNode

ReadStmtNode

ExpNode

Page 24: CPSC 388 – Compiler Design and Construction Code Generation

ReadStmtNode Examplesint x;int *p;int **q;*q=p=&x;scanf(“%d”,&x);scanf(“%d”,p);scanf(“%d”,*q); All three calls to scanf read in a value into variable x. The

value of the expression is the address of x. To store value into address do:

Generate code to compute value of expression (value is pushed onto stack)

Pop the value into T0 Store from V0 to address in T0

Page 25: CPSC 388 – Compiler Design and Construction Code Generation

ReadStmtNode Example

generate(“li”,V0,5);generate(“syscall”);myExp.codeGen();genPop(T0);generateIndexed(“sw”,V0,T0,0);

Page 26: CPSC 388 – Compiler Design and Construction Code Generation

Identifiers in Code Generation

Function call (id is name of function)

Expressions (can be just a name (id) or an id can be one of the operands)

Assignment statements (id of left-hand side)

Need to jump-and-link to instruction using the name of function

Generate code to fetch current value and push onto stack

Generate code to fetch the address of variable and push address onto stack

Page 27: CPSC 388 – Compiler Design and Construction Code Generation

IdNode Needs several methodsgenJumpAndLink()

generate jump and link code for given IdNode

codeGen()

pushes value of IdNode expression onto stack

genAddr()

pushes address of IdNode onto stack

Page 28: CPSC 388 – Compiler Design and Construction Code Generation

genJumpAndLink() for IdNode

simply generate a jump-and-link instruction (with opcode jal) using label as target of the jump.

If the called function is "main", the label is just "main". For all other functions, the label is of the form:

_<functionName>

Page 29: CPSC 388 – Compiler Design and Construction Code Generation

codeGen() for IdNode copy the value of the global / local

variable into a register (e.g., T0), then push the value onto the stack

Different for local or global variablesExamples:lw $t0 _g // load global g into T0 lw $t0 -4($fp) // load local into T0

How do you tell if variable is local or global? – Using Symbol Table

Page 30: CPSC 388 – Compiler Design and Construction Code Generation

genAddr() for IdNode

load the address of the identifier into a register then push onto the stack

Uses opcode for loading address la rather than loading values lw

Different for locals or globalsExamples:la $t0, _g // global

la $t0, -8($fp) // local

Page 31: CPSC 388 – Compiler Design and Construction Code Generation

AssignStmtNode

Push the address of the left-hand-side expression onto the stack.

Evaluate the right-hand-side expression, leaving the value on the stack.

Store the top-of-stack value into the second-from-the top address.

AssignStmtNode

ExpNodeExpNode

Page 32: CPSC 388 – Compiler Design and Construction Code Generation

Expression Node codeGen

Always generate code to leave value of expression on top of stack

Literals IntLitNode, StrLitNode

Function Call Non short-circuited operators Short-circuited operators

Page 33: CPSC 388 – Compiler Design and Construction Code Generation

IntLitNode

generate code to push the literal value onto the stack

Generated code should look like:li $t0, <value> # load value into T0

sw $t0, ($sp) # push onto stack

subu $sp, $sp, 4

Page 34: CPSC 388 – Compiler Design and Construction Code Generation

StrLitNode

Store string literal in data area Push address of string onto stack Two string lits should be equal if they

contain the same characters This means store only a single

instance of a string literal no matter how often it appears in user code

Page 35: CPSC 388 – Compiler Design and Construction Code Generation

Storing String Literals Code to store a string literal in data area

.data

<label>:.asciiz <string value> <label> needs to be a new label; e.g.,

returned by a call to nextLabel. <string value> needs to be a string in

quotes. You should be storing string literals that way, so just write out the value of the string literal, quotes and all.

Page 36: CPSC 388 – Compiler Design and Construction Code Generation

Storing Strings Once To avoid storing the same string literal

value more than once, keep a hashtable in which the keys are the string literals, and the associated information is the static-data-area label.

When you process a string literal, look it up in the hashtable: if it is there, use its associated label; otherwise, generate code to store it in the static data area, and add it to the hashtable.

Page 37: CPSC 388 – Compiler Design and Construction Code Generation

Pushing StrLitNodes onto stack

Generated Code:.text

la $t0, <label> #load addr into $t0

sw $t0, ($sp) #push onto stack

subu $sp, $sp, 4

Page 38: CPSC 388 – Compiler Design and Construction Code Generation

CallExpNode

Code Should: Evaluate each actual parameter, pushing the values

onto the stack; Jump and link (jump to the called function, leaving

the return address in the RA register). Push the returned value (which will be in register V0)

onto the stack.

CallExpNode

ExpListNodeIdNode

Since the codeGen method for an expression generates code to evaluate the expression, leaving the value on the stack, all we need to do for step 1 is call the codeGen method of the ExpListNode (which will in turn call the codeGen methods of each ExpNode in the list). For step 2, we just call the genJumpAndLink method of the IdNode. For step 3, we just call genPush(V0).

Page 39: CPSC 388 – Compiler Design and Construction Code Generation

Also CallStmtNode

CallExpNode pushes value onto stack (may be void, i.e. garbage from V0)

CallStmtNode MUST pop value off stack

CallExpNode

ExpListNodeIdNode

CallStmtNode

Page 40: CPSC 388 – Compiler Design and Construction Code Generation

Non-Short Circuited ExpNodes Plus, Minus, …, Not, Less, Equals,… All do Same basic sequence of tasks

Call each child's codeGen method to generate code that will evaluate the operand(s), leaving the value(s) on the stack.

Generate code to pop the operand value(s) off the stack into register(s) (e.g., T0 and T1). Remember that if there are two operands, the right one will be on the top of the stack.

Generate code to perform the operation (see Spim documentation for a list of opcodes).

Generate code to push the result onto the stack.

Page 41: CPSC 388 – Compiler Design and Construction Code Generation

Note on SPIM op-codes

The NOT opcode is a bit-wise note (flips bits), this won’t work for the Not boolean operations

Suggest using seq opcodeSeq Rdest, Rsrc1, Src2

Page 42: CPSC 388 – Compiler Design and Construction Code Generation

Example AddExpNode

public void codeGen() { // step 1: evaluate both operands myExp1.codeGen(); myExp2.codeGen(); // step 2: pop values in T0 and T1 genPop(T1); genPop(T0); // step 3: do the addition (T0 = T0 + T1) generate("add", T0, T0, T1); // step 4: push result genPush(T0)}

AddExpNode

ExpNodeExpNode

Page 43: CPSC 388 – Compiler Design and Construction Code Generation

Short-Circuited Operators

AndNode and OrNode Short-Circuit means the right operand

is evaluated ONLY if it is needed to be evaluated

Example: (J != 0) && (I/J > Epsilon)

Page 44: CPSC 388 – Compiler Design and Construction Code Generation

AndNode Procedure

Evaluate left operandIf left operand is true then

Evaluate right operandExpression value is value of right operand

ElseExpression value is false

Page 45: CPSC 388 – Compiler Design and Construction Code Generation

OrNode Procedure

Evaluate left operandIf left operand is false

evaluate right operandexpression is value of right operand

Elseexpression is true

Page 46: CPSC 388 – Compiler Design and Construction Code Generation

Short-Circuit Nodes

Need to do jump depending on values of sub-expressions

Look at if-node code for example of this

Page 47: CPSC 388 – Compiler Design and Construction Code Generation

You Try It

Write code for AndExpNode

Page 48: CPSC 388 – Compiler Design and Construction Code Generation

If Statement

Two Methods for Generating code Numeric Method

Evaluate condition, pop off stack, jump on particular value

Control-Flow Method Evaluate condition and jump to TrueLabel on true or

FalseLabel on false (i.e. ALWAYS do a jump) Requires a new method for Expression Nodes (i.e. don’t

put value on the stack, instead do jump) Call New method genJumpCode(LabelTrue,LabelFalse)

IfStmtNode

DeclListNode StmtListNodeExpNode

Page 49: CPSC 388 – Compiler Design and Construction Code Generation

codeGen for IfStmtNode (control-flow method)

public void codeGen() { String trueLab = nextLabel(); String doneLab = nextLab(); myExp.genJumpCode(trueLab, doneLab); genLabel(trueLab); myStmtList.codeGen(); genLabel(doneLab);}

Page 50: CPSC 388 – Compiler Design and Construction Code Generation

genJumpCode() for IdNode

Old waylw $t0, <var’s addr>push $t0

New waylw $t0, <var’s addr>beq $t0, FALSE, falseLabb trueLab

Page 51: CPSC 388 – Compiler Design and Construction Code Generation

genJumpCode() for LessNode Old Way

-- code to eval operands

-- pop values into T1, T0

slt $t2, $t0, $t1

push $t2

New Way-- code to eval

operands-- pop values into T1,

T0blt $t0, $t1,

trueLabB falseLab

Page 52: CPSC 388 – Compiler Design and Construction Code Generation

genJumpCode() for Short-Circuited Operators (AndExpNode)

Call genJumpCode() of left child. If child is false then jump to false label If child is true jump to right child

Generate label for right child Call genJumpCode() of right child.

If child is false jump to false label If child is true jump to true label

AndExpNode

ExpNodeExpNode

Page 53: CPSC 388 – Compiler Design and Construction Code Generation

genJumpCode() for AndExpNode

Public void genJumpCode(String trueLab, String falseLab) {String newLab=nextLabel();myExp1.genJumpCode(newLab,falseLab);genLabel(newLab);myExp2.genJumpCode(trueLab,falseLab);

}

Page 54: CPSC 388 – Compiler Design and Construction Code Generation

Example with genJumpCode

If (a && b>0) { …

IfStmtNode

DeclListNodeAndExpNode StmtListNode

IdNode LessExpNode

… …

Page 55: CPSC 388 – Compiler Design and Construction Code Generation

genJumpCode() Example IfStmtNode

creates two labels, trueLab, doneLab calls AndNode’s genJumpCode(trueLabel,doneLabel) Generate trueLab --code for StmtListNode Generate doneLabel

AndNode creates a label newLabel, calls IdNode’s

genJumpCode(newLabel,doneLabel) Generate newLabel Call LessNode’s genJumpCode(trueLab,doneLab)

Page 56: CPSC 388 – Compiler Design and Construction Code Generation

You Try It

What is the form of the code for genJumpCode() For an OrNode For a NotNode

Page 57: CPSC 388 – Compiler Design and Construction Code Generation

Comparing Numeric and Control-Flow methods Numeric Method -- code to evaluate left

operand, leaving value on stack

Pop into T0

Goto trueLab if t0==FALSE Push FALSE Goto doneLab

trueLab: -- code to evalute right

operand, leaving value on stack

doneLab:

Control-Flow Method --code to evaluate left

operand, including jumps to newLab and falseLab

newLab: --code to evaluate right

operand, including jumps to trueLab and falseLab

Page 58: CPSC 388 – Compiler Design and Construction Code Generation

You Try It

Compare two approaches for OrNode and NotNode