0% found this document useful (0 votes)
15 views

13 Runtime Systems

Compiler Design Notes

Uploaded by

Ayush Jindal
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
15 views

13 Runtime Systems

Compiler Design Notes

Uploaded by

Ayush Jindal
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 65

Runtime Environment

• Relationship between names and data


objects (of target machine)
• Allocation & de-allocation is managed by run
time support package
• Each execution of a procedure is an
activation of the procedure. If procedure is
recursive, several activations may be alive at
the same time.
• If a and b are activations of two procedures then
their lifetime is either non overlapping or nested
• A procedure is recursive if an activation can
begin before an earlier activation of the same
procedure has ended 1
Procedure
• A procedure definition is a declaration
that associates an identifier with a
statement (procedure body)
• When a procedure name appears in an
executable statement, it is called at
that point
• Formal parameters are the one that
appear in declaration. Actual
Parameters are the one that appear in
when a procedure is called
2
Activation tree
• Control flows sequentially
• Execution of a procedure starts at the beginning
of body
• It returns control to place where procedure was
called from
• A tree can be used, called an activation tree, to
depict the way control enters and leaves
activations
• The root represents the activation of main program
• Each node represents an activation of procedure
• The node a is parent of b if control flows from a to b
• The node a is to the left of node b if lifetime of a
occurs before b 3
Example
program sort; procedure quicksort (m, n
var a : array[0..10] of :integer);
integer; var i :integer;
:
i:= partition (m,n);
procedure readarray; quicksort (m,i-1);
var i :integer; quicksort(i+1, n);
: :
begin{main}
function partition (y, z readarray;
:integer) quicksort(1,9)
:integer; end.
var i, j ,x, v :integer;
:
4
Activation Tree
Sort

r q(1,9)

p(1,9) q(1,3) q(5,9)


returns 4

p(1,3) q(1,0) q(2,3) p(5,9) q(5,5) q(7,9)


returns 1 returns 6

p(2,3) q(2,1) q(3,3) p(7,9) q(7,7) q(9,9)


returns 2 returns 8

5
Control stack
• Flow of control in program corresponds
to depth first traversal of activation tree
• Use a stack called control stack to keep
track of live procedure activations
• Push the node when activation begins
and pop the node when activation ends
• When the node n is at the top of the
stack the stack contains the nodes along
the path from n to the root

6
Scope of declaration
• A declaration is a syntactic construct associating
information with a name
– Explicit declaration :Pascal (Algol class of languages)
var i : integer
– Implicit declaration: Fortran
i is assumed to be integer
• There may be independent declarations of same
name in a program.
• Scope rules determine which declaration applies
to a name
• Name binding

name environment storage state value


7
Storage organization
• The runtime storage
might be subdivided code
into static data
– Target code stack
– Data objects
– Stack to keep track of
procedure activation
– Heap to keep all other heap
information

8
Activation Record
• temporaries: used in
expression evaluation Temporaries
• local data: field for local data local data
• saved machine status: holds
info about machine status machine status
before procedure call Access links
• access link : to access non local
data Control links
• control link :points to Parameters
activation record of caller
• actual parameters: field to Return value
hold actual parameters
• returned value: field for
holding value to be returned
9
Activation Records: Examples
• Examples on the next few slides by Prof
Amitabha Sanyal, IIT Bombay
• C/C++ programs with gcc extensions
• Compiled on x86_64

10
Example 1 – Vanilla Program in C

11
Example 2 – Function with Local
Variables

12
Example 3 – Function with
Parameters

13
Example 4 – Reference Parameters

14
Example 5 – Global Variables

15
Example 6 – Recursive Functions

16
Example 7 – Array Access

17
Example 8 – Records and Pointers

18
Example 9 – Dynamically Created
Data

