0% found this document useful (0 votes)
17 views42 pages

Run Time Env Symbol Table Review

Uploaded by

qazafihussainx
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
17 views42 pages

Run Time Env Symbol Table Review

Uploaded by

qazafihussainx
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 42

Compiler Construction

(Course Code: CS 402)


Instructor(s): Mr. Noman Sohaib Qureshi (RCET)
Mr. Talha Waheed (UET)

Lecture Dated: 13-04-2013


B.Sc. Computer Science (Session: 2009)
Study Objective
 Run Time Environments
 Source Language Issues
 Activation Trees
 Control Stacks
 The Scope of a Declaration
 Binding of Names
 Storage Organization
 Storage Allocation Strategies
 Access to Non-Local Names
 Dynamic Scope
Study Objective (continued..)
 Run Time Environments
 Parameter Passing
 Symbol Tables
 Language Facilities for Dynamic Storage Allocation
 Dynamic Storage Allocation Techniques
 Studentn’s Reading Task: Overview of FORTRAN

Study Material:
Chapter 7 (Dragon Book) + Lecture
Run Time Environments

The allocation and deallocation of data objects is


managed by the run-time support package,
consisting of routines loaded with the generated
target code. Each execution of a procedure is
referred to as an activation of the procedure.
Source Language
Issues
 For specificity, suppose that a program is made up of procedures, as
in Pascal.
 Procedures :
A procedure definition is a declaration that, in its simplest form,
associates an identifier with a statement. The identifier is the
procedure name, and the statement is the procedure body.
Activation Trees
 1- Control flows sequentially; that is, the execution of a program
consists of a sequence of steps, with control being at some specific
point in the program at each step.

 2- Each execution of a procedure starts at the beginning of the


procedure body and eventually returns control to the point immediately
following the place where the procedure was called. This means the
flow of control between procedures can be depicted using trees.

 The lifetime of an activation of a procedure p is the sequence of steps


between the first and last steps in the execution of the procedure
body.

Activation Trees (continued..)
 Activation Trees for concurrent processes may also be
implemented using Linear Temporal Logic (LTL)
Control Stacks
 We can use a stack, called a control stack to keep track of live
procedure activations. The idea is to push the node for an activation
onto the control stack as the activation begins and to pop the node
when the activation ends.
The Scope of a Declaration

 A declaration in a language is a syntactic construct that


associates information with a name. Declarations may be
explicit, as in the Pascal fragment
 var i : integer;
Bindings of Names
 Even if each name is declared once in a program, the
same name may denote different data objects at run time.
The informal term "data object" corresponds to a storage
location that can hold values. In programming language
semantics, the term environment refers to a function that
maps a name to a storage location.
Bindings of Names
STORAGE ORGANIZATION

 The organization of run-time storage can be used for


languages such as e.g. Fortran, Pascal, and C.
Subdivision of Run-Time Memory: Suppose that the
compiler obtains a block of storage from the operating
system for the compiled program to run in. This run-time
storage might be subdivided to hold:
 1. the generated target code,
 2. data objects, and
 3. a counterpart of the control stack to keep track of
procedure activations.
Sub-Division of Runtime Memory
Activation Records

 Information needed by a single execution of a


procedure is managed using a contiguous
block of storage called an activation record or
frame, consisting of the collection of fields
shown.
Compile-Time Layout of Local Data

 The storage layout for data objects is strongly influenced by the


addressing constraints of the target machine. For example,
instructions to add integers may expect integers to be aligned, that is,
placed at certain positions in memory such as an address divisible by
4 etc.
STORAGE-ALLOCATION STRATEGIES

 Static Allocation: In static allocation, names are bound to


storage as the program is compiled, so there is no need
for a run-time support package.
Stack Allocation

 Stack allocation is based on the idea of a


control stack; storage is organized as a stack,
and activation records are pushed and popped
as activations begin and end, respectively.
Heap Allocation
 Heap allocation parcels out pieces of contiguous
storage, as needed for activation records or other
objects. Pieces may be de-allocated in any order, so
over time the heap will consist of alternate areas that
are free and in use.
ACCESS TO NONLOCAL NAMES

 The scope rules of a language determine the treatment of


references to nonlocal names. A common rule, called the
lexical- or static-scope rule, determines the declaration
that applies to a name by examining the program text
alone. Pascal, C, and Ada are among the many languages
that use lexical scope, with an added "most closely
nested" stipulation that is discussed below. An alternative
rule, called the dynamic-scope rule, determines the
declaration applicable to a name at run time, by
considering the current activations. Lisp, APL, and Snobol
are among the languages that use dynamic scope.
Blocks
 A block is a statement containing its own local data
