22
1 Runtime Organization (Chapter 6) Course Overview PART I: overview material 1 Introduction 2 Language processors (tombstone diagrams, bootstrapping) 3 Architecture of a compiler PART II: inside a compiler 4 Syntax analysis 5 Contextual analysis 6 Runtime organization 7 Code generation PART III: conclusion 8 Interpretation 9 Review

Course Overview

Embed Size (px)

DESCRIPTION

Course Overview. PART I: overview material 1Introduction 2Language processors (tombstone diagrams, bootstrapping) 3 Architecture of a compiler PART II: inside a compiler 4Syntax analysis 5Contextual analysis 6 Runtime organization 7Code generation PART III: conclusion - PowerPoint PPT Presentation

Citation preview

Page 1: Course Overview

1Runtime Organization (Chapter 6)

Course Overview

PART I: overview material1 Introduction

2 Language processors (tombstone diagrams, bootstrapping)

3 Architecture of a compiler

PART II: inside a compiler4 Syntax analysis

5 Contextual analysis

6 Runtime organization

7 Code generation

PART III: conclusion8 Interpretation

9 Review

Page 2: Course Overview

2Runtime Organization (Chapter 6)

Arguments

We have already discussed how space on the stack is allocated for arguments to routines.

We now discuss some specific issues about• passing by value versus passing by reference• passing of functional and procedural parameters

Page 3: Course Overview

3Runtime Organization (Chapter 6)

Arguments: by value or by reference

Some programming languages allow two kinds of parameter passing to functions/procedures.

Example: in Triangle (similar in Pascal or C++)

let proc S(var n:Integer, i:Integer) ~ n:=n+i; var today: record y:integer, m:Integer, d:Integer end;in begin b := {y ~ 2002, m ~ 2, d ~ 22}; ! b is non-local S(var b.m, 6);end

let proc S(var n:Integer, i:Integer) ~ n:=n+i; var today: record y:integer, m:Integer, d:Integer end;in begin b := {y ~ 2002, m ~ 2, d ~ 22}; ! b is non-local S(var b.m, 6);end

Constant/value parameterVar/reference parameter

Page 4: Course Overview

4Runtime Organization (Chapter 6)

Arguments: by value or by reference

Value parameters:At the call site the argument is an expression. The evaluation of that expression leaves some value on the stack. This value is passed to the procedure/function.Typical instructions for putting a value parameter on the stack:LOADL 6 LOAD 3[L1]

Var/reference parameters:Instead of passing a value on the stack, the address of a memory location is pushed. This implies a restriction that only “variable-like” things can be passed to a var parameter. In Triangle there is an explicit keyword var at the call-site, to signal passing a var parameter. In Pascal and C++ the reference is created implicitly (but the same restrictions apply). Typical instructions for putting a var parameter on the stack:LOADA 5[LB] LOADA 10[SB]

Page 5: Course Overview

5Runtime Organization (Chapter 6)

Functional / Procedural ParametersIn Triangle (and Pascal) a limited version of higher-order programming is possible. One may pass functions/procedures as arguments to other functions/procedures. (Unlike Scheme, they are not first-class values!) Example 1: let func twice(func doIt(Integer x): Integer,

Integer i) ~ doIt(doIt(i)); func double(Integer d): Integer ~ d*2; var twenty : Integerin begin twenty := twice(double,5);end

let func twice(func doIt(Integer x): Integer, Integer i) ~

doIt(doIt(i)); func double(Integer d): Integer ~ d*2; var twenty : Integerin begin twenty := twice(double,5);end

A procedural/functional parameter is passed by pushing a “closure” on the stack. A closure consists of two parts:1. the static link of the procedure/function2. the address of the procedure/function

Page 6: Course Overview

6Runtime Organization (Chapter 6)

Functional / Procedural Parameters

Example 2: (illustrates we can pass non-global functions as well)

let func twice(func doIt(Integer x): Integer, Integer i) ~ doIt(doIt(i)); func cubed(Integer b): Integer ~ let func multiply(Integer x): Integer ~ x*b in twice(multiply, b); in begin ... ... cubed(4) ... end

