0% found this document useful (0 votes)
46 views31 pages

ATCD Unit-5

The document discusses Syntax-Directed Translation (SDT) and Syntax-Directed Definitions (SDD) as methods for compiler design, detailing their components, evaluation orders, and applications. It also covers intermediate code generation, run-time environments, and the differences between synthesized and inherited attributes. Additionally, it highlights the advantages and disadvantages of SDT, the importance of evaluation order in SDD, and the role of intermediate representations in the compilation process.

Uploaded by

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

ATCD Unit-5

The document discusses Syntax-Directed Translation (SDT) and Syntax-Directed Definitions (SDD) as methods for compiler design, detailing their components, evaluation orders, and applications. It also covers intermediate code generation, run-time environments, and the differences between synthesized and inherited attributes. Additionally, it highlights the advantages and disadvantages of SDT, the importance of evaluation order in SDD, and the role of intermediate representations in the compilation process.

Uploaded by

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

UNIT - V

Syntax-Directed Translation: Syntax-Directed Definitions, Evaluation Orders for SDD's, Syntax-


Directed Translation Schemes, Implementing L-Attributed SDD's.

Intermediate-Code Generation: Variants of Syntax Trees, Three-Address Code.

Run-Time Environments: Stack Allocation of Space, Access to Nonlocal Data on the Stack, Heap
Management

Syntax Directed Translation:

Syntax-Directed Translation (SDT) is a method used in compiler design to convert source code
into another form while analyzing its structure. SDT is the action of translating a high-level
language program into an intermediate language or machine language according to the semantic
rules imposed by SDDs.

Semantic actions in SDT, act in coordination with the parsing process in order to provide the
translation of the input code.

These actions are declarative and they are triggered during the parsing phase of the message to
yield the result.

SDT relies on three key elements:

Lexical values of nodes (such as variable names or numbers).

Constants used in computations.

Attributes associated with non-terminals that store intermediate results.

The general process of SDT involves constructing a parse tree or syntax tree, then computing
the values of attributes by visiting its nodes in a specific order. However, in many cases,
translation can be performed directly during parsing, without explicitly building the tree.

Syntax Directed Definitions:

Syntax Directed Definitions (SDD) are formal methods of attaching semantic information to the
syntactic structure of a programming language. SDDs improve the means of context-free high-
level by instances, adding a semantic rule set for every production of the grammar.

The rules described in these definitions state how to derive values such as types, memory
locations, or fragments of code from the structure of an input object.
Syntax-Directed Definitions (SDDs)

A Syntax-Directed Definition (SDD) is a formal way of specifying the semantics of a


programming language or a context-free grammar. It associates semantic actions with the
production rules of a grammar, allowing the computation of attributes or values for the symbols
in the grammar.

Components of SDDs:

1. Grammar: A context-free grammar that defines the syntax of the language.


2. Attributes: Values associated with the symbols in the grammar, which can be computed
using semantic actions.
3. Semantic Actions: Code snippets that are executed when a production rule is applied, used
to compute attribute values.

Types of SDDs
1. Synthesized Attributes: Computed from the attributes of the child nodes in the parse tree.
2. Inherited Attributes: Computed from the attributes of the parent node or sibling nodes in
the parse tree.

Applications of SDDs
1. Compiler Design: SDDs are used to specify the semantics of programming languages and
generate compilers.
2. Parser Generation: SDDs can be used to generate parsers that compute attribute values
during parsing.
3. Semantic Analysis: SDDs can be used to perform semantic analysis, such as type checking
and scoping.

Example of SDD: Consider a simple arithmetic expression grammar with the following
production rules:

E -> E + T
E -> T
T -> T * F
T -> F
F -> id

An SDD for this grammar might define synthesized attributes for the value of each expression,
with semantic actions to compute the values:

E -> E + T { E.val = E.val + T.val }


E -> T { E.val = T.val }
T -> T * F { T.val = T.val * F.val }
T -> F { T.val = F.val }
F -> id { F.val = id.lexval }

Evaluation Orders for Syntax-Directed Definitions (SDDs)


The evaluation order for SDDs determines the order in which the semantic actions are executed
to compute the attribute values.

There are two main types of evaluation orders:


1. Dependency Graphs: A dependency graph represents the dependencies between attributes in
an SDD. It is used to determine a valid evaluation order for the semantic actions.

(a) Bottom-up Evaluation


 Used for SDDs with only synthesized attributes.
 Attributes are evaluated in a bottom-up manner, starting from the leaves
