In Chapter 7, our text provides illustrations of the sorts of run-time environment that are used in translation. Following our text, we assume the run-time storage comes in blocks of contiguous bytes, where a byte is the smallest unit of addressable memory. A bytes is eight bits and four bytes forms a machine word.
Ch 6 presented storage for elementary data types such as character and integer. Our project has strings and integers.
Storage layout for data objects is strongly influenced by addressing constraints of the target machine - SPIM and its RISC assembly language. If we were writing a compiler to generate target code for a CISC IBM PC family, we would have different conversations.
7.1 Storage Organizaton
From compiler writer perspective, executing target program runs in its own logical address space in which each program values has a location. The management and organization of this logical address space is shared between the compiler, operating system and target machine. The OS maps the logical addresses into physical addresses, which are usually spread through the memory.
Fig. 7.1 is especially useful and is recreated here:
------------------ | Code | static target code ------------------ | Static | global variables ------------------ | Heap | dynamic storage - storage for data outlives the proc call ------------------ | | | | | | | \|/ | | Free Memory | is filled by the Heap or the Stack growing | /|\ | | | | | | | ------------------ | Stack | Names local to a procedure and call/return info - data for proc call ------------------
The size of the generated target code is fixed at compile time, so the compiler can place the executable target code in a statically determined area Code, usually at the low end of memory. Similarly, the size of some program data objects, such as global constants, may be known at compile time and can be placed in a statically determined area called Static.
7.1.1 Static Versus Dynamic Storage Allocation
The compiler must layout and allocatino data to memory locations in the run-time environent. Static info is known at compile time. Dynamic info is know at run time. We will look at the Activation Records (AR), we might construct to handle the translation of procedures (possibly nested and possible recursively called). The two techniques we focus on in this course are:
using a Display (7.3.8) to manage these AR's
using Static and Dynamic Links (7.3.5) to manage the AR's
In modern languages, static allocation is used both for global variables that are fixed in size and accessible throughout the program execution and for program literals (constants) that needs to be fixed throughout execution.
Conceptually, we can bind static objects to absolute addresses. It is often
preferable to address a static data object as a pair
(DataArea, Offset)
Offset is fixed at compile-time, but the address of DataArea can be deferred to link- or run-time.
Alternatively, the address of DataArea can be loaded into a register,
which allows a static data item to be addresssed as
(Register,Offset)
This addressing form is avaiable on almost every machine. The advantage of addressing a piece of static data this way is that we can defer deciding on where a static object will be loaded until just before execution begins.
Almost all modern programming language include recursive procedures, a feature that requires dynamic allocation. Each recursive call requires the allocation of a new copy of a procedure's local variables; thus the number of data objects required during program execution is not known at compile time.
procedure p (a: integer) is b: real; c: array (1..10) of real; begin b := c(a) * 2.51; end;
------------------------- | Actual parameters | often use registers for this, but show space to add to discussion ------------------------- | Returned values | space for returned values of a function ------------------------- | Control link | points to AR of caller ------------------------- | Access link | may be needed to locate data needed by called proc (say in another proc's AR) ------------------------- | Saved machine status | status of machine just before proc call ------------------------- | Local Data | variable names declared in proc ------------------------- | Temporaries | evaluation of expressions (not using registers) -------------------------