Presentation is loading. Please wait.

Presentation is loading. Please wait.

Course Overview PART I: overview material PART II: inside a compiler

Similar presentations


Presentation on theme: "Course Overview PART I: overview material PART II: inside a compiler"— Presentation transcript:

1 Course Overview PART I: overview material PART II: inside a compiler
1 Introduction 2 Language processors (tombstone diagrams, bootstrapping) 3 Architecture of a compiler PART II: inside a compiler 4 Syntax analysis 5 Contextual analysis 6 Runtime organization 7 Code generation PART III: conclusion Interpretation 9 Review

2 Code Generation Algorithm
The code templates specify how code is to be generated => Determines code generation algorithm. Generating code: traversal of the AST emitting instructions one by one. The code templates determine the order of the traversal and the instructions to be emitted. We will now look at how to implement a Mini Triangle code generator in Java (or C++). Use the visitor design pattern!

3 Representation of Object Program: Instructions
public class Instruction { public byte op; // op-code (0..15) public byte r; // register field (0..15) public byte n; // length field (0..255) public short d; // operand field // ( ) public static final byte // op-codes LOADop = 0, LOADAop = 1, ... public static final byte // register numbers CBr = 0, CTr = 1, … // code base & top SBr = 4, STr = 5, … // stack base & top public Instruction(byte op, byte n, byte r, short d) { ... } }

4 Representation of Object Program: Emitting Code
public class Encoder { private Instruction[] code = new Instruction[1024]; private short nextInstrAddr = 0; private void emit(byte op, byte n, byte r, short d) { code[nextInstrAddr++] = new Instruction(op,n,r,d); } ... lots of other stuff in here of course ...

5 Developing a Code Generator “Visitor”
generate code as specified by execute[C] generate code as specified by evaluate[E] return “entity description” for the visited variable or constant name generate code as specified by elaborate[D] return the size of the type Program visitProgram generate code as specified by run[P] Command visit…Command Expression visit…Expression V-name visit…Vname Declaration visit…Declaration Type-Den visit…TypeDen Syntax Class Visitor method Behavior of the visitor method

6 Developing a Code Generator “Visitor”
For variables we have two distinct code generation functions: fetch and assign. => Not implemented as visitor methods but as separate methods. public void encodeFetch(Vname name) { ... as specified by fetch template ... } public void encodeAssign(Vname name) { ... as specified by assign template ...

7 Developing a Code Generator “Visitor”
public class Encoder implements Visitor { ... /* Generating code for entire Program */ public Object visitProgram(Program prog, Object arg) { prog.C.visit(this,arg); emit a halt instruction return null; }

8 Developing a Code Generator “Visitor”
Recall: execute [V := E] = evaluate [E] assign [V] /* Generating code for commands */ public Object visitAssignCommand( AssignCommand com, Object arg) { com.E.visit(this,arg); encodeAssign(com.V); return null; }

9 Developing a Code Generator “Visitor”
execute [I ( E )] = evaluate [E] CALL p where p is address of the routine named I public Object visitCallCommand( CallCommand com, Object arg) { com.E.visit(this,arg); short p = address of primitive routine for name com.I emit(Instruction.CALLop, Instruction.SBr, Instruction.PBr, p); return null; }

10 Developing a Code Generator “Visitor”
execute [C1 ; C2] = execute[C1] execute[C2] public Object visitSequentialCommand( SequentialCommand com, Object arg){ com.C1.visit(this,arg); com.C2.visit(this,arg); return null; } LetCommand, IfCommand, WhileCommand => later. - LetCommand is more complex: memory allocation and addresses - IfCommand and WhileCommand: complications with jumps

11 Developing a Code Generator “Visitor”
evaluate [IL] = LOADL v where v is the integer value of IL /* Expressions */ public Object visitIntegerExpression ( IntegerExpression expr, Object arg) { short v = valuation(expr.IL.spelling); emit(Instruction.LOADLop, 0, 0, v); return null; } public short valuation(String s) { ... convert string to integer value ...

12 Developing a Code Generator “Visitor”
evaluate [E1 O E2] = evaluate [E1] evaluate [E2] CALL p where p is the address of routine for O public Object visitBinaryExpression ( BinaryExpression expr, Object arg) { expr.E1.visit(this,arg); expr.E2.visit(this,arg); short p = address for expr.O operation emit(Instruction.CALLop, Instruction.SBr, Instruction.PBr, p); return null; } Remaining expression visitors are developed in a similar way.

13 Control Structures We have yet to discuss generation for IfCommand and WhileCommand. execute [while E do C] = JUMP h g: execute [C] h: evaluate[E] JUMPIF(1) g C E Complication: generating correct addresses for the jump instructions. We can determine the address of each instruction by incrementing a counter while emitting the instructions. Backwards jumps are easy but forward jumps are harder. Q: Why?

14 Control Structures Backwards jumps are easy:
The “address” of the target has already been generated and is known. Forward jumps are harder: When the jump is generated the target is not yet generated so its address is not (yet) known. There is a solution which is known as backpatching 1) Emit a jump with a “dummy” address (e.g. simply 0). 2) Remember the address where the jump instruction occurred. 3) When the target label is reached, go back and patch the jump instruction.

15 Backpatching Example: While
public Object visitWhileCommand ( WhileCommand com, Object arg) { short j = nextInstrAddr; emit(Instruction.JUMPop, 0, Instruction.CBr, 0); short g = nextInstrAddr; com.C.visit(this,arg); short h = nextInstrAddr; code[j].d = h; com.E.visit(this,arg); emit(Instruction.JUMPIFop, 1, Instruction.CBr, g); return null; } dummy address backpatch execute [while E do C] = JUMP h g: execute [C] h: evaluate[E] JUMPIF(1) g

16 Backpatching Example: If
public Object visitIfCommand ( IfCommand com, Object arg) { com.E.visit(this,arg); short j1 = nextInstrAddr; emit(Instruction.JUMPIFop, 0, Instruction.CBr, 0); com.C1.visit(this,arg); short j2 = nextInstrAddr; emit(Instruction.JUMPop, 0, short g = nextInstrAddr; code[j1].d = g; com.C2.visit(this,arg); short h = nextInstrAddr; code[j2].d = h; return null; } execute [if E then C1 else C2] = evaluate [E] JUMPIF(0) g execute [C1] JUMP h g: execute [C2] h:

17 Constants and Variables
We have not yet discussed generation for LetCommand. This is the place in Mini Triangle where declarations appear. Calculated during generation for elaborate[D] execute [let D in C] = elaborate[D] execute [C] POP(0) s if s > where s = amount of storage allocated by D How to know these? fetch [V] = LOAD d[SB] where d = address of V relative to SB assign [V] = STORE d[SB] where d = address of V relative to SB

18 Constants and Variables
Example: Accessing known values and known addresses. let const b ~ 10; var i: Integer; in i := i*b PUSH 1 LOAD 4[SB] LOADL 10 CALL mult STORE 4[SB] POP(0) 1 elaborate[const … ; var …] execute [i:=i*b]

19 Constants and Variables
Example: Accessing an unknown value. Not all constants have values known (at compile time). let var x: Integer; in let const y ~ x in putint(y) Depends on variable x: value not known at compile time. When visiting declarations the code generator must decide whether to represent constants in memory or as a literal value => Remember the address or the value somehow. (Q: How?) Q: Is there a difference between an unknown constant and a variable?

20 Constants and Variables
Example: Accessing an unknown value. let var x: Integer; in let const y ~ x in putint(y) PUSH 1 LOADL 365 LOAD 4[SB] CALL add LOAD 5[SB] CALL putint POP(0) 1 elaborate[var x: Integer] elaborate[const y ~ x] execute [putint(y)]

21 Constants and Variables
Descriptions of entities (constants and variables) When the code generator visits a declaration: 1) Must first decide whether to represent it as a known value or a known address. 2) If it’s an address then emit code to reserve space. 3) Create an entity description (an object that describes the variable or constant): contains its value or address, and also its size. 4) Put a link in the AST that points to this entity description. Example and picture on next slide

