Step after procedure call is to pass the actual parameters up to the activation record being created.
The operand of the param three address statement will be treated as a pointer to the value of the actual parameter (if call by reference is used) or as the value itself (if call by value).
Suppose we invoke procedure R ( A + B * C, D ), where A, B, C, D are integers. A suitable translation of this call into three address code is:
T1 := B * C T2 := A + T1
Param T2 Param D call R, 2
We assume that R, the procedure name, will be replaced at the time of code generation by the location in memory of its first statement, just as references to data such as A or T1 are replaced by their locations.
The translation into object code of statement param X is the equivalent to PUSH ( add ( X ) ) if call by reference is used, and PUSH ( X ) if call by value is used.
An array is generally passed by giving a pointer to its first location, regardless of the parameter passing convention used.
Procedure parameters are block-structured languages that present more difficulty.
Suppose procedure P2 passes P1 to Q as an actual procedure valued parameter, and Q then calls the procedure P1, by referring to its corresponding formal parameter.
Procedure Q may be in the static environment of P1.
If P1 references a name X local to Q, if the deep binding is used, the environment of P1 is fixed when it is passed by P2.
Then the most convenient representation of the passed parameter is a pair consisting of the procedure name (first location of its code) and a pointer to the activation record for that procedure R which defines P2, i.e., the procedure most closely surrounding the definition of P2.
Shallow binding, where the environment of the procedure parameter P1 is not substituted until it is called.
Shallow binding is used in a certain language such as SNOBOL, which uses dynamic binding of identifiers to names.
In that case, no environment pointer needs to be passed; the environment of P1 will be established when P1 is called.
When called by name is used to pass parameters, as in ALGOL, all parameters (except array names and procedures) are passed by giving a procedure (“thunk”) to evaluate that parameter.
The environment of the thunk is itself plus the environment of the procedure P passing it.
A suitable representation for the thunk is a pair consisting of the first address for its code and pointer to the current activation record for P, just as for any procedure passed by P as a parameter.
If P2 passes label L belonging to procedure P1 (P2 may be P1), we may represent L by a pair consisting of the location of L in code for P1 and a pointer to the activation record for P1 in the environment of P2.
A symbol table is a data structure used by a compiler to keep track of scope, life, and binding information about names.
These names are used in the source program to identify the various program elements, like variables, constants, procedures, and the labels of statements.
It is searched every time a name is encountered in the source text.
When a new name or new information about an existing name is discovered, the content of the symbol table changes.
So the symbol table must have an efficient mechanism for accessing the information held in the table as well as for adding new entries to the symbol table.
The symbol table is a useful abstraction to aid the compiler to ascertain and verify the semantics, or meaning, of a piece of code.
It will keep track of the names, types, locations, and properties of the symbol encountered in the program.