0% found this document useful (0 votes)
14 views5 pages

Intermediate Code Generation Notes (1)

Intermediate code generation translates source code into a machine-independent intermediate representation, facilitating optimization and code generation. It encompasses handling declarations, assignments, boolean expressions, case statements, backpatching, and procedure calls. This process acts as a bridge between the front-end and back-end of a compiler, ensuring efficient code generation.

Uploaded by

Garvit Dani
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)
14 views5 pages

Intermediate Code Generation Notes (1)

Intermediate code generation translates source code into a machine-independent intermediate representation, facilitating optimization and code generation. It encompasses handling declarations, assignments, boolean expressions, case statements, backpatching, and procedure calls. This process acts as a bridge between the front-end and back-end of a compiler, ensuring efficient code generation.

Uploaded by

Garvit Dani
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/ 5

Intermediate Code

Generation (Unit IV)


What is Intermediate Code Generation?
Intermediate code generation is like translating a book into a simpler language before final publication—it’s a phase in the
compiler where the source code (after syntax and semantic analysis) is translated into an intermediate representation
(IR) that’s easier to optimize and convert into machine code. This IR is machine-independent, meaning it can be used to
generate code for different target architectures. Common forms of IR include three-address code, quadruples, and triples.

Role of Intermediate Code Generation:


Acts as a bridge between the front-end (analysis) and back-end (code generation) of a compiler.
Simplifies optimization by providing a uniform representation.
Example: Source code x = a + b * c is translated into a sequence of simpler instructions.

Subtopics in Intermediate Code


Generation
1. Declarations
Declarations involve generating intermediate code for variable declarations, ensuring that memory is allocated and type
information is recorded in the symbol table.

Process:
Parse the declaration (e.g., int x;).
Update the symbol table with the variable’s name, type, and memory offset.
No explicit three-address code is generated for declarations, but the compiler ensures space allocation.
Example:
Source: int x, y;
Action: Symbol table entries: x: type=int, offset=0, y: type=int, offset=4 (assuming 4
bytes per int).
Note: For arrays (e.g., int arr[10];), the compiler calculates total memory (e.g., 10 * 4 = 40 bytes) and
stores the base address in the symbol table.

2. Assignment Statements
Assignment statements are translated into three-address code, where each instruction has at most three operands (e.g.,
t1 = a + b).

Process:
Parse the assignment (e.g., x = a + b * c).
Break it into simpler operations using temporary variables.
Generate three-address code.
Example:
Source: x = a + b * c
Intermediate Code:

t1 = b * c
t2 = a + t1
x = t2

Quadruples Representation: | Op | Arg1 | Arg2 | Result | |-----|------|------|--------| | * | b | c | t1 | | + | a | t1 |


t2 | | = | t2 | | x |
Triples Representation: | Op | Arg1 | Arg2 | |-----|------|------| | * | b | c | | + | a | (0) | | = | x | (1) | (Here, (0)
refers to the result of the first instruction, (1) to the second.)

3. Boolean Expressions
Boolean expressions (e.g., a < b && c > d) are used in control structures (if, while). They’re translated into
intermediate code with conditional jumps to handle true/false outcomes.

Process:
Evaluate the expression using short-circuit evaluation (e.g., stop if the first condition fails in &&).
Use labels to jump to true/false blocks.
Example:
Source: if (a < b && c > d) x = 1; else x = 0;
Intermediate Code:

if a < b goto L1
goto L2
L1: if c > d goto L3
goto L2
L3: x = 1
goto L4
L2: x = 0
L4:

Explanation:
L1, L2, L3, L4 are labels for jumps.
First checks a < b, jumps to L1 if true, else to L2 (false case).
At L1, checks c > d, jumps to L3 (true case) or L2 (false case).

4. Case Statements
Case statements (switch statements) are translated into intermediate code using a jump table or a series of conditional
jumps.

Process:
Evaluate the switch expression.
Generate jumps to the corresponding case labels.
Example:
Source:

switch (x) {
case 1: y = 10; break;
case 2: y = 20; break;
default: y = 0;
}

Intermediate Code:

if x == 1 goto L1
if x == 2 goto L2
goto L3
L1: y = 10
goto L4
L2: y = 20
goto L4
L3: y = 0
L4:

Alternative: Use a jump table for efficiency (array of labels indexed by x).

5. Backpatching
Backpatching is a technique to handle incomplete jumps in intermediate code (e.g., in if-else or while loops) by filling in
jump addresses later.

Process:
Generate code with placeholder jumps (e.g., goto _).
Maintain a list of instructions with unresolved jumps.
Fill in the labels once the target addresses are known.
Example:
Source: if (a > b) x = 1; else x = 0;
Initial Code (with placeholders):

100: if a > b goto _


101: x = 0
102: goto _
103: x = 1

Backpatching:
At 100, goto _ is filled as goto 103 (true case).
At 102, goto _ is filled as goto 104 (next instruction after false case).
Final Code:

100: if a > b goto 103


101: x = 0
102: goto 104
103: x = 1
104:

6. Procedure Calls
Procedure calls involve generating code for function calls, passing parameters, and handling return values.

Process:
Push parameters onto the stack or pass via registers.
Call the procedure (jump to its address).
Handle return values.
Example:
Source: y = foo(a, b);
Intermediate Code:

param a
param b
call foo, 2
y = return

Explanation:
param a, param b: Push parameters a and b.
call foo, 2: Call function foo with 2 arguments.
y = return: Store the return value in y.
Flowchart: Intermediate Code Generation
Process
[Syntax Tree] → [Generate Declarations (Symbol Table)] → [Translate Assignments] →
[Handle Boolean Expr (Jumps)] → [Process Case Stmts] → [Backpatch Jumps] →
[Generate Procedure Calls] → [Intermediate Code]

Quick Revision Box


Quick Revision: Intermediate Code Generation
1. Declarations: Update symbol table (e.g., int x).
2. Assignment: x = a + b * c → t1 = b * c, x = a + t1.
3. Boolean: a < b && c > d → Conditional jumps.
4. Case: switch(x) → Jump table or if-goto.
5. Backpatching: Fill placeholder jumps (if a > b goto _).
6. Procedure: y = foo(a, b) → param a, call foo.

Sticky Note-Style Visual


Sticky Note: Intermediate Code Tip
Assignment: t1 = b * c.
Boolean: if a < b goto L1.
Case: if x == 1 goto L1.
Backpatch: Fill goto _ later.
Procedure: param a, call foo.

Summary
Intermediate code generation translates source code into a machine-independent form like three-address code, handling
declarations (symbol table updates), assignments (e.g., x = a + b * c → t1 = b * c), boolean expressions (using
jumps), case statements (jump tables), backpatching (filling jump addresses), and procedure calls (parameter passing).
This IR simplifies optimization and final code generation.

You might also like