0% found this document useful (0 votes)
17 views10 pages

CTCD

Ctcd

Uploaded by

Ranjit47 H
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
17 views10 pages

CTCD

Ctcd

Uploaded by

Ranjit47 H
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 10

Storage Allocation and Parameters

1. i) Discuss in Storage allocations strategies


ii) Discuss in Parameter passing methods
2. Explain in detail about issues in the design of a code generator.
3. What is a symbol table? What type of information is stored in it? Discuss the use of data
structuresfor implementing a symbol table.
4. What are the principal sources of optimization? Explain with suitable examples.
5. Construct DAG for the following basic block
1. t1:= 4A;
2. t2:= a[t1]
3. t3:= 4*i
4. t4:= b[t3]
5. t5:= t2*t4
6. t6:= prod +t5
7. prod:= t6
8. t7:= i+1
9. i:=t7
10. if I <= 20 goto(1

very very detailed ans

1. i) Storage Allocation Strategies

In a compiler, storage allocation refers to how memory is allocated for variables, constants, and other
entities used in a program. The key strategies are:

Static Allocation: Memory is allocated at compile-time, and the lifetime of storage is the entire
program run. This is typically used for global variables and constants. The size and location of
data are fixed, and no dynamic memory management is required. Limitations: It cannot handle
recursive procedures or dynamically-sized data structures.
Stack Allocation: This method allocates memory during runtime in a stack-like structure,
typically for local variables and function calls. Memory is allocated when a function is invoked
and deallocated when it returns. This allows for recursion. Advantages: Efficient and simple
memory management. Disadvantages: Stack overflows if recursion is too deep.
Heap Allocation: Memory is dynamically allocated during runtime and is controlled manually
through the program (e.g., `malloc` in C or `new` in Java). This is used for dynamic data structures
like linked lists or trees that grow and shrink during execution. Advantages: Flexible memory
usage. Disadvantages: More complex, slower due to fragmentation, and memory management
issues like leaks.

ii) Parameter Passing Methods Parameter passing defines how arguments are passed to functions
or procedures.

Printed using Save ChatGPT as PDF, powered by PDFCrowd HTML to PDF API. 1/10
Call by Value: The actual value is passed to the function, meaning changes to the parameter
within the function do not affect the original variable. This is the most common method and is
safe but can be inefficient for large data structures.
Call by Reference: A reference (or address) to the actual variable is passed. Changes made
within the function affect the original variable. It is efficient for large data structures but can lead
to side effects since the original data can be altered.
Call by Value-Result: A combination where the value is passed, and any changes to the
parameter within the function are reflected back in the original variable when the function
returns. It is used in languages like Ada.
Call by Name: The argument expression is not evaluated before passing it but is substituted
directly in the function body, re-evaluated each time it's used. It is mainly theoretical but has
roots in lambda calculus and is used in lazy evaluation.

2. Issues in the Design of a Code Generator

A code generator translates an intermediate representation of code into machine code. The key
design issues include:

Target Machine Architecture: Understanding the target architecture (e.g., register allocation,
instruction set) is crucial for generating efficient code. Some architectures have limited registers
or special instruction sets.
Instruction Selection: The code generator must select appropriate machine instructions for
each operation. This depends on the complexity of the operation and the available instructions
of the target machine.
Register Allocation: Since machines have a limited number of registers, the code generator
must manage register usage efficiently. Register Spilling occurs when there are not enough
registers, forcing some values to be temporarily stored in memory, which slows down execution.
Instruction Scheduling: Optimizing the order in which instructions are issued to avoid pipeline
stalls or ensure parallel execution on processors with multiple cores. Dependency between
instructions may necessitate reordering.
Handling of Data Flow and Control Flow: Efficient translation of data flow (assignments,
expressions) and control flow (loops, branches) is necessary to produce optimized machine code.
Branch prediction and loop unrolling are examples of optimization techniques used here.
Optimization Trade-offs: High levels of optimization can increase compile-time and complexity.
The code generator should balance between compile-time performance and the level of
optimization applied to the code.

3. Symbol Table

A symbol table is a data structure used by a compiler to store and manage information about
identifiers (variables, functions, classes, etc.) in a source program.

Types of Information Stored:


Name of the identifier: Unique variable or function name.
Type: Data type (int, float, char, etc.).
Scope: The scope in which the identifier is valid (global, local, etc.).
Memory Location: Address or memory offset where the variable or function is stored.

Printed using Save ChatGPT as PDF, powered by PDFCrowd HTML to PDF API. 2/10
Attributes: Additional information, like size (for arrays), the number of parameters (for
functions), and type of parameters (for function overloading).
Data Structures for Symbol Table:
Hash Tables: Efficient in terms of lookup time. The hash function converts an identifier’s
name into a unique index in an array.
Binary Search Trees: The names of identifiers are stored in a sorted manner for faster
lookup, insertion, and deletion.
Linked Lists: Suitable for small scopes but inefficient for large programs due to linear
search time.

