17_mar_2004
TRANSCRIPT
-
8/10/2019 17_MAR_2004
1/2
Computer Science 332
Compiler Construction
Chapter 8: Intermediate CodeGeneration
Section 8.2: Procedure Declarations
8.2 Declarations : Single Procedure
Each local name has a symbol-table entry
Entry contains
Type : .type attribute
Relative address in procedure's activation record (e.g, Java
inttakes four bytes, doubletakes eight) : .widthattribute
Code-generating part of compiler uses a global variable offset
that is reset to zero as new procedures are declared
Code-generator proc. enter (name, type, width) creates symbol-
table entry with this info
Consider just declarations part of program....
P D { offset := 0}// initializaion
D D ;D
D id: T { enter(id.name, T.type, offset);
offset := offset + T.width) }
T integer { T.type := integer; T.width := 4 }
T double { T.type := double; T.width := 8 }
Problem : (look at first production)
offset := 0 code will be performed as last action, instead offirst
Solution: "dummy" non-terminal:
P M DM { offset := 0 }
8.2 Declarations : Nested Procedures
ML Example:
let fun f(x) =
let fun g(x, y) = x + y
in f(g(3, 4)) end end
Abstractly:
P DD D, D | id : T | fun id (D ) =S
Each procedure gets its own symbol table
Table for "inner" declaration points to table for "outer" linked list, searched from end to beginning (recalenvironmentsfrom CS312)
-
8/10/2019 17_MAR_2004
2/2
8.2 Declarations : Nested Procedures
nil
f:x
g
g:x
y
8.2 Declarations : Nested Procedures
Semantic rules are a little more complicated:
mktable (previous) creates and returns a new s.t., pointing to
previously created one
enter (table, name, type, offset) acts like enter, but using a
specified table
addwidth (table, width) records cumulative width of all
entries in table
enterproc (table, name, newtable) creates new entry for
procedure namein existing table, and assigns newtable to be
the s.t. for this new proc.
Can do it all in one pass, if we use stacks tblptr, offset to keep
track of symbol tables and offsets:
8.2 Declarations : Nested ProceduresP M D { addwidth(top(tblptr), top(offset));
pop(tblptr);pop(offset); } // done afterM's
// actionsM { t := mktable(nil);
push(t, tblptr);push(0, offset) }D D,D
D fun idN (D1) =S { t := top (tblptr);
addwidth (t, top ( offset)); pop(tblptr);pop(offset);
enterproc( top( tblptr), id.name, t ) }
continues ...
8.2 Declarations : Nested Procedures
D id: T { enter (top (tblptr), id.name, T.type, top ( offset));
top(offset) := top( offset) + T.width) }
N { t := mktable(top( tblptr) );
push(t, tblptr);push(0, offset) }
Let's try it with
let fun f(x:int) =
let fun g(x:int, y:int) = x + y
in f(g(3, 4)) end end