CSE-UNIT-5
CSE-UNIT-5
Syllabus
Run time storage
• The compiler demands for a block of memory to operating system. The
compiler utilizes this block of memory for running/executing the
compiled program. This block of memory is called Run-time storage.
Storage organization
• When the target program executes then it runs in its own logical
address space in which the value of each program has a
location.
• A chain of access links is formed on the top of the stack and represents
the program's scope or static structure.
Access links example
Procedure Calls
• The procedure is such an important and frequently used programming
construct that it is imperative for a compiler to generate good code for
procedure calls and returns.
• The run-time routines that handle procedure argument passing, calls and
returns are part of the run-time support package.
SDT for procedure calls
Calling sequences
• When a procedure call occurs then space is allocated for activation
record.
• Evaluate the argument of the called procedure.
• Establish the environment pointers to enable the called procedure to
access data in enclosing blocks.
• Save the state of the calling procedure so that it can resume execution
after the call.
• Also save the return address. It is the address of the location to which
the called routine must transfer after it is finished.
• Finally generate a jump to the beginning of the code for the called
procedure.
Nesting depth
• The nesting depth is the number of statement blocks that are
nested due to the use of control structures (branches, loops).
• The procedure of calculating nesting depth as follows:
The main programs nesting depth is “1”
when a new procedure begins, add ‘1” to the nesting depth
each time
when we exit from a nested procedure, subtract “1” from
depth each time.
Nesting depth example
Displays
• If access links are used in the search, then the search can be slow.
• So, optimization is used to access an activation record from the direct location
of the variable without any search
• Display is a global array of pointers to activation records, indexed by lexical
nesting depth. The number of display elements can be known at compiler time
• Displays are maintained in registers
• It is stored in static space
Displays- diagrammatic representation
Displays are auxiliary arrays that contain a pointer for every nesting
depth. At any point, d[i] is the pointer to the activation record which is
the highest in the stack for a procedure which is at depth i.
Contd.,
• In the above figure, we assume that each function f1(),f2(), f3(), and f4() lies
at different depths. d[1] holds the pointer to the activation record for f1(), the
only one for that depth. Similarly, there are pointers for each depth.
• Now if a procedure requires access to data from another procedure, let's say
f2() wants to access some data from f1(), then runtime only searches in
activations from d[i] where i is the nesting depth of f1() and follow the
pointer.
Code generator
• Code generator is used to produce the target code for three-
address statements. It uses registers to store the operands of the
three address statement.
• The code generated by the compiler is an object code of some
lower-level programming language, for example, assembly
language.
Contd.,
Contd.,
Tasks of code generator/ Design issues
The main task of code generator is to produce correct code
• Instruction selection
• Register allocation
• Instruction ordering
1. Instruction selection
• The job of instruction selector is to do a good job overall of choosing which
instructions to implement which operator in the low-level intermediate
representation with.
• Ex:
2. Register Allocation
• Register can be accessed faster than memory.
• The instructions involving operands in register are shorter and
faster than those involving in memory operand.
The following sub problems arise when we use registers:
• Register allocation: In register allocation, we select the set of
variables that will reside in register.
• Register assignment: In Register assignment, we pick the
register that contains variable.
Example
3. Evaluation order
• Order of evaluation of the nodes in an expression DAG or expression
tree can affect the number of registers required to evaluate the
expression.
• Some computation orders require fewer registers to hold
intermediate results than others.
A simple code generator
• Code generation is a process in which a compiler ‘code generator’ converts the
source code into a form that can be executed by a machine.
• The main job is to convert an intermediate representation into a linear
sequence of machine instructions.
• Code generation phase includes: instruction selection
instruction scheduling
register allocation
• A code generator is a compiler that translates the intermediate
representation of the source program into the target program.
4. If the current values of y or z have no next uses, are not live on exit from the
block, and are in registers, alter the register descriptor to indicate that, after
execution of x : = y op z , those registers will no longer contain y or z.
Contd.,
• The assignment d : = (a-b) + (a-c) + (a-c) might be translated into the following
three-address code sequence:
• Code sequence for the example is:
Contd.,
Object code forms
• In compiler design, object code is the output of the compilation process.
• It is generated from the source code by the compiler and represents the
low-level instructions that can be executed directly by the computer's
processor.
Contd.,
There are two main forms of object code:
1. Relocatable Object Code:
• This form of object code is not yet linked to any other code or libraries.
• It contains instructions that can be relocated to any memory location by the linker,
which is a program that combines multiple object files into a single executable file.
2. Executable Object Code:
• This form of object code is fully linked and ready to be executed by the computer's
processor.
• It contains all the necessary instructions and data to run the program, as well as any
required library code that was linked in during the compilation process.
Register Allocation and Assignment
• Instruction involving only register operands are shorter and faster than those
involving memory operands.
• This means proper use of register help in generating the good code.
• One approach to register allocation and assignment is to assign specific value
in an object program to certain registers.
• This simplifies the design of a compiler.
Contd.,
Strategies used in register and assignment
1.Global register allocation
2.Usage counts
3.Register assignment for outer loops
4.Register allocation by graph coloring
1. Global register allocation
• Allocation of variables to specific registers that is consistent across the block
boundaries is called global register allocation.
• The global register allocation has a strategy of storing the most frequently used
variables in fixed registers throughout the loop
• Another strategy is to assign some fixed number of global registers to hold the
most active value in each inner loop,
• The registers not already allocated may be used to hold values local to one
block.