annotating abstract syntax tree

35
Annotating Abstract Syntax Tree Professor Yihjia Tsai Tamkang University

Upload: byron-mayo

Post on 30-Dec-2015

50 views

Category:

Documents


5 download

DESCRIPTION

Annotating Abstract Syntax Tree. Professor Yihjia Tsai Tamkang University. program text. lexical analysis. tokens. syntax analysis. AST. context handling. annotated AST. Overview. context handling annotating the AST attribute grammars manual methods symbolic interpretation - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Annotating Abstract Syntax Tree

AnnotatingAbstract Syntax Tree

Professor Yihjia Tsai

Tamkang University

Page 2: Annotating Abstract Syntax Tree

Overview

• context handling

• annotating the AST• attribute grammars

• manual methods

• symbolic interpretation

• data-flow equations

program text

lexical analysis

syntax analysis

context handling

annotated AST

tokens

AST

Page 3: Annotating Abstract Syntax Tree

Manual methods for analyzing the AST

• preparing the grounds for code generation• constant propagation

• last-def analysis (reaching definitions)

• live analysis

• common subexpression elimination

• dead-code elimination

• ...

• we need flow-of-control information

Page 4: Annotating Abstract Syntax Tree

Threading the AST

• determine the control flow graph that records the successor(s) of AST nodes

-

*

‘c’

‘4’

*

‘a’

‘b’

*

‘b’

first

last• intermediate code

PUSH b

PUSH b

MUL

PUSH 4

PUSH a

MUL

PUSH c

MUL

SUB

Page 5: Annotating Abstract Syntax Tree

Threading the AST

• result is a post-order traversal of the AST

• global variable: Last node pointer

PROCEDURE Thread binary expression (Expr node pointer):

Thread expression (Expr node pointer .left operand);

Thread expression (Expr node pointer .right operand);

// link this node to the dynamically last node

SET Last node pointer .successor TO Expr node pointer;

// make this node the new dynamically last node

SET Last node pointer TO Expr node pointer;

*

‘c’

‘4’

*

‘a’

Page 6: Annotating Abstract Syntax Tree

Multiple successors

• problem: threading is built around single Last node pointer

IF

condition THEN ELSE

first

last

Page 7: Annotating Abstract Syntax Tree

Multiple successors

• problem: threading is built around single Last node pointer

• solution: introduce join node

IF

condition THEN ELSE

first

last

FI

Page 8: Annotating Abstract Syntax Tree

Symbolic interpretation

• behaviour of code is determined by (the values of) variables

• simulate run-time execution at compile time

• attach a stack representation to each arrow in the control flow graph

• an entry summarizes all compile-time knowledge about the variable/constant

Page 9: Annotating Abstract Syntax Tree

Symbolic interpretation

condition

IF

THEN ELSE

FI

Page 10: Annotating Abstract Syntax Tree

Symbolic interpretation

condition

IF

THEN ELSE

>

y 0yx

5

yx

5

5

yx

5

50

yx

5

T

yx

5

yx

5

yx

5

x = 7;

yx

57

yx

5

dead

code

FI

merge

Page 11: Annotating Abstract Syntax Tree

Exercise (5 min.)

• draw the control flow graph for

while C do S od

• propagate initial stack

when C represents y>x

and S stands for x:=7

yx

5

Page 12: Annotating Abstract Syntax Tree

Answers

Page 13: Annotating Abstract Syntax Tree

Answers

condition

WHILE

BODY

yx

5

yx

5

yx

5yx

5

b

yx

57

Page 14: Annotating Abstract Syntax Tree

Simple symbolic interpretation

• used in narrow compiler

• simple properties + simple control-flow

• example: detecting the use of uninitialized variables

• maintain property list

• advance list through

control flow graph

int foo(int n)

{ int first;

while (n-- > 0) {

if (glob[n] == KEY)

first = n;

}

return first;

}

Page 15: Annotating Abstract Syntax Tree

Trackinguninitialized variables

• parameter declaration:

• variable declaration:

• expression:

• assignment:

• control statement

• fork nodes:

• join nodes:

add (ID:Initialized) tuple

add (ID:Uninitialized) tuple

check status of used variables

set tuple to (ID:Initialized)

copy list

merge lists

merge( Init, Init) = Init

merge( Uninit, Uninit) = Uninit