of the parse tree.

(b) Top-down Evaluation


 Used for SDDs with inherited attributes.
 Attributes are evaluated in a top-down manner, starting from the root of the
parse tree.

2.Topological Sort:
A topological sort of the dependency graph can be used to determine a valid evaluation order
for the semantic actions. This ensures that the attributes are evaluated in an order that respects
the dependencies between them.

Importance of Evaluation Order


The evaluation order is crucial in SDDs because it ensures that the attribute values are
computed correctly and consistently. An incorrect evaluation order can lead to incorrect
attribute values or runtime errors.

Example: Consider an SDD with the following production rule:

E -> E + T { E.val = E.val + T.val }

In this case, a bottom-up evaluation order would first evaluate the attributes of E and T and then
compute the value of E using the semantic action.

By determining a valid evaluation order, we can ensure that the semantic actions are executed
correctly and the attribute values are computed consistently.

SDD v/s SDT Scheme:

Syntax Directed Definition Syntax Directed Translation

It refers to the translation of a string into


It is a context-free grammar where attributes
an array of actions.
and rules are combined and associated with
This is done by adding an action to a rule
grammar symbols and productions,
of context-free grammar.
respectively.
It is a type of compiler interpretation.

Attribute Grammar Translation Schemes

SDD: Specifies the values of attributes by SDT: Embeds program fragments (also
associating semantic rules with the called semantic actions) within
productions. production bodies.
Syntax Directed Definition Syntax Directed Translation

E → E + T { E.val := E1.val + T.val } E → E + T { print(‘+’); }

The position of the action defines the


Always written at the end of the body of
order in which the action is executed (in
production.
the middle of production or at the end).

More Readable More Efficient

Used to implement S-Attributed SDD and


Used to specify the non-terminals.
L-Attributed SDD.

Specifies what calculation is to be done


Specifies what calculation is to be done at
at each production and at what time they
each production.
must be done.

Left to right evaluation. Left to right evaluation.

Used to know the value of non-terminals. Used to generate Intermediate Code.

Attributes in Syntax-Directed Translation

An attribute is any quantity associated with a programming construct in a parse tree.


Attributes help in carrying semantic information during the compilation process.

Examples of Attributes:
 Data types of variables
 Line numbers for error handling
 Instruction details for code generation

Types of Attributes:
1. Synthesized Attributes

 Defined by a semantic rule associated with the production at node N in the parse tree.
 Computed only using the attribute values of the children and the node itself.
 Mostly used in bottom-up evaluation.

2. Inherited Attributes
 Defined by a semantic rule associated with the parent production of node N.
 Computed using the attribute values of the parent, siblings, and the node itself.
 Used in top-down evaluation.
Differences between Synthesized and Inherited Attributes

S.NO Synthesized Attributes Inherited Attributes

An attribute is said to be Synthesized


attribute if its parse tree node value is An attribute is said to be Inherited attribute if
determined by the attribute value at its parse tree node value is determined by the
1. child nodes. attribute value at parent and/or siblings node.

The production must have non- The production must have non-terminal as a
2. terminal as its head. symbol in its body.

A synthesized attribute at node n is A Inherited attribute at node n is defined only


defined only in terms of attribute in terms of attribute values of n’s parent, n
3. values at the children of n itself. itself, and n’s siblings.

It can be evaluated during a single It can be evaluated during a single top-down


4. bottom-up traversal of parse tree. and sideways traversal of parse tree.

Synthesized attributes can be


contained by both the terminals or Inherited attributes can’t be contained by
5. non-terminals. both, It is only contained by non-terminals.

Synthesized attribute is used by both


S-attributed SDT and L-attributed Inherited attribute is used by only L-
6. SDT. attributed SDT.

7.
Attribute Grammars:

An Attributed Grammar is a special type of grammar used in compiler design to add extra
information (attributes) to syntax rules. This helps in semantic analysis, such as type
checking, variable classification, and ensuring correctness in programming languages.
Think of it like a regular grammar with extra labels that help check things like variable
types, correctness of expressions, and rule enforcement.

Example of an Attribute Grammar:

Production Rule Semantic Rule

D→TL L.in := T.type (Passes type information)

T → int T.type := integer (Defines type as integer)

T → real T.type := real (Defines type as real)

L1.in := L.in
L → L1 , id addtype (id.entry, L.in) (Passes type info to child
and updates symbol table)