Use: Symbol tables facilitate semantic analysis, scope resolution, and code generation by storing
information that the compiler needs during different stages.

4. Principal Sources of Optimization

Optimization techniques improve code performance by reducing its runtime or memory usage
without changing its semantics. Major sources include:

Constant Folding: Replacing expressions that evaluate to a constant (e.g., `3 * 5` becomes `15`)
during compile-time, reducing computation at runtime.
Example:

int x = 5 * 10;

becomes:

int x = 50;

Common Subexpression Elimination: If an expression is computed more than once, it can be


computed once and reused.
Example:

y = (a + b) * c;
z = (a + b) * d;

becomes:

temp = a + b;
y = temp * c;

Printed using Save ChatGPT as PDF, powered by PDFCrowd HTML to PDF API. 3/10
z = temp * d;

Loop Optimization: Techniques like loop unrolling and loop invariant code motion aim to
improve the efficiency of loops by either reducing the overhead of loop control or minimizing the
number of operations within loops.
Example (Loop Invariant Code Motion):

for (i = 0; i < n; i++) {


x = 2 + 3;
arr[i] = x * i;
}

becomes:

x = 5;
for (i = 0; i < n; i++) {
arr[i] = x * i;
}

Dead Code Elimination: Removing code that does not affect the program, such as unused
variables or unreachable code blocks.
Example:

if (false) {
// This block will never be executed
x = 10;
}

5. Constructing a Directed Acyclic Graph (DAG) for the Basic Block

To represent the computation in a basic block, a DAG (Directed Acyclic Graph) shows the dependencies
between computations, reusing common subexpressions.
Basic Block:

css

1. t1 := 4 * A;
2. t2 := a[t1];
3. t3 := 4 * i;
4. t4 := b[t3];
5. t5 := t2 * t4;
6. t6 := prod + t5;
7. prod := t6;
8. t7 := i + 1;

Printed using Save ChatGPT as PDF, powered by PDFCrowd HTML to PDF API. 4/10
9. i := t7;
10. if i <= 20 goto (1)

DAG Construction:

1. Node for `4 * A` → t1
2. Node for `a[t1]` → t2
3. Node for `4 * i` → t3
4. Node for `b[t3]` → t4
5. Node for `t2 * t4` → t5
6. Node for `prod + t5` → t6
7. Node for `i + 1` → t7

These nodes show dependencies and optimize by reusing expressions like `4 * A` or `4 * i` wherever
necessary without recomputation.
DAG:

css

4 4
/ \
* *
/ \ / \
A i A i
\ /
a[t1] b[t3]
\ /
* +
\ /
+ prod

5q 16 marks detailed and formatted ans

5. Constructing a Directed Acyclic Graph (DAG) for the Basic Block

Problem Statement:
Construct a Directed Acyclic Graph (DAG) for the following basic block:

css

1. t1 := 4 * A;
2. t2 := a[t1];
3. t3 := 4 * i;
4. t4 := b[t3];
5. t5 := t2 * t4;
6. t6 := prod + t5;
7. prod := t6;
8. t7 := i + 1;

Printed using Save ChatGPT as PDF, powered by PDFCrowd HTML to PDF API. 5/10
9. i := t7;
10. if i <= 20 goto (1)

Introduction to DAG in Compiler Design

A Directed Acyclic Graph (DAG) is a data structure used in compiler design to represent expressions
in a basic block and the relationships among them. The purpose of DAGs is to:

Eliminate common subexpressions.


Reuse intermediate results to avoid recomputation.
Show dependencies between different computations.
Optimize the code generation process by identifying redundant computations.

Each node in a DAG represents either a constant, variable, or computed value, and directed edges
represent dependencies between operations.

Steps to Construct the DAG

The basic block contains a sequence of computations that involve array accesses, arithmetic
operations, and assignments. We will now break down each instruction and build the corresponding
DAG.

Step-by-Step Construction

1. Instruction 1: `t1 := 4 * A;`


This instruction multiplies the constant `4` with the variable `A`.
Create a node for `4` and a node for `A`. Then, create a multiplication node (`*`) with `4`
and `A` as children.
Assign the result of the multiplication to `t1`.
DAG Representation:

css

4 A
\ /
( * )
|
t1

2. Instruction 2: `t2 := a[t1];`


This instruction uses `t1` as an index to access an array `a` at position `t1`.
Since `t1` is already computed, we reuse it in this operation.
Create a node for `a[t1]` and assign the result to `t2`.
DAG Representation:

