CSE443 Compilers. Dr. Carl Alphonce 343 Davis Hall

Similar documents
CSE443 Compilers. Dr. Carl Alphonce 343 Davis Hall

CSE443 Compilers. Dr. Carl Alphonce 343 Davis Hall

Intermediate Code Generation

Intermediate Code Generation

intermediate-code Generation

CSE302: Compiler Design

Formal Languages and Compilers Lecture X Intermediate Code Generation

CSE443 Compilers. Dr. Carl Alphonce 343 Davis Hall

Compilerconstructie. najaar Rudy van Vliet kamer 140 Snellius, tel rvvliet(at)liacs(dot)nl. college 7, vrijdag 2 november 2018

CS2210: Compiler Construction. Code Generation

Concepts Introduced in Chapter 6

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

Intermediate Code Generation

Principle of Compilers Lecture VIII: Intermediate Code Generation. Alessandro Artale

Module 25 Control Flow statements and Boolean Expressions

Intermediate Representa.on

Concepts Introduced in Chapter 6

CSc 453 Intermediate Code Generation

CS322 Languages and Compiler Design II. Spring 2012 Lecture 7

CMPT 379 Compilers. Anoop Sarkar. 11/13/07 1. TAC: Intermediate Representation. Language + Machine Independent TAC

Intermediate Representations

THEORY OF COMPILATION

Run-Time Data Structures

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

Intermediate Code Generation Part II

Intermediate Code Generation

CMPSC 160 Translation of Programming Languages. Three-Address Code

CS 432 Fall Mike Lam, Professor. Code Generation

NARESHKUMAR.R, AP\CSE, MAHALAKSHMI ENGINEERING COLLEGE, TRICHY Page 1

CSE443 Compilers. Dr. Carl Alphonce 343 Davis Hall

Control Structures. Boolean Expressions. CSc 453. Compilers and Systems Software. 16 : Intermediate Code IV

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

TACi: Three-Address Code Interpreter (version 1.0)

Intermediate Representations & Symbol Tables

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

Symbol Tables. ASU Textbook Chapter 7.6, 6.5 and 6.3. Tsan-sheng Hsu.

Semantic actions for expressions

CSCI Compiler Design

The SPL Programming Language Reference Manual

CSE115 / CSE503 Introduction to Computer Science I Dr. Carl Alphonce 343 Davis Hall Office hours:

Semantic actions for declarations and expressions

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

& Simulator. Three-Address Instructions. Three-Address Instructions. Three-Address Instructions. Structure of an Assembly Program.

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

Chapter 6 Intermediate Code Generation

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

Intermediate-Code Generat ion

Java Identifiers, Data Types & Variables

CSE115 / CSE503 Introduction to Computer Science I. Dr. Carl Alphonce 343 Davis Hall Office hours:

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

Semantic actions for declarations and expressions

Languages and Compiler Design II IR Code Generation I

KU Compilerbau - Programming Assignment

Type Checking Binary Operators

CSE 504. Expression evaluation. Expression Evaluation, Runtime Environments. One possible semantics: Problem:

Lecture 7: Type Systems and Symbol Tables. CS 540 George Mason University

Object Code (Machine Code) Dr. D. M. Akbar Hussain Department of Software Engineering & Media Technology. Three Address Code

Intermediate Code Generation

CS /534 Compiler Construction University of Massachusetts Lowell. NOTHING: A Language for Practice Implementation

Example. program sort; var a : array[0..10] of integer; procedure readarray; : function partition (y, z :integer) :integer; var i, j,x, v :integer; :

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

CSE115 / CSE503 Introduction to Computer Science I Dr. Carl Alphonce 343 Davis Hall Office hours:

ECS 142 Project: Code generation hints (2)

Introduction to Programming Using Java (98-388)

CSE P 501 Compilers. Static Semantics Hal Perkins Winter /22/ Hal Perkins & UW CSE I-1

Today's Topics. CISC 458 Winter J.R. Cordy

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

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

CSIS1120A. 10. Instruction Set & Addressing Mode. CSIS1120A 10. Instruction Set & Addressing Mode 1

COMPILER CONSTRUCTION (Intermediate Code: three address, control flow)

Principles of Compiler Design

Scope, Functions, and Storage Management

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

Programming Languages and Compiler Design

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

LECTURE 18. Control Flow

CSE 401/M501 Compilers

Implementing Subprograms

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

CSE450. Translation of Programming Languages. Lecture 11: Semantic Analysis: Types & Type Checking

SOURCE LANGUAGE DESCRIPTION

CSE302: Compiler Design