addtype (id.entry, L.in) (Adds type info to symbol


L → id
table)

 D → T L → The type from T is passed to L.


 T → int / real → Assigns type integer or real to T.
 L → id → Assigns type information to identifier (id).

Grammar and Translation Rules:

SDT Scheme SDD Scheme

E → E + T{ print('+') } E → E + T E.code = E.code || T.code || ‘+’

E → E – T{ print('-') } E → E – T `E.code = E.code || T.code || ‘-‘

E→T E → T E.code = T.code

T → 0{ print('0') } T → 0 T.code = '0'


SDT Scheme SDD Scheme

T → 1{ print('1') } T → 1 T.code = '1'

… …

T → 9{ print('9') } T → 9 T.code = '9'

Advantages of Syntax Directed Translation:

Ease of implementation: SDT is a simple and easy-to-implement method for translating a


programming language. It provides a clear and structured way to specify translation rules
using grammar rules.

Separation of concerns: SDT separates the translation process from the parsing process,
making it easier to modify and maintain the compiler. It also separates the translation
concerns from the parsing concerns, allowing for more modular and extensible compiler
designs.

Efficient code generation: SDT enables the generation of efficient code by optimizing the
translation process. It allows for the use of techniques such as intermediate code generation
and code optimization.

Disadvantages of Syntax Directed Translation:

Limited expressiveness: SDT has limited expressiveness in comparison to other


translation methods, such as attribute grammars. This limits the types of translations that
can be performed using SDT.

Inflexibility: SDT can be inflexible in situations where the translation rules are complex
and cannot be easily expressed using grammar rules.

Limited error recovery: SDT is limited in its ability to recover from errors during the
translation process. This can result in poor error messages and may make it difficult to
locate and fix errors in the input program.

Evaluation Order For SDD:


Evaluation order for SDD includes how the SDD(Syntax Directed Definition) is
evaluated with the help of attributes, dependency graphs, semantic rules,
and S and L attributed definitions. SDD helps in the semantic analysis in the
compiler so it’s important to know about how SDDs are evaluated and their
evaluation order.
It requires some basic knowledge of grammar, production, parses tree, annotated
parse tree, synthesized and inherited attributes.
Terminologies:
 Parse Tree: A parse tree is a tree that represents the syntax of the production
hierarchically.

 Annotated Parse Tree: Annotated Parse tree contains the values and
attributes at each node.

 Synthesized Attributes: When the evaluation of any node’s attribute is based


on children.

 Inherited Attributes: When the evaluation of any node’s attribute is based on


children or parents.

1. Dependency Graphs:

A dependency graph provides information about the order of evaluation of


attributes with the help of edges. It is used to determine the order of evaluation
of attributes according to the semantic rules of the production. An edge from the
first node attribute to the second node attribute gives the information that first
node attribute evaluation is required for the evaluation of the second node
attribute. Edges represent the semantic rules of the corresponding production.
Dependency Graph Rules:

A node in the dependency graph corresponds to the node of the parse tree for
each attribute.
Edges (first node from the second node)of the dependency graph represent that
the attribute of the first node is evaluated before the attribute of the second node.

2. Ordering the Evaluation of Attributes:

The dependency graph provides the evaluation order of attributes of the nodes of
the parse tree. An edge( i.e. first node to the second node) in the dependency
graph represents that the attribute of the second node is dependent on the attribute
of the first node for further evaluation. This order of evaluation gives a linear
order called topological order.
There is no way to evaluate SDD on a parse tree when there is a cycle present in
the graph and due to the cycle, no topological order exists.
Production Table

S.No. Productions Semantic Rules

1. S⇢A&B S.val = A.syn + B.syn

A.syn = A1.syn * B.syn


2. A ⇢ A1 # B
A1.inh = A.syn

3. A1 ⇢ B A1.syn = B.syn

4. B ⇢ digit B.syn = digit.lexval

Annotated Parse Tree For 1#2&3


Intermediate code
Intermediate code is used to translate the source code into the machine
code. Intermediate code lies between the high-level language and the
machine language.

Fig: Position of intermediate code generator

o If the compiler directly translates source code into the machine code
without generating intermediate code then a full native compiler is
required for each new machine.
o The intermediate code keeps the analysis portion same for all the
compilers that's why it doesn't need a full compiler for every unique
machine.
o Intermediate code generator receives input from its predecessor phase
and semantic analyzer phase. It takes input in the form of an annotated
syntax tree.
o Using the intermediate code, the second phase of the compiler synthesis
phase is changed according to the target machine.

Intermediate representation
Intermediate code can be represented in two ways:

1. High Level intermediate code:


High level intermediate code can be represented as source code. To
enhance performance of source code, we can easily apply code
modification. But to optimize the target machine, it is less preferred.

2. Low Level intermediate code


Low level intermediate code is close to the target machine, which makes
it suitable for register and memory allocation etc. it is used for machine-
dependent optimizations.

Parse tree and Syntax tree


create a parse tree then it contains more details than actually needed. So,
it is very difficult to compiler to parse the parse tree. Take the following
parse tree as an example:
o In the parse tree, most of the leaf nodes are single child to their
parent nodes.
o In the syntax tree, we can eliminate this extra information.
o Syntax tree is a variant of parse tree. In the syntax tree, interior
nodes are operators and leaves are operands.
o Syntax tree is usually used when represent a program in a tree
structure.
A sentence id + id * id would have the following syntax tree:

Abstract syntax tree can be represented as:


Abstract syntax trees are important data structures in a compiler. It
contains the least unnecessary information.

Abstract syntax trees are more compact than a parse tree and can be
easily used by a compiler.

Postfix Notation
o Postfix notation is the useful form of intermediate code if the given
language is expressions.
o Postfix notation is also called as 'suffix notation' and 'reverse polish'.
o Postfix notation is a linear representation of a syntax tree.
o In the postfix notation, any expression can be written unambiguously
without parentheses.
o The ordinary (infix) way of writing the sum of x and y is with operator in
the middle: x * y. But in the postfix notation, we place the operator at the
right end as xy *.
o In postfix notation, the operator follows the operand.

Example
Production

1. E → E1 op E2
2. E → (E1)
3. E → id

Semantic Rule Program fragment

E.code = E1.code || E2.code || op print op

E.code = E1.code

E.code = id print id
Postfix Translation
In a production A → α, the translation rule of A.CODE consists of the concatenation of the
CODE translations of the non-terminals in α in the same order as the non-terminals appear in
α.

Production can be factored to achieve postfix form.

Postfix translation of while statement


The production

1. S → while M1 E do M2 S1
Can be factored as:

1. S → C S1
2. C → W E do
3. W → while
A suitable transition scheme would be

Production Rule Semantic Action

W → while W.QUAD = NEXTQUAD

C → W E do C W E do

S→ C S1 BACKPATCH (S1.NEXT, C.QUAD)


S.NEXT = C.FALSE
GEN (goto C.QUAD)

Postfix translation of for statement


The production

1. S for L = E1 step E2 to E3 do S1
Can be factored as

1. F → for L
2. T → F = E1 by E2 to E3 do
3. S → T S1

Three address code


o Three-address code is an intermediate code. It is used by the
optimizing compilers.
o In three-address code, the given expression is broken down into
several separate instructions. These instructions can easily
translate into assembly language.
o Each Three address code instruction has at most three operands.
It is a combination of assignment and a binary operator.

Example
GivenExpression:

a := (-c * b) + (-c * d)
Three-address code is as follows:
t1 := -c
t2 := b*t1
t3 := -c
t4 := d * t3
t5 := t2 + t4
a := t5
t is used as registers in the target program.
The three address code can be represented in two
forms: quadruples and triples.

Example-1: Convert the expression a * – (b + c) into three address codes.

Example 2,: Write three address codes for the following code
for(i = 1; i<=10; i++)
{
a[i] = x * 5;
}

3 address code for the for loop

Implementation of Three Address Code


There are 3 representations of three address code namely
 Quadruple
 Triples
 Indirect Triples
1. Quadruple: It is a structure which consists of 4 fields namely op, arg1,
arg2 and result. op denotes the operator and arg1 and arg2 denotes the
two operands and result is used to store the result of the expression.
Advantage
 Easy to rearrange code for global optimization.
 One can quickly access value of temporary variables using symbol
table.
Disadvantage
 Contain lot of temporaries.
 Temporary variable creation increases time and space complexity.
Example – Consider expression a = b * – c + b * – c. The three address
code is:
t1 = uminus c (Unary minus operation on c)
t2 = b * t1
t3 = uminus c (Another unary minus operation on c)
t4 = b * t3
t5 = t2 + t4
a = t5 (Assignment of t5 to a)
2. Triples: This representation doesn’t make use of extra temporary
variable to represent a single operation instead when a reference to
another triple’s value is needed, a pointer to that triple is used. So, it
consist of only three fields namely op, arg1 and arg2.
Disadvantage
 Temporaries are implicit and difficult to rearrange code.
 It is difficult to optimize because optimization involves moving
intermediate code. When a triple is moved, any other triple referring to
it must be updated also. With help of pointer one can directly access
symbol table entry.
Example – Consider expression a = b * – c + b * – c

3. Indirect Triples This representation makes use of pointer to the listing


of all references to computations which is made separately and stored. Its
similar in utility as compared to quadruple representation but requires less
space than it. Temporaries are implicit and easier to rearrange code.
Example – Consider expression a = b * – c + b * – c
Question – Write quadruple, triples and indirect triples for following
expression : (x + y) * (y + z) + (x + y + z)
Explanation – The three address code is:
(1) t1 = x + y
(2) t2 = y + z
(3) t3 = t1 * t2
(4) t4 = t1 + z
(5) t5 = t3 + t4
Implementation of Three Address Code
1. Source Code Parsing and Abstract Syntax Tree Generation.
 Lexical Analysis: source code is converted into tokens, keywords,
identifiers, operators, literals, etc.
 Syntax Analysis: An Abstract Syntax Tree that would be the
representation of the grammatical structure of the code.
 Semantic Analysis: Derivation of semantic errors type mismatches,
undeclared variables, etc. and builds a symbol table.
2. TAC Instructions Generation
 Traversal of the Abstract Syntax Tree: visiting each of the nodes in the
abstract syntax tree generates the proper TAC instructions.
 Use temporaries for intermediate computation.
 Three address form: Each instruction should have at most three
operands, two source and one target.
3. Evaluation of Expressions
 Arithmetic Expressions: Divide complex expression into simpler
expressions by using the temporaries. Example a + b * c which should
be encoded as follows:
 t1 = b * c
 t2 := a + t1
3. Logical Expressions:
 Translate the logical AND, OR and NOT operators into conditional
jumps. Uses temporary registers.
4. Control Flow Constructs
 If Statements :Use conditional jumps.
 While Loops : Involve in unconditional jumps to the loop header and
conditional jumps to exit.
 For Loops: Converted to equivalent while loops.
 Goto Statements: Unconditionally jump to the specified labels.
5. Procedure Calls
 Argument Passing : Arguments are pushed onto the stack
 Function Call: A jump is made to the function’s entry point.
 Return Value: Stored in a temporary variable while popping the
arguments off the stack..

Applications
 Optimization.
 Code generation.
 Debugging.
 Language translation.
https://www.geeksforgeeks.org/three-address-code-compiler/

Implementing an L-attributed Syntax-Directed Definition (SDD):


It involves building a parse tree, annotating it with attributes, and then evaluating the
attributes in a specific order. This process can be done either by building the entire tree first
and then annotating and evaluating, or by performing the evaluation during parsing, often
using a recursive-descent parser.

Detailed Implementation Steps:


1. Building the Parse Tree:
 Parse the input using a suitable parsing algorithm (e.g., LL parser for L-attributed SDDs) to
construct the parse tree.
 The parse tree represents the hierarchical structure of the input based on the grammar rules.
2. Annotating the Parse Tree:
 Assign attributes to each node in the parse tree.
 Synthesized Attributes: These are attributes associated with the head of a production rule and
are computed based on the attributes of the symbols in the body of the rule.
 Inherited Attributes: These are attributes associated with non-terminal symbols in the body of
a production rule and are inherited from the head of the rule, as well as from symbols to their
left in the production.
 L-attributed definitions restrict how inherited attributes can be computed, ensuring that the
dependency graph formed by the attributes has no cycles.
3. Evaluating the Attributes:
 Option 1: Build and Evaluate:
 Annotate the entire parse tree with attributes.
 Evaluate the synthesized attributes using a pre-order traversal of the tree.
 This method works for any non-circular SDD, where there are no cycles in the attribute
dependency graph.

 Option 2: Recursive Descent Parsing:


 Use a recursive-descent parser where each non-terminal symbol has a corresponding function.
 The function for a non-terminal receives its inherited attributes as arguments and returns its
synthesized attributes.
 This method allows for translation to occur during parsing.
 The function calls other functions for non-terminals in the body of the production, passing them
the appropriate arguments.
Key Considerations for L-Attributed SDDs:
 Dependency Graph: The dependency graph formed by the attributes should not have any
cycles.
 Left-to-Right Dependency: Inherited attributes in L-attributed SDDs can only depend on
attributes of symbols to their left in the production.
 Evaluation Order: The order in which attributes are evaluated can be influenced by the
evaluation method used (e.g., pre-order traversal, recursive-descent parsing).
Example:
Consider the production E -> E1 + E2.

 E.val (Synthesized):
The value of the expression E. It is calculated by adding the values of E1 and E2 (E.val =
E1.val + E2.val).
 E1.env (Inherited):
The environment (e.g., symbol table) in which E1 is evaluated. It is inherited from the head
E (E1.env := E.env).
 E2.env (Inherited):
The environment in which E2 is evaluated. It is also inherited from E (E2.env := E.env).

The synthesized attribute E.val depends on the synthesized


attributes E1.val and E2.val. The inherited attributes E1.env and E2.env depend on the
inherited attribute E.env. This adheres to the L-attributed definition where inherited attributes
are derived from the head and symbols to the left in the production.

Run-Time Environments: Stack Allocation of Space, Access to Nonlocal Data on the Stack, Heap
Management
A translation needs to relate the static source text of a program to the
dynamic actions that must occur at runtime to implement the program.
The program consists of names for procedures, identifiers, etc., that
require mapping with the actual memory location at runtime. Runtime
environment is a state of the target machine, which may include software
libraries, environment variables, etc., to provide services to the processes
running in the system.

SOURCE LANGUAGE ISSUES


Activation Tree
A program consist of procedures, a procedure definition is a declaration
that, in its simplest form, associates an identifier (procedure name) with a
statement (body of the procedure). Each execution of the procedure is
referred to as an activation of the procedure. Lifetime of an activation is
the sequence of steps present in the execution of the procedure. If ‘a’ and
‘b’ be two procedures then their activations will be non-overlapping (when
one is called after other) or nested (nested procedures). A procedure is
recursive if a new activation begins before an earlier activation of the
same procedure has ended. An activation tree shows the way control
enters and leaves activations. Properties of activation trees are :-
 Each node represents an activation of a procedure.
 The root shows the activation of the main function.
 The node for procedure ‘x’ is the parent of node for procedure ‘y’ if and
only if the control flows from procedure x to procedure y.
Example – Consider the following program of Quicksort
main() {

Int n;
readarray();
quicksort(1,n);
}

quicksort(int m, int n) {

Int i= partition(m,n);
quicksort(m,i-1);
quicksort(i+1,n);
}
The activation tree for this program will be:

First main function as the root then main calls readarray and quicksort.
Quicksort in turn calls partition and quicksort again. The flow of control in
a program corresponds to a pre-order depth-first traversal of the activation
tree which starts at the root.

CONTROL STACK AND ACTIVATION RECORDS


Control stack or runtime stack is used to keep track of the live procedure
activations i.e the procedures whose execution have not been completed.
A procedure name is pushed on to the stack when it is called (activation
begins) and it is popped when it returns (activation ends). Information
needed by a single execution of a procedure is managed using an
activation record or frame. When a procedure is called, an activation
record is pushed into the stack and as soon as the control returns to the
caller function the activation record is popped.
A general activation record consists of the following things:
 Local variables: hold the data that is local to the execution of the
procedure.
 Temporary values : stores the values that arise in the evaluation of an
expression.
 Machine status: holds the information about the status of the machine
just before the function call.
 Access link (optional): refers to non-local data held in other activation
records.
 Control link (optional): points to activation record of caller.
 Return value: used by the called procedure to return a value to calling
procedure
 Actual parameters
Control stack for the above quicksort example:

SUBDIVISION OF RUNTIME MEMORY


Runtime storage can be subdivided to hold :
 Target code- the program code, is static as its size can be determined
at compile time
 Static data objects
 Dynamic data objects- heap
 Automatic data objects- stack
STORAGE ALLOCATION TECHNIQUES
I. Static Storage Allocation
The names are bound with the storage at compiler time only and hence
every time procedure is invoked its names are bound to the same storage
location only So values of local names can be retained across activations
of a procedure. Here compiler can decide where the activation records go
with respect to the target code and can also fill the addresses in the target
code for the data it operates on.
 For any program, if we create a memory at compile time, memory will
be created in the static area.
 For any program, if we create a memory at compile-time only, memory
is created only once.
 It doesn’t support dynamic data structure i.e memory is created at
compile-time and deallocated after program completion.
 The drawback with static storage allocation is recursion is not
supported.
 Another drawback is the size of data should be known at compile time
Eg- FORTRAN was designed to permit static storage allocation.
II. Stack Storage Allocation
 Storage is organized as a stack and activation records are pushed and
popped as activation begins and end respectively. Locals are
contained in activation records so they are bound to fresh storage in
each activation.
 Recursion is supported in stack allocation
III. Heap Storage Allocation
 Memory allocation and deallocation can be done at any time and at any
place depending on the requirement of the user.
 Heap allocation is used to dynamically allocate memory to the
variables and claim it back when the variables are no more required.
 Recursion is supported.

PARAMETER PASSING: The communication medium among procedures


is known as parameter passing. The values of the variables from a calling
procedure are transferred to the called procedure by some mechanism.
Basic terminology :
 R- value: The value of an expression is called its r-value. The value
contained in a single variable also becomes an r-value if its appear on
the right side of the assignment operator. R-value can always be
assigned to some other variable.
 L-value: The location of the memory(address) where the expression is
stored is known as the l-value of that expression. It always appears on
the left side if the assignment operator.
 i.Formal Parameter: Variables that take the information passed by the
caller procedure are called formal parameters. These variables are
declared in the definition of the called function. ii.Actual
Parameter: Variables whose values and functions are passed to the
called function are called actual parameters. These variables are
specified in the function call as arguments.
Different ways of passing the parameters to the procedure:
 Call by Value: In call by value the calling procedure passes the r-value
of the actual parameters and the compiler puts that into called
procedure’s activation record. Formal parameters hold the values
passed by the calling procedure, thus any changes made in the formal
parameters do not affect the actual parameters.
 Call by Reference In call by reference the formal and actual
parameters refers to same memory location. The l-value of actual
parameters is copied to the activation record of the called function.
Thus the called function has the address of the actual parameters. If
the actual parameters does not have a l-value (eg- i+3) then it is
evaluated in a new temporary location and the address of the location
is passed. Any changes made in the formal parameter is reflected in
the actual parameters (because changes are made at the address).
 Call by Copy Restore In call by copy restore compiler copies the
value in formal parameters when the procedure is called and copy
them back in actual parameters when control returns to the called
function. The r-values are passed and on return r-value of formals are
copied into l-value of actuals.

#include <iostream>
using namespace std;

void swap(int& a, int& b)


{
/* A hybrid between call-by-value and call-by-reference
is copy-restore linkage (also known as copy in and
copy out ,or value-result) */

int copy_a, copy_b;


copy_a = a; // copy in phase
copy_b = b;

int temp = copy_a; // function proper


copy_a = copy_b;
copy_b = temp;

a = copy_a; // copy out phase


b = copy_b;
}

int main()
{
int a = 10, b = 20;
swap(a, b);
cout << a << " " << b << endl;
return 0;
}
// code added by raunakraj232

 Call by Name In call by name the actual parameters are substituted for
formals in all the places formals occur in the procedure. It is also
referred as lazy evaluation because evaluation is done on parameters
only when needed.
Advantages:
Portability: A runtime environment can provide a layer of abstraction
between the compiled code and the operating system, making it easier to
port the program to different platforms.
Resource management: A runtime environment can manage system
resources, such as memory and CPU time, making it easier to avoid
memory leaks and other resource-related issues.
Dynamic memory allocation: A runtime environment can provide
dynamic memory allocation, allowing memory to be allocated and freed as
needed during program execution.
Garbage collection: A runtime environment can perform garbage
collection, automatically freeing memory that is no longer being used by
the program.
Exception handling: A runtime environment can provide exception
handling, allowing the program to gracefully handle errors and prevent
crashes.
Disadvantages:
Performance overhead: A runtime environment can add performance
overhead, as it requires additional processing and memory usage.
Platform dependency: Some runtime environments may be specific to
certain platforms, making it difficult to port programs to other platforms.
Debugging: Debugging can be more difficult in a runtime environment, as
the additional layer of abstraction can make it harder to trace program
execution.
Compatibility issues: Some runtime environments may not be
compatible with certain operating systems or hardware architectures,
which can limit their usefulness.
Versioning: Different versions of a runtime environment may have
different features or APIs, which can lead to versioning issues when
running programs compiled with different versions of the same runtime
environment.

You might also like