Boolean expressions 1 productionsemantic action E  E1 or E2E1.trueLabel = E.trueLabel; E1.falseLabel = freshLabel(); E2.trueLabel = E.trueLabel; E2.falseLabel.

Slides:



Advertisements
Similar presentations
Chapter 6 Intermediate Code Generation
Advertisements

Decision Structures – The Syntax Tree Lecture 22 Fri, Apr 8, 2005.
Intermediate Code Generation
Intermediate Code Generation. 2 Intermediate languages Declarations Expressions Statements.
Backpatching: The syntax directed definition we discussed before can be implemented in two or more passes (we have both synthesized attributes and inheritent.
Lecture 08a – Backpatching & Recap Eran Yahav 1 Reference: Dragon 6.2,6.3,6.4,6.6.
Short circuit code for boolean expressions: Boolean expressions are typically used in the flow of control statements, such as if, while and for statements,
8 Intermediate code generation
Chapter 8 Intermediate Code Generation. Intermediate languages: Syntax trees, three-address code, quadruples. Types of Three – Address Statements: x :=
1 Compiler Construction Intermediate Code Generation.
Generation of Intermediate Code Compiler Design Lecture (03/30//98) Computer Science Rensselaer Polytechnic.
PSUCS322 HM 1 Languages and Compiler Design II IR Code Generation I Material provided by Prof. Jingke Li Stolen with pride and modified by Herb Mayer PSU.
Overview of Previous Lesson(s) Over View  Front end analyzes a source program and creates an intermediate representation from which the back end generates.
Compiler Construction Sohail Aslam Lecture Boolean Expressions E → E 1 and M E 2 {backpatch(E 1.truelist, M.quad); E.truelist = E 2.truelist; E.falselist.
Compiler Designs and Constructions
Three Address Code Generation Backpatching-I Prepared By: Siddharth Tiwary 04CS3010.
CS412/413 Introduction to Compilers Radu Rugina Lecture 16: Efficient Translation to Low IR 25 Feb 02.
Lecture 09 – IR (Backpatching) Eran Yahav 1 Reference: Dragon 6.2,6.3,6.4,6.6
Theory of Compilation Erez Petrank Lecture 7: Intermediate Representation Part 2: Backpatching 1.
Theory of Compilation Erez Petrank Lecture 6: Intermediate Representation 1.
Lecture 15 Control Flow Topics Review Positional Encoding of Booleans Short Circuit Evaluation Control Flow Statements Readings: 8.4, 8.6 March 13, 2006.
1 Intermediate representation Goals: –encode knowledge about the program –facilitate analysis –facilitate retargeting –facilitate optimization scanning.
Cse321, Programming Languages and Compilers 1 6/19/2015 Lecture #18, March 14, 2007 Syntax directed translations, Meanings of programs, Rules for writing.
Compiler Summary Mooly Sagiv html://
2.2 A Simple Syntax-Directed Translator Syntax-Directed Translation 2.4 Parsing 2.5 A Translator for Simple Expressions 2.6 Lexical Analysis.
CSc 453 Intermediate Code Generation Saumya Debray The University of Arizona Tucson.
CSc 453 Intermediate Code Generation Saumya Debray The University of Arizona Tucson.
1 Structure of a Compiler Front end of a compiler is efficient and can be automated Back end is generally hard to automate and finding the optimum solution.
COP 4620 / 5625 Programming Language Translation / Compiler Writing Fall 2003 Lecture 10, 10/30/2003 Prof. Roy Levow.
1 Semantic Analysis Aaron Bloomfield CS 415 Fall 2005.
Concordia University Department of Computer Science and Software Engineering Click to edit Master title style COMPILER DESIGN Review Joey Paquet,
Lesson 3 CDT301 – Compiler Theory, Spring 2011 Teacher: Linus Källberg.
Joey Paquet, Lecture 12 Review. Joey Paquet, Course Review Compiler architecture –Lexical analysis, syntactic analysis, semantic.
# 1 CMPS 450 Syntax-Directed Translations CMPS 450 J. Moloney.
1 Compiler Design (40-414)  Main Text Book: Compilers: Principles, Techniques & Tools, 2 nd ed., Aho, Lam, Sethi, and Ullman, 2007  Evaluation:  Midterm.
Topic #7: Intermediate Code EE 456 – Compiling Techniques Prof. Carl Sable Fall 2003.
1 Intermediate Code Generation Abstraction at the source level identifiers, operators, expressions, statements, conditionals, iteration, functions (user.
Introduction to Compiling
1 A Simple Syntax-Directed Translator CS308 Compiler Theory.
Course Revision.. Contents  Lexical Analysis  Our Compiler Structure  Tokens, Lexemes & Patterns  RE’s & Regular Definitions  Transition Diagrams.
Code Generation CPSC 388 Ellen Walker Hiram College.
Chap. 4, Intermediate Code Generation
Theory of Compilation Erez Petrank Lecture 6: Intermediate Representation and Attribute Grammars 1.
1 February 28, February 28, 2016February 28, 2016February 28, 2016 Azusa, CA Sheldon X. Liang Ph. D. Computer Science at Azusa Pacific University.
Three Address Code Generation of Control Statements continued..
Overview of Compilation Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Programming Language Principles Lecture 2.
CS 404Ahmed Ezzat 1 CS 404 Introduction to Compiler Design Lecture 1 Ahmed Ezzat.
CS 404Ahmed Ezzat 1 CS 404 Introduction to Compiler Design Lecture 10 Ahmed Ezzat.
CC410: System Programming Dr. Manal Helal – Fall 2014 – Lecture 12–Compilers.
Lecture 9 Symbol Table and Attributed Grammars
Compiler Design (40-414) Main Text Book:
A Simple Syntax-Directed Translator
Programming Languages Translator
Compilers Principles, Techniques, & Tools Taught by Jing Zhang
Compiler Construction
Intermediate Code Generation
Subject Name:COMPILER DESIGN Subject Code:10CS63
Compiler Optimization and Code Generation
CS 3304 Comparative Languages
Syntax-Directed Translation
Intermediate Code Generation Part II
Chapter 6 Intermediate-Code Generation
Intermediate Code Generation Part II
Intermediate Code Generation Part II
Compiler Design 21. Intermediate Code Generation
Three Address Code Generation – Backpatching
Intermediate Code Generation Part II
Intermediate Code Generation
Intermediate Code Generation Part II
Compiler Design 21. Intermediate Code Generation
Presentation transcript:

Boolean expressions 1 productionsemantic action E  E1 or E2E1.trueLabel = E.trueLabel; E1.falseLabel = freshLabel(); E2.trueLabel = E.trueLabel; E2.falseLabel = E.falseLabel; E.code = E1.code || gen (E1.falseLabel ‘:’) || E2.code E  E1 and E2E1.trueLabel = freshLabel(); E1.falseLabel = E.falseLabel; E2.trueLabel = E.trueLabel; E2.falseLabel = E.falseLabel; E.code = E1.code || gen (E1.trueLabel ‘:’) || E2.code E  not E1E1.trueLabel = E.falseLabel; E1.falseLabel = E.trueLabel; E.code = E1.code; E  (E1)E1.trueLabel = E.trueLabel; E1.falseLabel = E.falseLabel; E.code = E1.code; E  id1 relop id2E.code=gen (‘if’ id1.var relop id2.var ‘goto’ E.trueLabel)||gen(‘goto’ E.falseLabel); E  trueE.code = gen(‘goto’ B.trueLabel) E  falseE.code = gen(‘goto’ B.falseLabel); Generate code that jumps to E.trueLabel if E’s value is true and to B.falseLabel if E’s value is false.

Boolean expressions 2 productionsemantic action E  E1 or E2E1.trueLabel = E.trueLabel; E1.falseLabel = freshLabel(); E2.trueLabel = E.trueLabel; E.falseLabel = E.falseLabel; E.code = E1.code || gen (E1.falseLabel ‘:’) || E2.code

Boolean Expressions: an Example 3 E E E E E E a a < < b b or E E c c < < d d E E e e < < f f and

Boolean Expressions: an Example 4 E E E E E E a a < < b b or E E c c < < d d E E e e < < f f and if a < b goto : T 1 := 0101: goto : T 1 := 1103:

Boolean Expressions: an Example 5 E E E E E E a a < < b b or E E c c < < d d E E e e < < f f and if a < b goto : T 1 := 0101: goto : T 1 := 1103: if c < d goto : T 2 := 0105: goto : T 2 := 1107:

Boolean Expressions: an Example 6 E E E E E E a a < < b b or E E c c < < d d E E e e < < f f and if a < b goto : T 1 := 0101: goto : T 1 := 1103: if c < d goto : T 2 := 0105: goto : T 2 := 1107: if e < f goto : T 3 := 0109: goto : T 3 := 1111: 112:

Boolean Expressions: an Example 7 E E E E E E a a < < b b or E E c c < < d d E E e e < < f f and if a < b goto : T 1 := 0101: goto : T 1 := 1103: if c < d goto : T 2 := 0105: goto : T 2 := 1107: if e < f goto : T 3 := 0109: goto : T 3 := 1111: 112: 113: T 4 := T 2 and T 3

Boolean Expressions: an Example 8 E E E E E E a a < < b b or E E c c < < d d E E e e < < f f and if a < b goto : T 1 := 0101: goto : T 1 := 1103: if c < d goto : T 2 := 0105: goto : T 2 := 1107: if e < f goto : T 3 := 0109: goto : T 3 := 1111: 112: 113: T 4 := T 2 and T 3 T 5 := T 1 or T 4

Boolean expressions 9 productionsemantic action B  B1 or B2B1.trueLabel = B.trueLabel; B1.falseLabel = freshLabel(); B2.trueLabel = B.trueLabel; B2.falseLabel = B.falseLabel; B.code = B1.code || gen (B1.falseLabel ‘:’) || B2.code B  B1 and B2B1.trueLabel = freshLabel(); B1.falseLabel = B.falseLabel; B2.trueLabel = B.trueLabel; B2.falseLabel = B.falseLabel; B.code = B1.code || gen (B1.trueLabel ‘:’) || B2.code B  not B1B1.trueLabel = B.falseLabel; B1.falseLabel = B.trueLabel; B.code = B1.code; B  (B1)B1.trueLabel = B.trueLabel; B1.falseLabel = B.falseLabel; B.code = B1.code; B  id1 relop id2B.code=gen (‘if’ id1.var relop id2.var ‘goto’ B.trueLabel)||gen(‘goto’ B.falseLabel); B  trueB.code = gen(‘goto’ B.trueLabel) B  falseB.code = gen(‘goto’ B.falseLabel); Generate code that jumps to B.trueLabel if B’s value is true and to B.falseLabel if B’s value is false.

Boolean expressions 10 productionsemantic action B  B1 or B2B1.trueLabel = B.trueLabel; B1.falseLabel = freshLabel(); B2.trueLabel = B.trueLabel; B.falseLabel = B.falseLabel; B.code = B1.code || gen (B1.falseLabel ‘:’) || B2.code

Example 11 S S if B B then S1 B1 B2 and false true B1.trueLabel = freshLabel(); B1.falseLabel = B.falseLabel; B2.trueLabel = B.trueLabel; B2.falseLabel = B.falseLabel; B.code = B1.code || gen (B1.trueLabel ‘:’) || B2.code B.code = gen(‘goto’ B1.trueLabel) B.code = gen(‘goto’ B2.falseLabel)

Example 12 S S if B B then S1 B1 B2 and false true B.trueLabel = freshLabel(); B.falseLabel = S.next; S1.next = S.next; S.code = B.code || gen (B.trueLabel ‘:’) || S1.code B1.trueLabel = freshLabel(); B1.falseLabel = B.falseLabel; B2.trueLabel = B.trueLabel; B2.falseLabel = B.falseLabel; B.code = B1.code || gen (B1.trueLabel ‘:’) || B2.code B.code = gen(‘goto’ B1.trueLabel) B.code = gen(‘goto’ B2.falseLabel)

Computing the labels We can build the code while parsing the tree bottom- up, leaving the jump targets vacant. We can compute the values for the labels in a second traversal of the AST 13

Why is it difficult? Think of an if-then-else statement. To compute S1.next, we need to know the code of all blocks S1, B, S2, in order to compute the address that follows them. On the other hand, to compute the code of S1, we need to know S1.next, or S.next, which is not known before S1 is computed. So we cannot compute S1’s code with all jump targets, but we can compute it up to “leaving space” for future insertion of S1.next. Using backpatching we maintain a list of all empty spaces that need to jump to S1.next. When we know S1.next, we go over this list and update the jump targets with S1.next’s value. if B S thenelse S1S1 S2S2

Backpatching Goal: generate code in a single pass Generate code as we did before, but manage labels differently Keep targets of jumps empty until values are known, and then back-patch them For every label, maintain a list of instructions that jump to this label When the address of the label is known, go over the list and update the address of the label 15

BackPatching is putting the address instead of labels when the proper label is determined. Backpatching Algorithms perform three types of operations – makelist(i) – creates a new list containing only i, an index into the array of quadruples and returns pointer to the list it has made. – merge(i,j) – concatenates the lists pointed to by i and j,and returns a pointer to the concatenated list. – backpatch(p,i) – inserts i as the target label for each of the statements on the list pointed to by p. New synthesized attributes for B – B.truelist – list of jump instructions that eventually get the label where B goes when B is true. – B.falselist – list of jump instructions that eventually get the label where B goes when B is false. 16

Functions for list handling makelist(addr) – create a list of instructions containing addr merge(p1,p2) – concatenate the lists pointed to by p1 and p2, returns a pointer to the new list backpatch(p,addr) – inserts i as the target label for each of the instructions in the list pointed to by p 17

Accumulating the code Assume a bottom-up parsing so that the code is created in the correct order from left to right, bottom-up. The semantic analysis is actually executed during parsing and the code is accumulated. Recall that we associated two labels B.trueLabel and B.falseLabel for each expression B, which are the labels to which we should jump if B turns out true or false. We will now replace these with two lists B.truelist and B.falselist, which record all instructions that should be updated with the address of B.trueLabel or B.falseLabel when we discover their values. In addition, we also replace S.next with S.nextlist, maintaining all instructions that should jump to S.next, when we know what it is.

Accumulating Code (cont’d) B.truelist and B.falselist are generated attributes: the descendants tell the parent where there is code to fix. When ascending to the parent of B, we know what are the relevant addresses and we can backpatch them into all the instruction locations that are in the list. Similarly for S.nextlist. We will need a function nextinstr() that retruns the address of the next instruction.

Computing Boolean expressions Recall the code jumps to B.true ot B.false according to B’s value. Previously: Now with backpatching: { B.code := gen ( ' if ' id 1.var relop.op id 2.var ' goto ' B.true ) || gen ( ' goto ' B.false ) } B → id 1 relop id 2 { B.code := gen ( ' goto ' B.true ) } B → true { B.code := gen ( ' goto ' B.false ) } B → false { B.truelist := makelist ( nextinstr ) ; B.falselist := makelist ( nextinstr + 1 ) ; emit ( ' if ' id 1.var relop.op id 2.var ' goto_ ' ) || emit ( ' goto_ ' ) } B → id 1 relop id 2 { B.truelist := makelist ( nextinstr ) ; emit ( ' goto_ ' ) } B → true { B.falselist := makelist ( nextinstr ) ; emit ( ' goto_ ' ) } B → false

Computing Boolean expressions Recall the code jumps to B.true ot B.false according to B’s value. Previously: Now with backpatching: { B 1.true := B.false ; B 1.false := B.true ; B.code := B 1.code } B → not B 1 { B 1.true := B.true ; B 1.false := B.false ; B.code := B 1.code } B → ( B 1 ) { B.truelist := B 1.falselist ; B.falselist := B 1.truelist } B → not B 1 { B.truelist := B 1.truelist ; B.falselist := B 1.falselist } B → ( B 1 )

Computing Boolean expressions Recall the code jumps to B.true ot B.false according to B’s value. Previously: Now with backpatching: { B 1.true := B.true ; B 1.false := newlable() ; B 2.true := B.true ; B 2.false := B.false ; B.code := B 1.code || gen ( B 1.false ' : ') || B 2.code } B → B 1 or B 2 { B 1.true := newlabel (); B 1.false := B.false ; B 2.true := B.true ; B 2.false := B.false ; B.code := B 1.code || gen ( B 1.true ' : (' || B 2.code } B → B 1 and B 2 { backpatch ( B 1.falselist, M.instr ) ; B.truelist := merge ( B 1.truelist, B 2.truelist ) ; B.falselist := B 2.falselist } B → B 1 or M B 2 { backpatch ( B 1.truelist, M.instr ) ; B.truelist := B 2.truelist ; B.falselist := merge ( B 1.falselist, B 2.falselist ) } B → B 1 and M B 2 { M.instr := nextinstr } M → 

Backpatching Boolean expressions 23 productionsemantic action B  B1 or M B2backpatch(B1.falseList,M.instr); B.trueList = merge(B1.trueList,B2.trueList); B.falseList = B2.falseList; B  B1 and M B2backpatch(B1.trueList,M.instr); B.trueList = B2.trueList; B.falseList = merge(B1.falseList,B2.falseList); B  not B1B.trueList = B1.falseList; B.falseList = B1.trueList; B  (B1)B.trueList = B1.trueList; B.falseList = B1.falseList; B  id1 relop id2B.trueList = makeList(nextInstr); B.falseList = makeList(nextInstr+1); emit (‘if’ id1.var relop id2.var ‘goto _’) || emit(‘goto _’); B  trueB.trueList = makeList(nextInstr); emit (‘goto _’); B  falseB.falseList = makeList(nextInstr); emit (‘goto _’); M  M   M.instr = nextinstr;

Using a marker { M.instr = nextinstr;} Use M to obtain the address just before B2 code starts being generated 24 B1 or B B M M B2   Example:

Example 25 X 200 and x != y B B B B x x < < 100 B B x x > > 200 B B x x != y y B B and or M M M M   100: if x< 100 goto _ 101: goto _ B  id1 relop id2B.trueList = makeList(nextInstr); B.falseList = makeList(nextInstr+1); emit (‘if’ id1.var relop id2.var ‘goto _’) || emit(‘goto _’); B.t = {100} B.f = {101}  

Example 26 X 200 and x != y B B B B x x < < 100 B B x x > > 200 B B x x != y y B B and or M M M M   100: if x< 100 goto _ 101: goto _ B.t = {100} B.f = {101} M  M   M.instr = nextinstr; M.i = 102  

Example 27 X 200 and x != y B B B B x x < < 100 B B x x > > 200 B B x x != y y B B and or M M M M   100: if x< 100 goto _ 101: goto _ B.t = {100} B.f = {101} M.i = 102 B  id1 relop id2B.trueList = makeList(nextInstr); B.falseList = makeList(nextInstr+1); emit (‘if’ id1.var relop id2.var ‘goto _’) || emit(‘goto _’); 102: if x> 200 goto _ 103: goto _ B.t = {102} B.f = {103}  

Example 28 X 200 and x != y B B B B x x < < 100 B B x x > > 200 B B x x != y y B B and or M M M M   100: if x< 100 goto _ 101: goto _ B.t = {100} B.f = {101} M.i = : if x> 200 goto _ 103: goto _ B.t = {102} B.f = {103}   M  M   M.instr = nextinstr; M.i = 104

Example 29 X 200 and x != y B B B B x x < < 100 B B x x > > 200 B B x x != y y B B and or M M M M   100: if x< 100 goto _ 101: goto _ B.t = {100} B.f = {101} M.i = : if x> 200 goto _ 103: goto _ B.t = {102} B.f = {103}   M.i = 104 B  id1 relop id2B.trueList = makeList(nextInstr); B.falseList = makeList(nextInstr+1); emit (‘if’ id1.var relop id2.var ‘goto _’) || emit(‘goto _’); 104: if x!=y goto _ 105: goto _ B.t = {104} B.f = {105}

Example 30 X 200 and x != y B B B B x x < < 100 B B x x > > 200 B B x x != y y B B and or M M M M   100: if x< 100 goto _ 101: goto _ B.t = {100} B.f = {101} M.i = : if x> 200 goto : goto _ B.t = {102} B.f = {103}   M.i = : if x!=y goto _ 105: goto _ B.t = {104} B.f = {105} B  B1 and M B2backpatch(B1.trueList,M.instr); B.trueList = B2.trueList; B.falseList = merge(B1.falseList,B2.falseList); B.t = {104} B.f = {103,105}

Example 31 X 200 and x != y B B B B x x < < 100 B B x x > > 200 B B x x != y y B B and or M M M M   100: if x< 100 goto _ 101: goto 102 B.t = {100} B.f = {101} M.i = : if x> 200 goto : goto _ B.t = {102} B.f = {103}   M.i = : if x!=y goto _ 105: goto _ B.t = {104} B.f = {105} B.t = {104} B.f = {103,105} B  B1 or M B2backpatch(B1.falseList,M.instr); B.trueList = merge(B1.trueList,B2.trueList); B.falseList = B2.falseList; B.t = {100,104} B.f = {103,105}

Example : if x<100 goto _ 101: goto _ 102: if x>200 goto _ 103: goto _ 104: if x!=y goto _ 105: goto _ 100: if x<100 goto _ 101: goto _ 102: if x>200 goto : goto _ 104: if x!=y goto _ 105: goto _ 100: if x<100 goto _ 101: goto : if x>200 goto : goto _ 104: if x!=y goto _ 105: goto _ Before backpatching After backpatching by the production B  B1 and M B2 After backpatching by the production B  B1 or M B2

Backpatching for statements 33 productionsemantic action S  if (B) M S1backpatch(B.trueList,M.instr); S.nextList = merge(B.falseList,S1.nextList); S  if (B) M1 S1 N else M2 S2 backpatch(B.trueList,M1.instr); backpatch(B.falseList,M2.instr); temp = merge(S1.nextList,N.nextList); S.nextList = merge(temp,S2.nextList); S  while M1 (B) M2 S1 backpatch(S1.nextList,M1.instr); backpatch(B.trueList,M2.instr); S.nextList = B.falseList; emit(‘goto’ M1.instr); S  { L }S.nextList = L.nextList; S  AS.nextList = null; M  M   M.instr = nextinstr; N  N   N.nextList = makeList(nextInstr); emit(‘goto _’); L  L1 M Sbackpatch(L1.nextList,M.instr); L.nextList = S.nextList; L  SL.nextList = S.nextList

Generate code for procedures we will see handling of procedure calls in much more detail later 34 n = f(a[i]); t1 = i * 4 t2 = a[t1] // could have expanded this as well param t2 t3 = call f, 1 n = t3

Extend grammar for procedures type checking – function type: return type, type of formal parameters – within an expression function treated like any other operator symbol table – parameter names 35 D  define T id (F) { S } F   | T id, F S  return E; | … E  id (A) | … A   | E, A expressions statements

Summary Three address code is our IR. Intermediate code generation is executed while parsing (via semantic actions). Creating code for Boolean expressions and for control statements is more involved. We typically use short circuit evaluation, value of an expression is implicit in control location. We need to compute the branching addresses. Option 1: compute them in a second AST pass. Option 2: backpatching (a single pass): maintain lists of incomplete jumps, where all jumps in a list have the same target. When the target becomes known, all instructions on its list are “filled in”. 36

Recap Lexical analysis – regular expressions identify tokens (“words”) Syntax analysis – context-free grammars identify the structure of the program (“sentences”) Contextual (semantic) analysis – type checking defined via typing judgements – can be encoded via attribute grammars Syntax directed translation – attribute grammars Intermediate representation – many possible IRs – generation of intermediate representation – 3AC 37

Journey inside a compiler 38 Lexical Analysis Syntax Analysis Sem. Analysis Inter. Rep. Code Gen. float position; float initial; float rate; position = initial + rate * 60 Token Stream

Journey inside a compiler 39 Lexical Analysis Syntax Analysis Sem. Analysis Inter. Rep. Code Gen. 60 = + * AST idsymboltypedata 1positionfloat… 2initialfloat… 3ratefloat… symbol table S  ID = E E  ID | E + E | E * E | NUM

Journey inside a compiler 40 Lexical Analysis Syntax Analysis Sem. Analysis Inter. Rep. Code Gen. 60 = + * inttofloat 60 = + * AST coercion: automatic conversion from int to float inserted by the compiler idsymboltype 1positionfloat 2initialfloat 3ratefloat symbol table

Journey inside a compiler 41 Lexical Analysis Syntax Analysis Sem. Analysis Inter. Rep. Code Gen. t1 = inttofloat(60) t2 = id3 * t1 t3 = id2 + t2 id1 = t3 3AC 60 = + * inttofloat productionsemantic rule S  id = ES.code := E. code || gen(id.var ‘:=‘ E.var) E  E1 op E2E.var := freshVar(); E.code = E1.code || E2.code || gen(E.var ‘:=‘ E1.var ‘op’ E2.var) E  inttofloat(num)E.var := freshVar(); E.code = gen(E.var ‘:=‘ inttofloat(num)) E  id E.var := id.var; E.code = ‘’ t1 = inttofloat(60) t2 = id3 * t1 t3 = id2 * t2 id1 = t3 (for brevity, bubbles show only code generated by the node and not all accumulated “code” attribute) note the structure: translate E1 translate E2 handle operator

Journey inside a compiler 42 Inter. Rep. Code Gen. Lexical Analysis Syntax Analysis Sem. Analysis 3AC Optimized t1 = inttofloat(60) t2 = id3 * t1 t3 = id2 + t2 id1 = t3 t1 = id3 * 60.0 id1 = id2 + t1 value known at compile time can generate code with converted value eliminated temporary t3

Journey inside a compiler 43 Inter. Rep. Code Gen. Lexical Analysis Syntax Analysis Sem. Analysis Optimized t1 = id3 * 60.0 id1 = id2 + t1 Code Gen LDF R2, id3 MULF R2, R2, #60.0 LDF R1, id2 ADDF R1,R1,R2 STF id1,R1

Problem 3.8 from [Appel] A simple left-recursive grammar: E  E + id E  id A simple right-recursive grammar accepting the same language: E  id + E E  id Which has better behavior for shift-reduce parsing? 44

Answer The stack never has more than three items on it. In general, with LR-parsing of left-recursive grammars, an input string of length O(n) requires only O(1) space on the stack. 45 E  E + id E  id Input id+id+id+id+id id (reduce) E E + E + id (reduce) E E + E + id (reduce) E E + E + id (reduce) E E + E + id (reduce) E stack left recursive

Answer The stack grows as large as the input string. In general, with LR-parsing of right-recursive grammars, an input string of length O(n) requires O(n) space on the stack. 46 E  id + E E  id Input id+id+id+id+id id id + id + id id + id + id + id + id id + id + id + id id + id + id + id + id + id + id + id + id (reduce) id + id + id + id + E (reduce) id + id + id + E (reduce) id + id + E (reduce) id + E (reduce) E stack right recursive

Next… Runtime Environments 47