Oppolzer - Informatik / Stanford Pascal Compiler

Home       Lebenslauf       Schwerpunkte       Kenntnisse       Seminare       Kunden       Projekte       Produkte       Blog       Stanford Pascal       Kontakt

The Stanford Pascal Compiler / Evolution Steps

Back to Compiler main page

Static definitions

When implementing the new storage management, static variables would have been very useful. These static variables should be global definitions inside a module and keep their values across several invocations of procedures of the module, but they should not be visible outside the module.

The compiler supported var declarations in modules, but the generated code used the global stack register (R12) to address them, and the offsets were calculated without knowledge of the main programs characteristics, so there were overlays with variables of the main program. So, global var declarations in modules could not be used. As a consequence, the compiler now flags var declarations in modules (outside of procedures and functions) - but static declarations are allowed.

When looking for a possibility to implement static variables (not only global, but inside procedures, too), I discovered that there is already a CSECT for structured constants which has all the characteristics that are needed for static variables (and it is not write protected, which is important!). This CSECT is started by the P-Code instruction CST and the field definitions are done by DFC instructions.

I decided to put the static variables there, too.

This turned out to be kind of easy. The offsets are calculated from the same location counter (which I renamed to CONSTLCOUNTER in PASCAL1.PAS). The DFCs initialize the static variables to zero for numeric data, blank for characters and strings, and NIL for pointer, and hex zero for all complex types (arrays, sets, records). That is: inside a record, pointers and chars are NOT set to NULL and blank, but to hex zero, respectively. Maybe this can be done better, later.

A VALUE type initialization like in Pascal VS has to be done later, too.

When the first static definition is encountered inside a block and there was no STATIC CSECT so far, the STATIC CSECT is started (by issuing a CST instruction). The name of the STATIC CSECT is derived from the name of the Code CSECT. Every reference to a static variable is in fact an indirect reference, because the base address of the STATIC CSECT has to be loaded first (this was easy, because the compiler already knew how to do this from the structured constant logic).

In the first run, the base address of the STATIC CSECT was loaded via a V-address constant.

Then I realized that SNAPSHOT (aka PASSNAP) has to be extended to enable it to show static variables, too.

I added a flag (S = static, A = auto) to the file QRR, which is written by the compiler in the debug case. PASSNAP reads this file when printing variables. However, to be able to access the static variables, PASSNAP must have access to the base address of the STATIC CSECT. So I extended the header information of the Code CSECT and put the static address just behind the CSECT information, 4 bytes before the target of the initial branch. PASSNAP can find it by examining the displacement of the initial branch instruction at EPA (entry point address) and subtracting 4; this is necessary because the length of the CSECT information may vary between main program and subprograms (for example).

Because now the static address is stored at a known place in the Code CSECT header, I replaced all the V-constant references by references to this V-address constant (which can be located using the base register 10).

So it is now possible to have up to 4k of static variables added to every procedure or function and to the main program, which are initialized by the compiler in the way outlined above, and which keep their values across invocations.

Here is an example, how static definitions are used in the heap manager (PASLIBX) to hold a static heap control block (and other informations, that is: static counters of allocation and free requests) and to provide initial values that make sense to the application:

type (****************************************************) (* HANC: Heap Element *) (****************************************************) PHANC = -> HANC ; HANC = record ... end ; (****************************************************) (* HPCB: Heap Control Block *) (****************************************************) PHPCB = -> HPCB ; HPCB = record EYECATCH : CHAR4 ; FIRST : PHANC ; LAST : PHANC ; ACTIVE : INTEGER ; end ; static HEAPCB : HPCB ; PHEAP : PHPCB ; (****************************************************) (* statische Variablen: *) (* heap control block *) (* zeiger auf heap control block (anfangs nil) *) (* anzahl-felder fuer allocs und frees *) (****************************************************) ANZ_ALLOCS : INTEGER ; ANZ_FREES : INTEGER ; ... (****************************************************) (* Pointer auf Heap Control Block besorgen *) (****************************************************) if PHEAP = NIL then begin PHEAP := ADDR ( HEAPCB ) ; PHEAP -> . EYECATCH := 'HPCB' ; PHEAP -> . FIRST := NIL ; PHEAP -> . LAST := NIL ; PHEAP -> . ACTIVE := 1 ; end (* then *) ;

Back to Compiler main page