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

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

Some Spim Registers
$sp $fp $ra $v0, $a0 $t0-$t7

Stack pointer Frame pointer Return address Used for output and return value temporaries

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)

align 2 # align on word boundary .Global Variables  For each global variable.space N _v:  N is the size of the variable in bytes  int: 4 bytes  arrays: 4*(size of array) . v: .data .

Global Variable Example  Give source code int x.align . int y[10].data .align .space 2 4 2 40 _x: _y: .  Generate code .space .data .

Code Generation for Functions  For each Function     Function Function Function Function caller) preamble entry (setup AR) body (function‟s statements) exit (restore stack. return to .

Function Preamble  For the main function generate: .globl main main:  All other functions: .text .text _<fName>:  Where <fname> is the function name .

FP <.FP Caller‟s AR .SP New AR <.Function Entry <.SP parameters Caller‟s AR Space for Local vars Control link return add parameters <.

4 $fp. 0($sp) $sp. <size of locals in bytes>  Set FP addu subu  Push space for local vars . $sp. <size of params +8> $sp.Function Entry Steps  Push RA sw subu $ra. 4  Push CL sw subu $fp. $sp. 0($sp) $sp. $sp. $sp.

Function Body FnBodyNode DeclListNode StmtListNode  No need for code from DeclListNode  Call codeGen() for statement nodes in StmtListNode .

FP Caller‟s AR . $fp. $sp. $t0.Function Exit  Pop AR  Jump to RA field lw move lw move jr $ra.SP Space for Local vars Control link return add parameters <. $ra -<paramsize>($fp) New $fp AR -<paramsize+4>($fp) $t0 <.

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 .

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 .

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 .

. generate(“syscall”).V0.4). genPop(A0). else if (type is String) generate(“li”.codeGen().V0. if ( type is int) generate(“li”.1).Write Statement Example myExp.

If Statement IfStmtNode ExpNode DeclListNode StmtListNode Two Methods for Generating code  Numeric Method  Control-Flow Method .

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 using genLabel() .

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 .

then does syscall. 5 Loads special value 5 into register V0.Read Statement ReadStmtNode ExpNode     Code: li syscall $v0. 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 .

&x). scanf(“%d”.  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 . int *p.p). int **q.ReadStmtNode Examples int x. scanf(“%d”. The value of the expression is the address of x.*q). *q=p=&x. scanf(“%d”.  All three calls to scanf read in a value into variable x.

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

Identifiers in Code Generation  Function call (id is name of function) Need to jump-and-link to instruction using the name of function  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 current value and push onto stack 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 .

 If the called function is "main". the label is just "main". For all other functions. the label is of the form: _<functionName> .genJumpAndLink() for IdNode  simply generate a jump-and-link instruction (with opcode jal) using label as target of the jump.

T0). then push the value onto the stack  Different for local or global variables Examples: 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 .g.codeGen() for IdNode  copy the value of the global / local variable into a register (e..

-8($fp) // local . _g // global la $t0.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 globals Examples: la $t0.

.  Evaluate the right-hand-side expression.  Store the top-of-stack value into the second-from-the top address.AssignStmtNode AssignStmtNode ExpNode ExpNode  Push the address of the left-hand-side expression onto the stack. leaving the value on the stack.

StrLitNode  Function Call  Non short-circuited operators  Short-circuited operators .Expression Node codeGen  Always generate code to leave value of expression on top of stack  Literals  IntLitNode.

($sp) # push onto stack subu $sp.IntLitNode  generate code to push the literal value onto the stack  Generated code should look like: li $t0. 4 . <value> # load value into T0 sw $t0. $sp.

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 .

.  <string value> needs to be a string in quotes. quotes and all. e. so just write out the value of the string literal.Storing String Literals  Code to store a string literal in data area .asciiz <string value>  <label> needs to be a new label.g. You should be storing string literals that way..data <label>: . returned by a call to nextLabel.

keep a hashtable in which the keys are the string literals. use its associated label. . look it up in the hashtable: if it is there.Storing Strings Once  To avoid storing the same string literal value more than once. and the associated information is the staticdata-area label. and add it to the hashtable. otherwise.  When you process a string literal. generate code to store it in the static data area.

4 .Pushing StrLitNodes onto stack  Generated Code: . ($sp) #push onto stack subu $sp. $sp.text la $t0. <label> #load addr into $t0 sw $t0.

For step IdNode ExpListNode 2. pushing the values onto 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). leaving the value on the stack. For step 3.  Jump and link (jump to the called function. we just call genPush(V0). we just call the genJumpAndLink method of the IdNode.CallExpNode  Since the codeGen method for an expression generates code to evaluate the CallExpNode expression.  Push the returned value (which will be in register V0) onto the stack. leaving the return address in the RA register). .  Code Should:  Evaluate each actual parameter.

