1 languages and compilers (sprog og oversættere) lecture 11 bent thomsen department of computer...

79
1 Languages and Compilers (SProg og Oversættere) Lecture 11 Bent Thomsen Department of Computer Science Aalborg University nowledgement to Norm Hutchinson whose slides this lecture is based on.

Post on 19-Dec-2015

214 views

Category:

Documents


1 download

TRANSCRIPT

1

Languages and Compilers(SProg og Oversættere)

Lecture 11

Bent Thomsen

Department of Computer Science

Aalborg University

With acknowledgement to Norm Hutchinson whose slides this lecture is based on.

2

What This Lecture is About

A compiler translates a program from a high-level language into an equivalent program in a low-level language.

A compiler translates a program from a high-level language into an equivalent program in a low-level language.

TAM Program

Triangle Program

Compile

Run

Result

3

Programming Language specification

– A Language specification has (at least) three parts:

• Syntax of the language: usually formal: EBNF

• Contextual constraints:

– scope rules (often written in English, but can be formal)

– type rules (formal or informal)

• Semantics:

– defined by the implementation

– informal descriptions in English

– formal using operational or denotational semantics

4

The “Phases” of a Compiler

Syntax Analysis

Contextual Analysis

Code Generation

Source Program

Abstract Syntax Tree

Decorated Abstract Syntax Tree

Object Code

Error Reports

Error Reports

This lecture

5

Multi Pass Compiler

Compiler Driver

Syntactic Analyzer

callscalls

Contextual Analyzer Code Generator

calls

Dependency diagram of a typical Multi Pass Compiler:

A multi pass compiler makes several passes over the program. The output of a preceding phase is stored in a data structure and used by subsequent phases.

input

Source Text

output

AST

input output

Decorated AST

input output

Object Code

This lecture

6

Issues in Code Generation

• Code Selection:Deciding which sequence of target machine instructions will be used to implement each phrase in the source language.

• Storage AllocationDeciding the storage address for each variable in the source program. (static allocation, stack allocation etc.)

• Register Allocation (for register-based machines)How to use registers efficiently to store intermediate results.

We use a stack based machine. This is not an issue for us

7

Code Generation

Source Program

let var n: integer; var c: charin begin c := ‘&’; n := n+1end

let var n: integer; var c: charin begin c := ‘&’; n := n+1end

PUSH 2LOADL 38STORE 1[SB]LOAD 0LOADL 1CALL addSTORE 0[SB]POP 2HALT

PUSH 2LOADL 38STORE 1[SB]LOAD 0LOADL 1CALL addSTORE 0[SB]POP 2HALT

Target program

~~

Source and target program must be“semantically equivalent”

Semantic specification of the source language is structured in terms of phrases in the SL: expressions, commands, etc.=> Code generation follows the same “inductive” structure.

Q: Can you see the connection with formal semantics?

8

“Inductive” Code Generation

“Inductive” means: code generation for a “big” structure is defined in terms of putting together chunks of code that correspond to the sub-structures.

Example: Sequential command code generation

Semantic specification

The sequential command C1 ; C2 is executed as follows: first C1 is executed then C2 is executed.

Code generation function:

execute : Command -> Instruction*

execute [C1 ; C2] =

execute [C1]

execute [C2]

instructions for C1

instructions for C2instructions for C1 ; C2

9

“Inductive” Code Generation

Example: Assignment command code generation

Code generation function:

execute [I := E] =

evaluate [E]

STORE address [I]

instructions for E yield value for E on top of the stack

instruction to store result into variable

These “pictures” of the code layout for a particular source language construct are called code templates.

Inductive means: A code template specifies the object code to which a phrase is translated, in terms of the object code to which its subphrases are translated.

These “pictures” of the code layout for a particular source language construct are called code templates.

Inductive means: A code template specifies the object code to which a phrase is translated, in terms of the object code to which its subphrases are translated.

10

“Inductive” Code Generation

Example: code generation for a larger phrase in terms of its subphrases.

execute [f := f*n;

n := n-1]

execute [f := f*n]

execute [n := n-1]

LOAD fLOAD nCALL multSTORE f

LOAD nCALL predSTORE n

11

