Code Generation & Parameter Passing

Similar documents
The code generator must statically assign a location in the AR for each temporary add $a0 $t1 $a0 ; $a0 = e 1 + e 2 addiu $sp $sp 4 ; adjust $sp (!

Code Generation II. Code generation for OO languages. Object layout Dynamic dispatch. Parameter-passing mechanisms Allocating temporaries in the AR

Lecture Outline. Topic 1: Basic Code Generation. Code Generation. Lecture 12. Topic 2: Code Generation for Objects. Simulating a Stack Machine

Code Generation. Lecture 19

Code Generation. Lecture 12

The remote testing experiment. It works! Code Generation. Lecture 12. Remote testing. From the cs164 newsgroup

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

Code Generation Super Lectures

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

Wednesday, October 15, 14. Functions

G Programming Languages - Fall 2012

CA Compiler Construction

Run-time Environments

Run-time Environments

CIT Week13 Lecture

Compilers and computer architecture: A realistic compiler to MIPS

COL728 Minor2 Exam Compiler Design Sem II, Answer all 5 questions Max. Marks: 20

G Programming Languages Spring 2010 Lecture 4. Robert Grimm, New York University

System Software Assignment 1 Runtime Support for Procedures

Programming Languages

Scope, Functions, and Storage Management

Design Issues. Subroutines and Control Abstraction. Subroutines and Control Abstraction. CSC 4101: Programming Languages 1. Textbook, Chapter 8

Programming Languages Third Edition. Chapter 10 Control II Procedures and Environments

Separate compilation. Topic 6: Runtime Environments p.1/21. CS 526 Topic 6: Runtime Environments The linkage convention

Calling Conventions. Hakim Weatherspoon CS 3410, Spring 2012 Computer Science Cornell University. See P&H 2.8 and 2.12

Chapter 9 :: Subroutines and Control Abstraction

Procedure Calls Main Procedure. MIPS Calling Convention. MIPS-specific info. Procedure Calls. MIPS-specific info who cares? Chapter 2.7 Appendix A.

Chap. 8 :: Subroutines and Control Abstraction

Chapter 8 :: Subroutines and Control Abstraction. Final Test. Final Test Review Tomorrow

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

CS 314 Principles of Programming Languages. Lecture 13

Principles of Programming Languages

What the CPU Sees Basic Flow Control Conditional Flow Control Structured Flow Control Functions and Scope. C Flow Control.

CS558 Programming Languages

MIPS Functions and the Runtime Stack

Chapter 5: Procedural abstraction. Function procedures. Function procedures. Proper procedures and function procedures

Review of Activation Frames. FP of caller Y X Return value A B C

MIPS Programming. A basic rule is: try to be mechanical (that is, don't be "tricky") when you translate high-level code into assembler code.

Prof. Kavita Bala and Prof. Hakim Weatherspoon CS 3410, Spring 2014 Computer Science Cornell University. See P&H 2.8 and 2.12, and A.

CS143 - Written Assignment 4 Reference Solutions

CS558 Programming Languages Winter 2018 Lecture 4a. Andrew Tolmach Portland State University

Topic 7: Activation Records

Control Abstraction. Hwansoo Han

CS 480 Fall Runtime Environments. Mike Lam, Professor. (a.k.a. procedure calls and heap management)

See P&H 2.8 and 2.12, and A.5-6. Prof. Hakim Weatherspoon CS 3410, Spring 2015 Computer Science Cornell University

Programming Languages Third Edition. Chapter 7 Basic Semantics

Topic 3-a. Calling Convention 2/29/2008 1

Implementing Procedure Calls

Implementing Subprograms

Midterm II CS164, Spring 2006

CS164: Programming Assignment 5 Decaf Semantic Analysis and Code Generation

COMP 303 Computer Architecture Lecture 3. Comp 303 Computer Architecture

CSC 8400: Computer Systems. Using the Stack for Function Calls

Code Generation. Lecture 30

The Activation Record (AR)

Project Compiler. CS031 TA Help Session November 28, 2011

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

CS153: Compilers Lecture 8: Compiling Calls

Memory Usage 0x7fffffff. stack. dynamic data. static data 0x Code Reserved 0x x A software convention

Lecture 7: Procedures and Program Execution Preview

Do-While Example. In C++ In assembly language. do { z--; while (a == b); z = b; loop: addi $s2, $s2, -1 beq $s0, $s1, loop or $s2, $s1, $zero

Course Administration

! Those values must be stored somewhere! Therefore, variables must somehow be bound. ! How?

CSC 2400: Computer Systems. Using the Stack for Function Calls

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

Lecture 7: Procedures

Typical Runtime Layout. Tiger Runtime Environments. Example: Nested Functions. Activation Trees. code. Memory Layout

CSC 2400: Computer Systems. Using the Stack for Function Calls

Principle of Complier Design Prof. Y. N. Srikant Department of Computer Science and Automation Indian Institute of Science, Bangalore

Lecture 5: Procedure Calls

CSE Lecture In Class Example Handout

CSC 2400: Computing Systems. X86 Assembly: Function Calls"

LECTURE 19. Subroutines and Parameter Passing

Written Assignment 5 Due??

CSE 401/M501 Compilers

G Programming Languages - Fall 2012

Concepts Introduced in Chapter 7

CSE 504: Compiler Design. Runtime Environments

Code Generation Super Lectures

Chapter 2. Computer Abstractions and Technology. Lesson 4: MIPS (cont )

Lectures 5. Announcements: Today: Oops in Strings/pointers (example from last time) Functions in MIPS

Computer Architecture

Weeks 6&7: Procedures and Parameter Passing

CSc 520 final exam Wednesday 13 December 2000 TIME = 2 hours

CSc 520 Principles of Programming Languages. Questions. rocedures as Control Abstractions... 30: Procedures Introduction

Computer Architecture. Chapter 2-2. Instructions: Language of the Computer

CSC 2400: Computing Systems. X86 Assembly: Function Calls

Run-time Environment

Chapter 2A Instructions: Language of the Computer

CS2210: Compiler Construction. Runtime Environment

References and pointers

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

Runtime management. CS Compiler Design. The procedure abstraction. The procedure abstraction. Runtime management. V.

Ch. 11: References & the Copy-Constructor. - continued -

CS 61c: Great Ideas in Computer Architecture

Programming Languages: Lecture 12

ECE260: Fundamentals of Computer Engineering

Subroutines. Subroutine. Subroutine design. Control abstraction. If a subroutine does not fit on the screen, it is too long

Run-time Environments - 2

Transcription:

Code Generation & Parameter Passing

Lecture Outline 1. Allocating temporaries in the activation record Let s optimize our code generator a bit 2. A deeper look into calling sequences Caller/Callee responsibilities 3. Parameter passing mechanisms call-by-value, call-by-reference, call-by-value-result, call-by-name and call-by-need Compiler Design I (2011) 2

Extra Material in the Appendix (not covered in lecture) 4. Code generation for OO languages Object memory layout Dynamic dispatch 5. Code generation of data structure references Address calculations Array references 6. Code generation for logical expressions Short-circuiting Compiler Design I (2011) 3

An Optimization: Temporaries in the Activation Record Topic 1

Review The stack machine has activation records and intermediate results interleaved on the stack The code generator must assign a location in the AR for each temporary AR Temporaries AR Temporaries These get put here when we evaluate compound expressions like e 1 + e 2 (need to store e 1 while evaluating e 2 ) Compiler Design I (2011) 5

Review (Cont.) Advantage: Simple code generation Disadvantage: Slow code Storing/loading temporaries requires a store/load and $sp adjustment cgen(e 1 + e 2 ) = cgen(e 1 ) ; eval e 1 sw $a0 0($sp) ; save its value addiu $sp $sp-4 ; adjust $sp (!) cgen(e 2 ) ; eval e 2 lw $t1 4($sp) ; get e 1 add $a0 $t1 $a0 ; $a0 = e 1 + e 2 addiu $sp $sp-4 ; adjust $sp (!) Compiler Design I (2011) 6

An Optimization Idea: Predict how $sp will move at run time Do this prediction at compile time Move $sp to its limit, at the beginning The code generator must statically assign a location in the AR for each temporary Compiler Design I (2011) 7

Improved Code Old method cgen(e 1 + e 2 ) = cgen(e 1 ) sw $a0 0($sp) addiu $sp $sp-4 cgen(e 2 ) lw $t1 4($sp) add $a0 $t1 $a0 addiu $sp $sp-4 New idea cgen(e 1 + e 2 ) = cgen(e 1 ) sw $a0?($fp) statically allocate cgen(e 2 ) lw $t1?($fp) add $a0 $t1 $a0 Compiler Design I (2011) 8

Example add(w,x,y,z) begin x + (y + (z + (w + 42))) end What intermediate values are placed on the stack? How many slots are needed in the AR to hold these values? Compiler Design I (2011) 9

How Many Stack Slots? Let NS(e) = # of slots needed to evaluate e Includes slots for arguments to functions E.g: NS(e 1 + e 2 ) Needs at least as many slots as NS(e 1 ) Needs at least one slot to hold e 1, plus as many slots as NS(e 2 ), i.e. 1 + NS(e 2 ) Space used for temporaries in e 1 can be reused for temporaries in e 2 Compiler Design I (2011) 10

The Equations for Mini Bar NS(e 1 + e 2 ) = max(ns(e 1 ), 1 + NS(e 2 )) NS(e 1 -e 2 ) = max(ns(e 1 ), 1 + NS(e 2 )) NS(if e 1 = e 2 then e 3 else e 4 ) = max(ns(e 1 ), 1 + NS(e 2 ), NS(e 3 ), NS(e 4 )) NS(f(e 1,,e n )) = max(ns(e 1 ), 1 + NS(e 2 ), 2 + NS(e 3 ),, (n-1) + NS(e n ), n) NS(int) = 0 NS(id) = 0 Rule for f(e 1,, e n ): Each time we evaluate an argument, we put it on the stack. Compiler Design I (2011) 11

The Revised Activation Record For a function definition f(x 1,,x n ) begin e end the AR has 2 + NS(e) elements Return address Frame pointer NS(e) locations for intermediate results Note that f s arguments are now considered to be part of its caller s AR Compiler Design I (2011) 12

Picture: Activation Record popped by callee increasing values of addresses FP FP 4 x n... x 1 Old FP Return Addr. Temp NS(e)... Temp 1 direction of stack growth pushed by caller saved by callee (this diagram disagrees slightly with lecture 12: here, the callee saves FP) Compiler Design I (2011) 13

Revised Code Generation Code generation must know how many slots are in use at each point Add a new argument to code generation: the position of the next available slot Compiler Design I (2011) 14

Improved Code Old method cgen(e 1 + e 2 ) = cgen(e 1 ) sw $a0 0($sp) addiu $sp $sp -4 cgen(e 2 ) lw $t1 4($sp) add $a0 $t1 $a0 addiu $sp $sp 4 New method cgen(e 1 + e 2, ns) = cgen(e 1, ns) sw $a0 ns($fp) static allocation cgen(e 2, ns+4) lw $t1 ns($fp) add $a0 $t1 $a0 compile-time prediction Compiler Design I (2011) 15

Notes The slots for temporary values are still used like a stack, but we predict usage at compile time This saves us from doing that work at run time Allocate all needed slots at start of a function Exerc. Write some code which runs slower after performing the optimization just presented Hint: Think about memory usage (& caches, etc.) Compiler Design I (2011) 16

A Deeper Look into Calling Sequences Topic 2

Handling Procedure Calls and Returns Calling sequence: a code sequence that sets up a procedure call allocates an activation record (model-dependent) loads actual parameters saves machine state (return address, etc.) transfers control to callee Return sequence: a code sequence that handles the return from a procedure call deallocates the activation record sets up return value (if any) restores machine state (stack pointer, PC, etc.) Compiler Design I (2011) 18

Calling Sequences: Division of Responsibilities The code in a calling sequence is often divided up between the caller and the callee Calling sequence code caller callee If there are m calls to a procedure, the instructions in the caller s part of the calling sequence is repeated m times, while the callee s part is repeated exactly once This suggests that we should try to put as much of the calling sequence as possible in the callee However, it may be possible to carry out more callspecific optimization by putting more of the code into the caller instead of the callee Compiler Design I (2011) 19

Calling Sequences: Layout Issues General rule of thumb: Fields that are fixed early, are placed near the middle of the activation record The caller has to evaluate the actual parameters, and retrieve the return value these fields should be located near the caller s activation record The callee has to fill in machine status fields so that the callee can restore state on return the caller should have easy access to this part of the callee s activation record Compiler Design I (2011) 20

Calling/Return Sequences: Typical Actions Typical calling sequence: 1. caller evaluates actuals; pushes them on the stack 2. caller saves machine status on the stack (in the callee s AR) and updates the stack pointer 3. caller transfers control to the callee 4. callee saves registers, initializes local data, and begins execution Typical return sequence: 1. callee stores return value in the appropriate place 2. callee restores registers and old stack pointer 3. callee branches to the return address Compiler Design I (2011) 21

Example Activation Record: The SPARC Registers g0-g7 global registers o0-o7 outgoing args l0-l7 local registers i0-i7 incoming args function return address caller s o7/callee s i7 high addresses current fp caller s sp stack growth caller s frame locals and temporaries outgoing args not in o0-o5 space to save o0-05 if necessary addr of return value varies varies 6 words 1 word current sp space to save i0-i7 and l0-l7 if necessary 16 words callee s fp callee s frame low addresses Compiler Design I (2011) 22

Example Activation Record: Intel x86 high addresses caller s frame incoming arguments frame ptr ebp stack ptr esp low addresses return address saved registers saved ebp locals and temporaries callee s frame stack growth Compiler Design I (2011) 23

Example Activation Record: MIPS R3000 high addresses caller s frame incoming arguments locals and temporaries callee-save registers stack growth stack ptr $sp outgoing arguments callee s frame low addresses Compiler Design I (2011) 24

Parameter Passing Mechanisms Topic 3

Parameter Passing Mechanisms There are many semantic issues in programming languages centering on when values are computed, and the scopes of names Evaluation is the heart of computation Names are most primitive abstraction mechanism We will focus on parameter passing When are arguments of function calls evaluated? What are formal parameters bound to? Compiler Design I (2011) 26

Parameter Passing Mechanisms (Cont.) First, an issue not discussed much Order of argument evaluation - Usually not important for the execution of a program However, in languages that permit side-effects in call arguments, different evaluation orders may give different results e.g. a call f(++x,x) in C A standard evaluation order is then specified C compilers typically evaluate their arguments right-to-left. Why? Compiler Design I (2011) 27

Call-by-value C uses call-by-value everywhere (except macros...) Default mechanism in Pascal and in Ada callbyvalue(int y) { y = y + 1; print(y); } main() { int x = 42; print(x); callbyvalue(x); print(x); } output: x = 42 y = 43 x = 42 x s value does not change when y s value is changed Compiler Design I (2011) 28

Call-by-reference Available in C++ with the & type constructor (and in Pascal with the var keyword) callbyref(int &y) { y = y + 1; print(y); } main() { int x = 42; print(x); callbyref(x); print(x); } output: x = 42 y = 43 x = 43 x s value changes when y s value is changed Compiler Design I (2011) 29

Call-by-reference can be faked with pointers C++: C: callbyref(int &y) { y = y + 1; print(y); } main() { int x = 42; print(x); callbyref(x); print(x); } fakecallbyref(int *y) { *y = *y + 1; print(*y); } must explicitly pass the address of a local variable main() { int x = 42; print(x); fakecallbyref(&x); print(x); } Compiler Design I (2011) 30

Pointers to fake call-by-reference (cont.) It s not quite the same A pointer can be reassigned to point at something else; a C++ reference cannot The pointer itself was passed by value This is how you pass arrays (they are implicitly pointers) and structures in C Compiler Design I (2011) 31

Call-by-value-result Available in Ada for in out parameters (code below in C syntax) callbyvalueresult(int y, int z) { } y = y + 1; z = z + 1; print(y); print(z); main() { int x = 42; print(x); callbyvalueresult(x, x); print(x); } output: x = 42 y = 43 z = 43 x = 43 Note that x s value is different from both using call-by-value and call-by-reference Compiler Design I (2011) 32

What about Java? Primitive types (int, boolean, etc.) are always passed by value Objects are not quite -by-value nor -by-reference: If you reassign an object reference, the caller s argument does not get reassigned (like -by-value) But if the object referred-to is modified, that modification is visible to the caller (like -byreference) It s really ordinary call-by-value with pointers, but the pointers are not syntactically obvious Compiler Design I (2011) 33

Implementing Parameter Passing Call-by by-value value (easy, no special compiler effort) The arguments are evaluated at the time of the call and the value parameters are copied and either behave as constant values during the execution of the procedure (i.e., cannot be assigned to as in Ada), or are viewed as initialized local variables (in C or in Pascal) Call-by by-reference The arguments must have allocated memory locations The compiler passes the address of the variable, and the parameter becomes an alias for the argument Local accesses to the parameter are turned into indirect accesses Compiler Design I (2011) 34

Implementing Parameter Passing (Cont.) Call-by by-value-result The arguments are evaluated at call time and the value parameters are copied (as in call-by-value) and used as a local variables The final values of these variables are copied back to the location of the arguments when the procedure exits (note that the activation record cannot be freed by the callee!) Issues left unspecified: the order in which the results are copied back whether the locations of the arguments are calculated only on entry and stored, or whether they are recalculated on exit Compiler Design I (2011) 35

Call-by-name Whole different ballgame: it s like passing the text of the argument expression, unevaluated The text of the argument is viewed as a function in its own right Also passes the environment, so free variables are still bound according to rules of static scoping The argument is not evaluated until it is actually used, inside the callee Might not get evaluated at all! An optimized version of call-by-name is used in some functional languages (e.g. Haskell, Miranda, Lazy-ML) under the names lazy evaluation (or call-by-need) Compiler Design I (2011) 36

Call-by-name example (in C++-Extra ) code + environment (env has just x here) callbyname(int closure y) { eval print(y); print(y); // => print(x = x+1) } both evals main() have side { effects int x = 42; print(x); callbyname( [[ x = x+1 ]] ); print(x); } closure output: x = 42 y = 43 y = 44 x = 44 x s value changes when y is evaluated Compiler Design I (2011) 37

Code Generation for OO Languages Topic 4 (probably not covered in lecture)

Object Layout Object-Oriented (OO) code generation and memory layout OO Slogan: If C (child) is a subclass of P (parent), then an instance of class C can be used wherever an instance of class P is expected This means that P s methods should work with an instance of class C Compiler Design I (2011) 39

Two Issues How are objects represented in memory? How is dynamic dispatch implemented? Compiler Design I (2011) 40

Object Representation class P { x : Int <- 3; y : String <- "Hi"; f( ) : Int { x }; z : Bool <- true; g( ) : String { y }; }; self 0 1 2 3 4 5 tag: P x y f( ) z g( ) 3 Hi P.f: return self [1] true P.g: return self [2] Why method pointers? Why the tag? dynamic dispatch case self To call f: lw $t1 12($s0) jalr $t1 Compiler Design I (2011) 41

Subclass Representation class P {.. (same).. }; self class C inherits P { w : Int <- 42; // new P f( ) : Int { w }; // override h( ) : Bool { z }; // new }; C Idea: Append new fields 0 1 2 3 4 5 6 7 tag: C x y f( ) z g( ) w h( ) 3 Hi true overridden C.f: return self [6] P.g: return self [2] 42 To call f: lw $t1 12($s0) jalr $t1 C.h: return self [4] inherited Compiler Design I (2011) 42

Subclasses (Cont.) The offset for an attribute is the same in a class and all of its subclasses Any method for an A 1 can be used on a subclass A 2 Consider layout for A n < < A 3 < A 2 < A 1 Header A 1 attrs A 2 attrs A 3 attrs... A 1 object A 2 object A 3 object What about multiple inheritance? Compiler Design I (2011) 43

What s the point? Simple Just append subclass fields Efficient Code can ignore dynamic type -- just act as if it is the static type Supports overriding of methods Just replace the appropriate dispatch pointers We implement type conformance (compile-time concept) with representation conformance (run-time concept) Compiler Design I (2011) 44

An optimization: Dispatch Tables Consider 3 instances of class C: tag: C x y f( ) z g( ) w h( ) C.f: return self [6] tag: C x y f( ) z g( ) w h( ) tag: C x y f( ) z g( ) w h( ) C.h: return self [4] P.g: return self [2] Compiler Design I (2011) 45

Observation Every instance of a given class has the same values for all of its method pointers Space optimization: Put all method pointers for a given class into a common table, called the dispatch table Each instance has a pointer to the dispatch table Compiler Design I (2011) 46

Picture with Dispatch Table Consider again 3 instances of C: 0 1 2 3 4 5 tag: C dispptr x y z w tag: C dispptr x y z w tag: C dispptr x y z w minor point: the offsets have changed since we removed the method ptrs Objects are smaller Dispatch is slower f( ) C.f: return self [5] g( ) P.g: return self [3] h( ) C.h: return self [4] Compiler Design I (2011) 47

Subclassing Again P.f: return self [2] 0 1 2 3 4 tag: P dispptr x y z tag: C dispptr x y z w 0 1 2 3 4 5 call f: lw $t1 4($s0) lw $t1 0($t1) jalr $t1 0 1 f( ) g( ) P.g: return self [3] C.f: return self [5] f( ) g( ) h( ) C.h: return self [4] Compiler Design I (2011) 48

Real Object Layout Actually, the first 3 words of objects contain header information: Needed for garbage collector Class Tag Object Size Dispatch Ptr Attribute 1 Attribute 2... Offset (in bytes) 0 4 8 12 16 Compiler Design I (2011) 49

Summary of Dispatch Tables Pulled method pointers out, into separate table Makes objects smaller Makes (dynamic) dispatch slower Q: Why don t we do this for attributes? Exerc. Write some code that is slower with dispatch tables (instead of embedded method pointers) Exerc. Write some code that is faster with dispatch tables Compiler Design I (2011) 50