Principles of Compiler Design (Seng 3043) : Chapter - 8 Code Generation

Download as pptx, pdf, or txt
Download as pptx, pdf, or txt
You are on page 1of 25

Principles of Compiler Design (SEng 3043)

Chapter – 8
Code Generation
Debremarkos Institute of Technology
School of Computing
Software Engineering Academic Program

By Lamesginew A. ([email protected] ) 1
Outline
 Introduction
 Issues in the design of code generation
 The Target Machine
 Basic Blocks and flow graphs

2
Introduction
 It is the final phase of a compiler.
 It receives an intermediate representation (IR) from the front-end with
supplementary information in symbol table.
 It produces a semantically equivalent target program.
 Compulsory requirements for code generator
Target program must preserve semantic meaning of source program
Target program must be of high quality(it must make effective use of
available resources of the target machine).
The code generator itself must run efficiently.

3
,,, Cont’d

 It takes intermediate representation of the source program


as input and produces a target program or object program
as its output.
 The input to the code generation must be error free.
 Primary tasks of code generator:
 Instruction selection: choosing appropriate target-machine
instructions to implement the IR statements.
 Register allocation and assignment: deciding what values
to keep in which registers.
 Instruction ordering: deciding in what order to schedule
the execution of instructions.

4
Issues in the Design of a Code Generator
 In the design of code generators, tasks like instruction selection, register
allocation and assignment, and instruction ordering are encountered.
 They are dependent on the specifics of the intermediate representation, the
target language, and the run-time system.
 The most important criterion for a code generator is that it produce correct code.

 Input to the Code Generator


 The input is the intermediate representation (IR) of the source program, and
information in the symbol table.
 Assumptions
 Prior to code generation, the front end has scanned, parsed, and
translated the source program into a relatively low-level IR.
 All syntactic and semantic errors have been detected, that the necessary
type checking has taken place, and that type conversion operators have
been inserted wherever necessary.
 Therefore, code generator proceed on the assumption that its input is free
5
of these kinds of errors.
,,, Cont’d

 The Target Program


 Constructing good code generator depends on the instruction-set
architecture of the target machine.
 Common target-machine architectures are RISC, CISC, and stack based.
 A RISC machine: has many registers, three-address instructions,
simple addressing modes, and a relatively simple instruction-set
architecture.
 A CISC machine: has few registers, two-address instructions, a
variety of addressing modes, several register classes, variable-
length instructions, and instructions with side effects.
 In a stack-based machine: operations are performed on the
operands at the top of the stack. Top of the stack is typically kept
in registers. It requires too many swap and copy operations.
 The output of the code generator is the target program.
 The target program may take a variety of forms: Absolute Machine
language, Relocatable Machine code or Assembly language.
6
,,, Cont’d

• Absolute machine-language program: it can be placed in a fixed


location in memory and immediately executed. Programs can be
compiled and executed quickly.

• Relocatable machine-language program: it allows subprograms to be


compiled separately. A set of relocatable object modules can be linked
together and loaded for execution by a linking loader. There is
flexibility to compile subroutines separately and to call other
previously compiled programs from an object module.

• Assembly-language program: it makes the process of code generation


somewhat easier. We can generate symbolic instructions and use the
macro facilities of the assembler to help generate code.

7
,,, Cont’d
 Instruction Selection
• Code generator maps the IR program into a code sequence that can be
executed by the target machine.
• Factors affecting this mapping are the following
• the level of the IR
• the nature of the instruction-set architecture
• the desired quality of the generated code
 If the IR is high level, the code generator may translate using code
templates. However, such statement-by-statement code generation
often produces poor code that needs further optimization. If the IR
reflects the low-level details of the machine, then the code generator
can use this information to generate more efficient code sequences.
 The nature of the instruction set of the target machine (e.g. uniformity
and completeness of the instruction set) has a strong effect on the
difficulty of instruction selection. If the target machine does not
support each data type in a uniform manner, then each exception to the
general rule requires special handling. 8
 Instruction speeds and machine idioms are other important factors.,,, Cont’d
 For each type of three-address statement, we can design a code
skeleton that defines the target code to be generated for that construct.
 For example, the three-address statement x = y + z can be translated
into the code sequence
LD R0, y // R0 = y (load y into register R0)
ADD R0, R0, z // R0 = R0 + z (add z to R0)
ST x, R0 // x = R0 (store R0 into x)
 For example, for sequence of three-address statements
a=b+c
d=a+e
LD R0, b // R0 = b
ADD R0, R0, c // R0 = R0 + c
ST a, R0 // a = R0
LD R0, a // R0 = a
ADD R0, R0, e // R0 = R0 + e 9
,,, Cont’d
 The quality of the generated code is usually determined by its speed
