Chapter 12
|
Text - divided compiler into two parts:
- front end - focus on non-architecture concerns
- back end - focus on architecture concerns
Text Chapter 2 Lexical Analysis JVM Chapter 3 Parsing Chapter 4 Abstract Syntax Front Chapter 5 Semantic Analysis end Chapter 6 Activation Records Chapter 7 Translation to Intermediate Code Chapter 8 Basic Blocks and Traces Back Chapter 9 Instruction Selection end Chapter 10 Liveness Analysis Chapter 11 Register Allocation JVM - stack machine target architecture with no registers eliminated opportunity for several optimizing methods of text.
- Our goal was to produce a working MiniJava compiler by end of semester.
- Did not apply tiling or other instruction selection techniques, used ad hoc analysis of JavaC code to guide production of JVM from AST.
- Did calculate stack requirements of methods.
- Did not rearrange interior nodes of expression (i.e. d=a+b*c has interior nodes a, b, c) to reduce stack requirements (emit code for child with maximum stack requirement first)
PROCEDURE ENTRY/EXIT
The JVM method entry and exit was relatively simple, requiring:
- a signature (i.e. method name, parameter type and result type) - BuildSymbolTableVisitor
- frame offsets - FrameVisitor and JVMFrame
- stack need - StackVisitor
- appropriate return instruction - CodeVisitor
Procedure entry and exit on register machines is considerably more complicated due to:
- registers are global
- limited number of registers
- precolored registers (e.g. return result, frame pointer, ...)
- minimizing in-memory variables
Frame generation
Frame generation is specific to an architecture.
JVM
Frame generation was performed by:
- visiting each method declaration (FrameVisitor)
- computing the offsets (JVMFrame) and
- storing to the symbol table
- visiting each method declaration and use (CodeVisitor)
- using frame offsets when accessing frame variables
Other
In the text, frame information on registers used for parameter passing, etc. was separate from the IR generation.
The steps to code generation follow:
- IR with TEMPs
- IR to machine-specific code with TEMPs
- machine specific frame with precolored registers
- color machine-specific code TEMPs to registers
The steps for generating a register machine frame (Step 3 above) for each method of each class are:
- define registers of machine - literally a list of programmer accessible registers
- define precolored registers - frame pointer, stack pointer, function result
- compute offset of each in-frame parameter or local - these variables must occupy a memory location for one of the following reasons:
- pass by reference since must have memory address in frame
- local variable accessed by inner function, although register allocation over function boundaries can sometimes keep in register
- value too big for a register but can sometimes use multiple registers
- array parameter which is in many languages (C++) a reference anyway. Pointer arithmetic used to access array components
- register conflict though can often copy to another to avoid saving to memory
- more locals and parameters than registers, some are spilled into frame memory
- assign parameters to registers