Atcd - Unit 5
Atcd - Unit 5
Object code is the machine-readable version of the program generated by a compiler after
translating the source code (written in a high-level language) into a low-level language
(usually assembly or machine code). It is an intermediate representation, often in binary
format, that can be executed by the computer's processor after being linked.
1. Binary Format:
a. Object code consists of binary instructions (1s and 0s) that are understood
by the computer’s CPU.
2. Modular:
a. It represents small, independent modules (or object files), each
corresponding to a function or section of the program.
3. Contains Machine Instructions:
a. The object code contains the actual machine instructions corresponding to
the logic and operations of the source code.
4. Not Fully Executable:
a. Object code is not directly executable. It needs to be linked with other object
files and libraries to create a complete executable file.
Example:
A simple statement like int x = 5; in C would be translated into machine code in the
object file, which could look like:
MOV R1, 5 // Store 5 into register R1
MOV [x], R1 // Store value from R1 into variable 'x'
Purpose:
Object code is a crucial step in the compilation process, allowing for modular code
generation and enabling the linking process to produce a final executable program.
Register allocation and assignment are essential tasks in the code generation phase of a
compiler. They are concerned with efficiently using the limited number of registers
available in a processor to store variables and intermediate values during program
execution.
1. Register Allocation
Register allocation is the process of deciding which variables or values should be stored
in the limited number of CPU registers during the execution of a program. Since registers
are faster than memory, allocating registers to frequently used variables can significantly
improve the program’s performance.
Key Concepts:
Registers vs. Memory: Registers are small storage locations within the CPU that
can be accessed very quickly compared to memory. Using registers effectively
improves the execution speed of the program.
Limited Registers: CPUs typically have a small number of registers (e.g., 8 to 32),
so not all variables can be stored in registers at the same time. This makes efficient
register allocation crucial for performance.
Goals of Register Allocation:
2. Register Assignment
Register assignment follows register allocation and refers to the actual process of
assigning specific registers to variables. Once the allocation decision is made (i.e., which
variables need to be in registers), the next task is to assign them to specific registers.
Example:
Consider the following variables and their live intervals during execution:
If there are only two registers available, the allocation might look like this:
1. Graph Coloring:
o A common method where a graph is constructed where each node
represents a variable, and an edge represents an interference between two
variables (i.e., they are live at the same time). The goal is to color the graph
with the minimum number of colors (each color represents a register).
2. Spilling:
o When there are more variables than available registers, some variables need
to be "spilled" to memory. This means storing the variable in memory and
loading it into a register when needed.
o Linear Scan:
o A simpler approach where variables are allocated to registers in a linear pass
through the program, prioritizing recently used variables.
Conclusion:
Register allocation optimizes the use of CPU registers, and register assignment ensures
that specific registers are allocated to variables during execution. Together, they are vital
for improving the efficiency of the compiled code, reducing memory access times, and
enhancing the overall performance of the program.
These issues collectively ensure that the generated code is efficient, correct, and portable
across different machines and architectures.
The generic code generation algorithm is a crucial part of a compiler that translates an
intermediate representation (IR) of the source program into the target machine code
(machine instructions). The goal is to produce efficient and correct code while considering
the constraints and features of the target architecture.
Example:
ADD R1, R3 ; R1 = a + d
MOV e, R1 ; Store result in e
Conclusion:
The generic code generation algorithm is designed to convert high-level code into
machine code by selecting the right instructions, managing registers, and optimizing
control flow. The overall aim is to generate code that is correct, efficient, and tailored to
the target architecture.
Benefits:
t1 = 5 + a
t2 = x[t1]
t3 = 5 + a
t4 = y[t3]
t5 = t2 + t4
t6 = b * t5
b = t6
t7 = a * 3
a = t7 if a < log(0 to 1)
Steps to Create the DAG:
5
|
a--+--> (t1 = 5 + a)
|
x[t1]--> (t2 = x[t1])
|
y[t3]--> (t4 = y[t3])
|
(t2 + t4)--> (t5 = t2 + t4)
|
b * t5--> (t6 = b * t5)
|
b = t6
|
a * 3--> (t7 = a * 3)
|
a = t7 if a < log(0 to 1)
Conclusion:
The DAG representation of a basic block is a powerful way to structure and optimize
intermediate code. It eliminates redundant computations, simplifies instruction selection,
and aids in further optimizations during code generation. By capturing the flow of data and
dependencies, DAGs enable the compiler to generate more efficient and optimized
machine code.