Beruflich Dokumente
Kultur Dokumente
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
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
Purpose
Stack pointer Frame pointer Return address Used for output and return value temporaries
Methods Used
generate(opcode, arg1, arg2, arg3) generateIndexed(opcode,R1,R2,offset) genPush(R1) genPop(R1) String nextLabel() genLabel(label)
Global Variables
For each global variable, v:
.data .align 2 # align on word boundary .space N
_v:
Generate code
.data .align .space .data .align .space
2 4 2 40
_x:
_y:
Function Preamble
For the main function generate:
.text .globl main main:
Function Entry
<- SP New AR
<- FP
Callers AR
Push CL
sw subu $fp, 0($sp) $sp, $sp, 4
$fp, $sp, <size of params +8> $sp, $sp, <size of locals in bytes>
Set FP
addu subu
Function Body
FnBodyNode DeclListNode StmtListNode
No need for code from DeclListNode Call codeGen() for statement nodes in StmtListNode
Function Exit
Pop AR Jump to RA field
lw move lw move jr $ra, $t0, $fp, $sp, $ra -<paramsize>($fp) New $fp AR -<paramsize+4>($fp) $t0
<- SP Space for Local vars Control link return add parameters <- FP
Callers AR
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
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.
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
If Statement
IfStmtNode ExpNode DeclListNode StmtListNode
You Try It
Write the actual code needed for IfStmtNode What is the form for IfElseStmtNode?
What is the form for WhileStmtNode?
Return Stmt
ReturnStmtNode ReturnStmtNode ExpNode
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
Read Statement
ReadStmtNode ExpNode
Code:
li syscall $v0, 5
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 Examples
int 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
ReadStmtNode Example
generate(li,V0,5); generate(syscall); myExp.codeGen(); genPop(T0); generateIndexed(sw,V0,T0,0);
Expressions (can be just a name (id) or an id can be one of the operands) Assignment statements (id of lefthand side)
Generate code to fetch the address of variable and push address onto stack
IdNode
Needs several methods genJumpAndLink() generate jump and link code for given IdNode codeGen() pushes value of IdNode expression onto stack genAddr() pushes address of IdNode onto stack
AssignStmtNode
AssignStmtNode
ExpNode
ExpNode
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.
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
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
<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.
CallExpNode
Since the codeGen method for an expression generates code to evaluate the CallExpNode 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 IdNode ExpListNode 2, we just call the genJumpAndLink method of the IdNode. For step 3, we just call genPush(V0).
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.
Also CallStmtNode
CallStmtNode CallExpNode
IdNode
ExpListNode
CallExpNode pushes value onto stack (may be void, i.e. garbage from V0) CallStmtNode MUST pop value off stack
Example AddExpNode
AddExpNode
ExpNode
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) }
ExpNode
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)
AndNode Procedure
Evaluate left operand If left operand is true then Evaluate right operand Expression value is value of right operand Else Expression value is false
OrNode Procedure
Evaluate left operand If left operand is false evaluate right operand expression is value of right operand Else expression is true
Short-Circuit Nodes
Need to do jump depending on values of sub-expressions Look at if-node code for example of this
You Try It
Write code for AndExpNode
If Statement
IfStmtNode ExpNode DeclListNode StmtListNode
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. dont put value on the stack, instead do jump) Call New method genJumpCode(LabelTrue,LabelFalse)
New way
lw beq b $t0, <vars addr> $t0, FALSE, falseLab trueLab
New Way
-- code to eval operands -- pop values into T1, T0 blt $t0, $t1, trueLab B falseLab
ExpNode
ExpNode
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
DeclListNode
StmtListNode
IdNode
LessExpNode
genJumpCode() Example
IfStmtNode
creates two labels, trueLab, doneLab calls AndNodes genJumpCode(trueLabel,doneLabel) Generate trueLab --code for StmtListNode Generate doneLabel
AndNode
creates a label newLabel, calls IdNodes genJumpCode(newLabel,doneLabel) Generate newLabel Call LessNodes genJumpCode(trueLab,doneLab)
You Try It
What is the form of the code for genJumpCode()
For an OrNode For a NotNode
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
You Try It
Compare two approaches for OrNode and NotNode