Status: Profs. Aiken CS 143 Lecture 11 1 Profs. Aiken CS 143 Lecture 11 2

Download as pdf or txt
Download as pdf or txt
You are on page 1of 9

Status

• We have covered the front-end phases


– Lexical analysis
Run-time Environments – Parsing
– Semantic analysis
• Next are the back-end phases
Lecture 11 – Optimization
– Code generation

• We’ll do code generation first . . .

Profs. Aiken CS 143 Lecture 11 1 Profs. Aiken CS 143 Lecture 11 2

Run-time environments Outline

• Before discussing code generation, we need to • Management of run-time resources


understand what we are trying to generate
• Correspondence between
• There are a number of standard techniques – static (compile-time) and
for structuring executable code that are – dynamic (run-time) structures
widely used
• Storage organization

Profs. Aiken CS 143 Lecture 11 3 Profs. Aiken CS 143 Lecture 11 4

Run-time Resources Memory Layout

• Execution of a program is initially under the Low Address


control of the operating system
Code

• When a program is invoked: Memory


– The OS allocates space for the program
– The code is loaded into part of the space
– The OS jumps to the entry point (i.e., “main”)
Other Space

High Address
Profs. Aiken CS 143 Lecture 11 5 Profs. Aiken CS 143 Lecture 11 6

1
Notes What is Other Space?

• By tradition, pictures of machine organization • Holds all data for the program
have: • Other Space = Data Space
– Low address at the top
– High address at the bottom
• Compiler is responsible for:
– Lines delimiting areas for different kinds of data
– Generating code
– Orchestrating use of the data area
• These pictures are simplifications
– E.g., not all memory need be contiguous

Profs. Aiken CS 143 Lecture 11 7 Profs. Aiken CS 143 Lecture 11 8

Code Generation Goals Assumptions about Execution

• Two goals: 1. Execution is sequential; control moves from


– Correctness one point in a program to another in a well-
– Speed defined order

• Most complications in code generation come 2. When a procedure is called, control


from trying to be fast as well as correct eventually returns to the point immediately
after the call

Do these assumptions always hold?


Profs. Aiken CS 143 Lecture 11 9 Profs. Aiken CS 143 Lecture 11 10

Activations Lifetimes of Variables

• An invocation of procedure P is an activation • The lifetime of a variable x is the portion of


of P execution in which x is defined

• The lifetime of an activation of P is • Note that


– All the steps to execute P – Lifetime is a dynamic (run-time) concept
– Including all the steps in procedures P calls – Scope is a static concept

Profs. Aiken CS 143 Lecture 11 11 Profs. Aiken CS 143 Lecture 11 12

2
Activation Trees Example

• Assumption (2) requires that when P calls Q, Class Main {


then Q returns before P does g() : Int { 1 };
f(): Int { g() };
• Lifetimes of procedure activations are main(): Int {{ g(); f(); }};
properly nested }
Main
• Activation lifetimes can be depicted as a tree g f

g
Profs. Aiken CS 143 Lecture 11 13 Profs. Aiken CS 143 Lecture 11 14

Example 2 Notes

Class Main { • The activation tree depends on run-time


g() : Int { 1 }; behavior
f(x:Int): Int { if x = 0 then g() else f(x - 1) fi};
main(): Int {{f(3); }}; • The activation tree may be different for
} every program input

• Since activations are properly nested, a stack


can track currently active procedures
What is the activation tree for this example?

Profs. Aiken CS 143 Lecture 11 15 Profs. Aiken CS 143 Lecture 11 16

Example Example

Class Main { Class Main {


g() : Int { 1 }; g() : Int { 1 };
f(): Int { g() }; f(): Int { g() };
main(): Int {{ g(); f(); }}; main(): Int {{ g(); f(); }};
} }
Main Stack Main Stack
Main g Main
g

Profs. Aiken CS 143 Lecture 11 17 Profs. Aiken CS 143 Lecture 11 18

3
Example Example

Class Main { Class Main {


g() : Int { 1 }; g() : Int { 1 };
f(): Int { g() }; f(): Int { g() };
main(): Int {{ g(); f(); }}; main(): Int {{ g(); f(); }};
} }
Main Stack Main Stack