let func twice(func doIt(Integer x): Integer, Integer i) ~ doIt(doIt(i)); func cubed(Integer b): Integer ~ let func multiply(Integer x): Integer ~ x*b in twice(multiply, b); in begin ... ... cubed(4) ... end

accesses lexically scoped var

See pictures of stack beginning on next slide…

Page 7: Course Overview

7Runtime Organization (Chapter 6)

Functional / Procedural Parameters

4

SB

LBarg b

ST

linkdata

right after calling cubed right before call to twice

4LB

arg b

ST

linkdata

multiplyclosure

4

arg #1

arg #2

static link

function address

multiplyfunctioncode

Page 8: Course Overview

8Runtime Organization (Chapter 6)

Functional / Procedural Parameters

right after call to twice

4

LB

arg b

ST

linkdata

multiplyclosure

4

arg doIt

arg ilinkdata

4

LB

arg b

ST

linkdata

multiplyclosure

4

arg doIt

arg ilinkdata

before first call to doIt

4arg #1

multiply multiply

multiplyclosure multiply

Note: to avoid clutter, dynamiclinks are not shown.Only some static links are shown.

closure to call

Page 9: Course Overview

9Runtime Organization (Chapter 6)

Functional / Procedural Parameters

4

LB

arg b

ST

linkdata

multiplyclosure

4

arg doIt

arg ilinkdata

before first call to doIt

4arg #1

4

LB

arg b

ST

linkdata

multiplyclosure

4

arg doIt

arg ilinkdata

right after first call to doIt

4arg x

multiply multiply

linkdata

multiplyclosure multiply

execution of CALLI instruction (Call Indirect)

closure to call

Page 10: Course Overview

10Runtime Organization (Chapter 6)

Functional / Procedural Parameters

4

LB

arg b

ST

linkdata

multiplyclosure

4

arg doIt

arg ilinkdata

right after first call to doIt

4arg x

multiply

linkdata

4

LB

arg b

ST

linkdata

multiplyclosure

4

arg doIt

arg ilinkdata

just before x*b in multiply

4arg x

multiply

linkdata

4value of xvalue of b 4

LOAD [-1]LBLOAD [-1]L1

Page 11: Course Overview

11Runtime Organization (Chapter 6)

Functional / Procedural Parameters

4

LB

arg b

ST

linkdata

multiplyclosure

4

arg doIt

arg ilinkdata

just before return doIt/multiply

4arg x

multiply

linkdata16value of x*b

4

LB

arg b

ST

linkdata

multiplyclosure

4

arg doIt

arg ilinkdata

just after return doIt/multiply

multiply

16value of doIt(4)

Page 12: Course Overview

12Runtime Organization (Chapter 6)

Functional / Procedural Parameters

4

LB

arg b

ST

linkdata

multiplyclosure

4

arg doIt

arg ilinkdata

just before second call to doIt

multiply

16arg #1multiplyclosure multiply

closure to call

4

LB

arg b

ST

linkdata

multiplyclosure

4

arg doIt

arg ilinkdata

just before x*b in multiply

16arg x

multiply

linkdata16value of x

value of b 4LOAD [-1]LBLOAD [-1]L1

Page 13: Course Overview

13Runtime Organization (Chapter 6)

Functional / Procedural Parameters

4

LB

arg b

ST

linkdata

multiplyclosure

4

arg doIt

arg ilinkdata

just after return doIt/multiply= just before return from “twice”

multiply

64value of doIt(16)

4LB

ST

linkdata

multiplyclosure

64

arg doIt

value of twice(multiply,4)multiply

just after return from “twice”=just before return from cubed

64

just after return from cubed

value of cubed(4)ST

Page 14: Course Overview

14Runtime Organization (Chapter 6)

Functional / Procedural Parameters

Why does the stack allocation model for functional/procedural parameters work?

More precisely, why can closure objects and the static frames they point to be completely in the stack? (In Scheme for example static environments are allocated in the heap.)