declarations. The concept of a block originated with Algol.
In C, a block has the syntax
{ declarations statements }

 Blocks may be:


• Nested
• Non-Neted
Scope
 Static (Compile Time)
 Dynamic (Run Time)
Parameter Passing
 Call by Value
 Call by Reference
 Copy-Restore:
• A hybrid between call-by-value and call-by-reference is copy-restore linkage, (also
known as copy-in copy-out, or value-result).

 Call by Name
Symbol Table
 A compiler uses a symbol table to keep track of scope
and binding information about names. The symbol
table is searched every time a name is encountered in
the source text. Changes to the table occur if a new
name or new information about an existing name is
discovered.
Scopes and Symbol Tables
 The declaration of a name has a limited scope: a
portion of the program where the name will be
visible. Such declarations are called local
declarations, whereas a declaration that makes
the declared name visible in the entire program is
called global

Course: Introduction to Compiler Design & Construction (Level: UG) Copyright© 2011
Professor Mogensen, University of Copenhagen, Denmark; Dexter Kozen, Cornell University,
Ithaca, USA;
Binding
 Binding Concepts

 Objects in Programming

 Binding & Compilation

Course: Introduction to Compiler Design & Construction (Level: UG) Copyright© 2011
Professor Mogensen, University of Copenhagen, Denmark; Dexter Kozen, Cornell University,
Ithaca, USA;
Symbol Tables
 A symbol table is a table that binds names to information. We need a number
of operations on symbol tables to accomplish this:
 We need an empty symbol table, in which no name is defined.
 We need to be able to bind a name to a piece of information. In case the name
is already defined in the symbol table, the new binding takes precedence over
the old.
 We need to be able to look up a name in a symbol table to find the information
the name is bound to. If the name is not defined in the symbol table, we need
to be told that.
 We need to be able to enter a new scope.
 We need to be able to exit a scope, reestablishing the symbol table to what it
was before the scope was entered.

Course: Introduction to Compiler Design & Construction (Level: UG) Copyright© 2011
Professor Mogensen, University of Copenhagen, Denmark; Dexter Kozen, Cornell University,
Ithaca, USA;
Implementation of Symbol Tables

 There are many ways to implement symbol tables,


but the most important distinction between these
is how scopes are handled.

 This may be done using a persistent (or functional) data


structure, or it may be done using an imperative (or
destructively updated) data structure.

Course: Introduction to Compiler Design & Construction (Level: UG) Copyright© 2011
Professor Mogensen, University of Copenhagen, Denmark; Dexter Kozen, Cornell University,
Ithaca, USA;
Persistent Mechanism

 A persistent data structure has the property that no


operation on the structure will destroy it. Conceptually, a
new modified copy is made of the data structure whenever
an operation updates it, hence preserving the old structure
unchanged

 This means that it is trivial to reestablish the old symbol


table when exiting a scope, as it has been preserved by
the persistent nature of the data structure. In practice, only
a small portion of the data structure is copied when a
symbol table is updated, most is shared with the previous
version.
Course: Introduction to Compiler Design & Construction (Level: UG) Copyright© 2011
Professor Mogensen, University of Copenhagen, Denmark; Dexter Kozen, Cornell University,
Ithaca, USA;
Imperative Approach

 In the imperative approach, only one copy of the symbol


table exists, so explicit actions are required to store the
information needed to restore the symbol table to a
previous state.

 Imperative approach may be implemented by PDAs (Push


Down Automatas)

Course: Introduction to Compiler Design & Construction (Level: UG) Copyright© 2011
Professor Mogensen, University of Copenhagen, Denmark; Dexter Kozen, Cornell University,
Ithaca, USA;
Simple Persistent Symbol Tables

LIST BASED
Course: Introduction to Compiler Design & Construction (Level: UG) Copyright© 2011
Professor Mogensen, University of Copenhagen, Denmark; Dexter Kozen, Cornell University,
Ithaca, USA;
Simple Persistent Symbol Tables (continued…)

 When a new element is added to the front of a list or an


element is taken off the front of the list, the old list still
exists and can be used elsewhere

 Simple Persistent Symbol Tables may be implemented by


TM.

Course: Introduction to Compiler Design & Construction (Level: UG) Copyright© 2011
Professor Mogensen, University of Copenhagen, Denmark; Dexter Kozen, Cornell University,
Ithaca, USA;
Simple Persistent Symbol Tables (continued…)

 empty: An empty symbol table is an empty list.


 bind: A new binding (name/information pair) is added
(consed) to the front of the list.
 lookup: The list is searched until a pair with a matching
