Intermediate code generation Simplifying initial assumptions a 3-address code will be used for instructions  choice of instruction mnemonics and layouts.

Slides:



Advertisements
Similar presentations
Chapter 6 Intermediate Code Generation
Advertisements

Synopsys University Courseware Copyright © 2012 Synopsys, Inc. All rights reserved. Compiler Optimization and Code Generation Lecture - 3 Developed By:
Intermediate Code Generation
Chapter 8 ICS 412. Code Generation Final phase of a compiler construction. It generates executable code for a target machine. A compiler may instead generate.
Lecture 08a – Backpatching & Recap Eran Yahav 1 Reference: Dragon 6.2,6.3,6.4,6.6.
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.
The Functions and Purposes of Translators Code Generation (Intermediate Code, Optimisation, Final Code), Linkers & Loaders.
Compiler Construction
Compiler Principle and Technology Prof. Dongming LU Mar. 28th, 2014.
CS412/413 Introduction to Compilers Radu Rugina Lecture 16: Efficient Translation to Low IR 25 Feb 02.
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.
Code Generation for Basic Blocks Introduction Mooly Sagiv html:// Chapter
Slide 1 Chapter 3 Attribute Grammars. Slide 2 Attribute Grammars Certain language structures cannot be described using EBNF. Attribute grammars are extensions.
Improving Code Generation Honors Compilers April 16 th 2002.
Introduction to a Programming Environment
1 Type Type system for a programming language = –set of types AND – rules that specify how a typed program is allowed to behave Why? –to generate better.
Compiler Construction A Compulsory Module for Students in Computer Science Department Faculty of IT / Al – Al Bayt University Second Semester 2008/2009.
Chapter 2 A Simple Compiler
1 MATERI PENDUKUNG OPERATOR Matakuliah: M0074/PROGRAMMING II Tahun: 2005 Versi: 1/0.
CSC 8310 Programming Languages Meeting 2 September 2/3, 2014.
Abstract Syntax Trees Lecture 14 Wed, Mar 3, 2004.
2.2 A Simple Syntax-Directed Translator Syntax-Directed Translation 2.4 Parsing 2.5 A Translator for Simple Expressions 2.6 Lexical Analysis.
Syntax & Semantic Introduction Organization of Language Description Abstract Syntax Formal Syntax The Way of Writing Grammars Formal Semantic.
1 Abstract Syntax Tree--motivation The parse tree –contains too much detail e.g. unnecessary terminals such as parentheses –depends heavily on the structure.
CPSC 388 – Compiler Design and Construction Parsers – Context Free Grammars.
CS412/413 Introduction to Compilers Radu Rugina Lecture 15: Translating High IR to Low IR 22 Feb 02.
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.
Syntax-Directed Translation
1 Semantic Analysis Aaron Bloomfield CS 415 Fall 2005.
Chapter 8 Intermediate Code Zhang Jing, Wang HaiLing College of Computer Science & Technology Harbin Engineering University.
Compiler Chapter# 5 Intermediate code generation.
Chapter 8 High-Level Programming Languages. 8-2 Chapter Goals Describe the translation process and distinguish between assembly, compilation, interpretation,
Lesson 3 CDT301 – Compiler Theory, Spring 2011 Teacher: Linus Källberg.
CSE 425: Control Flow I Categories of Control Flow Constructs Sequencing –order of expressions and statements Selection –if, else, switch Iteration –loops.
Chapter 2. Design of a Simple Compiler J. H. Wang Sep. 21, 2015.
Introduction to Code Generation and Intermediate Representations
Chapter 1 Introduction Study Goals: Master: the phases of a compiler Understand: what is a compiler Know: interpreter,compiler structure.
Copyright © 2006 Addison-Wesley. All rights reserved. Ambiguity in Grammars A grammar is ambiguous if and only if it generates a sentential form that has.
SE424 Languages with Context A Block Structured Language.
8-1 Compilers Compiler A program that translates a high-level language program into machine code High-level languages provide a richer set of instructions.
1 Compiler & its Phases Krishan Kumar Asstt. Prof. (CSE) BPRCE, Gohana.
1 A Simple Syntax-Directed Translator CS308 Compiler Theory.
Principle of Programming Lanugages 3: Compilation of statements Statements in C Assertion Hoare logic Department of Information Science and Engineering.
An Attribute Grammar for Tiny Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida Programming Language Principles Lecture 18.
Overview of Previous Lesson(s) Over View 3 Model of a Compiler Front End.
Code Generation How to produce intermediate or target code.
Compiler Construction CPCS302 Dr. Manal Abdulaziz.
Prof. Necula CS 164 Lecture 171 Operational Semantics of Cool ICOM 4029 Lecture 10.
SDTs used to implement SDDs A non-cyclic SDD (having definitions of attributes) can always be implemented by a SDT (having actions that assign values to.
Programming Languages Meeting 3 September 9/10, 2014.
Intermediate Code Generation CS 671 February 14, 2008.
1 Compiler Construction (CS-636) Muhammad Bilal Bashir UIIT, Rawalpindi.
Syntax Analysis Or Parsing. A.K.A. Syntax Analysis –Recognize sentences in a language. –Discover the structure of a document/program. –Construct (implicitly.
PZ03CX Programming Language design and Implementation -4th Edition Copyright©Prentice Hall, PZ03CX - Language semantics Programming Language Design.
Semantic analysis Jakub Yaghob
System Software Unit-1 (Language Processors) A TOY Compiler
Syntax-Directed Translation
A Simple Syntax-Directed Translator
Compiler Construction (CS-636)
Compilers Principles, Techniques, & Tools Taught by Jing Zhang
Intermediate code generation Jakub Yaghob
Chapter 6 Intermediate-Code Generation
SYNTAX DIRECTED DEFINITION
Intermediate Code Generation
Presentation transcript:

Intermediate code generation Simplifying initial assumptions a 3-address code will be used for instructions  choice of instruction mnemonics and layouts is lecturer’s own symbolic locations and jump targets, like in many assembly languages, will be used  these would need to be resolved to actual machine addresses before the code could be run all operands in arithmetic expressions and comparisons are integers we deal only with arithmetic expressions, boolean expressions, assignment statements, while-loop statements  ignoring e.g. type declarations, if-then-else statements, most array references, function and procedure calls, record and class definitions, etc etc code is generated as a string, by concatenating substrings code is stored as the value of an attribute of a parse tree node run-time speed of generated code is not a concern Compiler Construction1

Arithmetic expressions: simple code generation The general idea is that semantic actions are associated with every production in the grammar dealing with expressions and subexpressions. These actions systematically set two particular attributes  ‘code’ – a string containing arbitrarily many 3-address-code instructions  ‘loc’ – a symbol naming the location where the value for the (sub)expression will be placed when those instructions are executed New locations can be invented as required. Code construction may involve adding something to the code already generated for sub- sub-expressions. Compiler Construction2 E ::= E + T{E.loc=newloc(); E.code=E 1.code || T.code || gen(add, E.loc, E 1.loc,T.loc)}

Add actions to a basic grammar Compiler Construction3 E ::= E + T | E – T | T T ::= T * F | T / F | F F ::= id | num

Add actions to a basic grammar Compiler Construction4 E ::= E + T | E – T | T T ::= T * F | T / F | F F ::= id | num { F.loc = newloc(); F.code=gen(loadimmediate, F.loc, num.lexval)}

Add actions to a basic grammar Compiler Construction5 E ::= E + T | E – T | T T ::= T * F | T / F | F F ::= id | num { F.loc = id.lexval; F.code=“”} { F.loc = newloc(); F.code=gen(loadimmediate, F.loc, num.lexval)}

Add actions to a basic grammar Compiler Construction6 E ::= E + T | E – T | T T ::= T * F | T / F | F F ::= id | num { F.loc = id.lexval; F.code=“”} { T.loc = F.loc; T.code=F.code} { F.loc = newloc(); F.code=gen(loadimmediate, F.loc, num.lexval)}

Add actions to a basic grammar Compiler Construction7 E ::= E + T | E – T | T T ::= T * F | T / F | F F ::= id | num { F.loc = id.lexval; F.code=“”} { T.loc = F.loc; T.code=F.code} { T.loc = newloc(); T.code=T 1.code || F.code || gen(div, T.loc, T 1.loc,F.loc)} { F.loc = newloc(); F.code=gen(loadimmediate, F.loc, num.lexval)}

Add actions to a basic grammar Compiler Construction8 E ::= E + T | E – T | T T ::= T * F | T / F | F F ::= id | num { F.loc = id.lexval; F.code=“”} { T.loc = F.loc; T.code=F.code} { T.loc = newloc(); T.code=T 1.code || F.code || gen(div, T.loc, T 1.loc,F.loc)} { T.loc = newloc(); T.code=T 1.code || F.code || gen(mul, T.loc, T 1.loc,F.loc)} { F.loc = newloc(); F.code=gen(loadimmediate, F.loc, num.lexval)}

Add actions to a basic grammar Compiler Construction9 E ::= E + T | E – T | T T ::= T * F | T / F | F F ::= id | num { F.loc = id.lexval; F.code=“”} { T.loc = F.loc; T.code=F.code} { T.loc = newloc(); T.code=T 1.code || F.code || gen(div, T.loc, T 1.loc,F.loc)} { T.loc = newloc(); T.code=T 1.code || F.code || gen(mul, T.loc, T 1.loc,F.loc)} { E.loc = T.loc; E.code=T.code} { F.loc = newloc(); F.code=gen(loadimmediate, F.loc, num.lexval)}

Add actions to a basic grammar Compiler Construction10 E ::= E + T | E – T | T T ::= T * F | T / F | F F ::= id | num { F.loc = id.lexval; F.code=“”} { T.loc = F.loc; T.code=F.code} { T.loc = newloc(); T.code=T 1.code || F.code || gen(div, T.loc, T 1.loc,F.loc)} { T.loc = newloc(); T.code=T 1.code || F.code || gen(mul, T.loc, T 1.loc,F.loc)} { E.loc = T.loc; E.code=T.code} { E.loc = newloc(); E.code=E 1.code || T.code || gen(sub, E.loc, E 1.loc,T.loc)} { F.loc = newloc(); F.code=gen(loadimmediate, F.loc, num.lexval)}

Add actions to a basic grammar Compiler Construction11 E ::= E + T | E – T | T T ::= T * F | T / F | F F ::= id | num { F.loc = id.lexval; F.code=“”} { T.loc = F.loc; T.code=F.code} { T.loc = newloc(); T.code=T 1.code || F.code || gen(div, T.loc, T 1.loc,F.loc)} { T.loc = newloc(); T.code=T 1.code || F.code || gen(mul, T.loc, T 1.loc,F.loc)} { E.loc = T.loc; E.code=T.code} { E.loc = newloc(); E.code=E 1.code || T.code || gen(sub, E.loc, E 1.loc,T.loc)} { E.loc = newloc(); E.code=E 1.code || T.code || gen(add, E.loc, E 1.loc,T.loc)} { F.loc = newloc(); F.code=gen(loadimmediate, F.loc, num.lexval)}

Is ‘code’ a synthesised attribute? That grammar had left-recursive productions, unsuited to top-down parsing, and all attributes were synthesised. If left-recursion is eliminated from a grammar, we have seen previously that for an existing synthesised attribute it may be necessary to introduce two new attributes, one inherited and one synthesised. There is a pattern for doing this: Where there are two original productions A ::= A b | c, a new nonterminal is needed, say A’ three non-left-recursive productions are needed For any existing synthesised attribute q used in the 2 original productions  the original q attribute is used only in the new production for A ::= c A’  an inherited attribute, say qi, passes progressively refined values for q down the right hand side of a parse tree, from A to A’ and from A’ to lower A’  a synthesised attribute, say qs, passes the ultimate value for q back up the tree Compiler Construction12

Attribute transformations in left-recursion removal Compiler Construction13 A ::= A b A ::= c { A.q = f ( A 1.q, b.q)} { A.q = g(c) } A ::= c { A’.qi = g(c) } A’ { A.q = A’.qs } A’ ::= b { A’ 1.qi = f( A’.qi, b.q)} A’ { A’.qs = A’ 1.qs} A’ ::=  { A’.qs = A’.qi} These grammars both generate one c followed by any number of b’s E ::= E + T E ::= E – T E ::= T { …, E.code= f1 (E 1.code, T.code) } { …, E.code = f2(E 1.code, T.code) } { …, E.code = g(T) } E ::= T { ? } E’ { E.code=E’.codes } E’ ::= + T { ? } E’ { E’.codes = E’ 1.codes } E’ ::= - T { ? } E’ { E’codes = E’ 1.codes } E’ ::=  { E’.codes = E’.codei } These grammars both generate one T followed by any number of either “+ T” or “- T” sequences Exercise: What replaces the ?s (in terms of f1, f2 and g)

Assignment statements In a programming language assignment statement, the value of an expression on the right-hand side is calculated and stored in a location named on the left-hand side. In general the location may be something simple like an identifier, an array element, a record slot. Calculation of a storage address is perhaps required. The expression on the right-hand side may be arbitrarily complicated. Calculation of a quantity is required. These two kinds of calculation are for so-called lvalue and rvalue respectively. Assn ::= id := Expr Assn ::= id [ Expr ] := Expr Compiler Construction14 { Assn.code = Expr.code || gen(load, id.lexval, Expr.loc)} { Assn.addr = newloc(); Assn.code = Expr 2.code || Expr 1.code || gen(add, Assn.addr, symtabaddr(id.lexval), Expr 1.loc) || gen(loadindirect, Assn.addr, Expr 2.loc)} gets the identifier’s address from compiler’s symbol table

Boolean Expressions Boolean expression syntax usually includes elements for  logical constants true and false  comparisons of arithmetic quantities – equal, not equal, greater, etc  boolean variables, array elements, functions etc  logical operators and or and not Boolean expressions have two uses  to calculate boolean quantities to be stored in variables, arrays etc  to determine flow of control – in loops, in if-then-else statements Compound boolean expressions can be evaluated in two distinct ways  akin to arithmetic expressions: evaluate subexpressions then combine values  in a “short-circuit” mode: later subexpressions may not always get evaluated Compiler Construction15 e.g. (k >= 0) and (k <= 99) and (B[k] /= 0)

Jumping code Code generated for boolean expressions almost always includes jumps & labels to affect control flow to use short-circuit evaluation exception possible only if both full evaluation and calculation to produce a value Compiler Construction16 Syntax WHILE boolexpr DO statement label one: <code for boolexpr that jumps -- to label two if true -- to label three if false> label two: jump to label one label three: Translation sketch Syntax bool 1 AND bool 2 Translation sketch (short-circuit) <code for bool 1 that jumps -- to label four if true -- to falselabel if false> label four: <code for bool 2 that jumps -- to truelabel if true -- to falselabel if false> inherited attributes in SDD/SDT

Semantic actions for sample of boolean productions Bool ::= Compiler Construction17 Expr < Expr Bool AND Bool { Bool.code= { Bool 1.falselabeli = Bool.falselabeli Bool 2.falselabeli = Bool.falselabeli Bool 1.truelabeli = newlabel() Bool 2.truelabeli = Bool.truelabeli Bool.code = Expr 1.code || Expr 2.code || gen(jumpifless, Expr 1.loc, Expr 2.loc, Bool.falselabeli) || gen(jumpalways, Bool.truelabeli) } Bool 1.code || gen(label, Bool 1.truelabeli) || Bool 2.code } Labels are not actual instructions, though they are generated as if they were. They are names attached to the next actual instruction in the sequence.

Where Boolean expressions are found Grammar productions which have a Bool anywhere on the right-hand-side must provide values for its falselabeli and truelabeli attributes In translating While loops, two labels are needed anyway to handle a return-to-start and escape-to-end situation. A third label is needed if the boolean expression is to be given short-circuit treatment – language designer’s choice In translating If-Then-Else statements, two labels are needed anyway, to handle the jump to the start of the else-code, and to handle the completion of the then-code. Again a third label is needed, labelling the start of the then-code, if the boolean expression is to be given short-circuit treatment. In translating assignments to boolean variables, two labels are needed. Compiler Construction18

Translating a While Loop Compiler Construction19 Stmt ::=while Bool do Stmt { Stmt.label_one= newlabel(); Stmt.label_two=newlabel(); Stmt.label_three=newlabel(); Bool.truelabeli=Stmt.label_two; Bool.falselabel=Stmt.label_three; { } { Stmt.code = gen(label, Stmt.label_one) || Bool.code || gen(label, Stmt.label_two) || Stmt 1.code || gen(jumpalways, Stmt.label_one) || gen(label, Stmt.label_three) }

Translating a While Loop Compiler Construction20 Stmt 0 ::=while Bool do Stmt 1 { Stmt 0.label_one= newlabel(); Stmt 0.label_two=newlabel(); Stmt 0.label_three=newlabel(); Bool.truelabeli=Stmt 0.label_two; Bool.falselabel=Stmt 0.label_three; { } { Stmt 0.code = gen(label, Stmt 0.label_one) || Bool.code || gen(label, Stmt 0.label_two) || Stmt 1.code || gen(jumpalways, Stmt 0.label_one) || gen(label, Stmt 0.label_three) }