It is sufficient to ensure that every closure object can never outlive the static frame to which it points.

multiplyclosure

Pointsupwardis OK!

multiplyclosure

Points downwardwould be BAD!

Page 15: Course Overview

15Runtime Organization (Chapter 6)

Recursion

How are recursive functions and procedures supported on a low-level machine?=> Surprise! The stack memory allocation model already works!Example:let func fac(n:Integer) ~ if (n<=1) then 1 else n*fac(n-1);in begin putint(fac(6));end

let func fac(n:Integer) ~ if (n<=1) then 1 else n*fac(n-1);in begin putint(fac(6));end

Why does it work? Because every activation of a function gets its own activation record on the stack, with its own parameters, locals etc. All procedures and functions are “reentrant”.Older languages (e.g. FORTRAN) that use static allocation for locals have problems with recursion.

Page 16: Course Overview

16Runtime Organization (Chapter 6)

Recursion: General Idea

Why the stack allocation model works for recursion:Like other function/procedure calls, lifetimes of local variables and parameters for recursive calls behave like a stack.

fac(3)

fac(2)

fac(1)

fac(4) fac(4)

fac(3)

fac(2)

fac(4)fac(4)

fac(3) fac(3)

fac(2)

fac(2)

fac(1)

fac(3)

fac(2)

fac(4)

fac(3)?

?

fac(4)

Page 17: Course Overview

17Runtime Organization (Chapter 6)

Recursion: In Detail

let func fac(n:Integer) ~ if (n<=1) then 1 else n*fac(n-1);in begin putint(fac(6));end

let func fac(n:Integer) ~ if (n<=1) then 1 else n*fac(n-1);in begin putint(fac(6));end

SB arg 1 6ST

before call to facSB arg 1 6

ST

right after enteringfac

linkdata

SB arg n 6

right before recursivecall to fac

linkdata

LB

ST

LB

6value of n5arg: value of n-

1

Page 18: Course Overview

18Runtime Organization (Chapter 6)

Recursion

SB arg n 6

right before recursivecall to fac

linkdata

ST

LB

6value of n5arg

SB arg n 6

right before next recursive call to fac

linkdata

ST

LB

6value of n5arg n

linkdata

54

value of narg

SB arg n 6

right before next recursive call to fac

linkdata

LB

6value of n5arg n

linkdata

54

value of narg

linkdata

43

ST

value of narg

Page 19: Course Overview

19Runtime Organization (Chapter 6)

Recursion

LB

ST

Is the spaghetti of static and dynamic links getting confusing?

Let’s zoom in on just a single activation of the fac procedure. The pattern is always the same:

argument n

link data

to caller context (= previous LB)to lexical context (= SB)

nn-1

Intermediate results in the computation of n*fac(n-1);

?

just before recursive call in fac

Page 20: Course Overview

20Runtime Organization (Chapter 6)

Recursion

LB

ST

link data

result = 1

just before the return from the “deepest call”: n=1 after return from deepest call

LB

STresult=1

?caller frame

(what’s in here?)

argument n=2

link data

n=2 Next step:multiplyargument n=1

Page 21: Course Overview

21Runtime Organization (Chapter 6)

Recursion

just before the return from the “second deepest call”: n=2(after return from deepest call and multiply)

LB

ST?

caller frame(what’s in here?)

argument n=2

link data

2*fac(1)=2 Next step: return

to caller contextto lexical context (= SB)

result

From here on down the stack is shrinking,multiplying each time with a bigger n

Page 22: Course Overview

22Runtime Organization (Chapter 6)

Recursion

LB

ST

argument n

link data

nrecurs. arg: n-1

just before recursive call in fac

LB

ST

argument n

link data

nfac(n-1)

after completing recursive call

Calling a recursive function is just like calling any other function. After completion it just leaves its result on the top of the stack!A recursive call can happen in the midst of expression evaluation.Intermediate results, local variables, etc. simply remain on the stack, and computation proceeds when the recursive call is completed.