and size.
 IR program can be implemented by many different code sequences,
with significant cost differences.

• Example: for the three-address statement a = a + 1


• if the target machine has an "increment" instruction (INC), it can be
implemented (more efficient) by INC a, rather than the following
obvious code sequence:
LD R0, a // R0 = a
ADD R0, R0, #1 // R0 = R0 + 1
ST a, R0 // a = R0
 We need to know instruction costs in order to design good code
sequences but, accurate cost information is often difficult to obtain.
 Deciding which machine-code sequence is best may also require
knowledge about the context in which that construct appears.
10
,,, Cont’d
 Register Allocation
 A key problem in code generation is deciding what values to hold in
what registers.
 Registers are the fastest computational unit on the target machine, but
we usually do not have enough of them to hold all values.
 Values not held in registers need to reside in memory.
 Instructions involving register operands are invariably shorter and
faster than those involving operands in memory
 So efficient utilization of registers is particularly important.
 Two sub-problems
• Register allocation: selecting the set of variables that will reside in
registers at each point in the program
• Register assignment: selecting specific register that a variable
reside in

11
,,, Cont’d

 Evaluation order
 The order in which computations are performed can affect the
efficiency of the target code.
 Some computation orders require fewer registers to hold
intermediate results than others.
 However, picking a best order in the general case is a difficult
problem.
 Initially, we shall avoid the problem by generating code for the
three-address statements in the order in which they have been
produced by the intermediate code generator.

12
The Target Machine
 Familiarity with the target machine and its instruction set is a
prerequisite for designing a good code generator.
 Implementing code generation requires thorough understanding of the
target machine architecture and its instruction set.
 A Simple Target Machine Model
 The target computer models a three-address machine with load and store
operations, computation operations, jump operations, and conditional jumps.
 The following are instructions available.
 Load operations: LD dst, addr (dst = addr). Eg.: LD r, x and LD r1, r2
 Store operations: ST x, r
 Computation operations: OP dst, srcl, src2. E.g: SUB rl, r2, r3  rl = r2 – r3.
Unary operators do not have a src2.
 Unconditional jumps: BR L causes to branch to label L.
 Conditional jumps: Bcond r, L, where r is a register, L is a label, and
cond is the common tests on values in the register r. Example, BLTZ r, L
causes a jump to label L if the value in register r is less than zero.
13
,,, Cont’d

 The target machine has a variety of addressing modes, listed below:


 Variable name: x referring to memory location that is reserved for x

 Indexed address: a(r), where a is a variable and r is a register. It is computed by


taking the l-value of a and adding to it with the value in register r. E.g: LD R1, a(R2)
means R1 = contents(a + contents(R2))

 Integer indexed by a register: like LD R1, 100(R2); R1 = contents(100+contents(R2)),

 Indirect addressing mode: *r (the memory location found in the location represented
by the contents of register r) and *100(r) [the memory location found in the location
obtained by adding 100 to the contents of r]. Example, LD R1, *100(R2) has the
effect of setting R1 = contents(contents(l00 + contents(R2)))

 Immediate constant addressing mode: like LD R1, #100; loads the integer 100 into
register R1

14
,,, Cont’d
Eg-1: The three-address statement x = y - z can be implemented by the
machine instructions:
LD R1, y // R1 = y
LD R2, z // R2 = z
SUB R1, R1, R2 // R1 = R1 - R2
ST x, R1 // x = R1

Eg-2: Suppose a is an array whose elements are 8-byte values (real).


machine instructions for the three-address instruction b = a[i] are:
LD R1, i // R1 = i
MUL R1, R1, 8 // R1 = Rl * 8
LD R2, a(R1) // R2 = contents(a + contents(R1))
ST b, R2 // b = R2
Eg-3: Similarly, machine instruction for a[j] = c
LD R1, c // R1 = c
LD R2, j // R2 = j
MUL R2, R2, 8 // R2 = R2 * 8 15
,,, Cont’d

Eg-4: for x = *p
LD R1, p // R1 = p
LD R2, 0(R1) // R2 = contents(0 + contents(R1))
ST x, R2 // x = R2
Eg-5: for *p = y
LD R1, p // R1 = p
LD R2, y // R2 = y
ST 0(R1), R2 // contents(0 + contents(R1)) = R2
Eg-6: for conditional-jump, if x < y goto M
LD R1, x // R1 = x
LD R2, y // R2 = y
SUB R1, R1, R2 // R1 = R1 - R2
BLTZ R1, M // if R1 < 0 jump to M
16
,,, Cont’d

Program and Instruction Costs