Specifying Code Generation with Code Templates

note: A “phrase class” typically corresponds to a non-terminal of the abstract syntax.

This in turn corresponds to an abstract class in the Java classes that implement the AST nodes. (for example Expression, Command, Declaration)

fP […Q…R…] = …fQ [Q] …fR [R] …

We specify the function fP by code templates. Typically they look like:

For each “phrase class” P in the abstract syntax of the source language:

Define code functions fP : P -> Instruction*that translate each phrase in class P to object code.

12

Specifying Code Generation with Code Templates

Example: Code templates specification for Mini TriangleRECAP: The Mini Triangle AST

Program ::= Command ProgramCommand ::= V-name := Expression AssignCmd | let Declaration in Command LetCmd ...Expression ::= Integer-Literal IntegerExp | V-name VnameExp | Operator Expression UnaryExp | Expression Op Expression BinaryExpDeclaration ::= ...V-name::= IdentifierSimpleVName

Program ::= Command ProgramCommand ::= V-name := Expression AssignCmd | let Declaration in Command LetCmd ...Expression ::= Integer-Literal IntegerExp | V-name VnameExp | Operator Expression UnaryExp | Expression Op Expression BinaryExpDeclaration ::= ...V-name::= IdentifierSimpleVName

13

Specifying Code Generation with Code Templates

The code generation functions for Mini Triangle

Phrase Class Function Effect of the generated code

Program

Command

Expres-sionV-name

V-nameDecla-ration

run P

execute C

evaluate E

fetch V

assign Velaborate D

Run program P then halt. Starting and finishing with empty stackExecute Command C. May update variables but does not shrink or grow the stack!Evaluate E, net result is pushing the value of E on the stack.Push value of constant or variable on the stack.Pop value from stack and store in variable VElaborate declaration, make space on the stack for constants and variables in the decl.

14

Code Generation with Code Templates

run [C] =execute [C]HALT

The code generation functions for Mini Triangle

Programs:

Commands:

execute [V := E] =evaluate [E]assign [V]

execute [I ( E )] =evaluate [E]CALL p where p is address of the routine named I

15

Code Generation with Code Templates

Commands:

execute [C1 ; C2] =execute [C1]execute [C2]

execute [if E then C1 else C2] =evaluate [E]JUMPIF(0) gexecute [C1]JUMP h

g: execute [C2]h:

C1

C2

E

g:

h:

16

Code Generation with Code Templates

execute [while E do C] =JUMP h

g: execute [C]h: evaluate[E]

JUMPIF(1) g

CE

Commands:

execute [while E do C] =g: evaluate [E] JUMPIF(0) h

execute[C]JUMP g

h:

Alternative While Command code template:

EC

17

Code Generation with Code Templates

execute [repeat C until E] =g: execute [C]h: evaluate[E]

JUMPIF(0) g

execute [let D in C] =elaborate[D]execute [C]POP(0) s if s>0

where s = amount of storage allocated by D

Repeat Command code template:

CE

18

Code Generation with Code Templates

evaluate [IL] = note: IL is an integer literalLOADL v where v = the integer value of IL

evaluate [V] = note: V is variable namefetch[V]

evaluate [O E] = note: O is a unary operatorevaluate[E]CALL p where p = address of routine for O

evaluate [E1 O E2] = note: O is a binary operatorevaluate[E1]evaluate[E2]CALL p where p = address of routine for O

Expressions:

19

Code Generation with Code Templates

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

Variables: note: Mini Triangle only needs static allocation (Q: why is that? )

20

Code Generation with Code Templates

elaborate [const I ~ E] =evaluate[E]

elaborate [var I : T] =PUSH s where s = size of T

elaborate [D1 ; D2] =elaborate [D1]elaborate [D2]

Declarations:

THE END: these are all the code templates for Mini Triangle.

Now let’s put them to use in an example.

21

Example of Mini Triangle Code Generation

execute [while i>0 do i:=i+2] =JUMP h

g: LOAD iLOADL 2CALL addSTORE i

h: LOAD iLOADL 0CALL gtJUMPIF(1) g

evaluate [i>0]

execute [i:=i+2]evaluate [i+2]

22

Special Case Code Templates