22 Constants and Variables
let const b ~ 10; var i: Integer; in i := i*b Recall: Applied occurrences of Identifiers point to their declaration. LetCommand SequentialDeclaration ConstDecl VarDecl Ident Int.Exp Ident Ident Ident Ident b 10 i i i b known value value = 10 size = 1 known address address = 4 size = 1

23 Constants and Variables
let var x: Integer; in let const y ~ x in putint(y) LetCommand Note: Triangle also has unknown addresses. (More about these in next lecture.) VarDecl Ident x ConstDecl Ident y Q: When do unknown addresses occur? Hint: Consider pass by reference. known address address = 4 size = 1 unknown value address = 5 size = 1

24 Static Storage Allocation
Example 1: Global variables TAM Address: a 0[SB] b 1[SB] c 2[SB] d 3[SB] let var a: Integer; var b: Boolean; var c: Integer; var d: Integer; in ... Note: In this example all globals have the same size (1). In Triangle this is not always the case.

25 Static Storage Allocation
Example 2: Static allocation with nested blocks TAM Address: a 0[SB] b 1[SB] c 2[SB] d 1[SB] let var a: Integer; in begin ... let var b: Boolean; var c: Integer; in begin ... end; let var d: Integer; end Same address! Q: Why can b and d share the same address?

