Course Overview PART I: overview material PART II: inside a compiler

Slides:



Advertisements
Similar presentations
Programming Languages and Paradigms
Advertisements

CSI 3120, Implementing subprograms, page 1 Implementing subprograms The environment in block-structured languages The structure of the activation stack.
1 Languages and Compilers (SProg og Oversættere) Code Generation.
Procedures in more detail. CMPE12cGabriel Hugh Elkaim 2 Why use procedures? –Code reuse –More readable code –Less code Microprocessors (and assembly languages)
Prof. Necula CS 164 Lecture 141 Run-time Environments Lecture 8.
Stacks and HeapsCS-3013 A-term A Short Digression on Stacks and Heaps CS-3013 Operating Systems A-term 2008 (Slides include materials from Modern.
Procedures in more detail. CMPE12cCyrus Bazeghi 2 Procedures Why use procedures? Reuse of code More readable Less code Microprocessors (and assembly languages)
Digression on Stack and Heaps CS-502 (EMC) Fall A Short Digression on Stacks and Heaps CS-502, Operating Systems Fall 2009 (EMC) (Slides include.
1 Chapter 7: Runtime Environments. int * larger (int a, int b) { if (a > b) return &a; //wrong else return &b; //wrong } int * larger (int *a, int *b)
1 Languages and Compilers (SProg og Oversættere) Lecture 10 Bent Thomsen Department of Computer Science Aalborg University With acknowledgement to Norm.
CS 536 Spring Run-time organization Lecture 19.
3/17/2008Prof. Hilfinger CS 164 Lecture 231 Run-time organization Lecture 23.
Names and Scopes CS 351. Program Binding We should be familiar with this notion. A variable is bound to a method or current block e.g in C++: namespace.
Honors Compilers Addressing of Local Variables Mar 19 th, 2002.
Run-Time Storage Organization
1 Pertemuan 20 Run-Time Environment Matakuliah: T0174 / Teknik Kompilasi Tahun: 2005 Versi: 1/6.
Run time vs. Compile time
Run-time Environment and Program Organization
Chapter 10 Implementing Subprograms. Copyright © 2007 Addison-Wesley. All rights reserved. 1–2 Semantics of Call and Return The subprogram call and return.
Stacks and HeapsCS-502 Fall A Short Digression Stacks and Heaps CS-502, Operating Systems Fall 2007 (Slides include materials from Operating System.
1 Contents. 2 Run-Time Storage Organization 3 Static Allocation In many early languages, notably assembly and FORTRAN, all storage allocation is static.
Chapter 8 :: Subroutines and Control Abstraction
Chapter 7: Runtime Environment –Run time memory organization. We need to use memory to store: –code –static data (global variables) –dynamic data objects.
1 Languages and Compilers (SProg og Oversættere) Bent Thomsen Department of Computer Science Aalborg University With acknowledgement to Norm Hutchinson.
Compilation (Chapter 3) 1 Course Overview PART I: overview material 1Introduction 2Language processors (tombstone diagrams, bootstrapping) 3Architecture.
CS3012: Formal Languages and Compilers The Runtime Environment After the analysis phases are complete, the compiler must generate executable code. The.
LANGUAGE TRANSLATORS: WEEK 24 TRANSLATION TO ‘INTERMEDIATE’ CODE (overview) Labs this week: Tutorial Exercises on Code Generation.
Runtime Environments Compiler Construction Chapter 7.
Compiler Construction
CSc 453 Runtime Environments Saumya Debray The University of Arizona Tucson.
CPSC 388 – Compiler Design and Construction Runtime Environments.
Lesson 13 CDT301 – Compiler Theory, Spring 2011 Teacher: Linus Källberg.
1 Languages and Compilers (SProg og Oversættere) Bent Thomsen Department of Computer Science Aalborg University With acknowledgement to Norm Hutchinson.
Procedures. Why use procedures? ? Microprocessors (and assembly languages) provide only minimal support for procedures Must build a standard form for.
Run-Time Storage Organization Compiler Design Lecture (03/23/98) Computer Science Rensselaer Polytechnic.
Runtime Organization (Chapter 6) 1 Course Overview PART I: overview material 1Introduction 2Language processors (tombstone diagrams, bootstrapping) 3Architecture.
RUN-Time Organization Compiler phase— Before writing a code generator, we must decide how to marshal the resources of the target machine (instructions,
Runtime Organization (Chapter 6) 1 Course Overview PART I: overview material 1Introduction 2Language processors (tombstone diagrams, bootstrapping) 3Architecture.
7. Runtime Environments Zhang Zhizheng
RUNTIME ENVIRONMENT AND VARIABLE BINDINGS How to manage local variables.
ISBN Chapter 10 Implementing Subprograms.
Subprograms - implementation. Calling a subprogram  transferring control to a subprogram: save conditions in calling program pass parameters allocate.
Code Generation (Chapter 7) 1 Course Overview PART I: overview material 1Introduction 2Language processors (tombstone diagrams, bootstrapping) 3Architecture.
Run-Time Environments Presented By: Seema Gupta 09MCA102.
Code Generation Instruction Selection Higher level instruction -> Low level instruction Register Allocation Which register to assign to hold which items?
Procedures Procedures are very important for writing reusable and maintainable code in assembly and high-level languages. How are they implemented? Application.
Implementing Subprograms
Lecture 3 Translation.
Chapter 14 Functions.
Data Types In Text: Chapter 6.
Run-Time Environments Chapter 7
Names and Attributes Names are a key programming language feature
Implementing Subprograms
Run-time organization
Run-Time Storage Organization
Run-Time Storage Organization
Introduction to Compilers Tim Teitelbaum
Implementing Subprograms
Recursion and Implementation of Functions
Activation records Programming Language Design and Implementation (4th Edition) by T. Pratt and M. Zelkowitz Prentice Hall, 2001 Section
UNIT V Run Time Environments.
Course Overview PART I: overview material PART II: inside a compiler
CMPE 152: Compiler Design March 7 Class Meeting
Course Overview PART I: overview material PART II: inside a compiler
Run Time Environments 薛智文
Activation records Programming Language Design and Implementation (4th Edition) by T. Pratt and M. Zelkowitz Prentice Hall, 2001 Section
Implementing Subprograms
Topic 2b ISA Support for High-Level Languages
Chapter 14 Functions.
Implementing Functions: Overview
Presentation transcript:

Course Overview PART I: overview material PART II: inside a compiler 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 Interpretation 9 Review

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

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++) Var/reference parameter Constant/value parameter 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

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]

Functional / Procedural Parameters In 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 : Integer in 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/function 2. the address of the procedure/function

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 accesses lexically scoped var See pictures of stack beginning on next slide…

Functional / Procedural Parameters right after calling cubed right before call to twice SB arg b 4 LB arg b 4 link data LB link data arg #1 multiply closure multiply function code ST arg #2 4 ST static link function address

Functional / Procedural Parameters right after call to twice before first call to doIt arg b arg b 4 4 link data link data arg doIt arg doIt multiply closure multiply closure multiply multiply arg i arg i 4 4 LB LB link data link data ST arg #1 4 closure to call multiply closure multiply ST Note: to avoid clutter, dynamic links are not shown. Only some static links are shown.

Functional / Procedural Parameters execution of CALLI instruction (Call Indirect) before first call to doIt right after first call to doIt arg b arg b 4 4 link data link data arg doIt arg doIt multiply closure multiply closure multiply multiply arg i arg i 4 4 LB link data link data arg #1 4 arg x 4 LB closure to call multiply closure link data multiply ST ST

Functional / Procedural Parameters right after first call to doIt just before x*b in multiply arg b arg b 4 4 link data link data arg doIt arg doIt multiply closure multiply closure multiply multiply arg i arg i 4 4 link data link data arg x 4 arg x 4 LB LB link data link data ST value of x LOAD [-1]LB 4 value of b LOAD [-1]L1 4 ST

Functional / Procedural Parameters just before return doIt/multiply just after return doIt/multiply arg b arg b 4 4 link data link data arg doIt arg doIt multiply closure multiply closure multiply multiply arg i arg i 4 4 LB link data link data value of doIt(4) arg x 4 16 LB ST link data value of x*b 16 ST

Functional / Procedural Parameters just before second call to doIt just before x*b in multiply arg b arg b 4 4 link data link data arg doIt arg doIt multiply closure multiply closure multiply multiply arg i arg i 4 4 LB link data link data arg #1 16 arg x 16 LB closure to call multiply closure link data multiply ST value of x LOAD [-1]LB 16 value of b LOAD [-1]L1 4 ST

Functional / Procedural Parameters just after return doIt/multiply = just before return from “twice” just after return from “twice” =just before return from cubed arg b 4 4 LB link data link data arg doIt arg doIt multiply closure multiply closure multiply multiply arg i value of twice(multiply,4) 4 64 LB ST link data value of doIt(16) 64 just after return from cubed ST value of cubed(4) 64 ST

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. Points upward is OK! multiply closure Points downward would be BAD! multiply closure

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 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.

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(4) ? fac(4) fac(4) fac(3) fac(3) fac(4) fac(3) fac(4) fac(3) fac(2) fac(2) fac(4) ? fac(3) fac(2) fac(1) fac(3) fac(2) fac(2) fac(1)

right before recursive Recursion: In Detail let func fac(n:Integer) ~ if (n<=1) then 1 else n*fac(n-1); in begin putint(fac(6)); end right after entering fac right before recursive call to fac before call to fac SB SB SB arg 1 arg 1 arg n 6 6 6 ST LB LB link data link data ST value of n 6 arg: value of n-1 5 ST

right before recursive Recursion right before recursive call to fac right before next recursive call to fac right before next recursive call to fac SB SB SB arg n arg n arg n 6 6 6 LB link data link data link data value of n value of n value of n 6 6 6 arg arg n arg n 5 5 5 ST LB link data link data value of n value of n 5 5 arg arg 4 4 ST LB link data value of n 4 arg 3 ST

Recursion 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: just before recursive call in fac to caller context (= previous LB) ? to lexical context (= SB) argument n LB link data n Intermediate results in the computation of n*fac(n-1); n-1 ST

just before the return from Recursion just before the return from the “deepest call”: n=1 after return from deepest call argument n=2 link data n=2 LB caller frame (what’s in here?) ? Next step: multiply argument n=1 result=1 LB ST link data result = 1 ST

? Recursion just before the return from the “second deepest call”: n=2 (after return from deepest call and multiply) to caller context to lexical context (= SB) argument n=2 link data 2*fac(1)=2 LB caller frame (what’s in here?) ? result Next step: return ST From here on down the stack is shrinking, multiplying each time with a bigger n

after completing recursive call Recursion just before recursive call in fac after completing recursive call argument n argument n LB LB link data link data n n recurs. arg: n-1 fac(n-1) ST ST 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.