There are often several ways to generate code for an expression, command, etc.

The templates we defined work, but sometimes we can get more efficient code for special cases => special case code templates.

Example:

evaluate [i+1] =LOAD iLOADL 1CALL add

what we get with the “general” code

templates

evaluate [i+1] =LOAD iCALL succ

more efficient code forthe special case “+1”

23

Special Case Code Templates

Example: some special case code template for “+1”, “-1”, …

evaluate [E + 1] =evaluate [E] CALL succ

evaluate [E - 1] =evaluate [E] CALL pred

evaluate [1 + E] =evaluate [E] CALL succ

A special-case code template is one that is applicable to phrases of a special form. Such phrases are also covered by a more general form.

24

Special Case Code Templates

Example: “Inlining” known constants.

execute [let const n~7; var i:Integer in i:=n*n] =

LOADL 7PUSH 1LOAD nLOAD nCALL multSTORE iPOP(0) 2

execute [i:=n*n]

elaborate [var i:Integer]elaborate [const n~7]

This is how the code looks like with no special case templates

25

Special Case Code Templates

Example: “Inlining” known constants.

elaborate [const I ~ IL] = no codeSpecial case templates for inlining literals.

fetch [I] = special case if I is a known literal constant LOADL v where v is the known value of I

execute [let const n~7; var i:Integer in i:=n*n] =PUSH 1LOADL 7LOADL 7CALL multSTORE iPOP(0) 1

26

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.

27

Representation of Object Program: Instructions

public class Instruction {public byte op; // op-code 0..15public byte r; // register field (0..15)public byte n; // length field (0..255)public short d; // operand field (-32767..+32

public static final byte // op-codesLOADop = 0, LOADAop = 1, ...

public static final byte // register numbersCBr = 0, CTr = 1, …SBr = 4, STr = 5, …

public Instruction(byte op,byte n, byte r,short d) { ... }

}

28

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 ...}

29

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

PhraseClass

visitor method Behavior of the visitor method

30

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 ...}

31

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 instructionreturn null;

}

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 instructionreturn null;

}

32

Developing a Code Generator “Visitor”

/* Generating code for commands */

public Object visitAssignCommand(AssignCommand com,Object arg) {

com.E.visit(this,arg);encodeAssign(com.V);return null;

}

/* Generating code for commands */

public Object visitAssignCommand(AssignCommand com,Object arg) {

com.E.visit(this,arg);encodeAssign(com.V);return null;

}

RECAP: execute [V := E] =evaluate [E]assign [V]

33

Developing a Code Generator “Visitor”

public Object visitCallCommand(CallCommand com,Object arg) {

com.E.visit(this,arg);short p = address of primitive routine for

name com.Iemit(Instruction.CALLop,

Instruction.SBr,Instruction.PBr, p);

return null;}

public Object visitCallCommand(CallCommand com,Object arg) {

com.E.visit(this,arg);short p = address of primitive routine for

name com.Iemit(Instruction.CALLop,

Instruction.SBr,Instruction.PBr, p);

return null;}

execute [I ( E )] =evaluate [E]CALL p where p is address of the routine named I

34

Developing a Code Generator “Visitor”

public Object visitSequentialCommand(SequentialCommand com,Object arg) {

com.C1.visit(this,arg);com.C2.visit(this,arg);return null;

}

public Object visitSequentialCommand(SequentialCommand com,Object arg) {

com.C1.visit(this,arg);com.C2.visit(this,arg);return null;

}

execute [C1 ; C2] =execute[C1]execute[C2]

LetCommand, IfCommand, WhileCommand => later. - LetCommand is more complex: memory allocation and addresses - IfCommand and WhileCommand: complications with jumps

35

Developing a Code Generator “Visitor”