g Main g Main
f f
f f
g g
Profs. Aiken CS 143 Lecture 11 19 Profs. Aiken CS 143 Lecture 11 20

Revised Memory Layout Activation Records

Low Address • The information needed to manage one


procedure activation is called an activation
Code
record (AR) or frame
Memory
• If procedure F calls G, then G’s activation
Stack record contains a mix of info about F and G.

High Address
Profs. Aiken CS 143 Lecture 11 21 Profs. Aiken CS 143 Lecture 11 22

What is in G’s AR when F calls G? The Contents of a Typical AR for G

• F is “suspended” until G completes, at which • Space for G’s return value


point F resumes. G’s AR contains information • Actual parameters
needed to resume execution of F. • Pointer to the previous activation record
– The control link; points to AR of caller of G
• G’s AR may also contain: • Machine status prior to calling G
– G’s return value (needed by F) – Contents of registers & program counter
– Actual parameters to G (supplied by F) – Local variables
– Space for G’s local variables
• Other temporary values

Profs. Aiken CS 143 Lecture 11 23 Profs. Aiken CS 143 Lecture 11 24

4
Example 2, Revisited Stack After Two Calls to f

Class Main {
Main
g() : Int { 1 };
f (result)
f(x:Int):Int {if x=0 then g() else f(x - 1)(**)fi};
3
main(): Int {{f(3); (*)
}};} (*)
result f (result)
AR for f: argument 2
control link
return address (**)
Profs. Aiken CS 143 Lecture 11 25 Profs. Aiken CS 143 Lecture 11 26

Notes The Main Point

• Main has no argument or local variables and its


result is never used; its AR is uninteresting The compiler must determine, at compile-time,
• (*) and (**) are return addresses of the the layout of activation records and generate
invocations of f code that correctly accesses locations in the
– The return address is where execution resumes activation record
after a procedure call finishes

Thus, the AR layout and the code generator


• This is only one of many possible AR designs must be designed together!
– Would also work for C, Pascal, FORTRAN, etc.

Profs. Aiken CS 143 Lecture 11 27 Profs. Aiken CS 143 Lecture 11 28

Example Discussion

The picture shows the state after the call to the • The advantage of placing the return value 1st
2nd invocation of f returns in a frame is that the caller can find it at a
Main fixed offset from its own frame
f (result)
3 • There is nothing magic about this organization
– Can rearrange order of frame elements
(*) – Can divide caller/callee responsibilities differently
f 1 – An organization is better if it improves execution
2 speed or simplifies code generation

Profs. Aiken CS 143 Lecture 11


(**) 29 Profs. Aiken CS 143 Lecture 11 30

5
Discussion (Cont.) Globals

• Real compilers hold as much of the frame as • All references to a global variable point to the
possible in registers same object
– Especially the method result and arguments – Can’t store a global in an activation record

• Globals are assigned a fixed address once


– Variables with fixed address are “statically
allocated”
• Depending on the language, there may be
other statically allocated values

Profs. Aiken CS 143 Lecture 11 31 Profs. Aiken CS 143 Lecture 11 32

Memory Layout with Static Data Heap Storage

Low Address • A value that outlives the procedure that


Code creates it cannot be kept in the AR
method foo() { new Bar }
Memory Static Data The Bar value must survive deallocation of foo’s AR

Stack • Languages with dynamically allocated data use


a heap to store dynamic data

High Address
Profs. Aiken CS 143 Lecture 11 33 Profs. Aiken CS 143 Lecture 11 34

Notes Notes (Cont.)

• The code area contains object code • Both the heap and the stack grow
– For most languages, fixed size and read only
• The static area contains data (not code) with • Must take care that they don’t grow into each
fixed addresses (e.g., global data) other
– Fixed size, may be readable or writable
• The stack contains an AR for each currently • Solution: start heap and stack at opposite
active procedure ends of memory and let them grow towards
– Each AR usually fixed size, contains locals each other
• Heap contains all other data
– In C, heap is managed by malloc and free
Profs. Aiken CS 143 Lecture 11 35 Profs. Aiken CS 143 Lecture 11 36