merge( x, x) = Maybe

int foo(int n)

{ int first;

while (n-- > 0) {

if (glob[n] == KEY)

first = n;

}

return first;

}

Page 16: Annotating Abstract Syntax Tree

Simple symbolic interpretation

• flow-of-control structures with one entry and one exit point (no GOTOs)

• the values of the property are severely constrained (see book)

• example: constant propagation

Page 17: Annotating Abstract Syntax Tree

Constant propagation

• record the exact value iso Initializedint i = 0;

while (condition) {

if (i>0) printf("loop reentered\n");

i++;

}

• simple symbolic interpretation fails

// i == 0

// i == 0

// i == 1

// i == {0,1}

Page 18: Annotating Abstract Syntax Tree

Full symbolic interpretation

• maintain a property list for each entry point (label), initially set to empty

• traverse flow of control graphL: merge current-list into list-L

continue with list-L

jump L;merge current-list into list-L

continue with the empty list

• repeat until nothing changedguarantee termination – select suitable property

Page 19: Annotating Abstract Syntax Tree

int i = 0;

while (condition) {

if (i>0) printf("loop reentered\n");

i++;

}

int i = 0;

L:

if (condition) {

if (i>0) printf("loop reentered\n");

i++;

goto L;

}

Constant propagation

• full symbolic interpretation

• property: unknown < value < any

// i == 0

// i == 1// empty

// i == ANY

// i == ANY

// i == 0

// i == 0// i == ANY

// i == ANY

Page 20: Annotating Abstract Syntax Tree

Data flow equations

• “automated” full symbolic interpretation• stack replaced by collection of sets

• IN(N)• OUT(N)

• semantics are expressed by constant sets• KILL(N)• GEN(N)

• equations• IN(N) = M predecessor[N] OUT(M)

• OUT(N) = IN(N) \ KILL(N) GEN(N)

n = n-1;

IN

OUT

Page 21: Annotating Abstract Syntax Tree

Data flow equations

• solved through iteration (closure algorithm)• data-flow nodes may not change the stack

• individual statements• basic blocks

• example: trackinguninitialized variables• properties: I x, M x, U x• GEN(x = expr ;) =• KILL(x = expr ;) =

int foo(int n)

{ int first;

while (n-- > 0) {

if (glob[n] == KEY)

first = n;

}

return first;

}{I x}{U x, M x}

int foo(int n)

{ int first;

L: n = n-1;

if (n >= 0) {

if (glob[n] == KEY)

first = n;

goto L;

}

return first;

}

Page 22: Annotating Abstract Syntax Tree

T

T

Data flow equations

• solved through iteration (closure algorithm)• data-flow nodes may not change the stack

• individual statements• basic blocks

• example: trackinguninitialized variables• properties: I x, M x, U x• GEN(x = expr ;) =• KILL(x = expr ;) =

{I x}{U x, M x}

if (glob[n] == KEY)

first = n;

goto L;

return first;

L: n = n-1;

if (n >= 0)

F

F

1

2

3

4

5

6

Page 23: Annotating Abstract Syntax Tree

{}

{}

{}

{}

{}

{}

IN(N) = M predecessor[N] OUT(M)

OUT(N) = IN(N) \ KILL(N) GEN(N)

Iterative solution

• initialization: set all sets to empty

• iterate from top to bottom

{I n, U f}

{I n, U f}

{I n, U f}

{I n, U f}

{I n, I f}

{I n, M f}

{I n, M f}

{I n, M f}

T

T F

return first;6

F

first = n;4

goto L;5

L: n = n-1;1

int foo(int n)