We often associate a cost with compiling and running a program.
some common cost measures are the length of compilation time and
the size, running time and power consumption of the target program.
Determining the actual cost of compiling and running a program is a
complex problem.
We will assume each target-language instruction has an associated
cost.
For simplicity, we take the cost of an instruction to be one plus the
costs associated with the addressing modes of the operands.
Addressing modes involving registers have zero additional cost, while
those involving a memory location or constant in them have an
additional cost of one.

17
• Some examples: ,,, Cont’d

 The instruction LD R0, R1 copies the contents of register R1 into


register R0. This instruction has a cost of one.
 The instruction LD R0, M loads the contents of memory location M
into register R0. The cost is two.
 The instruction LD R1, *100(R2) loads into register R1 the value
given by contents(contents(l00 + contents(R2))). The cost is three.
 The instruct ion ADD R1, R1, #1 adds the constant 1 to the contents of
R1, and has cost two.
• Difficulty in generating code
Example, a = b + c can be implemented by many instructions.
1) LD R0 , b
ADD R0, R0, c
LD a, R0 Cost = 6
2) LD a, b
18
ADD a, a, c Cost = 6
,,, Cont’d

 Assuming R0, R1, and R2 contain the addresses of a, b, and c,


respectively, we can use:
3) LD *R0, *R1
ADD *R0, *R0, *R2 Cost = 2
 Assuming R1 and R2 contain the values of b and c, respectively, and
that the value of b is not needed after the assignment, we can use:
4) ADD R1, R1, R2
LD a, R1 Cost = 3

19
Basic Blocks and Flow graphs
 flow graph :- a graph representation of intermediate code.
 The representation is constructed as follows:
Partition the intermediate code into basic blocks, with the
properties that
 The flow of control can only enter the basic block
through the first instruction in the block. That is, there
are no jumps into the middle of the block.
 Control will leave the block without halting or
branching, except possibly at the last instruction in the
block.
The basic blocks become the nodes of a flow graph, whose
edges indicate which blocks can follow which other blocks.

20
,,, Cont’d
 Basic block
 A basic block is a sequence of consecutive statements in which flow of
control enters at the beginning and leaves at the end without halt or
possibility of branching except at the end.
 We begin a new basic block with the first instruction and keep adding
instructions until we meet either a jump, a conditional jump, or a label on the
following instruction.
• Algorithm: Partitioning three-address instructions into basic blocks.
• Input: A sequence of three-address instructions.
• Output: A list of the basic blocks for that sequence in which each instruction
is assigned to exactly one basic block.
• Method: First, determine leaders, that is, the first instruction the basic block.
The rules for finding leaders are:
 The first three-address instruction in the intermediate code is a leader.
 Any instruction that is the target of a conditional or unconditional jump is a leader.
 Any instruction that immediately follows a conditional or unconditional jump is a
leader.
• Then, for each leader, its basic block consists of itself and all instructions up
21
to but not including the next leader or the end of the intermediate program.
For example: for the following intermediate code ,,, Cont’d

 First, instruction 1 is a leader by rule (1)


 To find the other leaders, we first need to find the jumps.
 There are 3 conditional jumps at instructions 9,11 & 17.
 By rule (2), the targets of these jumps are leaders; they
are instructions 3, 2, and 13, respectively.
 Then, by rule (3), each instruction following a jump is
a leader; those are instructions 10 and 12.
 Note that no instruction follows 17 in this code, but if
there were code following, the 18th instruction would
also be a leader.
 Hence, the leaders are instructions 1, 2, 3, 10, 12, and 13.
 The basic block of each leader contains all the
instructions from itself until just before the next leader.
 The basic block of 1 is just 1, for leader 2 the block is
just 2. Leader 3 has a basic block consisting of
instructions 3 through 9, inclusive.
 Instruction 10's block is 10 and 11;
 Instruction 12's block is just 12,
 Instruction 13's block is 13 through 17.
22
,,, Cont’d
Flow Graphs
 Once an intermediate-code program is partitioned into basic blocks,
we represent the flow of control between them by a flow graph.
 The nodes of the flow graph are the basic blocks.
 There is an edge from block B to block C if and only if it is
possible for the first instruction in block C to immediately follow
the last instruction in block B.
 Often we add two nodes, called the entry and exit that do not
correspond to executable intermediate instructions.
 There is an edge from the entry to the first executable node of the
flow graph, that is, to the basic block that comes from the first
instruction of the intermediate code.
 There is an edge to the exit from any basic block that contains an
instruction that could be the last executed instruction of the
program.

23
,,, Cont’d

For example: for previous set of basic


blocks, the flow graph is the following.
 The entry points to basic block B1,
since B1 contains the first
instruction of the program. The only
successor of B1 is B2.
 Block B3 has two successors: itself
and B4
 Only B6 points to the exit of the
flow graph.

24
OU
K Y
AN
TH

RY
VE
! !
CH
MU

You might also like