26 Static Storage Allocation in the Code Generator
Entitity Descriptions: public abstract class RuntimeEntity { public short size; ... } public class KnownValue extends RuntimeEntity { public short value; public class UnknownValue extends RuntimeEntity { public short address; public class KnownAddress extends RuntimeEntity {

27 Static Storage Allocation in the Code Generator
Entity Descriptions: public abstract class AST { public RuntimeEntity entity; // mostly used for Decls ... }

28 Static Storage Allocation in the Code Generator
public Object visit...Command( ...Command com, Object arg) { short gs = shortValueOf(arg); // global storage in use generate code as specified by execute[com] return null; } public Object visit...Expression( ...Expression expr, Object arg) { short gs = shortValueOf(arg); // global storage in use generate code as specified by evaluate[expr] return new Short(size of expr result); public Object visit...Declaration( ...Declaration dec, Object arg) { short gs = shortValueOf(arg); // global storage in use generate code as specified by elaborate[dec] return new Short(amount of memory allocated by dec);

29 Static Storage Allocation in the Code Generator
The visitor is started … public void encode(Program prog) { prog.visit(this, new Short(0)); } Amount of global storage previously allocated is initially = 0

30 Static Storage Allocation in the Code Generator
Some specific examples of visitor methods elaborate [var I : T] = PUSH s where s = size of T public Object visitVarDeclaration( VarDeclaration decl, Object arg) { short gs = shortValueOf(arg); short s = shortValueOf(decl.T.visit(this, null)); decl.entity = new KnownAddress(s, gs); emit(Instruction.PUSHop, 0, 0, s); return new Short(s); } Remember the size and address of the variable

31 Static Storage Allocation in the Code Generator
elaborate [D1 ; D2] = elaborate [D1] elaborate [D2] public Object visitSequentialDeclaration( SequentialDeclaration decl, Object arg) { short gs = shortValueOf(arg); short s1 = shortValueOf(decl.D1.visit(this,arg)); short s2 = shortValueOf(decl.D2.visit(this, new Short(gs+s1))); return new Short(s1+s2); }

32 Static Storage Allocation in the Code Generator
execute [let D in C] = elaborate[D] execute [C] POP(0) s if s > where s = amount of storage allocated by D public Object visitLetCommand( LetCommand com, Object arg) { short gs = shortValueOf(arg); short s = shortValueOf(com.D.visit(this,arg)); com.C.visit(this,new Short(gs+s)); if (s > 0) emit(Instruction.POPop, 0, 0, s); return null; }

33 Static Storage Allocation in the Code Generator
fetch [I] = special case if I is a known literal constant LOADL v where v is the known value of I fetch [V] = LOAD d[SB] where d = address of V relative to SB public void encodeFetch(Vname name, short s) { RuntimeEntity ent = VName.I.decl.entity; if (ent instanceof KnownValue) { short v = ((KnownValue)ent).value; emit(Instruction.LOADLop, 0, 0, v); } else { short d = (ent instanceof UnknownValue) ? ((UnknownValue)ent).address : ((KnownAddress)ent).address ; emit(Instruction.LOADop, 0, Instruction.SBr, d); }

34 Stack Allocation, Procedures and Functions
So far we have seen how code generation works for Mini Triangle. Next we will extend code generation to handle remainder of Triangle: 1) How procedures and functions are compiled. 2) How to modify the code generator to compute addresses when we use a stack allocation model (instead of static allocation).


Download ppt "Course Overview PART I: overview material PART II: inside a compiler"

Similar presentations


Ads by Google