/* 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 ...}

/* 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 ...}

evaluate [IL] = LOADL v where v is the integer value of IL

36

Developing a Code Generator “Visitor”

public Object visitBinaryExpression (BinaryExpression expr,Object arg) {

expr.E1.visit(this,arg);expr.E2.visit(this,arg);short p = address for expr.O operationemit(Instruction.CALLop,

Instruction.SBr, Instruction.PBr, p);

return null;}

public Object visitBinaryExpression (BinaryExpression expr,Object arg) {

expr.E1.visit(this,arg);expr.E2.visit(this,arg);short p = address for expr.O operationemit(Instruction.CALLop,

Instruction.SBr, Instruction.PBr, p);

return null;}

evaluate [E1 O E2] = evaluate [E1]evaluate [E2] CALL p where p is the address of routine for O

Remaining expression visitors are developed in a similar way.

37

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

A complication is the generation of the correct addresses for the jump instructions.

We can determine the address of the instructions by incrementing a counter while emitting instructions.

Backwards jumps are easy but forward jumps are harder.Q: why?

CE

38

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 backpatching1) Emit jump with “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.

39

Backpatching Example

public Object WhileCommand (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;

}

public Object WhileCommand (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;

}

execute [while E do C] =JUMP h

g: execute [C]h: evaluate[E]

JUMPIF(1) g

dummy address

backpatch

40

Constants and Variables

We have not yet discussed generation of LetCommand. This is the place in Mini Triangle where declarations are.

execute [let D in C] =elaborate[D]execute [C]POP(0) s if s>0

where s = amount of storage allocated by D

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

How to know these?

Calculated during generation forelaborate[D]

41

Constants and Variables

Example

let const b ~ 10; var i:Integer; in

i := i*b

let const b ~ 10; var i:Integer; in

i := i*b

PUSH 1LOAD 4[SB]LOADL 10CALL multSTORE 4[SB]

execute [i:=i*b]

elaborate[const … ; var …]

Accessing known values and known addresses

42

Constants and Variables

Example

let var x:Integer; in

let const y ~ 365 + xin putint(y)

let var x:Integer; in

let const y ~ 365 + xin putint(y)

Accessing an unknown value.

Not all constants have values known (at compiler time).

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

=> We have to remember the address or the value somehow.

43

Constants and Variables

Example

let var x:Integer; in

let const y ~ 365 + xin putint(y)

let var x:Integer; in

let const y ~ 365 + xin putint(y)

Accessing an unknown value.

PUSH 1LOADL 365LOAD 4[SB]CALL addSTORE 5[SB]LOAD 5[SB]CALL putint execute [putint(y)]

elaborate[var x:Integer]

elaborate[const y ~ 365 + x]

44

Constants and Variables

Entity descriptionsWhen the code generator visits a declaration: 1) it decides whether to represent it as a known value or a known address 2) if its an address then emit code to reserve space. 3) make an entity description: an object that describes the variable or constant: its value or address, its size. 4) put a link in the AST that points to the entity description

Example and picture on next slide

45

Constants and Variables

SequentialDeclaration

ConstDecl

let const b ~ 10; var i:Integer; in i := i*b

let const b ~ 10; var i:Integer; in i := i*b

VarDecl

Int.Exp

10

Ident

b

Ident

i

known valuesize = 1value = 10

known addressaddress = 4size = 1

LetCommand

Ident

i

Ident

i

Ident

b

RECAP: Applied occurrences of Identifiers point to their declaration

46

Constants and Variables

let var x:Integer; in let const y ~ 365 + x in putint(y)

let var x:Integer; in let const y ~ 365 + x in putint(y)

known addressaddress = 4size = 1

unknown valueaddress = 5size = 1

LetCommand

VarDecl

Ident

x

ConstDecl

Ident

y

Note: There are also unknownaddresses. More about these later.

47

Static Storage Allocation

let var a: Integer; var b: Boolean; var c: Integer; var d: Integer; in ...

let var a: Integer; var b: Boolean; var c: Integer; var d: Integer; in ...

TAM Address:a 0[SB]b 1[SB]c 2[SB]d 3[SB]

Example 1: Global variables

Note: In this example all globals have the same size: 1. This is not always the case.

48

Static Storage Allocation

let var a: Integer;in begin ... let var b: Boolean; var c: Integer; in begin ... end; ... let var d: Integer; in begin ... end; ...end

let var a: Integer;in begin ... let var b: Boolean; var c: Integer; in begin ... end; ... let var d: Integer; in begin ... end; ...end

TAM Address:a 0[SB]

b 1[SB]c 2[SB]

d 1[SB]

Example 2: Static allocation with nested blocks

Same address!

Q: Why can b and d share thesame address?

49

Static Storage Allocation: In the Code Generator

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 {

public short address;...

}

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 {

public short address;...

}

Entity Descriptions:

50

Static Storage Allocation: In the Code Generator

public abstract class AST {public RuntimeEntity entity; // mostly used for Decls...

}

public abstract class AST {public RuntimeEntity entity; // mostly used for Decls...

}

Entity Descriptions:

Note: This is an addition to the AST class and requires recompilation of a lot of code if added late in the compiler implementation, but there seems to be no way around it!

51

Static Storage Allocation: In the Code Generator

public Object visit...Command( ...Command com, Object arg) { short gs = shortValueOf(arg); generate code as specified by execute[com] return null;}public Object visit...Expression( ...Expression expr, Object arg) { short gs = shortValueOf(arg); generate code as specified by evaluate[com] return new Short(size of expr result);}public Object visit...Declaration( ...Declaration dec, Object arg) { short gs = shortValueOf(arg); generate code as specified by elaborate[com] return new Short(amount of extra allocated by dec);}

public Object visit...Command( ...Command com, Object arg) { short gs = shortValueOf(arg); generate code as specified by execute[com] return null;}public Object visit...Expression( ...Expression expr, Object arg) { short gs = shortValueOf(arg); generate code as specified by evaluate[com] return new Short(size of expr result);}public Object visit...Declaration( ...Declaration dec, Object arg) { short gs = shortValueOf(arg); generate code as specified by elaborate[com] return new Short(amount of extra allocated by dec);}

52

Static Storage Allocation: In the Code Generator

public void encode(Program prog) { prog.visit(this, new Short(0));}

public void encode(Program prog) { prog.visit(this, new Short(0));}

Amount of global storage already allocated. Initially = 0

The visitor is started …

53

Static Storage Allocation: In the Code Generator

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);}

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);}

Some concrete examples of visit methods

elaborate [var I : T] =PUSH s where s = size of T

Remember the address/size of the variable

54

Static Storage Allocation: In the Code Generator

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);}

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);}

elaborate [D1 ; D2] =elaborate [D1]elaborate [D2]

55

Static Storage Allocation: In the Code Generator

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;}

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;}

execute [let D in C] =elaborate[D]execute [C]POP(0) s if s>0

where s = amount of storage allocated by D

56

Static Storage Allocation: In the Code Generator

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 = (entity instanceof UnknownValue) ?

((UnknownValue)ent).address :((KnownAddress)ent).address ;

emit(Instruction.LOADop, 0, Instruction.SBr, d); }}

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 = (entity instanceof UnknownValue) ?

((UnknownValue)ent).address :((KnownAddress)ent).address ;

emit(Instruction.LOADop, 0, Instruction.SBr, d); }}

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

57

Stack Allocation, Procedures and Functions

Now we will have a look at

1) how procedures and functions are compiled

2) how to modify code generator to compute addresses when we use a stack allocation model (instead of static allocation)

58

RECAP: TAM Frame Layout Summary

LB

ST

local variablesand intermediate

results

dynamic linkstatic link

return address

Local data, grows and shrinksduring execution.

Link data

arguments Arguments for current procedurethey were put here by the caller.

59

RECAP: Accessing global/local variables

Example: Compute the addresses of the variables in this program

let var a: array 3 of Integer; var b: Boolean; var c: Char; proc Y() ~ let var d: Integer; var e: ... in ... ; proc Z() ~ let var f: Integer; in begin ...; Y(); ... endin begin ...; Y(); ...; Z(); end

let var a: array 3 of Integer; var b: Boolean; var c: Char; proc Y() ~ let var d: Integer; var e: ... in ... ; proc Z() ~ let var f: Integer; in begin ...; Y(); ... endin begin ...; Y(); ...; Z(); end

Var Size Address

abc

de

f

311

[0]SB[3]SB[4]SB

1?

1

[2]LB[3]LB

[2]LB

60

RECAP: TAM addressing schemas overview

We now have a complete picture of the different kinds of addresses that are used for accessing variables and formal parameters stored on the stack.

Type of variable

Global

Local

Parameter

Non-local, 1 level up

Non-local, 2 levels up...

Load instruction

LOAD +offset[SB]

LOAD +offset[LB]

LOAD -offset[LB]

LOAD +offset[L1]

LOAD +offset[L2]

61

How To Characterize Addresses now?

When we have a static allocation model only, an address can be characterized by a single positive integer (i.e. the offset from SB)

Now we generalize this to stack allocation (for nested procedures)Q: How do we characterize an address for a variable/constant now?

A: We need two numbers. - nesting level - offset (similar to static allocation)

Q: How do we compute the addresses to use in an instruction that loads or stores a value from/to a variable?

62

How To Characterize Addresses of Vars/Constants

Example: Compute the addresses of the variables in this program

let var a: array 3 of Integer; var b: Boolean; proc foo() ~ let var d: Integer; var e: ... proc bar() ~ let var f: Integer; in ...bar body... in ...foo body... ;in ... global code ...

let var a: array 3 of Integer; var b: Boolean; proc foo() ~ let var d: Integer; var e: ... proc bar() ~ let var f: Integer; in ...bar body... in ...foo body... ;in ... global code ...

Var Size Addr Accessing

ab

de

f

31

1?

1

(0,0)(0,3)

(1,0)(1,1)

(3,0)

0[SB]3[SB]

0[LB]

?

How to access depends on … where are you accessing from!accessing e from foo body =>accessing e from bar body =>

1[LB]1[L1]

63

New Fetch / Assign Code Templates

fetch [I] =LOADL(s) d[r]

s = Size of the type of I

d from address of I is (d, l)

r determined by l and cl (current level)

How to determine r

l = 0 ==> r = SBl = cl ==> r = LBotherwise ==> r = L(cl-l)

64

How To Modify The Code Generator

public class Frame { public byte level; public short size;}

public class Frame { public byte level; public short size;}

An info structure to pass as argument in the visitor (instead of “gs”)

Before it was sufficient to pass the current size (gs) of the global frame since without procedures all storage is allocated at level 0. With subprograms we need to know the current level and the size of the frame.

65

How To Modify The Code Generator

public class EntityAddress { public byte level; public short displacement;}

public class EntityAddress { public byte level; public short displacement;}

Different kind of “address” in entity descriptors

public class UnknownValue extends RuntimeEntity {public EntityAddress address;...

}public class KnownAddress extends RuntimeEntity {

public EntityAddress address;...

}

public class UnknownValue extends RuntimeEntity {public EntityAddress address;...

}public class KnownAddress extends RuntimeEntity {

public EntityAddress address;...

}

66

How To Modify The Code Generator

Changes to code generator (visitor)

Example:

public Object visitVarDeclaration( VarDeclaration decl, Object arg) { Frame frame = (Frame)arg; short s = shortValueOf(decl.T.visit(this,null)); decl.entity = new KnownAddress(s,frame); emit(Instruction.PUSHop, 0, 0, s); return new Short(s);}

public Object visitVarDeclaration( VarDeclaration decl, Object arg) { Frame frame = (Frame)arg; short s = shortValueOf(decl.T.visit(this,null)); decl.entity = new KnownAddress(s,frame); emit(Instruction.PUSHop, 0, 0, s); return new Short(s);}

etc.

Q: When will the level of a frame be changed? Q: When will the size be changed?

67

Change of frame level and size

• In the visitor/encoding method for translating a procedure body, the frame level must be incremented by one and the frame size set to 3 (space for link data)

Frame outerFrame …Frame localFrame = new Frame(outerFrame.level +1, 3);

• The encoder starts at frame level 0 and with no storage allocated:

public void encoder(Program prog) {Frame globalFrame = new Frame(0,0);prog.visit(this, globalFrame);

}

68

Procedures and Functions

We extend Mini Triangle with procedures:

Declaration ::= ... | proc Identifier ( ) ~ CommandCommand ::= ... | Identifier ( )

Declaration ::= ... | proc Identifier ( ) ~ CommandCommand ::= ... | Identifier ( )

First , we will only consider global procedures (with no arguments).

69

Code Template: Global Procedure

elaborate [proc I () ~ C] =JUMP g

e: execute [C]RETURN(0) 0

g:

C

execute [I ()] =CALL(SB) e

70

Code Template: Global Procedure

Example: let var n: Integer; proc double() ~ n := n*2in begin n := 9; double() end

let var n: Integer; proc double() ~ n := n*2in begin n := 9; double() end

0: PUSH 11: JUMP 72: LOAD 0[SB]3: LOADL 24: CALL mult5: STORE 0[SB]6: RETURN(0) 07: LOADL 98: STORE 0[SB]9: CALL(SB) 210:POP(0) 111:HALT

n := n*2

var n: Integer

proc double() ~ n := n*2

n := 9double()

71

Procedures and Functions

We extend Mini Triangle with functions:

Declaration ::= ... | func Identifier ( ) : TypeDenoter ~ ExpressionExpression ::= ... | Identifier ( )

Declaration ::= ... | func Identifier ( ) : TypeDenoter ~ ExpressionExpression ::= ... | Identifier ( )

First , we will only consider global functions (with no arguments).

This is all pretty much the same as procedures (except for the RETURN)

72

Code Template: Global Function

elaborate [func I () : T ~ E] =JUMP g

e: evaluate [E]RETURN(s) 0

g:

C

evaluate [I ()] =CALL(SB) e

where s is the size of T

73

Nested Procedures and Functions

Again, this is all pretty much the same except for static links.

When calling a (nested) procedure we must tell the CALL where to find the static link.

Revised code template:

execute [I ()] =CALL(r) e

evaluate [I ()] =CALL(r) e

e from address of I is (d, l)

r determined by l and cl (current level)

74

Procedures and Functions: Parameters

We extend Mini Triangle with ...

Declaration ::= ... | proc Identifier (Formal) : TypeDenoter ~ ExpressionExpression ::= ... | Identifier (Actual) Formal ::= Identifier : TypeDenoter | var Identifier : TypeDenoterActual ::= Expression | var VName

Declaration ::= ... | proc Identifier (Formal) : TypeDenoter ~ ExpressionExpression ::= ... | Identifier (Actual) Formal ::= Identifier : TypeDenoter | var Identifier : TypeDenoterActual ::= Expression | var VName

75

Procedures and Functions: Parameters

Parameters are pushed right before calling a proc/func.They are addressed like locals, but with negative offsets (in TAM).

LB

ST

local variablesand intermediate

results

dynamic linkstatic link

return address

arguments

let proc double(var n:Integer) ~ n := n*2in ...

let proc double(var n:Integer) ~ n := n*2in ...

UnknownAddress

address = (1,-1)

76

Code Templates Parameters

elaborate [proc I(FP) ~ C] =JUMP g

e: execute [C]RETURN(0) d

g:

execute [I (AP)] =passArgument [AP]

CALL(r) e

passArgument [E] =evaluate [E]

passArgument [var V] =fetchAddress [V]

where d is the size of FP

Where (l,e) = address of routine bound to I,Cl = current routine level

r = display-register(cl,l)

77

Code Templates Parameters

An “UnknownAddress” extra case for fetch and assign

fetch [V] = if V bound to unknown address LOAD d[r] where (d,l) = address where the LOADI(s) unknown address will be stored at runtime.

s is the size of the type of V

assign [V] =LOAD d[r] STOREI(s) where d = address where the unknown

address will be stored a runtime.

78

Runtime Entities Overview

Known Unknown

Value

Address

Routine

const lucky ~ 888 const foo ~ x + 10

value: 888 address: (level,offset) the address where value will be stored

proc double() ~ ...

address: (level,offset) ofthe routine (label e intemplate)

A procedure or function parameter.address: (level,offset)address where closure object will be stored.

var counter : Integer

address: (level,offset) of the variable.

A var parameteraddress: (level,offset) of the address where the pointer will be stored.

79

Code generation summary

• Create code templates inductively– There may be special case templates generating equivalent,

but more efficient code

• Use visitors pattern to walk the AST recursively emitting code as you go along– Back patching is needed for forward jumps

– It is necessary to keep track of frame level and allocated space

• That’s it folks!– At least for Mini Triangle on TAM