css

4 A
\ /
( * ) t1
| |
t1 ( a[t1] )

Printed using Save ChatGPT as PDF, powered by PDFCrowd HTML to PDF API. 6/10
|
t2

3. Instruction 3: `t3 := 4 * i;`


This instruction multiplies `4` with the variable `i`.
Create a node for `4` and a node for `i`. Then, create a multiplication node (`*`) with `4`
and `i` as children.
Assign the result to `t3`.
DAG Representation:

css

4 A 4 i
\ / \ /
( * ) ( * )
| |
t1 t3
|
( a[t1] )
|
t2

4. Instruction 4: `t4 := b[t3];`


This instruction uses `t3` as an index to access an array `b` at position `t3`.
Since `t3` is already computed, we reuse it in this operation.
Create a node for `b[t3]` and assign the result to `t4`.
DAG Representation:

css

4 A 4 i
\ / \ /
( * ) ( * )
| |
t1 t3
| |
( a[t1] ) ( b[t3] )
| |
t2 t4

5. Instruction 5: `t5 := t2 * t4;`


This instruction multiplies `t2` and `t4`.
Both `t2` and `t4` are already computed, so we reuse them.
Create a multiplication node (`*`) with `t2` and `t4` as children, and assign the result to
`t5`.
DAG Representation:

css

4 A 4 i
\ / \ /
( * ) ( * )
| |
t1 t3
| |
( a[t1] ) ( b[t3] )

Printed using Save ChatGPT as PDF, powered by PDFCrowd HTML to PDF API. 7/10
| |
t2 t4
\ /
( * )
|
t5

6. Instruction 6: `t6 := prod + t5;`


This instruction adds `prod` to `t5`.
Create a node for `prod` and reuse `t5`.
Create an addition node (`+`) with `prod` and `t5` as children, and assign the result to `t6`.
DAG Representation:

css

4 A 4 i
\ / \ /
( * ) ( * )
| |
t1 t3
| |
( a[t1] ) ( b[t3] )
| |
t2 t4
\ /
( * )
|
t5 prod
\ /
( + )
|
t6

7. Instruction 7: `prod := t6;`


This is an assignment of `t6` to `prod`.
We don’t need to create a new node since the assignment just updates the value of `prod`.
DAG Representation:

css

4 A 4 i
\ / \ /
( * ) ( * )
| |
t1 t3
| |
( a[t1] ) ( b[t3] )
| |
t2 t4
\ /
( * )
|
t5 prod
\ /
( + )
|
t6

8. Instruction 8: `t7 := i + 1;`


This instruction increments `i` by 1.

Printed using Save ChatGPT as PDF, powered by PDFCrowd HTML to PDF API. 8/10
Create a node for the constant `1`, and then create an addition node (`+`) with `i` and `1`
as children. Assign the result to `t7`.
DAG Representation:

css

4 A 4 i 1
\ / \ / |
( * ) ( * ) ( + )
| | / \
t1 t3 i 1
| |
( a[t1] ) ( b[t3] )
| |
t2 t4
\ /
( * )
|
t5 prod
\ /
( + )
|
t6

9. Instruction 9: `i := t7;`
This is another simple assignment where `t7` is assigned to `i`.
No new node is needed, as this simply updates the value of `i`.
DAG Representation:

css

4 A 4 i 1
\ / \ / |
( * ) ( * ) ( + )
| | / \
t1 t3 i 1
| |
( a[t1] ) ( b[t3] )
| |
t2 t4
\ /
( * )
|
t5 prod
\ /
( + )
|
t6

10. Instruction 10: `if i <= 20 goto (1)`


This is a conditional jump based on the value of `i`.
We check if `i` is less than or equal to `20`. If true, the program jumps back to instruction
1.
DAG Representation:
Since this is a control statement, it does not affect the DAG structure but marks the control
flow dependency.

Final DAG Representation

Printed using Save ChatGPT as PDF, powered by PDFCrowd HTML to PDF API. 9/10
The final DAG for the basic block represents dependencies between all expressions:

css

4 A 4 i 1
\ / \ / |
( * ) ( * ) ( + )
| | / \
t1 t3 i 1
| |
( a[t1] ) ( b[t3] )
| |
t2 t4
\ /
( * )
|
t5 prod
\ /
( + )
|
t6

Conclusion

The DAG allows us to represent the basic block efficiently by identifying and reusing common
subexpressions.
It minimizes redundant calculations and optimizes code generation, which is crucial for achieving
better runtime performance.
ChatGPT can make mistakes. Check important info.

Printed using Save ChatGPT as PDF, powered by PDFCrowd HTML to PDF API. 10/10

You might also like