Compiler Design Unit 5 Part 2
Compiler Design Unit 5 Part 2
Flow Analysis
Global Data Flow Analysis
• To efficiently optimize the code compiler collects all the information
about the program and distribute this information to each block of the
flow graph. This process is known as data-flow graph analysis.
• Certain optimization can only be achieved by examining the entire
program. It can't be achieve by examining just a portion of the program.
• Here using the value of the variable, we try to find out that which
definition of a variable is applicable in a statement.
• Based on the local information a compiler can perform some
optimizations. For example, consider the following code:
• x = a + b;
• x=6*3
• In this code, the first assignment of x is useless. The value computer
for x is never used in the program.
• At compile time the expression 6*3 will be computed, simplifying the
second assignment statement to x = 18;
For example, consider the following code:
a = 1;
b = 2;
c = 3;
if (....)
x = a + 5;
else
x = b + 4;
c = x + 1;
• In this code, at line 3 the initial assignment is useless and x +1
expression can be simplified as 7.
• Global data flow analysis is used to solve a specific problem “User definition
chaining”.
• Problem: Given that the identifier A is used at a point p in the program. At
what point could the value of A have been defined.
• Reaching definition: Determination of each variable whenever they are
declared in the program.
1. Stack storage. Names local to a procedure are allocated space on a stack. The
stack supports the normal call/return policy for procedures.
2. Heap storage. Data that may outlive the call to the procedure that created it
is usually allocated on a "heap" of reusable storage. The heap is an area of
virtual memory that allows objects or other data elements to obtain storage
when they are created and to return that storage when they are invalidated.
• Procedure calls and returns are usually managed by a run-time stack called
the control stack.
• Each live activation has an activation record (sometimes called a frame) on
the control stack, with the root of the activation tree at the bottom, and
the entire sequence of activation records on the stack corresponding to
the path in the activation tree to the activation where control currently
resides.
• The latter activation has its record at the top of the stack.
• The contents of activation records vary with the
language being implemented.
• Here is a list of the kinds of data that might appear
in an activation record:
6. Space for the return value of the called function, if any. Again, not all called
procedures return a value, and if one does, we may prefer to place that value
in a register for efficiency.
7. The actual parameters used by the calling procedure. Commonly, these
values are not placed in the activation record but rather in registers, when
possible, for greater efficiency. However, we show a space for them to be
completely general.
• The heap is the portion of the store that is used for data that lives
indefinitely, or until the program explicitly deletes it.
• While local variables typically become inaccessible when their procedures
end, many languages enable us to create objects or other data whose
existence is not tied to the procedure activation that creates them.
• For example, both C++ and Java give the programmer new to create objects
that may be passed - or pointers to them may be passed - from procedure to
procedure, so they continue to exist long after the procedure that created
them is gone.
• Such objects are stored on a heap.
3.1 The Memory Manager
• Memory manager is the subsystem that allocates and deallocates space within
the heap; it serves as an interface between application programs and the
operating system.
• The memory manager keeps track of all the free space in heap storage at all
times.
It performs two basic functions:
1. Allocation.
• When a program requests memory for a variable or object, the memory manager
produces a chunk of contiguous heap memory of the requested size.
• If possible, it satisfies an allocation request using free space in the heap; if no
chunk of the needed size is available, it seeks to increase the heap storage space
by getting consecutive bytes of virtual memory from the operating system.
• If space is exhausted, the memory manager passes that information back to the
application program.
2. Deallocation.
• The memory manager returns deallocated space to the pool of free space, so it
can reuse the space to satisfy other allocation requests.
• Memory managers typically do not return memory to the operating system,
even if the program's heap usage drops.
• Similarly, the size of some program data objects, such as global constants,
and data generated by the compiler, such as information to support garbage
collection, may be known at compile time, and these data objects can be
placed in another statically determined area called Static.
• One reason for statically allocating as many data objects as possible is that
the addresses of these objects can be compiled into the target code.
• To maximize the utilization of space at run time, the other two areas, Stack
and Heap, are at the opposite ends of the remainder of the address space.
• These areas are dynamic; their size can change as the program executes.
• These areas grow towards each other as needed. The stack is used to store
data structures called activation records that get generated during procedure
calls.
• An activation record is used to store information about the status of the
machine, such as the value of the program counter and machine registers,
when a procedure call occurs.
• When control returns from the call, the activation of the calling procedure
can be restarted after restoring the values of relevant registers and setting
the program counter to the point immediately after the call.
• Data objects whose lifetimes are contained in that of an activation can be
allocated on the stack along with other information associated with the
activation.
• Many programming languages allow the programmer to allocate and
deallocate data under program control.
• For example, C has the functions malloc and free that can be used to obtain
and give back arbitrary chunks of storage.
• The heap is used to manage this kind of long-lived data.
Runtime Environments
• A compiler must accurately implement the abstractions embodied in the
source language definition.
• These abstractions typically include the concepts such as names, scopes,
bindings, data types, operators, procedures, parameters, and
flow-of-control constructs.
• The compiler must cooperate with the operating system and other
systems software to support these abstractions on the target machine.
• To do so, the compiler creates and manages a run-time environment in which
it assumes its target programs are being executed.