19
Issues to be addressed
• Can procedures be recursive?
• What happens to locals when
procedures return from an activation?
• Can procedure refer to non local
names?
• How to pass parameters?
• Can procedure be parameter?
• Can procedure be returned?
• Can storage be dynamically allocated?
• Can storage be de-allocated?
20
Layout of local data
• Assume byte is the smallest unit
• Multi-byte objects are stored in consecutive
bytes and given address of first byte
• The amount of storage needed is determined
by its type
• Memory allocation is done as the
declarations are processed
– Keep a count of memory locations allocated for
previous declarations
– From the count relative address of the storage
for a local can be determined
– As an offset from some fixed position
21
Layout of local data
• Data may have to be aligned (in a word)
padding is done to have alignment.
• When space is important
– Complier may pack the data so no padding is left
– Additional instructions may be required to
execute packed data
– Tradeoff between space and execution time

22
Storage Allocation Strategies
• Static allocation: lays out storage
at compile time for all data objects
• Stack allocation: manages the
runtime storage as a stack
• Heap allocation :allocates and de-
allocates storage as needed at
runtime from heap
23
Static allocation
• Names are bound to storage as the
program is compiled
• No runtime support is required
• Bindings do not change at run time
• On every invocation of procedure
names are bound to the same
storage
• Values of local names are retained
across activations of a procedure
24
• Type of a name determines the amount of
storage to be set aside
• Address of a storage consists of an offset
from the end of an activation record
• Compiler decides location of each
activation
• All the addresses can be filled at compile
time
• Constraints
– Size of all data objects must be known at
compile time
– Recursive procedures are not allowed
– Data structures cannot be created dynamically
25
Stack Allocation

Sort Sort

Sort Sort
readarray readarray

Sort Sort
qsort(1,9)
readarray qsort(1,9)

Sort Sort
readarray qsort(1,9) qsort(1,9)

partition(1,9) qsort(1,3) qsort(1,3)


26
Calling Sequence
• A call sequence
Parameter and
allocates an Return value

Control link Caller’s


activation record and Activation
Links and saved values record
enters information Space for temporaries
And local data
into its field Caller’s
Parameter and
responsibility
Return value
• A return sequence Control link Callee’s
Activation
restores the state of Links and saved values record
Callee’s
the machine so that responsibility
Space for temporaries
And local data
calling procedure can
continue execution
27
Call Sequence
• Caller evaluates the actual
parameters
• Caller stores return address and
other values (control link) into
callee’s activation record
• Callee saves register values and
other status information
• Callee initializes its local data and
begins execution
28
Return Sequence
• Callee places a return value next
to activation record of caller
• Restores registers using
information in status field
• Branch to return address
• Caller copies return value into its
own activation record
29
Long/Unknown Length Data
ptr to A
ptr to B activation of P
ptr to C

array A

array B
Long length
data
array C

activation of Q
activation of Q
Called by P

arrays of Q

30
Dangling references
Referring to locations which have been deallocated
main() {
int *p;
p = dangle(); /* dangling reference */
}

int *dangle() {
int i=23;
return &i;
}

31
Heap Allocation
• Stack allocation cannot be used if:
– The values of the local variables must be
retained when an activation ends
– A called activation outlives the caller
• In such a case de-allocation of activation
record cannot occur in last-in first-out
fashion
• Heap allocation gives out pieces of
contiguous storage for activation records

32
Heap Allocation …
• Pieces may be de-allocated in any order
• Over time the heap will consist of alternate
areas that are free and in use
• Heap manager is supposed to make use of
the free space
• For efficiency reasons it may be helpful to
handle small activations as a special case

33
Heap Allocation …
• For each size of interest keep a linked list of
free blocks of that size
• Fill a request of size s with block of size s′
where s′ is the smallest size greater than or
equal to s.
• When the block is deallocated, return it to
the corresponding list

34
Heap Allocation …

• For large blocks of storage use heap


manager
• For large amount of storage computation
may take some time to use up memory
– time taken by the manager may be negligible
compared to the computation time

35
Access to non-local names

• Scope rules determine the treatment of


