Analysis of Activation Records and Dataflow Analysis in Compiler Design, Exams of Programming Languages

Information on the analysis of activation records and dataflow analysis in compiler design. It includes problem solutions related to activation record layouts, optimizing activation records, necessity of control links and return addresses, recursion detection algorithm, and dataflow analysis imprecision. The document also covers common errors and incorrect rules.

Typology: Exams

2012/2013

Uploaded on 04/02/2013

shaila_210h
shaila_210h 🇮🇳

4.3

(36)

178 documents

1 / 5

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
Problem 1
The output of the program is 4.
One (of several) correct activation record layouts looksas follows:
------------
| args |
------------
| fp1 |
------------ main
| ra1 |
------------
|p |
------------
|r |
------------
------------
| r/y |
------------
| p/x |
------------
|fp2|f
------------
| ra2 |
------------
|t |
------------
------------
| y/s |
------------
| t/r |
------------ g
| fp3 |
------------
| ra3 |
------------
|4 |
------------
SP points to 4
FP points to fp3
control links: fp3 points to fp2, and fp2 points to fp1
Return addresses: ra2 points to the end of function main (right after f(p,r) in main); ra3
points to the end of function f (right after g(t, y) in f).
Calling convention:
args: caller
1
pf3
pf4
pf5

Partial preview of the text

Download Analysis of Activation Records and Dataflow Analysis in Compiler Design and more Exams Programming Languages in PDF only on Docsity!

Problem 1

  • The output of the program is 4.
  • One (of several) correct activation record layouts looks as follows:

| args |

| fp1 | ------------ main

| ra1 |

| p |

| r |


| r/y |

| p/x |

| fp2 | f

| ra2 |

| t |


| y/s |

| t/r | ------------ g

| fp3 |

| ra3 |

| 4 |

- SP points to 4 - FP points to fp - control links: fp3 points to fp2, and fp2 points to fp - Return addresses: ra2 points to the end of function main (right after f(p,r) in main); ra points to the end of function f (right after g(t, y) in f). - Calling convention: ∗ args: caller

∗ fp: we accepted two possible answers: (1) either, or (2) callee ∗ ra: either ∗ locals: callee Note: fp/ra can be in any order, as long as they are consistent across the whole stack. Locals ’p’ and ’r’ in main can be in any order as well. ”args” for main is optional, as is the ”4” in the activation record for g. fp can point to either fp3 or ra3. Control links should point accordingly to where fp points to.

Point deductions: Missing part of activation record: -1. Incorrect order of stack contents: -1. Incorrect or missing boundaries: -1. Incorrect answer to what caller/callee pushes: -1. SP/FP not shown or incorrectly pointed: -1. Control links missing or inaccurate/inconsistent: -1. Missing pointers from RA’s or incorrect pointers: -1. Stack not drawn: -1.

  • If sp (whose value changes during the execution of the method) is to be used for accessing AR entries, the compiler must maintain the distance of sp’s value from some fixed location in the AR. This value is then used to adjust the offset when generating the code for accessing the AR entry. Note: the generated code isn’t more complex than that of the fp-based code; only the code generator is more complex.

Optimizing the Activation Records

  • Necessity of control link and return address: - Control link is not needed because the location of the activation record can be static, and therefore known at compile time. We will not need a seperate register to store this address. - Return address is still needed because the function can be called from multiple call sites in the program. A return address won’t be needed if a function has only one point of invocation in the program, meaning that this location can be determined statically.
  • Recursion Detection Algorithm: There were different kinds of answers for this algorithm. The main idea is the following, a DFS following the method invocations in the program. If at any point we see an already visited method, then there is recursion:

Set visited; // maintain a set of visited methods

visit(MethodDeclaration d) { visited = {d.name};

visit all of the body statements. }

visit(MethodInvocation i) { if(i element of visited) { signal that we have recursion }

The incorrect rule is both unsound and incomplete. It is unsound because it allows incorrect programs like boolean x = 3; x to pass, and incomplete because it does not allow safe pro- grams like boolean x = false; x to pass (only one program example was necessary for full credit).

O, M  e 0 : T 0 O, M  e 1 : T 1

... O, M  en : Tn M (T 0 , f ) = (T 1 ′, T 2 ′,... , T (^) n′, Tr) Ti = T (^) i′ (for 1 ≤ i ≤ n) O, M  e 0 .f (e 1 ,... , en) : Tr

Incorrect

O, M  e 0 : T 0 O, M  e 1 : T 1

... O, M  en : Tn M (T 0 , f ) = (T 1 ′, T 2 ′,... , T (^) n′, Tr) Ti ≤ T (^) i′ (for 1 ≤ i ≤ n) O, M  e 0 .f (e 1 ,... , en) : Tr

Correct

The incorrect rule is incomplete. Suppose we have classes A and B, with B ≤ A. If we have some method void foo(A a) {... }, the method call foo(new B()) will not be allowed to pass, even though the code is safe.

Problem 4

The ..... should be filled as follows (in order): push(peek(-1));, TypeDeclaration, push(peek(-4));, -1, peek(-1), 0. Here is the complete, filled-in specification.

PROLOGUE: [| private AST ast = new AST(new HashMap());

private SimpleName makeSimpleName(int offset) { return ast.newSimpleName(((Token)peek(offset)).getLexeme()); } |]

PROGRAM -> _ [| push(new ArrayList()); |] CLASSDECLLIST ;

CLASSDECLLIST -> CLASSDECL [| ((List)peek(-1)).add(peek(0)); push(peek(-1)); |] CDTAIL ;

CDTAIL -> CLASSDECLLIST | _ ;

CLASSDECL -> [| TypeDeclaration td = ast.newTypeDeclaration(); td.setName(makeSimpleName(0)); push(td); |] [| push(((TypeDeclaration)peek(-1)).bodyDeclarations()); |] FIELDDECLLIST [|

push(peek(-4)); |] ;

FIELDDECLLIST -> FIELDDECL [| ((List)peek(-1)).add((FieldDeclaration)peek(0)); push(peek(-1)); |] FIELDDECLLIST | _ ;

FIELDDECL -> FIELDID [| ((FieldDeclaration)peek(-1)).setType(ast.newPrimitiveType(PrimitiveType.INT)); push(peek(-1)); |] ;

FIELDID -> [| VariableDeclarationFragment vdf = ast.newVariableDeclarationFragment(); vdf.setName((SimpleName)ast.newSimpleName(((Token)peek(0)).getLexeme())); push(ast.newFieldDeclaration(vdf)); |] ;