{ int first;0

if (glob[n] == KEY)3

if (n >= 0)2

statement KILL GEN

0 In Uf

1 Un Mn In

4 Uf Mf If

Page 24: Annotating Abstract Syntax Tree

Iterative solution

statement

iteration 1 iteration 2

KILL GEN IN OUT IN OUT

0 In Uf In Uf In Uf

1 Un Mn In In Uf In Uf In Uf In Uf

2 In Uf In Uf In Mf In Mf

3 In Uf In Uf In Mf In Mf

4 Uf Mf If In Uf In If In Mf In If

5 In Mf In Mf In Mf In Mf

6 In Uf In Uf In Mf In Mf

Page 25: Annotating Abstract Syntax Tree

Efficient data-flow equations

• limit to (set of) on/off properties• set union = bitwise OR• set difference = bitwise AND NOT

• combine statements into basic blocks• KILL[S1;S2] = KILL[S1] KILL[S2]

• GEN[S1;S2] = GEN[S2] (GEN[S1] \ KILL[S2])

• sort data-flow graph• depth-first traversal (break cycles!)

Page 26: Annotating Abstract Syntax Tree

Live analysis

• a variable is live at node N if the value it holds is used on some path further down the control-flow graph; otherwise it is dead

• useful information for register allocation

• information must flow “backwards” (up) through the control-flow graph• difficult for symbolic interpretation• easy for data flow equations

Page 27: Annotating Abstract Syntax Tree

Solving data-flow equations

• forwards

• backwards

IN(N) = M predecessor[N] OUT(M)

OUT(N) = IN(N) \ KILL(N) GEN(N)

if (cond)

IN

OUT

OUT(N) = M successor[N] IN(M)

IN(N) = OUT(N) \ KILL(N) GEN(N)

Page 28: Annotating Abstract Syntax Tree

Exercise (5 min.)

• determine the KILL and GEN sets for the property “V is live here” for the following statements

statement S KILL GEN

v = a b

v = M[i]

M[i] = v

f(a1, ... ,an)

v = f(a1, ... ,an)

if a>b then goto L1 else goto L2

L:

goto L

Page 29: Annotating Abstract Syntax Tree

Answers

• determine the KILL and GEN sets for the property “V is live here” for the following statements

statement S KILL GEN

v = a b

v = M[i]

M[i] = v

f(a1, ... ,an)

v = f(a1, ... ,an)

if a>b then goto L1 else goto L2

L:

goto L

{v} {a,b} \ KILLS[S]

{v} {i} \ KILLS[S]

{} {i,v}

{} {a1, ... ,an}

{v} {a1, ... ,an} \ KILLS[S]{} {a,b}

{} {}

{} {}

Page 30: Annotating Abstract Syntax Tree

Exercise (7 min.)

• draw the control-flow graph for the following code fragment

• perform backwards live analysis using the KILL and GEN sets from the previous exercise

double average(int n, double v[])

{ int i;

double sum = 0.0;

for (i=0; i<n; i++) {

sum += v[i];

}

return sum/n;

}

Page 31: Annotating Abstract Syntax Tree

Answers

OUT(N) = M successor[N] IN(M)

IN(N) = OUT(N) \ KILL(N) GEN(N)

statement KILL GEN

1

2

3

4

2

3

1

4

Page 32: Annotating Abstract Syntax Tree

Answers

OUT(N) = M successor[N] IN(M)

IN(N) = OUT(N) \ KILL(N) GEN(N)

statement KILL GEN

1

2

3

4

sum = 0.0;

i = 0;

if (i<n)

sum += v[i];

i++;

return sum/n;

2

3

1

4

Page 33: Annotating Abstract Syntax Tree

Answers

sum = 0.0;

i = 0;

if (i<n)

sum += v[i];

i++;

return sum/n;

live: n

live: n, i, sum

live: n, i, sum

live: n, sum

live: n, i, sum

OUT(N) = M successor[N] IN(M)

IN(N) = OUT(N) \ KILL(N) GEN(N)

statement KILL GEN

1 sum, i

2 i, n

3 sum, i sum, i

4 sum, n

2

3

1

4

Page 34: Annotating Abstract Syntax Tree

Answers

statement

iteration 1 iteration 2 iteration 3

KILL GEN OUT IN OUT IN OUT IN

0 n

1 sum, i i, n n i, n, sum n

2 i, n i, n i, n, sum i, n, sum i, n, sum i, n, sum

3 sum, i sum, i i, n i, n, sum i, n, sum i, n, sum i, n, sum i, n, sum

4 sum, n n, sum i, n, sum i, n, sum

process nodes top to bottom (from 0 to 4)

processing nodes in reverse (from 4 to 0) requires only two iterations

Page 35: Annotating Abstract Syntax Tree

Summary

manual methods for annotating the AST• threading

• symbolic interpretation

• data-flow equations

symbolic interpretationdata-flow equations

simple full

method stack-based simulation IN, OUT, GEN, KILL sets

granularity AST node basic block

algorithm one-pass iterative iterative

direction forwards forwards & backwards