non-local names
• A common rule is lexical scoping or static
scoping (most languages use lexical
scoping)
– Most closely nested declaration
• Alternative is dynamic scoping
– Most closely nested activation
36
Block
• Statement containing its own data declarations
• Blocks can be nested
– also referred to as block structured
• Scope of the declaration is given by most
closely nested rule
– The scope of a declaration in block B includes B
– If X is not declared in B then an occurrence of X in B
is in the scope of declaration of X in B′ such that
• B′ has a declaration of X
• B′ is most closely nested around B
37
Example
main()
{ BEGINNING of B0
int a=0 Scope B0, B1, B3
int b=0 Scope B0
{ BEGINNING of B1
int b=1 Scope B1, B2
{ BEGINNING of B2
int a=2 Scope B2
print a, b
} END of B2

{ BEGINNING of B3
int b=3 Scope B3
print a, b
} END of B3
print a, b
} END of B1
print a, b
} END of B0
38
Blocks … { // a0
{ // b0
{ // b1
• Blocks are simpler to { // a2
handle than procedures }
{ //b3
• Blocks can be treated as }
parameter less }
}
procedures }
• Either use stack for
memory allocation a0

• OR allocate space for b0


complete procedure b1
body at one time
a2 b3
39
Lexical scope without nested procedures
• A procedure definition cannot occur within
another
• Therefore, all non local references are global and
can be allocated at compile time
• Any name non-local to one procedure is non-local
to all procedures
• In absence of nested procedures use stack
allocation
• Storage for non locals is allocated statically
– Any other name must be local to the top of the stack
• Static allocation of non local has advantage:
– Procedures can be passed/returned as parameters

40
Scope with nested procedures
Program sort; procedure quicksort(m,n:integer);
var a: array[1..n] of integer; var k,v : integer;
x: integer;
procedure readarray; function partition(y,z:integer): integer;
var i: integer; var i,j: integer;
begin begin

end;
end; begin
procedure exchange(i,j:integer) .
begin end;
begin
end; .
end.

41
Nesting Depth
• Main procedure is at depth 1
• Add 1 to depth as we go from enclosing to
enclosed procedure

Access to non-local names


• Include a field ‘access link’ in the activation
record
• If p is nested in q then access link of p
points to the access link in most recent
activation of q 42
sort

quicksort(1,9)

quicksort(1,3)

Stack
partition(1,3)

exchange(i,j)

43
Access to non local names …
• Suppose procedure p at depth np refers to a
non-local a at depth na (na ≤ np), then
storage for a can be found as
– follow (np-na) access links from the record at
the top of the stack
– after following (np-na) links we reach
procedure for which a is local
• Therefore, address of a non local a in p can
be stored in symbol table as
– (np-na, offset of a in record of activation
having a )
44
How to setup access links?
• Code to setup access links is part of
the calling sequence.
• suppose procedure p at depth np calls
procedure x at depth nx.
• The code for setting up access links
depends upon whether or not the
called procedure is nested within the
caller.

45
How to setup access links?
np < nx
• Called procedure x is nested more deeply
than p.
• Therefore, x must be declared in p.
• The access link in x must point to the access
link of the activation record of the caller
just below it in the stack

46
How to setup access links?
np ≥ nx
• From scoping rules enclosing procedure at
the depth 1,2,… ,nx-1 must be same.
• Follow np-(nx-1) links from the caller.
• We reach the most recent activation of the
procedure that statically encloses both p
and x most closely.
• The access link reached is the one to which
access link in x must point.
• np-(nx-1) can be computed at compile
time.
47
Procedure Parameters
program param (input,output);
procedure b( function h(n:integer): integer);
begin
print (h(2))
end;
procedure c;
var m: integer;
function f(n: integer): integer;
begin
return m + n
end;
begin
m :=0; b(f)
end;
begin
c
end.

48
Procedure Parameters …
• Scope of m does not include procedure b
• within b, call h(2) activates f
• how is access link for activation of f is set
up?
• a nested procedure must take its access
link along with it
• when c passes f:
– it determines access link for f as if it were
calling f
– this link is passed along with f to b
• When f is activated, this passed access link
is used to set up the activation record of f
49
Procedure Parameters …
param