Also CallStmtNode CallStmtNode CallExpNode IdNode ExpListNode  CallExpNode pushes value onto stack (may be void. garbage from V0)  CallStmtNode MUST pop value off stack . i.e.

…  All do Same basic sequence of tasks  Call each child's codeGen method to generate code that will evaluate the operand(s).g. Not. the right one will be on the top of the stack. Less. ..Non-Short Circuited ExpNodes  Plus. T0 and T1). Minus. ….  Generate code to pop the operand value(s) off the stack into register(s) (e.  Generate code to push the result onto the stack.  Generate code to perform the operation (see Spim documentation for a list of opcodes). Remember that if there are two operands. leaving the value(s) on the stack. Equals.

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 opcode Seq Rdest. Src2 . Rsrc1.

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

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 .

pop off stack. don‟t put value on the stack. jump on particular value  Evaluate condition and jump to TrueLabel on true or FalseLabel on false (i.e. instead do jump)  Call New method genJumpCode(LabelTrue. ALWAYS do a jump)  Requires a new method for Expression Nodes (i.e.If Statement IfStmtNode ExpNode DeclListNode StmtListNode Two Methods for Generating code  Numeric Method  Control-Flow Method  Evaluate condition.LabelFalse) .

doneLab). genLabel(doneLab). String doneLab = nextLab(). myExp.codeGen(). } . myStmtList. genLabel(trueLab).codeGen for IfStmtNode (controlflow method) public void codeGen() { String trueLab = nextLabel().genJumpCode(trueLab.

FALSE. <var‟s addr> $t0  New way lw beq b $t0.genJumpCode() for IdNode  Old way lw push $t0. falseLab trueLab . <var‟s addr> $t0.

pop values into T1.code to eval operands -. T0 blt $t0. trueLab B falseLab . $t1. T0 slt $t2.genJumpCode() for LessNode  Old Way -. $t1 push $t2  New Way -.code to eval operands -.pop values into T1. $t0.

 If child is false jump to false label  If child is true jump to true label .  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.genJumpCode() for Short-Circuited Operators (AndExpNode) AndExpNode ExpNode ExpNode  Call genJumpCode() of left child.

} .genJumpCode(trueLab.falseLab). String falseLab) { String newLab=nextLabel(). genLabel(newLab).genJumpCode() for AndExpNode Public void genJumpCode(String trueLab.falseLab). myExp2. myExp1.genJumpCode(newLab.

Example with genJumpCode If (a && b>0) { … IfStmtNode AndExpNode DeclListNode StmtListNode IdNode LessExpNode … … .

genJumpCode() Example  IfStmtNode      creates two labels.doneLab) . trueLab.doneLabel)  Generate newLabel  Call LessNode‟s genJumpCode(trueLab. calls IdNode‟s genJumpCode(newLabel. doneLab calls AndNode‟s genJumpCode(trueLabel.doneLabel) Generate trueLab --code for StmtListNode Generate doneLabel  AndNode  creates a label newLabel.

You Try It  What is the form of the code for genJumpCode()  For an OrNode  For a NotNode .

including jumps to trueLab and falseLab trueLab: -. leaving value on stack Pop into T0 Goto trueLab if t0==FALSE Push FALSE Goto doneLab  Control-Flow Method --code to evaluate left operand. leaving value on stack doneLab: .Comparing Numeric and ControlFlow methods  Numeric Method -.code to evalute right operand. including jumps to newLab and falseLab newLab: --code to evaluate right operand.code to evaluate left operand.

You Try It  Compare two approaches for OrNode and NotNode .

Sign up to vote on this title
UsefulNot useful

Master Your Semester with Scribd & The New York Times

Special offer for students: Only $4.99/month.

Master Your Semester with a Special Offer from Scribd & The New York Times

Cancel anytime.