6
Memory Layout with Heap Data Layout

Low Address • Low-level details of machine architecture are


Code important in laying out data for correct code
and maximum performance
Memory Static Data
• Chief among these concerns is alignment
Stack

Heap High Address


Profs. Aiken CS 143 Lecture 11 37 Profs. Aiken CS 143 Lecture 11 38

Alignment Alignment (Cont.)

• Most modern machines are (still) 32 bit • Example: A string


– 8 bits in a byte “Hello”
– 4 bytes in a word Takes 5 characters (without a terminating \0)
– Machines are either byte or word addressable
• Data is word aligned if it begins at a word • To word align next datum, add 3 “padding”
boundary characters to the string
• Most machines have some alignment
restrictions • The padding is not part of the string, it’s just
– Or performance penalties for poor alignment unused memory
Profs. Aiken CS 143 Lecture 11 39 Profs. Aiken CS 143 Lecture 11 40

Next Topic: Stack Machines Example of Stack Machine Operation

• A simple evaluation model • The addition operation on a stack machine


• No variables or registers
• A stack of values for intermediate results 5
• Each instruction:
– Takes its operands from the top of the stack 5
7 
– Removes those operands from the stack 7 12
– Computes the required operation on them 9 9 9
– Pushes the result on the stack … … …

pop add push


Profs. Aiken CS 143 Lecture 11 41 Profs. Aiken CS 143 Lecture 11 42

7
Example of a Stack Machine Program Why Use a Stack Machine ?

• Consider two instructions • Each operation takes operands from the same
– push i - place the integer i on top of the stack place and puts results in the same place
– add - pop two elements, add them and put
the result back on the stack • This means a uniform compilation scheme
• A program to compute 7 + 5:
push 7 • And therefore a simpler compiler
push 5
add

Profs. Aiken CS 143 Lecture 11 43 Profs. Aiken CS 143 Lecture 11 44

Why Use a Stack Machine ? Optimizing the Stack Machine

• Location of the operands is implicit • The add instruction does 3 memory operations
– Always on the top of the stack – Two reads and one write to the stack
• No need to specify operands explicitly – The top of the stack is frequently accessed
• No need to specify the location of the result • Idea: keep the top of the stack in a register
• Instruction “add” as opposed to “add r1, r2” (called accumulator)
– Register accesses are faster
 Smaller encoding of instructions
 More compact programs • The “add” instruction is now
• This is one reason why Java Bytecodes use a acc  acc + top_of_stack
stack evaluation model – Only one memory operation!

Profs. Aiken CS 143 Lecture 11 45 Profs. Aiken CS 143 Lecture 11 46

Stack Machine with Accumulator Stack Machine with Accumulator. Example

Invariants • Compute 7 + 5 using an accumulator


• The result of an expression is in the
accumulator
7 5 12
• For op(e1,…,en) push the accumulator on the
acc

stack after computing e1,…,en-1 7 7
– After the operation pops n-1 values stack … … … …

acc  7 acc  5 acc  acc + top_of_stack


• Expression evaluation preserves the stack push acc pop
Profs. Aiken CS 143 Lecture 11 47 Profs. Aiken CS 143 Lecture 11 48

8
A Bigger Example: 3 + (7 + 5) Notes

Code Acc Stack • It is very important evaluation of a


acc  3 3 <init> subexpression preserves the stack
push acc 3 3, <init> – Stack before the evaluation of 7 + 5 is 3, <init>
acc  7 7 3, <init> – Stack after the evaluation of 7 + 5 is 3, <init>
push acc 7 7, 3, <init> – The first operand is on top of the stack
acc  5 5 7, 3, <init>
acc  acc + top_of_stack 12 7, 3, <init>
pop 12 3, <init>
acc  acc + top_of_stack 15 3, <init>
pop 15 <init>
Profs. Aiken CS 143 Lecture 11 49 Profs. Aiken CS 143 Lecture 11 50

You might also like