<f, >

50
Displays
• Faster access to non
locals d[1]
d[2] s
d[3] q(1,9)
• Uses an array of
saved d[2]
pointers to
activation records q(1,3)
saved d[2]

p(1,3)
• Non locals at depth i saved d[3]
are in the activation
e(1,3)
record pointed to by saved d[2]
d[i]

51
Setting up Displays
• When a new activation record for a
procedure at nesting depth i is set up:
• Save the value of d[i] in the new activation
record
• Set d[i] to point to the new activation
record
• Just before an activation ends, d[i] is reset
to the saved value

52
Justification for Displays
• Suppose procedure at depth j calls procedure at
depth i
• Case j < i then i = j + 1
– called procedure is nested within the caller
– first j elements of display need not be changed
– old value of d[i] is saved and d[i] set to the new
activation record
• Case j ≥ i
– enclosing procedure at depths 1…i-1 are same and are
left un-disturbed
– old value of d[i] is saved and d[i] points to the new
record
– display is correct as first i-1 records are not disturbed
53
Dynamic Scoping: Example
• Consider the following program

program dynamic (input, output);


var r: real;

procedure show;
begin write(r) end;

procedure small;
var r: real;
begin r := 0.125; show end;

begin
r := 0.25; // writeln prints a newline character
show; small; writeln;
show; small; writeln;
end.
54
Example …
• Output under lexical scoping
0.250 0.250
0.250 0.250

• Output under dynamic scoping


0.250 0.125
0.250 0.125
55
Dynamic Scope
• Binding of non local names to storage do
not change when new activation is set up

• A non local name x in the called activation


refers to same storage that it did in the
calling activation

56
Implementing Dynamic Scope
• Deep Access
– Dispense with access links
– use control links to search into the stack
– term deep access comes from the fact that
search may go deep into the stack
• Shallow Access
– hold current value of each name in static
memory
– when a new activation of p occurs a local name
n in p takes over the storage for n
– previous value of n is saved in the activation
record of p
57
Parameter Passing
• Call by value
– actual parameters are evaluated and
their r-values are passed to the called
procedure
– used in Pascal and C
– formal is treated just like a local name
– caller evaluates the actual parameters
and places rvalue in the storage for
formals
– call has no effect on the activation
record of caller
58
Parameter Passing …
• Call by reference (call by address)
– the caller passes a pointer to each
location of actual parameters
– if actual parameter is a name then
l-value is passed
– if actual parameter is an expression then
it is evaluated in a new location and the
address of that location is passed

59
Parameter Passing …
• Copy restore (copy-in copy-out, call by
value result)
– actual parameters are evaluated, rvalues
are passed by call by value, lvalues are
determined before the call
– when control returns, the current rvalues
of the formals are copied into lvalues of
the locals

60
Parameter Passing …
• Call by name (used in Algol)
– names are copied
– local names are different from
names of calling procedure
– Issue: swap(x, y) { swap(i,a[i]):
temp = x temp = i
x =y i = a[i]
y = temp a[i] = temp
}
61
3AC for Procedure Calls
S  call id ( Elist )
Elist  Elist , E
Elist  E
• Calling sequence
– allocate space for activation record
– evaluate arguments
– establish environment pointers
– save status and return address
– jump to the beginning of the procedure
81
Procedure Calls …
Example
• parameters are passed by reference
• storage is statically allocated
• use param statement as place holder
for the arguments
• called procedure is passed a pointer to
the first parameter
• pointers to any argument can be
obtained by using proper offsets
82
Procedue Calls
• Generate three address code needed to evaluate
arguments which are expressions
• Generate a list of param three address
statements
• Store arguments in a list
S  call id ( Elist )
for each item p on queue do emit('param' p)
emit('call' id.place)
Elist  Elist , E
append E.place to the end of queue
Elist  E
initialize queue to contain E.place
83
Procedure Calls
• Practice Exercise:
How to generate intermediate code for
parameters passed by value? Passed by
reference?

84

You might also like