CSE443 Compilers. Dr. Carl Alphonce 343 Davis Hall

CMPT Sample Final Exam

General issues. Section 9.1. Compiler Construction: Code Generation p. 1/18

Intermediate Code Generation

Programming Fundamentals - A Modular Structured Approach using C++ By: Kenneth Leroy Busbee

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

KU Compilerbau - Programming Assignment

Type Checking. Error Checking

Page No 1 (Please look at the next page )

Intermediate Code Generation

Procedure and Object- Oriented Abstraction

What is SaM? SaM is a simple stack machine designed to introduce you to compilers in a few lectures SaM I: written by Dr. Keshav Pingali around 2000

The PCAT Programming Language Reference Manual

Summary: Direct Code Generation

CS 536 Introduction to Programming Languages and Compilers Charles N. Fischer Lecture 11

CSE443 Compilers. Dr. Carl Alphonce 343 Davis Hall

COMP-520 GoLite Tutorial

This section provides some reminders and some terminology with which you might not be familiar.

Transcription:

CSE443 Compilers Dr. Carl Alphonce alphonce@buffalo.edu 343 Davis Hall http://www.cse.buffalo.edu/faculty/alphonce/sp17/cse443/index.php https://piazza.com/class/iybn4ndqa1s3ei

shift/reduce conflict with easy fix pblock and dblock similarities seem to result in difficulties (grammar conflicts) Have all teams run into this? A simple fix seems to be: change the delimiters used in dblock from '(' and ')' to '[' and ']', as in: dblock is: '[' declaration-list ']'

Phases of a compiler Intermediate Representation (IR): specification and generation Figure 1.6, page 5 of text

Three address code instructions (see 6.2.1, pages 364-5) 1. x = y op z 2. x = op y (treat i2r and r2i as unary ops) 3. x = y 4. goto L 5. if x goto L / iffalse x goto L 6. if x relop y goto L 7. function calls: - param x - call p, n - y = call p - return y 8. x = y[i] and x[i] = y Need operators for various types: let's use <t>op, as in i+ or r* or b< 9. x = &y, x = *y, *x = y