name is found. The information paired with the name is
then returned. If the end of the list is reached, an indication
that this happened is returned instead. This indication can
be made by raising an exception or by letting the lookup
function return a special value representing “not found”.
This requires a type that can hold both normal information
and this special value, i.e., a sum-type.

Course: Introduction to Compiler Design & Construction (Level: UG) Copyright© 2011
Professor Mogensen, University of Copenhagen, Denmark; Dexter Kozen, Cornell University,
Ithaca, USA;
Simple Persistent Symbol Tables (continued…)

 enter: The old list is remembered, i.e., a reference is made


to it.
 exit: The old list is recalled, i.e., the above reference is
used.

Course: Introduction to Compiler Design & Construction (Level: UG) Copyright© 2011
Professor Mogensen, University of Copenhagen, Denmark; Dexter Kozen, Cornell University,
Ithaca, USA;
Simple Imperative Symbol Table

STACK
BASED
PDAs

Course: Introduction to Compiler Design & Construction (Level: UG) Copyright© 2011
Professor Mogensen, University of Copenhagen, Denmark; Dexter Kozen, Cornell University,
Ithaca, USA;
Simple Imperative Symbol Table (continued…)

 A simple imperative symbol table can be implemented as a


stack, (which works in a way similar to the list-based
functional implementation in terms of end result however
different in terms of working i.e. stack/PDAs are
destructive and list is persistent)

Course: Introduction to Compiler Design & Construction (Level: UG) Copyright© 2011
Professor Mogensen, University of Copenhagen, Denmark; Dexter Kozen, Cornell University,
Ithaca, USA;
Simple Imperative Symbol Table (continued…)

 empty: An empty symbol table is an empty stack.


 bind: A new binding (name/information pair) is pushed on
top of the stack.
 lookup: The stack is searched top-to-bottom until a
matching name is found. The information paired with the
name is then returned. If the bottom of the stack is
reached, we instead return an error-indication.
 enter: We push a marker on the top of the stack.
 exit: We pop bindings from the stack until a marker is
found. This is also popped from the stack.

Course: Introduction to Compiler Design & Construction (Level: UG) Copyright© 2011
Professor Mogensen, University of Copenhagen, Denmark; Dexter Kozen, Cornell University,
Ithaca, USA;
Efficiency Issues

 *Efficiency issues depend on the programming


implementation of the compiler and best practices in data
structures may be followed; however it is out of the scope
of this course and the current text *[1]
 For Example, hashing is a better approach to be followed
rather than sequential search in resolving binding issues in
symbol tables.


* [1] Coding the theoretical designed model is out of the scope of this course. Students may at PG level will find it
useful. Interested students may consult TAs for details and PG level courses.

Course: Introduction to Compiler Design & Construction (Level: UG) Copyright© 2011
Professor Mogensen, University of Copenhagen, Denmark; Dexter Kozen, Cornell University,
Ithaca, USA;
Shared or Separate Name Spaces

 In some languages (like Pascal) a variable and a function


in the same scope may have the same name, as the
context of use will make it clear whether a variable or a
function is used. We say that functions and variables have
separate name spaces, which means that defining a name
in one space doesn’t affect the same name in the other
space.

 On the other side, some languages have a shared name


space for variables and functions.

Course: Introduction to Compiler Design & Construction (Level: UG) Copyright© 2011
Professor Mogensen, University of Copenhagen, Denmark; Dexter Kozen, Cornell University,
Ithaca, USA;
Shared or Separate Name Spaces (continued…)

 Name spaces may be shared or separate for all the kinds


of names that can appear in a program, e.g., variables,
functions, types, exceptions, constructors, classes, field
selectors etc. Which name spaces are shared is language-
dependent.

 Separate name spaces are easily implemented using one


symbol table per name space, whereas shared name
spaces naturally share a single symbol table. However, it
is sometimes convenient to use a single symbol table even
if there are separate name spaces.

Course: Introduction to Compiler Design & Construction (Level: UG) Copyright© 2011
Professor Mogensen, University of Copenhagen, Denmark; Dexter Kozen, Cornell University,
Ithaca, USA;
LANGUAGE FACILITIES FOR DYNAMIC STORAGE ALLOCATION

 Storage for such data is usually taken from a heap.


Allocated data is often retained until it is explicitly de-
allocated. The allocation itself can be either explicit or
implicit.
DYNAMIC STORAGE ALLOCATION TECHNIQUES

 The techniques needed to implement dynamic


storage allocation depend on how storage is
deallocated. If deallocation is implicit, then the run-
time support package is responsible for determining
when a storage block is no longer needed. There is
less a compiler has to do if deallocation is done
explicitly by the programmer.
FORTRAN Overview
 Lecture Reading: Historical Overview of Fortran and storage

allocation in Fortran

You might also like