Compilers. Intermediate representations and code generation. Yannis Smaragdakis, U. Athens (original slides by Sam

Similar documents
COMP 181. Prelude. Intermediate representations. Today. High-level IR. Types of IRs. Intermediate representations and code generation

COMP 181. Prelude. Intermediate representations. Today. Types of IRs. High-level IR. Intermediate representations and code generation

CS415 Compilers. Intermediate Represeation & Code Generation

Intermediate Representations

Copyright 2003, Keith D. Cooper, Ken Kennedy & Linda Torczon, all rights reserved. Students enrolled in Comp 412 at Rice University have explicit

Intermediate Representations

opt. front end produce an intermediate representation optimizer transforms the code in IR form into an back end transforms the code in IR form into

Intermediate Representations

CSE P 501 Compilers. Intermediate Representations Hal Perkins Spring UW CSE P 501 Spring 2018 G-1

Intermediate Representation (IR)

CSE 401/M501 Compilers

Intermediate representation

Lecture 15-16: Intermediate Code-Generation

Prof. Mohamed Hamada Software Engineering Lab. The University of Aizu Japan

Front End. Hwansoo Han

Intermediate Representations & Symbol Tables

Intermediate Code Generation

Alternatives for semantic processing

Principles of Compiler Design

Code Generation. The Main Idea of Today s Lecture. We can emit stack-machine-style code for expressions via recursion. Lecture Outline.

We can emit stack-machine-style code for expressions via recursion

IR Lowering. Notation. Lowering Methodology. Nested Expressions. Nested Statements CS412/CS413. Introduction to Compilers Tim Teitelbaum

Code Generation. Lecture 30

Acknowledgement. CS Compiler Design. Intermediate representations. Intermediate representations. Semantic Analysis - IR Generation

Computer Science Department Carlos III University of Madrid Leganés (Spain) David Griol Barres

Lecture Outline. Code Generation. Lecture 30. Example of a Stack Machine Program. Stack Machines

Fall Compiler Principles Lecture 6: Intermediate Representation. Roman Manevich Ben-Gurion University of the Negev

Writing Evaluators MIF08. Laure Gonnord

CS412/CS413. Introduction to Compilers Tim Teitelbaum. Lecture 19: Efficient IL Lowering 5 March 08

COMP-421 Compiler Design. Presented by Dr Ioanna Dionysiou

Compiler Design. Code Shaping. Hwansoo Han

A Simple Syntax-Directed Translator

CS2210: Compiler Construction. Code Generation

6. Intermediate Representation

CSc 453. Compilers and Systems Software. 13 : Intermediate Code I. Department of Computer Science University of Arizona

Code Shape II Expressions & Assignment

Compilers. Type checking. Yannis Smaragdakis, U. Athens (original slides by Sam

6. Intermediate Representation!

Semantic actions for declarations and expressions

CMPSC 160 Translation of Programming Languages. Three-Address Code

Compilers. Lecture 2 Overview. (original slides by Sam

Intermediate Representations

Semantic actions for declarations and expressions. Monday, September 28, 15

Compilers and computer architecture: A realistic compiler to MIPS

Intermediate Representations

Compiler Theory. (Intermediate Code Generation Abstract S yntax + 3 Address Code)

Static Checking and Intermediate Code Generation Pat Morin COMP 3002

CSc 453 Intermediate Code Generation

Module 27 Switch-case statements and Run-time storage management

Run-time Environments. Lecture 13. Prof. Alex Aiken Original Slides (Modified by Prof. Vijay Ganesh) Lecture 13

Fall Compiler Principles Lecture 5: Intermediate Representation. Roman Manevich Ben-Gurion University of the Negev

Semantic actions for declarations and expressions

Administration CS 412/413. Why build a compiler? Compilers. Architectural independence. Source-to-source translator

Concepts Introduced in Chapter 6

Where we are. What makes a good IR? Intermediate Code. CS 4120 Introduction to Compilers

CS 432 Fall Mike Lam, Professor. Code Generation

COMPILER CONSTRUCTION Seminar 03 TDDB

CODE GENERATION Monday, May 31, 2010

Stating the obvious, people and computers do not speak the same language.

CS1622. Semantic Analysis. The Compiler So Far. Lecture 15 Semantic Analysis. How to build symbol tables How to use them to find

1 Lexical Considerations

6.035 Project 3: Unoptimized Code Generation. Jason Ansel MIT - CSAIL

G Compiler Construction Lecture 12: Code Generation I. Mohamed Zahran (aka Z)

CS 360 Programming Languages Interpreters

Tour of common optimizations

Agenda. CSE P 501 Compilers. Big Picture. Compiler Organization. Intermediate Representations. IR for Code Generation. CSE P 501 Au05 N-1

An Overview of Compilation

Intermediate Representations Part II

CS 406/534 Compiler Construction Putting It All Together

Intermediate Code Generation

About the Authors... iii Introduction... xvii. Chapter 1: System Software... 1

tokens parser 1. postfix notation, 2. graphical representation (such as syntax tree or dag), 3. three address code

Compiler Optimization Intermediate Representation

Chapter 2A Instructions: Language of the Computer

Compilers. Compiler Construction Tutorial The Front-end

Concepts Introduced in Chapter 6

CSE 413 Languages & Implementation. Hal Perkins Winter 2019 Structs, Implementing Languages (credits: Dan Grossman, CSE 341)

Project Compiler. CS031 TA Help Session November 28, 2011

Intermediate Code Generation

Compiler Code Generation COMP360

Comp 204: Computer Systems and Their Implementation. Lecture 22: Code Generation and Optimisation

CS 406/534 Compiler Construction Intermediate Representation and Procedure Abstraction

Semantic analysis and intermediate representations. Which methods / formalisms are used in the various phases during the analysis?

IR Generation. May 13, Monday, May 13, 13

Three-Address Code IR

Syntax-directed translation. Context-sensitive analysis. What context-sensitive questions might the compiler ask?

Compiler Theory. (Semantic Analysis and Run-Time Environments)

Semantic actions for expressions

Intermediate Representations. Reading & Topics. Intermediate Representations CS2210

UNIT 3

CSE 504: Compiler Design. Instruction Selection

Administration. Where we are. Canonical form. Canonical form. One SEQ node. CS 412 Introduction to Compilers

Semantic Analysis computes additional information related to the meaning of the program once the syntactic structure is known.

UNIT-3. (if we were doing an infix to postfix translator) Figure: conceptual view of syntax directed translation.

Programming Languages Third Edition. Chapter 9 Control I Expressions and Statements

Computing Inside The Parser Syntax-Directed Translation, II. Comp 412 COMP 412 FALL Chapter 4 in EaC2e. source code. IR IR target.

Intermediate Representation

CMPT 379 Compilers. Parse trees

Lecture 3 Local Optimizations, Intro to SSA

Programming Language Processor Theory

Transcription:

Compilers Intermediate representations and code generation Yannis Smaragdakis, U. Athens (original slides by Sam Guyer@Tufts)

Today Intermediate representations and code generation Scanner Parser Semantic checker Intermediate code generation Back end High-level IR Low-level IR 2

Intermediate representations IR design affects compiler speed and capabilities Some important IR properties Ease of generation, manipulation, optimization Size of the representation ti Level of abstraction: level of detail in the IR How close is IR to source code? To the machine? What kinds of operations are represented? Often, different IRs for different jobs Typically: High-level IR: close to the source language Low-level IR: close to the machine assembly code 3

Types of IRs Three major categories Structural Graph oriented Heavily used in IDEs, language translators Tend to be large Examples: Trees, DAGs Linear Pseudo-code for an abstract machine Level of abstraction varies Simple, compact data structures Easier to rearrange Hybrid Combination of graphs and linear code Examples: 3 address code Stack machine code Example: Control-flow graph 4

High-level IR High-level language g constructs Array accesses, field accesses Complex control flow Loops, conditionals, switch, break, continue Procedures: callers and callees Arithmetic and logic operators Including things like short-circuit && and Often: tree structured Arbitrary nesting of expressions and statements 5

Abstract Syntax Tree AST: parse tree with some intermediate nodes removed x 2 * y x - * 2 y What is this representation good for? Interpreters We can reconstruct original source Program understanding tools Language translators 6

Directed Acyclic Graph A directed acyclic graph (DAG) AST with a unique node for each value - z w / x Why do this? * 2 y More compact (sharing) Encodes redundancy z x - 2 * y w x / 2 Same expression twice means that the compiler might arrange to evaluate it just once! 7

Low-level IR Linear stream of abstract instructions Instruction: single operation and assignment x = y op z x y op z op x, y, z Must break down high-level constructs Example: t 2 * y z = x 2 * y z x - t Introduce temps as necessary: called virtual registers Simple control-flow Label and goto label1: goto label1 if_goto x, label1 Jump to label1 if x has non-zero value 8

Stack machines Originally for stack-based computers Now, Java VM x 2 * y push x push 2 push y multiply subtract What are advantages? Introduced names are implicit, not explicit Simple to generate and execute code Compact form who cares about code size? Embedded systems Systems where code is transmitted (the Net) Post-fix notation 11

IR Trade-offs for (i=0; i<n; i++) A[i] = i; A = for [] i i Loop invariant Strength reduce to temp2 += 4 loop: temp1 = &A i=0;i<n;i++ temp2 = i * 4 temp3 = temp1 + temp2 store [temp3] = i... goto loop 12

IR Summary Intermediate representations High-level Rich structure, close to source Good for source-level tools, IDEs Example: abstract syntax tree Low-level Linear sequence, close to the machine Good for optimization Example: abstract machine code, bytecode Essence of compilation: Translating from the high-level h l IR to low-level l l IR 13

Towards code generation t1 = c == 0 if_goto t1, lab1 if (c == 0) { t2 = n * n while (c < 20) { c = t2 + 2 c = c + 2; goto end } lab1: } t3 = c >= 20 else if_goto t3, end c = n * n + 2; c = c + 2 goto lab1 end: 14

Code generation Convert from high-level IR to low-level IR HIR is complex, with nested structures LIR is low-level, with everything explicit Often called lowering or linearizing the code Result is a sequence of LIR instructions Need a systematic algorithm Idea: Define translation for each AST node, assuming we can get code to implement children Come up with a scheme to stitch them together Recursively descend the AST 15

Lowering scheme General scheme Code template for each AST node Captures key semantics of each construct Has holes for the children of the node Implemented in a function called generate To fill in the template: Call generate function recursively on children Plug code into the holes How to stitch code together? Generate returns a temporary that holds the result Emit code that combines the results 16

Example: add expression Source: AST: Flow chart: expr1 + expr2 + Code to compute expr1 expr1 expr2 Code to compute expr2 Code template: <code for expr1> <code for expr2> <result> = <expr1> + <expr2> Add results 17

Example: while loop Source: AST: Flow chart: while (cond) body; while Code to compute cond Code template: cond body top_label: <code for condition> ifnot_goto <cond>, end_label <code for body> goto top_label end_label: Is cond true? Code for body Exit 18

Generation scheme Two problems: Getting the order right How to pass values between the pieces of code Solution: order Append each instruction to a global buffer Emit instructions in the desired order Solution: passing values Request a new (unique) temporary variable name Generate code that computes value into the temp Return the name of the temp to higher-level generate call 19

While loop Compiler: generate(whilenode w) { E = new _ label() T = new_label() emit( $T: ) t = generate(w.condition) emit( ifnot_goto $t, $E ) generate(w.body) emit( goto $T ) emit( $E: ) } Code template: top: <code for condition> ifnot_goto <cond>, end <code for body> goto top end: 20

Lowering expressions Arithmetic operations expr1 op expr2 expr1 op expr2 Generate code for left and right children, get the registers holding the results t1 = generate(expr1) t2 = generate(expr2) r = new_temp() emit( r = t1 op t2 ) return r Return the register to generate call above Obtain a fresh register name Emit code for this operation 21

Lowering scheme Emit function Appends low-levellevel abstract instructions to a global buffer Order of calls to emit is important! Scheme works for: Binary arithmetic Unary operations Logic operations What about && and? In C and Java, they are shortcircuiting Need control flow Code expr1 expr2 r = t1 op t2 22

Short-circuiting If expr1 is true, don t eval expr2 expr1 expr2 E = new_label() r = new_temp() t1 = generate(expr1) p emit( r = t1 ) emit( if_goto t1, E ) t2 = generate(expr2) emit( r = t2 ) emit( E: ) return r expr1 expr2 23

Details E = new_label() r = new_ temp() t3 = t1 = generate(expr1) emit( r = t1 ) emit( if_goto t1, E ) t1 = expr1 r = t1 if_goto t1, E t2 = generate(expr2) t2 = expr2 emit( r = t2 ) r = t2 emit( ( E: ) E: return r... L: ifgoto t1 = 24

Helper functions emit() The only function that generates instructions Adds instructions to end of buffer At the end, buffer contains code new_label() Generate a unique label name Does not update code new_temp() Generate a unique temporary name May require type information (from where?) 25

Short-circuiting && expr1 && expr2 N = new_label() E = new_label() r = new_temp() && t1 = generate(expr1) emit( r = t1 ) emit( ( if_g goto t1, N ) expr1 expr2 emit( goto E ) emit( N: ) t2 = generate(expr2) emit( r = t2 ) emit( E: ) return r 26

Short-circuiting && Can we do better? expr1 && expr2 && expr1 expr2 E = new_label() r = new_temp() t1 = generate(expr1) emit( r = t1 ) emit( ifnot_goto t t1, E ) t2 = generate(expr2) emit( r = t2 ) emit( E: ) return r 27

Array access Depends on abstraction expr1 [ expr2 ] OR: Emit array op Lower later r = new_temp() a = generate(expr1) o = generate(expr2) emit( o = o * size ) emit( a = a + o ) emit( r = load a ) return r Type information from the symbol table 28

Statements Simple sequences statement1; statement2;... statementn; generate(statement1) generate(statement2)... generate(statementn) Conditionals if (expr) statement; E = new_label() t = generate(expr) emit( ifnot_goto t, E ) generate(statement) emit( E: ) 29

Loops Emit label for top of loop Generate condition and loop body while (expr) statement; E = new_label() T = new_label() emit( ( T: ) t = generate(expr) emit( ifnot_goto t, E ) generate(statement) emit( goto T ) emit( E: ) 30

For loop How does for work? for (expr1; expr2; expr3) statement 32

Assignment How should we generate x = y? Problem Difference between right-side and left-side Right-side: a value r-value Left-side: a location l-value Example: array assignment A[i] = B[j] Store to this location Load from this location 33

Special generate Define special generate for l-values lgenerate() returns register containing address Use lgenerate() for left-side Return r-value for nested assignment expr1 = expr2; r = generate(expr2) l = lgenerate(expr1) emit( store *l = r ) return r 34

Example: arrays Code: A[i] = B[j] Two versions of generate: r = new_temp() a = generate(arr) o = generate(index) emit( o = o * size ) emit( a = a + o ) emit( r = load a ) return r r-value case a = generate(arr) o = generate(index) emit( o = o * size ) emit( a = a + o ) return a l-value case 35

At leaves Depends on level of abstraction generate(v) for variables All virtual registers: return v Strict register machine: emit( r = load &v ) Note: may introduce many temporaries Later: where is storage for v? More specifically: how the does the compiler set aside space for v and compute its address? generate(c) for constants Special cases to avoid r = # 36

Generation: Big gpicture Reg generate(astnode node) { Reg r; switch (node.getkind()) { case BIN: t1 = generate(node.getleft()); t2 = generate(node.getright()); r = new_temp(); emit( r = t1 op t2 ); break; case NUM: r = new_temp(); emit( ( r = node.getvalue() ); break; case ID: r = new_temp(); o = symtab.getoffset(node.getid()); g ()); emit( r = load <address of o> ); break; } return rn r } 37

Example if (c == 0) { while (c < 20) { c = c + 2; } } else c = n * n + 2; if == c 0 while < = c 20 c + = c + * 2 n n c 2 38

Example while < = E = new_label() = L0 T = new_label() = L1 emit( T: ) t = generate(expr) emit( ifnot_goto t, E ) generate(statement) emit( goto T ) emit( E: ) L1: Code c 20 c + c 2 39

Example while < = E = new_label() = L0 T = new_label() = L1 emit( T: ) t = generate(expr) emit( ifnot_goto t, E ) generate(statement) emit( goto T ) emit( E: ) L1: Code c 20 c + c 2 40

Example while < = E = new_label() = L0 T = new_label() = L1 emit( T: ) t = generate(expr) emit( ifnot_goto t, E ) generate(statement) emit( goto T ) emit( E: ) L1: Code c 20 c + c 2 t1 = generate(expr1) t2 = generate(expr2) r = new_temp() emit( ( r = t1 op t2 ) return r 41

Example while < = E = new_label() = L0 T = new_label() = L1 emit( T: ) t = generate(expr) emit( ifnot_goto t, E ) generate(statement) emit( goto T ) emit( E: ) Code L1: R0 = load c c 20 c + c 2 t1 = generate(expr1) t2 = generate(expr2) r = new_temp() emit( ( r = t1 op t2 ) return r r = new_temp() = R0 emit( r = load v ) return r 42

Example while < = E = new_label() = L0 T = new_label() = L1 emit( T: ) t = generate(expr) emit( ifnot_goto t, E ) generate(statement) emit( goto T ) emit( E: ) Code L1: R0 = load c c 20 c + c 2 t1 = generate(expr1)=r0 t2 = generate(expr2) r = new_temp() emit( ( r = t1 op t2 ) return r 43

Example while < = c 20 c + c 2 E = new_label() = L0 T = new_label() = L1 emit( T: ) t = generate(expr) emit( ifnot_goto t, E ) generate(statement) emit( goto T ) emit( E: ) t1 = generate(expr1)=r0 t2 = generate(expr2) r = new_temp() emit( ( r = t1 op t2 ) return r Code L1: R0 = load c R1 = 20 r = new_ temp() = R1 emit( r = 20 ) return r 44

Example while < = c 20 c + c 2 E = new_label() = L0 T = new_label() = L1 emit( T: ) t = generate(expr) emit( ifnot_goto t, E ) generate(statement) emit( goto T ) emit( E: ) t1 = generate(expr1)=r0 t2 = generate(expr2)=r1 r = new_temp() = R2 emit( ( r = t1 op t2 ) return r Code L1: R0 = load c R1 = 20 R2 = R0 < R1 45

Example while < = c 20 c + c 2 E = new_label() = L0 T = new_label() = L1 emit( T: ) t = generate(expr)=r2 emit( ifnot_goto t, E ) generate(statement) emit( goto T ) emit( E: ) Code L1: R0 = load c R1 = 20 R2 = R0 < R1 not_goto R2,L0 46

Example while < = c 20 c + c 2 E = new_label() = L0 T = new_label() = L1 emit( T: ) t = generate(expr)=r2 emit( ifnot_goto t, E ) generate(statement) emit( goto T ) emit( E: ) r = generate(expr2) l = lgenerate(expr2) emit( store *l = r ) return r Code L1: R0 = load c R1 = 20 R2 = R0 < R1 not_goto R2,L0 47

Example while < = c 20 c + c 2 E = new_label() = L0 T = new_label() = L1 emit( T: ) t = generate(expr)=r2 emit( ifnot_goto t, E ) Code generate(statement) L1: emit( goto T ) emit( E: ) R0 = load c R1 = 20 r = generate(expr2) R2 = R0 < R1 l = lgenerate(expr2) not_goto R2,L0 emit( store *l = r ) R3 = load c return r R4 = 2 R5 = R3 + R2 t1 = generate(expr1)=r3 t2 = generate(expr2)=r4 r = new_temp() = R5 emit( r = t1 op t2 ) return r 48

Example while < = c 20 c + c 2 E = new_label() = L0 T = new_label() = L1 emit( T: ) t = generate(expr)=r2 emit( ifnot_goto t, E ) Code generate(statement) L1: emit( goto T ) emit( E: ) R0 = load c R1 = 20 r = generate(expr2)=r5 R2 = R0 < R1 l = lgenerate(expr2) not_goto R2,L0 emit( store *l = r ) R3 = load c return r R4 = 2 R5 = R3 + R2 49

Example < while = c 20 c + c 2 E = new_label() = L0 T = new_label() = L1 emit( T: ) t = generate(expr)=r2 emit( ifnot_goto t, E ) Code generate(statement) L1: emit( goto T ) emit( E: ) R0 = load c R1 = 20 r = generate(expr2)=r5 R2 = R0 < R1 l = lgenerate(expr2) not_goto R2,L0 emit( store *l = r ) R3 = load c return r R4 = 2 R5 = R3 + R2 R6 = & c r = new_temp()= R6 emit( r = & v ) return r Something like: R6 = base + offset 50

Example while < = c 20 c + c 2 E = new_label() = L0 T = new_label() = L1 emit( T: ) t = generate(expr)=r2 emit( ifnot_goto t, E ) Code generate(statement) L1: emit( goto T ) emit( E: ) R0 = load c R1 = 20 r = generate(expr2)=r5 R2 = R0 < R1 l = lgenerate(expr2)=r6 not_goto R2,L0 emit( store *l = r ) R3 = load c return r R4 = 2 R5 = R3 + R2 R6 = & c store [R6]=R5 51

Example while < = c 20 c + c 2 E = new_label() = L0 T = new_label() = L1 emit( T: ) t = generate(expr)=r2 emit( ifnot_goto t, E ) generate(statement) emit( goto T ) emit( E: ) Code L1: R0 = load c R1 = 20 R2 = R0 < R1 not_goto R2,L0 R3 = load c R4 = 2 R5 = R3 + R2 R6 = & c store [R6]=R5 goto L1 L0: 52

Code R7 = load c Example R8 = 0 == c 0 < while if = c 20 c + c 2 = c + n * 2 n R9 = R7 == R8 not_goto R9,L3 L1: R0 = load c R1 = 20 R2 = R0 < R1 not_goto R2,L0 R3 = load c R4 = 2 R5 = R3 + R2 R6 = & c store [R6]=R5 goto L1 L0: goto L4 L3:... L4: 53

Code R7 = load c Nesting R8 = 0 while (c<20) c = c + 2 c < 20 c = c + 2 c + 2 R9 = R7 == R8 not_goto R9,L3 L1: R0 = load c R1 = 20 R2 = R0 < R1 not_goto R2,L0 R3 = load c R4 = 2 R5 = R3 + R2 R6 = & c store [R6]=R5 goto L1 L0: goto L4 L3:... L4: 54

Code quality Code R7 = c R8 = 0 y R9 = R7 == R8 not_goto R9,L3 L1: R0 = c Many CPUs have a R1 = 20 fast R2 = R0 < R1 c == 0 test not_goto R2,L0 R3 = c Are there ways to make this code better? Can use accumulators: c = c + 2 Label leads to another goto; may have multiple labels R4 = 2 R5 = R3 + R2 c = R5 goto L1 L0: goto L4 L3:... L4: 55

Efficient lowering Reduce number of temporary registers Don t copy variable values unnecessarily Accumulate values, when possible Reuse temporaries, where possible highly depends on IR (e.g., if load-store, cannot do much) Generate more efficient labels Don t generate multiple adjacent labels Avoid goto-label-goto Typically done later, as a separate control-flow optimization 56

Avoiding extra copies Basic algorithm Recursive generation traverses to leaves At leaves, generate: R = v or R = c Improvement Stop recursion one level early Check to see if children are leaves Don t call generate recursively on variables, constants 58

Avoiding copies expr1 op expr2 op v expr1 if (expr1 is-a Var) t1 = (Var) expr1 else t1 = generate(expr1) if (expr2 is-a Var) t2 = (Var) expr2 else t2 = generate(expr2) r = new_temp() emit( r = t1 op t2 ) return r 59

Example Expr1 is (a+b) Not a leaf Recursively generate code Return temp Expr2 is c Return c Emit (R0* c ) ( a + b ) * c Code R0 = a + b R1 = R0 * c 60

Use accumulation Idea: We only need 2 registers to evaluate expr1 op expr2 Reuse temp assigned to one of the subexpressions if (expr1 is var) t1 = (Var) expr1 else t1 = generate(expr1) if (expr2 is var) t2 = (Var) expr2 else t2 = generate(expr2) p emit( t1 = t1 op t2 ) return t1 61

Example Combined: Remove copies Accumulate value ( a + b ) * c Only need one register Code How many would the original scheme have used? R0 = a + b R0 = R0 * c 62

Reuse of temporaries Idea: expr1 op expr2 t1 = generate(expr1) t2 = generate(expr2) r = new_temp() emit( r = t1 op t2 ) return r Can generate(expr1) and generate(expr2) share temporaries? Yes, except for t1 and t2 Observation: temporaries have a limited lifetime Lifetime confined to a subtree 63

Reuse of temporaries Subtrees can share registers R n-1 Algorithm: Use a stack of registers Start at # = 0 op R n R n+ expr2 Each call to ogenerate: eae expr1 expr2 Push next number Use any register > # When done, pop back up R n+ R# = expr1 R# = R# op expr2 64

Miscellaneous Code shape Consider expression x + y + z t1 = x + z t1 = y + z t2 = t1 + z t2 = t1 + y t2 = t1 + x Code: t1 = x + y What if x = 3 and y = 2 What if y+z evaluated ed earlier e in code? Ordering for performance Using associativity and commutativity very hard Operands op1 must be preserved while op2 is computed Emit code for more intensive i one first 65

Code Generation Tree-walk algorithm Notice: generates code for children first Effectively, a bottom up algorithm So that t means. Right! Use syntax directed translation Can emit LIR code in productions Pass register names in $$, $1, $2, etc. Can generate assembly: one-pass compiler Tricky part: assignment 66

One-pass code generation Goal::= Expr:e {: RES = e :} Expr::= Expr:e + Term:t {: r = new_temp(); emit( r = e + t ); RES = r; :} Expr:e Term:t {: r = new_temp(); emit( r = e - t ); RES = r; :} Term::= Term:t * Fact:f {: r = new_temp(); emit( r = t * f ); RES = r; :} Term:t / Fact:f {: r = new_temp(); emit( r = t / f ); RES = r; :} Fact::= ID:i {: r = new_temp(); o = symtab.getoffset(i); emit( r = load <address of o> ); RES = r; :} NUM:n {: r = new_temp(); emit( r = $n ); RES = r; :} 67