dblocks (6.3.5 and 6.3.6) records (in separate symbol table), sequence of declarations at start of sblock definition > type identifier ':' dblock { st.put(identifier.lexeme, TYPE, dblock.type, dblock.width dblock > '(' { Env.push(st); st = new Env(); Stack.push(offset); offset = 0; declaration-list ')' { dblock.type=record(st); dblock.width=offset; st=env.pop(); offset=stack.pop(); declaration-list > declaration ';' declaration-list declaration-list > declaration declaration > identifier ':' { id-list.type = identifier; < however you store types identifier-list (maybe pointer into st?) identifier-list > identifier ( sbinop constant ) ',' { st.put(identifier.lexeme, VAR, identifier-list.type, offset); offset = offset + identifier-list.type.width; identifier-list identifier-list > identifier ( sbinop constant ) { st.put(identifier.lexeme, VAR, identifier-list.type, offset); offset = offset + identifier-list.type.width; Just suggestions, not to be taken literally

dblocks (6.3.5 and 6.3.6) records (in separate symbol table), sequence of declarations at start of sblock definition > type identifier ':' dblock { st.put(identifier.lexeme, TYPE, dblock.type, dblock.width dblock > '(' { Env.push(st); st = new Env(); Stack.push(offset); offset = 0; declaration-list ')' We can specialize due to the structure of our grammar: see next slide! { dblock.type=record(st); dblock.width=offset; st=env.pop(); offset=stack.pop(); declaration-list > declaration ';' declaration-list declaration-list > declaration declaration > identifier ':' { id-list.type = identifier; < however you store types identifier-list (maybe pointer into st?) identifier-list > identifier ( sbinop constant ) ',' { st.put(identifier.lexeme, VAR, identifier-list.type, offset); offset = offset + identifier-list.type.width; identifier-list identifier-list > identifier ( sbinop constant ) { st.put(identifier.lexeme, VAR, identifier-list.type, offset); offset = offset + identifier-list.type.width; Just suggestions, not to be taken literally

dblocks (6.3.5 and 6.3.6) records (in separate symbol table), sequence of declarations at start of sblock Since declarations must be gathered together at the start of an sblock, and cannot themselves be directly nested, we can do better: dblock > '(' { Env.push(st); st = new Env(); Stack.push(offset); offset = 0; declaration-list ')' { dblock.type=record(st); dblock.width=offset; st=env.pop(); offset=stack.pop(); offset = 0 offset = 4 { ( integer : x, y ) integer: x integer: x integer: x push onto stack offset = 16 offset = 24 { ( real : x, z ) pop from stack push onto stack integer: y integer: y real: x integer: y Boolean: y character: z { ( Boolean : y ; character : z ) offset = 9 offset = 10 real: z pop from stack

dblocks (6.3.5 and 6.3.6) records (in separate symbol table), sequence of declarations at start of sblock Since declarations must be gathered together at the start of an sblock, and cannot themselves be directly nested, we can do better: dblock > '(' { Env.push(st); st = new Env(); Stack.push(offset); offset = 0; declaration-list ')' { dblock.type=record(st); dblock.width=offset; st=env.pop(); offset=stack.pop(); offset = 0 { ( integer : x, y ) { ( real : x, z ) { ( Boolean : y ; character : z ) offset = 4 push onto stack offset = 16 offset = 24 pop from stack push onto stack offset = 9 pop from stack offset = 10 integer: x integer: y AT RUNTIME

dblocks (6.3.5 and 6.3.6) records (in separate symbol table), sequence of declarations at start of sblock Since declarations must be gathered together at the start of an sblock, and cannot themselves be directly nested, we can do better: dblock > '(' { Env.push(st); st = new Env(); Stack.push(offset); offset = 0; declaration-list ')' { dblock.type=record(st); dblock.width=offset; st=env.pop(); offset=stack.pop(); offset = 0 { ( integer : x, y ) { ( real : x, z ) { ( Boolean : y ; character : z ) offset = 4 push onto stack offset = 16 offset = 24 pop from stack push onto stack offset = 9 pop from stack offset = 10 integer: x integer: y real: x real: z AT RUNTIME

dblocks (6.3.5 and 6.3.6) records (in separate symbol table), sequence of declarations at start of sblock Since declarations must be gathered together at the start of an sblock, and cannot themselves be directly nested, we can do better: dblock > '(' { Env.push(st); st = new Env(); Stack.push(offset); offset = 0; declaration-list ')' { dblock.type=record(st); dblock.width=offset; st=env.pop(); offset=stack.pop(); offset = 0 { ( integer : x, y ) { ( real : x, z ) { ( Boolean : y ; character : z ) offset = 4 push onto stack offset = 16 offset = 24 pop from stack push onto stack offset = 9 pop from stack offset = 10 integer: x integer: y AT RUNTIME

dblocks (6.3.5 and 6.3.6) records (in separate symbol table), sequence of declarations at start of sblock Since declarations must be gathered together at the start of an sblock, and cannot themselves be directly nested, we can do better: dblock > '(' { Env.push(st); st = new Env(); Stack.push(offset); offset = 0; declaration-list ')' { dblock.type=record(st); dblock.width=offset; st=env.pop(); offset=stack.pop(); offset = 0 { ( integer : x, y ) { ( real : x, z ) { ( Boolean : y ; character : z ) offset = 4 push onto stack offset = 16 offset = 24 pop from stack push onto stack offset = 9 pop from stack offset = 10 integer: x integer: y Boolean: y character: z AT RUNTIME

dblocks (6.3.5 and 6.3.6) records (in separate symbol table), sequence of declarations at start of sblock Since declarations must be gathered together at the start of an sblock, and cannot themselves be directly nested, we can do better: dblock > '(' { Env.push(st); st = new Env(); Stack.push(offset); offset = 0; declaration-list ')' { dblock.type=record(st); dblock.width=offset; st=env.pop(); offset=stack.pop(); offset = 0 { ( integer : x, y ) { ( real : x, z ) { ( Boolean : y ; character : z ) offset = 4 push onto stack offset = 16 offset = 24 pop from stack push onto stack offset = 9 pop from stack offset = 10 integer: x integer: y AT RUNTIME

Dealing with alignment Boolean: a integer: x { [ Boolean : a ; integer : x ; character c; real : y ] character: c { [ character : d ; integer : r, s ] { [ Boolean : f, g ; real : t ; character h ] real: y Blocks are not aligned.

Dealing with alignment Boolean: a { [ Boolean : a ; integer : x ; character c; real : y ] integer: x { [ character : d ; integer : r, s ] character: c { [ Boolean : f, g ; real : t ; character h ] real: y Blocks are not aligned, but memory wasted to padding

Dealing with alignment integer: x { [ Boolean : a ; integer : x ; character c; real : y ] { [ character : d ; integer : r, s ] real: y { [ Boolean : f, g ; real : t ; character h ] Boolean: a character: c Blocks are aligned, no padding needed here.

Dealing with alignment integer: x { [ Boolean : a ; integer : x ; character c; real : y ] { [ character : d ; integer : r, s ] real: y { [ Boolean : f, g ; real : t ; character h ] Boolean: a character: c Blocks are aligned, padding needed before embedded scope block. integer: r integer: s character: d

Expressions (6.4) exp > exp > assignable { exp.addr = assignable.addr; exp.code = exp 1.code; exp > '(' exp 1 ')' { exp.addr = exp 1.addr; exp.code = exp 1.code; exp > exp 1 binaryoperator exp 2 { exp.addr = new Temp(); exp.code = exp 1.code exp 2.code gen(exp.addr '=' exp 1.addr '+' exp 2.addr;

Assignables (6.4) assignable > identifier { assignable.addr = ; assignable.isfuncall = whether identifier has a function type - check symbol table assignable > assignable 1 ablock assignable 1 can be function call: we can return pointers to functions & arrays { assignable.addr = ; temporary of return value, if function call, else address of array element has a function type - check symbol table assignable.isfuncall = whether identifier assignable > assignable 1 recop identifier { assignable 1 can be function call so we can return pointers to records

'assignable' is poorly named statement > assignable sbinop expression ';' { if assignable.isfuncall then error

resolving overloaded operators Fig 6.27, p. 390: after type checking and possibly coercions, then 6.5.3 choose correct operation to perform E -> E1 + E2 { E.type = max(e1.type, E2.type); a1 = widen(e1.addr, E1.type, E.type); a2 = widen(e2.addr, E2.type, E.type); E.addr = new Temp(); gen(e.addr '=' a1 '+' a2);

resolving overloaded operators Fig 6.27, p. 390: after type checking and possibly coercions, then 6.5.3 choose correct operation to perform E -> E1 + E2 { E.type = max(e1.type, E2.type); a1 = widen(e1.addr, E1.type, E.type); a2 = widen(e2.addr, E2.type, E.type); E.addr = new Temp(); gen(e.addr '=' a1 '+' a2); Are we doing int addition or floating point addition? i+ vs. f+??

Skip 6.5.4-6.5.6

Control flow Booleans to control flow Booleans as values

Boolean expressions! X X & Y X Y We will do short-circuit evaluation if (X Y & Z) then { A else { B is translated as if X goto LA iffalse Y goto LB iffalse Z goto LB LA: A goto END LB: B END: (next instruction)

Boolean expressions A more concrete example: if ( r < s r = s & 0 < s) then { A else { B is translated as if r < s goto LA iffalse r = s goto LB iffalse 0 < s goto LB LA: A goto END LB: B END: (next instruction)

Boolean expressions A more concrete example: if ( r < s r = s & 0 < s) then S1 else S2 is translated as if r < s goto LA iffalse r = s goto LS1 iffalse 0 < s goto LS2 LS1: A goto END LS2: B END: (next instruction) CMP r s BLT LA "The compare instruction compares two values and updates condition codes based on the difference obtained from subtracting s from r The Zero (Z) flag is set if the difference is zero. Otherwise it is reset (0). The Negative (N) flag is set if the difference is negative the Carry (C) flag is set if there is a carry out when the difference is computed. The Overflow (V) flag is set if the result of the difference overflows a 32-bit value." [Schindler, p. 46]

Flow-of-Control (6.3.3) if ( B ) then S1 else S2 B.true = newlabel() B.false = newlabel() S.next = S1.next = S2.next S.code = B.code label(b.true) S1.code gen('goto' S.next) label(b.false) S2.code LS1 LS2 B.code S1.code goto END S2.code iftrue: goto LS1 iffalse: goto LS2 END

Flow-of-Control (6.3.3) S -> if ( B ) then S1 B.true = newlabel() B.false = S.next = S1.next S.code = B.code label(b.true) S1.code LS1 B.code S1.code iftrue: goto LS1 iffalse: goto END END

Flow-of-Control (6.3.3) while ( B ) then S1 BEGIN B.code iftrue: goto LS1 iffalse: begin = newlabel() LS1 goto END B.true = newlabel() B.false = S.next S1.code S1.next = begin S.code = label(begin) B.code label(b.true) S1.code gen('goto' begin) END goto BEGIN

Value of Boolean expression "When E appears in S -> while (E) S1, method jump is called at node E.n [ ] When E appears in S -> id = E;, method rvalue is called at node E.n" [p. 408]

Figure 6.42 [p. 409] Translation of: x = a<b && c<d iffalse a < b goto L1 ifflase c < d goto L1 t = true goto L2 L1: t = false L2: x = t