1 Pascal-6000 Internal Reference Manual ===================================== Edited by Dave Bianchi Jim Miner Academic Computing Services and Systems | University of Minnesota Version 4.1 | May, 1986 | Differences from Version 4.0 are indicated by change bars in the right | margin. An asterisk indicates deleted text. | _________ +COPYRIGHT Portions of Pascal-6000 Release 4 are copyright by the University of Minnesota. It is not to be sold or distributed without the express written permission of the University of Minnesota, Academic Computing Services and | Systems. All names and references are to be left intact. The | machine-retrievable documention on the release tape is under a limited copyright. That is, you are free to copy and distribute the writeups within your organization providing that it is not done for profit and that all names and references are left intact. 1 1 Pascal-6000 Internal Reference Manual 27 May 86 Table of Contents ================= page section 1 Introduction 1 Acknowledgements 1 1. Overview 2 2. The Pascal-6000 Compiler 2 2.1. Syntax Analysis | 3 2.2. Recovery from Syntax Errors | 3 2.3. Analysis of Declarations | 3 2.4. Recovery from Context-Sensitive Errors | 4 2.5. Address Assignment and Code Generation | 5 3. Pascal-6000 Run-Time Structures 5 3.1. Summary of Run-Time-System Routines 7 3.2. Register Conventions 8 3.3. Files and File Variables 8 3.3.1. Extended FET (EFET) Format 11 3.3.2. Input and Output Conventions 13 3.3.3. Binary Input and Output 14 3.3.4. Text Input and Output 14 3.3.5. Multi-file Files | 15 3.3.6. Segmented Files 16 3.4. Dynamic Allocation 17 3.5. Data-Space Structures 17 3.5.1. Logical Data-Space Structure 17 3.5.2. Physical Data-Space Structure 18 3.5.3. Stack Chunks 19 3.5.4. Activation Records 20 3.5.5. Parameter Descriptors 21 3.6. Code Structures 21 3.6.1. Code Segments 21 3.6.2. Block Header Word 22 3.6.3. PMD Header Table 22 3.6.4. Program Information Table 24 3.6.5. Local Variable Descriptions | 25 3.6.6. Block-Entry Code 27 3.6.7. Prologue Code 27 3.6.8. Statements Code 27 3.6.9. Epilogue Code 28 3.6.10. Block-Exit Code 28 3.6.11. Calls 29 3.6.12. Non-Local Gotos 30 4. Pascal-6000 Memory Manager 30 4.1. Summary of Memory Manager Routines 31 4.2. Memory Manager Parameters and Variables 32 4.3. Node Structure 32 4.4. Alternative Heap Management 33 4.5. Memory Manager Algorithms and Data Structures 41 References 42 History 1 1 Pascal-6000 Internal Reference Manual 27 May 86 ____________ +INTRODUCTION This manual describes the structure and operation of the Pascal-6000 Pascal compiler and run-time system. This document is not intended to be the only internal reference for Pascal-6000 but rather a supplement to information sources listed in the Reference section. It contains such internal documentation as might be useful for maintaining the processor. Much of the information was originally internal documentation in the run-time system. Other material has been added during the development of Release 4. _______________ +ACKNOWLEDGMENTS The material in this manual has been written by many people, including Dave Bianchi, Jeff Drummond, Dan Germann, Andy Mickel, Jim Miner, and John Strait. ________ +1. OVERVIEW The Pascal-6000 system consists of 4 main parts. 1. The compiler (largely written in Pascal) generates relocatable object code for CDC 6000, CDC 7000, and Cyber 70, 170, 700 and 800 series computers. 2. The run-time system (written mostly in COMPASS) includes all operating system interface routines. 3. The Pascal support routines include higher level character input and output routines, the Post-Mortem Dump routine, and various procedure and function packages. 4. The COMPASS support routines include medium level character input and output routines, mathematical routines, and other procedures and functions which for one reason or another are coded in assembly language. 1 1 Pascal-6000 Internal Reference Manual 27 May 86 ________________________ +2. THE PASCAL-6000 COMPILER The compiler was developed in 6 steps, each an enrichment of its predecessor using the stepwise-refinement method of structured programming: Step 1 - Syntax analysis for syntactically correct programs. Step 2 - Recovery from syntax errors. Step 3 - Analysis of declarations. Step 4 - Processing context-sensitive errors. Step 5 - Address assignment. Step 6 - Code generation. _______________ +2.1. SYNTAX ANALYSIS The compiler compiles in one pass using top-down, one-symbol-lookahead syntax analysis with no backtracking. However, in several places, more than one symbol lookahead is required and semantic analysis resolves the choices. The syntax analysis is implemented as a set of recursive-descent procedures. These procedures are based on the syntax of the revised report and are nested as tightly as their mutual interaction permits. The order, names, and nesting of these procedures are: BLOCK CONSTANT TYP SIMPLETYPE FIELDLIST LABELDECLARATION TYPEDECLARATION VARDECLARATION PROCEDUREDECLARATION PARAMETERLIST BODY STATEMENT SELECTOR VARIABLE CALL EXPRESSION SIMPLEEXPRESSION TERM FACTOR ASSIGNMENT COMPOUNDSTATEMENT GOTOSTATEMENT IFSTATEMENT CASESTATEMENT WHILESTATEMENT REPEATSTATEMENT FORSTATEMENT WITHSTATEMENT 2 1 Pascal-6000 Internal Reference Manual 27 May 86 ______________ +2.2. ERROR RECOVERY Error recovery is incorporated into the syntax analysis procedures. Each procedure is passed an actual parameter which is a set of symbols not to be skipped in the event of an error. These symbols are those which may legitimately follow the string of symbols to be scanned and usually include such additional symbols as a calling syntax procedure may wish to handle in the event of error recovery. See Chapter five in: Algorithms + Data Structures = Programs, by Niklaus Wirth, 1976. ________________________ +2.3. ANALYSIS OF DECLARATIONS The analysis of declarations uses an identifier table and a structure table. The identifier table is organized as a stack with one entry for each declaration scope currently open. Each stack entry points to an unbalanced binary tree of identifiers and also contains information such as the kind of syntactic unit (e.g. block, parameter list) that constitutes the scope. The stack is represented by the array DISPLAY, together with the global variables TOP and LEVEL that indicate the topmost scope and topmost block scope respectively. Insertion and lookup of identifiers within the table is provided by two procedures ENTERID and SEARCHID. Standard identifiers supported by the language are held as a scope corresponding to a pseudo-block enclosing the main program at level 0. Additional, non-standard, predeclared identifiers are similarly held at level -1. The structure table holds entries for all types underlying the data defined by the program being compiled. The type entries are categorized by the "form" of the type so represented (scalars, -- which include required and enumerated but not subrange types -- subranges, pointers, sets, etc.). Thus all identifier-table entries have a common field IDTYPE which points to the type entry that describes the identifier's type. A general-purpose Boolean function COMPTYPES tests the compatibility of two types. ______________________________________ +2.4. RECOVERY FROM CONTEXT-SENSITIVE ERRORS Recovery from context-sensitive errors is provided by handling duplicate, misused, and undeclared identifiers in ENTERID and SEARCHID. Type ambiguities are handled by setting the type pointer to NIL. COMPTYPES is defined to return True if either of the two types is undefined (= NIL). 3 1 Pascal-6000 Internal Reference Manual 27 May 86 ______________________________________ +2.5. ADDRESS ASSIGNMENT AND CODE GENERATION This compiler is designed to run on CDC 6000/7000 and Cyber 70,170,700,800 Series Computer Systems. The address assignment and code generation parts of the compiler try to minimize memory references and recalculation of accesses to components of structured variables. Run-time storage organization manages both a stack and a heap. A global variable GATTR (Global ATTribute Record) describes the expression or variable access being compiled. If a dyadic operation must be compiled, a local variable LATTR is assigned the value of GATTR. The attribute record distinguishes 4 kinds of expressions: constants, variables, conditions, and other, and is able to manage associated information for address calculation. A register map is managed for the X, A, and B registers of the CDC-6000 hardware architecture. The register map is manipulated via the procedures LOAD, NEEDX, NEEDB, DECREFX, and STORE which implement several heuristics to decide which registers are worth saving. Control structures are compiled by determining their distributor and concentrator points of computational flow. The register map must be saved at all distributor points and cleared at the concentrator points. See the article: "On Code Generation in a Pascal Compiler" by Urs Ammann in Software Practice and Experience, (7:3), June-July, 1977, pp. 391-423. Release 3 incorporated remembrance of constants using the procedure LOADCST. Changes from the original code-generation design are sketchily described in comments in procedures INDEXCODE, LOADFILEWORD, and SETADDRESS. The installation notes on the Release 2 and Release 3 tapes provide useful information. Release 4 incorporated a MERGEREGMAP procedure to save the common contents of the register maps at some concentrator points, notably after if, case, and for statements. * 4 1 Pascal-6000 Internal Reference Manual 27 May 86 ___________________________________ +3. THE PASCAL-6000 RUN-TIME STRUCTURES The Pascal-6000 run time system can be sub-divided into several major groups of routines: 1. Initialization of the Pascal-6000 system. This involves the creation of the run time stack and the run time heap, and all other global system information. 2. Termination of the Pascal-6000 system. This includes both normal termination at the end of a program and error recovery in the case of abnormal conditions or error termination. 3. Low level input and output routines requiring direct calls to the operating system. These include opening and closing files, and such Pascal routines as RESET, REWRITE, GET, PUT, and others. 4. The dynamic allocation routines NEW and DISPOSE. 5. Other procedures and functions, such as DATE and MESSAGE, which require direct calls to the operating system. ___________________________________ +3.1. SUMMARY OF RUN-TIME-SYSTEM ROUTINES The following table summarizes the externally-called routines. These fall into one of three catagories: 1. Routines which are directly user-callable, yet are known under a different name, such as WRITELN (P.PUTLN). These correspond to predefined Pascal routines. 2. Routines whose calls are generated by the compiler to maintain the run time environment, such as P.OPEN. 3. Routines which are called from the library (or by user-written COMPASS routines) to maintain the run time environment, such as P.SABRT. 5 1 Pascal-6000 Internal Reference Manual 27 May 86 ______________________________________ + Pascal-6000 Externally-Called Routines Routine External Pascal Name Name Name Description ------- -------- ------- ----------- ACV P.ACV Allocate and Copy Parameter. CFV P.CFV Commission (create) File Variable. CLK P.CLOCK CLOCK CP Time in Milliseconds (function). CLO P.CLO Close EFET. CPV P.CPV Copy Parameter Value. DTE P.DATE DATE System Date. DFV P.DFV Decommission (destroy) File Variable. TDS P.DISPD DISPOSE Test and Deallocate Heap Storage. END P.END Return Control to the Operating System. GTB P.GETB GET Get Binary. GTC P.GETC GET Get Character. GCH P.GETCH GET Get Character Helper. GTL P.GETLN READLN Get Line. GTS P.GETS GETSEG Get Segment. GTO P.GTO GOTO External Label. HLT P.HALT HALT HALT with a Message. PRS P.INIT Initialize the Pascal Run Time System. INV P.INV Initialize New Variables. IOE P.IOE Input/Output Error. MSG P.MSG MESSAGE Display Message to User Dayfile. TNW P.NEWD NEW Allocate Checked Heap Storage. NFN P.NFN Create New File Name of form "SCRnnnn". OPE P.OPE Open EFET. OSO P.OS Return Operating System Ordinal. PAG P.PAGE PAGE Start Page. PEG P.PEG Common Global Block Entry. PEN P.PEN Common Non-Global Block Entry. PEX P.PEX Common Block Exit. PTB P.PUTB PUT Put Binary. PTC P.PUTC PUT Put Character. PCH P.PUTCH PUT Put Character Helper. PTL P.PUTLN WRITELN Put Line. PTS P.PUTS PUTSEG Put Segment. RST P.RESET RESET Rewind File and Prepare for Reading. RWT P.REWRT REWRITE Rewind File and Prepare for Writing. RPE P.RPE Restore Pascal Environment. RWS P.RWRTS REWRITE Rewrite Segmented File with Skip Count. ABT P.SABRT Common Error Routine. SCO P.SCO Stack-Chunk Overflow. SCU P.SCU Stack-Chunk Underflow. SPE P.SPE Save Pascal Environment. TIM P.TIME TIME System Time of Day. VPE P.VPE Variable Procedure Entry. 6 1 Pascal-6000 Internal Reference Manual 27 May 86 The routines in the following table are internal to the run time system, but have external entry points for use by other routines. _____________________________ + Pascal-6000 Internal Routines Routine External Name Name Description ------- -------- ----------- CAD P.CAD Convert Address to Display Code. CFD P.CFD Convert Integer to Pascal 10:3 Form. EFD P.EFD Examine First Delimiter (CCDR). FCA P.FCA Find Current Activation. FOB P.FOB Flush Output Buffer. FXF P.FXF Flush External File Buffers. | ISM P.ISM Issue Statistics Message to Dayfile. PPF P.PPF Prepare for Positioning Pascal file. RMP P.RMP Record Manager Put (SCOPE 2 only). RPF P.RPF Rewind Pascal File. RWR P.RWR Process Read Without Reset Error. SKP P.SKP Skip Records. SNM P.SNM Set Name in Message. SPK P.SPK Set Pointer Key. SRS P.SRS Set Read Status. SWS P.SWS Set Write Status. TMS P.TMS Terminate Message String. WWR P.WWR Process Write Without Rewrite Error. ____________________ +3.2. REGISTER CONVENTIONS Unless otherwise noted, all routines in the run time system observe the following register conventions. (A0) = Current line number in Pascal source code (if PMD is on). (B1) = 1. (B4) = Address plus one of the end of the current stack chunk. (B5) = Address of the current activation record (AR). (B6) = Address of the top of the parameter stack. 7 1 Pascal-6000 Internal Reference Manual 27 May 86 ________________________ +3.3. FILES AND FILE VARIABLES The Pascal-6000 Run-Time System contains several routines to support operations on Pascal file variables. Pascal-6000 represents each file variable by an Extended File Environment Table (EFET) together with a file in the operating system and an input-output buffer. Segmented files are an extension to Pascal-6000 to deal with the multi-level file structure common to CDC operating systems. __________________________ +3.3.1. EXTENDED FET (EFET) FORMAT This section describes the structure of EFETs. It defines many symbolic offsets and bit positions within EFETs; the symbols are defined in the common deck COMSPAS and are also available in the systems text PASTEXT. See "Pascal-6000 Installation Handbook". WARNINGS: (1) Not all code in the compiler or run-time system has been adapted to use the symbolic constants. All new code should use the constants. (2) The symbolic offsets are relative to a location in the middle of the EFET (called the "EFET word"), rather than being relative to the first word of the EFET. (3) A Pascal file variable is addressed sometimes by the first word address of the EFET (usually in the compiler), and sometimes by the "EFET word". This is complicated by the fact that the offset of the "EFET word" from the first word is different between EFETs that describe textfiles and EFETs that describe non-textfiles. (4) The format of EFETs is subject to change in order to accomodate future extensions. Actual Symbolic Offset Offset Contents -13 EFETLCNT * Textfile Line Counter. -12 EFETCBUF * Textfile Unpacked Character Buffer ... ... * (10 words) -2 EFETSNTL * Textfile End-of-buffer Sentinel -1 EFETPTR Current Element Pointer Word 0 EFET EFET word 1 -- System Interface Tables ... ... (system dependent size -- see below) An asterisk (*) indicates words present only in textfile EFETs. _____________________ +Textfile Line Counter The Textfile Line Counter is initialized to -1 by P.OPE whenever the file variable is opened. The value is decremented whenever a line is written; an error occurs if it becomes zero. The compiler generates code in the 8 1 Pascal-6000 Internal Reference Manual 27 May 86 main block to place the OUTPUT line limit in the OUTPUT EFET after it has been opened. __________________________________ +Textfile Unpacked Character Buffer The current element (Pascal-level "buffer variable") of a textfile is accessed by a pointer (in the current element pointer word) that points into the character buffer. When a textfile is being read, each word in the input-output buffer is unpacked into the character buffer, and GET advances the current element pointer. The data in the buffer is always terminated by a word with bit 59 set. This word indicates either an end-of-line or the end-of-buffer. When a textfile is being written, the program places each character in the current element of the character buffer, PUT advances the current element pointer, and when the buffer is full or an end-of-line is written the character buffer is packed into the next word of the input-output buffer. _______________________________ +Textfile End-of-buffer Sentinel The end-of-buffer sentinel is always present to "terminate" the data in the character buffer when there is no end-of-line sentinel in the buffer. ____________________________ +Current Element Pointer Word This word contains a pointer to the current element (the Pascal "buffer variable") of the file. If the file variable is not a textfile, the pointer points into the input-output buffer; otherwise, it points into the character buffer. In addition, for textfiles only, this word contains some status bits. These and the pointer field have symbolic bit positions as described below. Actual Symbolic Bit Bit Contents 59 PEOLN EOLN flag 58 PREWRITE Textfile Rewrite Flag (same as in EFET word) 0 PPOINTER 18-bit Current Element Pointer This can be viewed as: 1/EOLN, 1/REWRITE, 40/, 18/POINTER 9 1 Pascal-6000 Internal Reference Manual 27 May 86 _________ +EFET Word The lower bit position of each field in the EFET word is described by a symbolic constant, as shown below. Actual Symbolic Field | Bit Bit Width Contents | | 51 EDISPC EDISPCW disposition code | | 36 ERT ERTW record type (SCOPE 2 only): | RT = 0B means W-type | RT = 7B means U-type (undefined) | RT =10B means S-type | RT = 3B means Z-type | | 18 EWSALEN 18 actual WSA length (SCOPE 2 only) | (The value passed to P.CFV in B7) | | 18 EDCCHS EDCCHSW index into display code buffer | (APASCAL only) | | 0 ELRL 18 logical record length (1 for textfiles; | otherwise, size of components in words) | This appears as: EDISPCW/disposition code, 9/0, ERTW/RT, 18/WSALEN, 18/LRL | The disposition code bits are as follows: 59 EEOSF EOS/EOF flag for segmented/non-segmented files 58 EEOF EOF flag (1 means end of file) 57 ESEGMENT Segmented file flag (1 means segmented) 56 EREWRITE Rewrite flag (1 means rewritten) 55 ETEXT Textfile flag (1 means textfile) 54 ETERMFIL Terminal file flag (1 means "/" in program heading) 53 EPERSIST Persistent file flag (1 means persistent) 52 ECONNECT Terminal connection flag (1 means connected) | 51 EPROGPAR Program parameter flag (1 means program parameter) _______________________ +System Interface Tables The format of the "system interface tables" depends on the operating system, as shown below. Note that distinct symbols are used for offsets in the different formats. 10 1 Pascal-6000 Internal Reference Manual 27 May 86 For non-SCOPE 2 systems: Actual Symbolic Offset Offset Contents 1 EFETFET File Environment Table (FET) first word: 42/LFN, 18/Code and Status 2 EFETFRST FET second word 3 EFETIN FET third word 4 EFETOUT FET fourth word 5 EFETLIM FET fifth word ... -- (FETSZ words total FET length) For SCOPE 2 systems: Actual Symbolic Offset Offset Contents 1 EFITBUF WSA buffer descriptor: 24/BUFLEN, 18/BUFADR, 18/EOR 2 EFITOUT ) 2 EFITIN ) IN/OUT pointer 3 EFITFIT FIT first word ... -- (FITSZ words total FIT length) ____________________________ +3.3.2. INPUT AND OUTPUT CONVENTIONS A file may be read only if it has been reset and may be written only if it has been rewritten. This may be determined by the rewrite flags which are set by SWS and cleared by SRS. When a file variable is commissioned, if it is a program parameter bound to actual INPUT or if it is a non-persistent file variable (i.e., local or heap variable) then it is initialized for reading, otherwise it is initialized for writing. For non-SCOPE 2 systems: Input and output files are distinguished by the CIO function code (status) in the lower 18 bits of the FET first word as well as by the rewrite flags. An input file is denoted by a READ code (bit 2 is not set), and an output file is denoted by a WRITE code (bit 2 is set). A WRITER code (24B) is present if either 1. The file has not yet been written, i.e. CIO has not yet been called, or 2. An end of record has recently been written (by PTS). At any point where the code is in question (such as after a rewind or skip), a READ or WRITE code must be set. SRS may be called to set a READ status and fill the buffer, or SWS may be called to set a WRITE status. When an output file is closed, its buffer is flushed with a WRITER unless 1. The buffer is empty, and 2. The function code in the FET is a WRITER. 11 1 Pascal-6000 Internal Reference Manual 27 May 86 For SCOPE 2 systems: On SCOPE 2, the file INPUT is opened with the PD field in the FIT set to input; the file OUTPUT is opened with the PD field set to output; and all other files are opened with the PD field set to input-output. Input and output files are subsequently distinguished by the setting of the rewrite bits in the Pascal EFET. A file is regarded as currently opened for writing if the file is a textfile and the text-file rewrite bit is set in EFET-1, or the file is not a textfile and the word-file rewrite bit is set in EFET. When a file opened for writing is RESET, an end-of-partition mark is added by a call to the record manager macro ENDFILE. 12 1 Pascal-6000 Internal Reference Manual 27 May 86 _______________________ +3.3.3. BINARY INPUT AND OUTPUT Binary input and output (that are non-text I/O) are performed by P.GETB and P.PUTB which correspond to the Pascal procedures GET and PUT. For a binary file, the file variable (called POINTER in the EFET description given above) points to the current element of the file in the CIO circular buffer. In case of an input file, the pointer has the same value as the OUT pointer in the CIO FET (EFET+4). In the case of an output file, it has the same value as the IN pointer in the FET (EFET+3). The current element of the file can thereby be located regardless of whether the file is currently an input or output file. The size of the circular buffer must be a multiple of the logical record length (LRL) in order to prevent a (multiword) component of the file from wrapping around the buffer. When GET or PUT is called, the file variable and its associated FET pointer are advanced circularly. If advancing the pointer makes the buffer half empty for an input file or half full for an output file, then CIO is called to perform an input or output function. In this way, the run time system attempts to keep input buffers full and output buffers empty to overlap execution with input and output activity. Under SCOPE 2.1, a linear buffer allocated when the file is commissioned serves to buffer all data exchanges between the Pascal input-output system and the SCOPE 7000 record manager. For a file opened for input, EOR is initialized by P.SRS to BUFADR, and subsequently updated by P.GETB to BUFADR + record-length whenever a record is read by record manager. For a file opened for output, EOR is initialised by P.SWS to BUFADR + BUFLEN. On a file opened for input, IN holds the word address of the next component for Pascal binary files, and the next burstable word of characters for textfiles. Components can be read from the buffer as long as IN + LRL <> EOR. When this condition becomes false, the buffer is refreshed from disc by record manager, and IN is reset to BUFADR. On a file opened for output, OUT holds the word address of the next buffer location available for storing the current component of a Pascal binary file, and the next word of characters packed from the EFET of a textfile. Components can be added to the buffer as long as OUT + LRL <> BUFLEN. When this condition becomes false, the buffer is emptied by record manager and written to disc as a single record by P.RMPUT. OUT is reset to BUFADR. When a file is opened, the buffer is created and BUFLEN defaults to this value. It is altered, after the call to the OPENM macro if: 1) RT = W,Z and MRL < BUFLEN then BUFLEN := MRL 2) RT = F,U then BUFLEN := LRL The following dayfile message is issued SET FL= nnnnnnn FOR FILE xxxxxxx 13 1 Pascal-6000 Internal Reference Manual 27 May 86 _____________________ +3.3.4. TEXT INPUT AND OUTPUT Text file input and output is performed by the routines P.GETC and P.PUTC which correspond to the Pascal procedures GET and PUT. For text files, the file variable points to the current element of the file in the character buffer (EFET-12 through EFET-2). The current element of the file can thereby be located regardless of whether the file is a text or binary file. The compiler generates inline code for P.GETC and P.PUTC, and generates calls to P.GETCH and P.PUTCH to handle the extra work of unpacking and packing characters. When P.GETC is called (or performed inline), the file pointer is advanced. If advancing the file pointer empties the char buffer, or advances to the end of line, P.GETCH is called to handle this special case. If the pointer is advanced to a word with only the upper bit set, this indicates that the end of line has been reached. In this case, P.GETCH sets the EOLN bit in EFET-1, sets the current element to blank, and sets the next element to negative zero. If the file pointer is advanced to a negative zero word, this indicates that the character buffer is empty, and P.GETCH unpacks a new word from the CIO/7RM buffer. Before unpacking, P.GETCH in turn calls P.GETB to advance to the next 10 character word of the file. When P.PUTC is called (or performed inline), the file pointer is advanced. If the pointer is advanced to a negative zero word, this indicates that the character buffer is full, and P.PUTCH is called to pack the ten characters from the character buffer into the CIO/7RM buffer. After packing, P.PUTCH in turn calls P.PUTB to advance the buffer pointers. ________________ +3.3.5. MULTI-FILE FILES | | Two predeclared procedures and a predeclared function allow processing of | multi-file files. These routines are analogous to those for manipulating | multi-record (segmented) files (see below), and are described in the | chapter FILES in the Pascal-6000 writeup. They are summarized in the | following table. | | GETFILE(F) Advances F to the beginning of the next file. | | GETFILE(F,N) Positions F to the beginning of the Nth file counting from | the current file. N = 0 positions at the beginning of the | current file. N > 0 advances, and N < 0 backspaces. | GETFILE(F,1) is the same as GETFILE(F). | | EOI(F) Boolean function that returns TRUE if the end-of-information | has been reached while reading F. | | GETFILE is implemented using calls to SKIPFF and SKIPFB. The following | table summarizes the action taken for a given value of N: | | N <= 0 N = 1 N > 1 | ------ ----- ----- | NOT EOF SKIPFB(1-N) SKIPFF(1) SKIPFF(N) | EOF SKIPFB(1-N) No Action SKIPFF(N-1) | 14 1 Pascal-6000 Internal Reference Manual 27 May 86 _______________ +3.3.6. SEGMENTED FILES In order to allow manipulation of multi-record files (which the compiler uses for relocatable binaries), the segmented-files mechanism was added to Pascal-6000. A Pascal segment corresponds directly to a KRONOS or SCOPE logical record. This extension is described in the chapter SEGFILE of the Pascal-6000 writeup. Several predefined procedures were added or altered to provide mechanisms for manipulating segmented files. These are summarized in the following table. GETSEG(F) Advances F to the beginning of the next segment, and prepares for reading. GETSEG(F,N) Positions F to the beginning of the Nth segment counting from the current segment. N = 0 positions to the beginning of the current segment, N > 0 advances, and N < 0 backspaces. GETSEG(F,1) is the same as GETSEG(F). PUTSEG(F) Marks the end of segment while writing F. This is used when the generation of a segment segment is completed. REWRITE(F,N) Initiates writing at the beginning of the Nth segment counting from the current one. Positioning is the same as for GETSEG(F,N). REWRITE(F,1) advances one segment, and so is NOT the same as REWRITE(F) which rewinds. Note that this CANNOT be used to rewrite in place on a segmented file. Writing on such a file releases the remainder of the file. The positioning routines GETSEG(F,N) and REWRITE(F,N) are not implemented with random access I/O, but rather with SKIPF and SKIPB. Since KRONOS and SCOPE are oriented toward forward processing of sequential files, positioning is less efficient for N <= 0 than it is for N > 0. For segmented files, the EFET contains both an EOS bit and an EOF bit. To keep processing simple, the bit position which is used as the EOF bit for non-segmented files (bit 59) is used as the EOS bit for segmented files. RESET(F) and REWRITE(F) are handled identically for non-segmented and segmented files, as a rewind followed by set-read and set-write respectively. GETSEG(F,N) is done as a skip(N) and set-read, and REWRITE(F,N) is done as skip(N) and set-write. When N <= 0, skip(N) does a SKIPB(1-N). When N > 0, the processing done by skip(N) is summarized in the following table. In the table, EOS refers to the EOS bit in the EFET, and EOR refers to the EOR bit in the FET first word (bit 4). N = 1 N > 1 ----- ----- NOT (EOS OR EOR) SKIPF(1) SKIPF(N) EOS OR EOR No Action SKIPF(N-1) 15 1 Pascal-6000 Internal Reference Manual 27 May 86 __________________ +3.4. DYNAMIC ALLOCATION In Pascal-6000, the standard procedure NEW is used to allocate chunks of memory. The standard procedure DISPOSE is used to return chunks to the free storage pool. NEW allocates storage by calling P.ALM and DISPOSE liberates storage by calling P.LIM. If a pointer type is declared (*$T-*) TYPE P = ^T with the run time tests off, it is the 17-bit address of a chunk large enough to hold an element of type T. If it is declared (*$T+*) TYPE P = ^T with the tests on (the default condition), it is a 36-bit quantity of the form 18/KEY, 18/ADDRESS where ADDRESS is the address of the second word of a chunk that is one word larger than necessary to hold an element of type T. The first word of this node has the form 24/0, 18/KEY, 18/ADDRESS and for a pointer reference to be valid, the header word must be bit identical to the pointer. The header word of a checked chunk and the value of the pointer are set by NEW. An 18-bit counter is used to generate key values; zero is not a valid key value. This allows for 262143 calls to NEW before key values are non-unique. The header word of a checked chunk and the value of the pointer are cleared by DISPOSE. Thanks to Professor Charles Fischer of the University of Wisconsin for suggesting this method to test pointer references at run time. 16 1 Pascal-6000 Internal Reference Manual 27 May 86 _____________________ +3.5. DATA-SPACE STRUCTURES ____________________________ +3.5.1. LOGICAL DATA-SPACE STRUCTURE The data space of a Pascal-6000 program logically consists of two parts: the "activation stack" and the "heap". When a Pascal block (program, procedure, or function) is activated, a local data space is created; when that block activation is terminated, that local data space is destroyed. Because of the structure of Pascal, local data spaces are created and destroyed in a stack discipline -- last created is first destroyed. The local data spaces that exist at a given time comprise the activation stack. The top-most activation is said to be the "currently executing" activation. Each program activation has a heap that contains all Pascal "identified variables" (i.e., variables that are identified by pointers) that are created by the program activation. The local data space for an activated block logically contains the following: - A description of each actual parameter that is passed to the activated block; - Linkage information needed to terminate the activation and to resume execution either of the calling activation or of the destination activation of a non-local goto statement; - Linkage information needed to access each variable and block (procedure and function) that is accessible but non-local to the activated block; - A representation of and description of each variable and block (procedure and function) that is declared local to the activated block; - A representation of any compiler-generated temporaries used in the algorithm of the activated block; and - A representation of constant values used in the algorithm of the activated block. _____________________________ +3.5.2 PHYSICAL DATA-SPACE STRUCTURE A local data space consists physically of the following. - An "activation record" that is allocated in the activation-record stack as discussed below. - Auxilliary memory areas (e.g., CIO buffers) that are allocated separately and that are accessible indirectly via the activation record. Invariant information (e.g., constant value representations) is usually stored with the code space, and is described in that section. The activation record for the currently executing activation is always accessible via the address in register B5; register B6 contains the 17 1 Pascal-6000 Internal Reference Manual 27 May 86 address of the word that follows the last word of the activation record. Each activation record except for that of the program-block is allocated dynamically on the activation-record stack. The activation-record stack is physically composed of memory areas called "stack chunks"; each stack chunk contains one or more activation records. The stack chunks are linked backwards from the chunk that contains the currently executing activation record to form a stack. The activation record for the program-block is allocated statically by a loader module. A little kludginess allows the program-block activation record to look like it is allocated in the first stack chunk. ____________ +3.5.3. STACK CHUNKS Stack chunks are created by P.SCO, which is called by the block-entry code, and are destroyed by P.SCU, which is called when the first activation in a stack chunk is terminated. The first word of each chunk except the first contains a "chunk linkage" of the following form. 6/0, 18/old B4, 18/old B6, 18/RA where "old B4", "old B6", and "RA" are, respectively, the contents of B4 and the contents of B6 prior to the call that created this chunk, and the return address for that call. There is no chunk linkage in the first stack chunk, because no call creates that chunk. It is created before the program begins execution, with B6 pointing to the first word of the chunk and B5 pointing to the first word of the static global data area. That is, the program's parameter stack is allocated in the first stack chunk, but the activation record is statically allocated via a loader module. B4 always contains the last word address + 1 of the stack chunk that contains the currently executing activation. The size of the initial stack chunk and the minimum size of all other stack chunks are parameters that are provided by the compiler to the stack-management code. See the Program Information Table (3.6.4). 18 1 Pascal-6000 Internal Reference Manual 27 May 86 __________________ +3.5.4. ACTIVATION RECORDS Each activation record has the following structure. AR-ARPS: ... .. : AR-1: 30/EQ RA, 30/DL (B5) --> AR: 30/BHW, 30/SL AR+PFLC) .. ) PARAMS parameter words AR+PFLC+PARAMS-1) AR+PFLC+PARAMS) function result word, if .. ) block is a function, AR+LCMAX-1) and local variables. AR+LCMAX) .. ) parameter stack AR+LCMAX+PSMAX-1) where: ARPS is the Activation-Record Prefix Size; BHW is the address of the Block Header Word for the activated block; SL is the static link if the block is at level > 2, or is zero for a block at level = 2 and for the program block; DL is the dynamic link (i.e., address of the second word of the caller's activation record); DL is zero for the program activation; RA is the return address within the caller. If the activation record is the first one in the current stack chunk then RA = P.SCU (see P.SCO); in the program activation record, EQ RA is zero; AR is the address of the second word of the activation record; PFLC is the offset from AR at which allocation of parameters, variables, and temporaries starts in every activation record except that of the program-block; LCMAX is the offset from AR at which the parameter stack starts; PSMAX is the largest size of the parameter stack (used to pass parameters to other activations, and to hold activation linkages at block entry); PARAMS is the number of parameters declared for the activated block. LCMAX+ARPS, PSMAX, and PARAMS are fields of the Block Header Word. PFLC and ARPS are Pascal-6000 constants, available in common deck COMSPAS. Currently, PFLC = 1, and ARPS = 1. When an activation is actually executing, the register B5 contains AR, and B6 is usually AR+LCMAX. B6 may be greater than AR+LCMAX when nested calls (actual parameter lists) are being executed. B4 contains the last word address + 1 of the current stack chunk. 19 1 Pascal-6000 Internal Reference Manual 27 May 86 _____________________ +3.5.5. PARAMETER DESCRIPTORS Up to 5 parameters may be passed in X-registers. This is based on the value of the X-compiler option setting at the time of the procedure or function declaration. If the X option was set to N, the first N parameters are passed in registers X0 to X(N-1) and the common entry routine P.PEN stores them into memory starting at (B6)+ARPS+PFLC. If there are more than N parameters, the rest are passed through memory starting at the location with address (B6)+ARPS+PFLC+N. If the compiler option setting X0 is used, all parameters are passed through memory starting at (B6)+ARPS+PFLC. Each parameter is described by one word, which may contain a value or one or two addresses. The following list describes the various kinds of parameters. - For a VAR parameter, the address of the variable is passed. - For a value parameter that is less than or equal to one word in size, the value itself is passed. - For a value parameter that is larger than one word, the address of the actual parameter is passed. - For a procedural or functional parameter, the entry-point address (EPT) and static link (SL) are passed as 24/0, 18/SL, 18/EPT - For a conformant array parameter, the address of the array and the address of the descriptor are both passed only if the parameter is the first in the parameter group (i.e., if it is the first of a group of parameters which share a common conformant-array-schema). If the parameter is not the first parameter of the group, then the address of the array is passed. If the parameter is the first in the parameter group, the address of the array and the address of the descriptor are passed as 24/0, 18/DESCRIPTOR, 18/ARRAY the descriptor contains a three word block for each conformant subscript which has the form SIZE HIGH SUBSCRIPT LOW SUBSCRIPT For the first subscript, SIZE is the size of the whole array. For the rest of the subscripts, SIZE is the size of the sub-arrays. The prologue code of the called procedure or function copies the descriptor into the activation record, if it is the first parameter of the parameter group. If the conformant array parameter is a VAR parameter, the address of the array is restored to the parameter word. If the parameter is passed by value, the array is copied into the local activation record and the address of the local copy is stored in the parameter word. 20 1 Pascal-6000 Internal Reference Manual 27 May 86 _______________ +3.6. CODE STRUCTURES ______________________ +3.6.1. CODE-SEGMENT STRUCTURE The code segment for each block has the following general form. The symbolic addresses are used within this document and within the compiler and run-time-system sources. Absolute Relative Address Address Content BHW 0 * Block Header Word PMD Header Table if any EPT EPTIC * Block-Entry Code Prologue Code Statement Code XIT XITIC Epilogue Code * Block-Exit Code CST CSTIC Local Constants PMD PMDIC Local Variable Descriptions P.PIT PITIC Program Information Table (program-block only) The items marked with an asterisk (*) are present in every code segment. _________________ +3.6.2 BLOCK HEADER WORD The first word in the code segment for each block contains the Block Header Word for that block. The Block Header Word has the following form. 1/PG, 1/PH, 3/(5-REGS), 10/PARAMS, 15/XITIC, 12/PSMAX, 18/LCMAX+ARPS where: PG is 1 if the block is a program-block, otherwise 0; PH is 1 if a PMD Header Table follows this Block Header Word (i.e., PMD is not suppressed), otherwise 0; PH = 1 if PG = 1; REGS is the number of parameters passed in X registers to this block; (5-REGS) = 5 if PG = 1; PARAMS is the total number of formal parameters declared for this block; XITIC if nonzero, XITIC is the offset from BHW of the Epilogue Code for this block (i.e., XIT = BHW + XITIC); if XITIC is zero, there is no Epilogue Code; XITIC = 0 if PG = 1; PSMAX is the maximum space needed for the block's parameter stack; LCMAX+ARPS is the size of the block's activation record, except for the parameter stack; if PG = 1, then this field of the Block Header Word is altered by the initialization code to a value K such that following the initialization code B5+K-ARPS is the first word address of the initial stack chunk. 21 1 Pascal-6000 Internal Reference Manual 27 May 86 ________________ +3.6.3. PMD-HEADER TABLE The PMD Header Table is present in every program-block and in every other block where the PMD is not suppressed (using the "P0" compiler-option setting). It tells the name of the block (up to ten characters), and the location of the Local Variable Descriptions table. The form is as follows (note changes from Release 3). BHW+1: 1/PP, 1/FB, 7/0, 6/COUNT, 15/EPTIC, 15/CSTIC, 15/PMDIC BHW+2: 10H"name" where: PP is 1 if the "P" compiler option setting for this block is "+", otherwise 0; FB is 1 if the block is a function-block, otherwise 0; COUNT is used by the PMD processor to count activations of this block; initially zero; EPTIC ) CSTIC ) relative addresses described above; zero if PP = 0; PMDIC ) "name" is the Pascal-source name of the program, procedure, or function, either truncated or space-filled to 10 characters; _________________________ +3.6.4. PROGRAM INFORMATION TABLE The Program Information Table always has the entry-point name "P.PIT". It is used to transmit several kinds of parameters from the compiler to the run-time system. It has the following form. Offset Actual Symbolic Contents 0 60/5LP.PIT 1 PITVERS 6/RELNUM, 6/1L., 6/VERNUM, 6/1L., 6/LEVNUM, 6/ASCFLAG, 6/DLIBNUM, 6/LLIBNUM, 12/0 2 PITMAIN 12/0, 18/PGBHW, 12/0, 18/PGAR 3 PITFLAG 1/P, 1/E, 1/Z, 1/MZ, 56/0 4 PITPMD ) 12/0, 18/PMDEPT, 12/0, 18/OUTPUT 4 PITOUTP ) 5 PITIDS ) 1/IR *, 11/0, 18/INIDS *, 12/0, 18/MFL 5 PITMFL ) 6 PITSCS 12/0, 18/ISC *, 12/0, 18/MSC 7 PITMCS 1/AI, 11/0, 18/MINDEC, 1/AD, 11/0, 18/MININC 22 1 Pascal-6000 Internal Reference Manual 27 May 86 where: * indicates that the field so marked is zeroed by the run-time-system initialization code; RELNUM is the distributed release number (from COMSPAS); VERNUM is the distributed version number (from COMSPAS); LEVNUM is the local level number (from COMSPAS); ASCFLAG is the full-ASCII indicator (from COMSPAS); 55B means regular, 01B means full-ASCII; DLIBNUM is the distributed library-generation number (from COMSPAS); LLIBNUM is the local library-generation number (from COMSPAS); PGBHW is address of the Block Header Word for the program-block; PGAR is the program-block activation record address; P indicates that PMD may be present (1) or not (0) in some blocks; E indicates that program parameters appeared (1) or did not appear (0) in the source program-heading. Z indicates that initial and final statistics messages should (1) or should not (0) be issued to the dayfile; MZ indicates that PMM should (1) or should not (0) issue a dayfile message before changing the job field length; PMDEPT is the entry-point address of the post-mortem dump routine (P.PMD) if P=1, otherwise zero; OUTPUT is the address of the EFET for the standard file-variable OUTPUT if it exists, otherwise zero; IR indicates that the run-time system should (1) or should not (0) initially reduce the field length to (CS+INIDS), where CS is the code-space size; this field is zeroed by P.INM (PMM initialization); INIDS is the initial size of managed memory; this field is zeroed by P.INM (PMM initialization); MFL is the user-specified maximum field length; this field is altered by P.INM (PMM initialization) to be the minimum of the user-specified MaxFL and the job MFL; ISC is the size of the initial stack chunk; this field is zeroed by P.INIT (P.SYSTM initialization); MSC is the minimum size of stack chunks except the initial one; AI indicates that field length may (1) or may not (0) be increased by the memory manager; MININC is the smallest amount by which the field length may be increased, except where that would exceed the maximum field length; AD indicates that field length may (1) or may not (0) be decreased by the memory manager; MINDEC is the smallest amount by which the field length may be decreased by the memory manager. 23 1 Pascal-6000 Internal Reference Manual 27 May 86 ___________________________ +3.6.5. LOCAL VARIABLE DESCRIPTIONS | | Local variable descriptions are present in every block where the PMD is ON | (P+ compiler-option setting). This part of the code segment consists of a | sequence of two-word entries, followed by a zero word (to terminate the | list). Only nonstructured variables (and parameters) have PMD | descriptions. Variables of the following types have a PMD description, and | are identified by their symbol values. | | _____________ ______________ ____________ + Variable Type COMSPAS Symbol Symbol Value | INTEGER PMDINT 1 | REAL PMDREAL 2 | CHAR PMDCHAR 3 | BOOLEAN PMDBOOL 4 | Enumerated Type PMDENUM 5 | ALFA PMDALFA 6 | Unchecked pointer PMDUPTR 7 | Checked pointer PMDCPTR 8 | | For each variable (or parameter), a description of the following form is | generated. | | PMD+i: 10H"name" | PMD+i+1: 30/0, 11/VT, 1/IR, 18/RA | | where: | | "name" is the Pascal-source name of the variable, either truncated or | space-filled to 10 characters. | VT is the variable type as defined in COMSPAS (above). | IR is 1 if the variable is indirectly referenced, otherwise 0. | RA is the offset of the variable from AR (first word of the | activation record). Register B5 usually contains the address of | the current AR. If IR is 1, then B5+RA is the address of the | variable; otherwise B5+RA is the address of the variable. | 24 1 Pascal-6000 Internal Reference Manual 27 May 86 ________________ +3.6.6. BLOCK-ENTRY CODE _____________________________________________ +Block-Entry Code for Procedures and Functions The "quick" block-entry code does not call a run-time system subroutine except to handle stack-chunk overflow, whereas the "short" block-entry code does call a subroutine to perform the entire entry. Unlike other releases, these Block-Entry Code sequences leave the parameter registers (X0..X4) undefined. These assume ARPS = 1 and PFLC = 1. _____________________________ +Quick Global Block-Entry Code EPT SA0 line num current line number PS trap non-return jumps SA5 EPT 30/EQ RA, 30/0 SX6 BHW LX6 30 30/BHW, 30/0 SX7 B5 60/DL SA6 B6+B1 AR BX7 X7+X5 30/EQ RA, 30/DL SA7 B6 AR-1 BX7 X0 *** if num in-reg params >= 1 SA7 A6+B1 *** if num in-reg params >= 1 BX6 X1 *** if num in-reg params >= 2 SA6 A7+B1 *** if num in-reg params >= 2 BX7 X2 *** if num in-reg params >= 3 SA7 A6+B1 *** if num in-reg params >= 3 BX6 X3 *** if num in-reg params >= 4 SA6 A7+B1 *** if num in-reg params >= 4 BX7 X4 *** if num in-reg params = 5 SA7 A6+B1 *** if num in-reg params = 5 SX6 LCMAX+ARPS+PSMAX space needed SX7 B6 old top SX5 B4 limit IX7 X7+X6 lwa+1 needed IX5 X5-X7 PL X5,GAMMA if no overflow (lwa+1 <= limit) SA5 BHW RJ =XP.SCO stack-chunk overflow GAMMA SB5 B6+B1 new AR. *** perform in one word SB6 B6+LCMAX+ARPS new AR+LCMAX. *** perform in one word _____________________________ +Short Global Block-Entry Code EPT SA0 line num current line number PS trap non-return jumps SB3 BHW RJ =XP.PEG enter global block 25 1 Pascal-6000 Internal Reference Manual 27 May 86 _________________________________ +Quick Non-global Block-Entry Code EPT SA0 linenum current line number PS trap non-return jumps PL X5,BETA if X5 = static link. BX6 X5 descriptor mask is in X5 SA5 B5 ALPHA LX6 1 SA5 X5 NG X6,ALPHA BETA SX6 X5 60/SL SA5 EPT 30/EQ RA, 30/0 SX7 B5 60/DL BX7 X7+X5 30/EQ RA, 30/DL SX5 BHW Block Header Word SA7 B6 AR-1 LX5 30 BX6 X6+X5 30/BHW, 30/SL SA6 B6+1 AR BX7 X0 *** if num in-reg params >= 1 SA7 A6+B1 *** if num in-reg params >= 1 BX6 X1 *** if num in-reg params >= 2 SA6 A7+B1 *** if num in-reg params >= 2 BX7 X2 *** if num in-reg params >= 3 SA7 A6+B1 *** if num in-reg params >= 3 BX6 X3 *** if num in-reg params >= 4 SA6 A7+B1 *** if num in-reg params >= 4 BX7 X4 *** if num in-reg params = 5 SA7 A6+B1 *** if num in-reg params = 5 SX6 LCMAX+ARPS+PSMAX space needed SX7 B6 old top SX5 B4 limit IX7 X7+X6 lwa+1 needed IX5 X5-X7 PL X5,GAMMA if no overflow (lwa+1 <= limit) SA5 BHW Block Header Word RJ =XP.SCO stack-chunk overflow GAMMA SB5 B6+B1 new AR. *** perform in one word SB6 B6+LCMAX+ARPS new AR+LCMAX. *** perform in one word _________________________________ +Short Non-global Block-Entry Code EPT SA0 line num current line number PS trap non-return jumps SB3 BHW RJ =XP.PEN enter non-global block 26 1 Pascal-6000 Internal Reference Manual 27 May 86 _____________________________ +Block-Entry Code for Programs The block-entry code for a program consists of: EPT SB7 PARAMS Number of program parameters RJ =XP.INIT Initialize Run-Time System RJ =XP.EER Enable Error Recovery The return jump to P.EER is not generated if PMD is entirely suppressed (that is, if the "P" compiler option is set to zero before the program heading). _____________ +3.6.7. PROLOGUE CODE The prologue code for a block performs any of the following, as needed. - Initialize the activation record to an unusual value if it is not the program activation record and if the "T" compiler option is on. - Commission each external file that is a program parameter (if the block is a program block). - Copy conformant-array-parameter descriptors into local activation record. - Allocate memory from PMM for, and copy initial value into, each "very large" value parameter. - Allocate memory from PMM for each "very large" local variable, and if the "T" compiler option is on, initialize the memory to an unusual value. - Copy large value parameters into local variables. - Commission all local file-variables. A value parameter or variable declared in a procedure block or function block is "very large" if its size exceeds the setting of the "MV" compiler option at the point of declaration of the variable or parameter. A value parameter or variable that is not "very large" is called "large" if its size exceeds one word or if it is a value conformant-array parameter. "Commissioning" a file variable consists of initializing the EFET and (if necessary) allocating buffer space from PMM. In the special cases of the program parameters INPUT and OUTPUT, commissioning may also include a RESET- or REWRITE-like action. ______________ +3.6.8. STATEMENT CODE The statement code for a block performs the actions specified by the statement-part of the block. _____________ +3.6.9. EPILOGUE CODE The epilogue code performs any of the following, as necessary. - Liberate memory allocated for "very large" local variables and for "very large" value conformant-array parameters. - Decommission local file-variables (thereby liberating buffers). 27 1 Pascal-6000 Internal Reference Manual 27 May 86 - Decommission external file-variables that are program parameters (if the block is a program-block). Because the Epilogue Code may be executed either as part of a normal return or as part of a non-local goto, the statement number register (A0) is neither set nor altered by the Epilogue Code. _______________ +3.6.10. BLOCK-EXIT CODE __________________________________ +Block-Exit Code for Program Blocks A program-block is exited by a jump to P.END, as follows. EQ =XP.END Note that Release 3 performed a Return Jump, rather than a straight jump, to P.END. _________________________________________________ +Block-Exit Code for Procedure and Function Blocks The block-exit code for a function-block must load the function-activation result into register X6 before executing one of the following. This assumes ARPS = 1. Version 1 (Quick): SA1 B5-B1 30/EQ RA, 30/DL SB6 B5-B1 *** perform in one word SB5 X1 *** perform in one word LX1 30 SB7 X1 JP B7 (B7 = RA) Version 2 (Short): EQ =XP.PEX ___________________________________ +3.6.11. PROCEDURE AND FUNCTION CALLING CODE Before any call to a Pascal block, the following condition must hold: B6 + ARPS + PFLC + PARAMS <= B4 where PARAMS is the number of parameters in the called block. The compiler ensures that this condition is satisfied. The condition allows the entry code safely to store all parameters and the first ARPS+PFLC words of the callee's activation record. _______________________________________ +Calling Actual Procedures and Functions A call to an actual block (i.e., one that is not a formal parameter) requires three things: (a) passing parameters, if any (see 3.5.5); (b) passing the Static Link for the callee if it is not a global procedure or 28 1 Pascal-6000 Internal Reference Manual 27 May 86 function; and (c) Return Jumping to the callee's entry point. The Static Link is passed in X5 either as an address or as a mask, depending on the relative nesting levels of the caller and the callee. If the callee is local to the caller, or at the same level, then an address is passed; otherwise, if the caller is more deeply nested than the callee, the difference in their nesting levels is the number of high-order bits set in X5. This scheme requires only one 15-bit instruction in the caller to describe the static link. _______________________________________ +Calling Formal Procedures and Functions A call to a formal block (i.e., a procedure or function that is a formal parameter) also has three parts: (a) pass parameters, (b) load the formal-procedure (or function) descriptor into X5, and (c) Return Jump to P.VPE. ___________________ +3.6.12. NON-LOCAL GOTO CODE Non-local gotos are executed by P.GTO by scanning down the dynamic-link chain, and performing the following to each activation that is terminated by the goto-statement. - Alter the return address in the activation so that execution of block-exit code will return to part of P.GTO. If this is the first activation record in a stack chunk, then the return address is the lower 18 bits of the chunk linkage (at B5-2); otherwise the return address is in bits 47-30 of the activation linkage word (at B5-1). - Examine the Block Header Word of the activation's block, and perform any epilogue code indicated by a nonzero XITIC field. If the XITIC field is zero, there is no epilogue code, and P.GTO can simply jump to P.PEX (Block-Exit). In both cases, B5 and B6 will be reset to their state before the activation that is being terminated, and control will return to P.GTO (due to (1)). When the destination activation is reached, P.GTO must reset B6 to B5+LCMAX before restarting the destination block; LCMAX+ARPS is available in the Block Header Word for that block. This is to deallocate any parameter stack in case the goto occurred during evaluation of a parameter. If the destination activation is the program, then the Block Header Word "LCMAX+ARPS" field actually contains a value K, such that B5+K-ARPS is the fwa of the global parameter stack. The transfer to P.GTO is as follows. SX1 DAR destination activation record SX7 DLA destination label address EQ =XP.GTO Note the change in registers for passing parameters from Release 3; also note that Release 3 did a Return Jump to P.GTO, whereas Release 4 does a straight jump. 29 1 Pascal-6000 Internal Reference Manual 27 May 86 __________________________ +4. PASCAL-6000 MEMORY MANAGER The Pascal-6000 memory manager implements the routines necessary for automatic field length management in the Pascal-6000 system. Managed memory extends from the "Load FL" up to (FL-1); "available" memory extends from FL up to "Maximum FL". Managed memory expands or contracts at execution time when FL is increased or decreased, respectively, by PMM. FL can never be increased to exceed Maximum FL, and it can never be decreased to less than Load FL. We assume that PMM is completely responsible for managing memory and changing FL. PMM is incompatible with Control Data's CMM, and will abort during initialization if CMM is in use. Furthermore, the program must not attempt to control FL directly by making MEMORY requests to the operating system. To a client of PMM (e.g., the run-time system routines that allocate or deallocate input-output buffers), a "chunk" of memory is "allocated" by specifying the minimum size required. PMM returns a chunk having at least that size. The chunk is identified by the address of the first word of the chunk. The client may use all words of the chunk, but must not alter any managed memory outside of the chunks that it has allocated. In particular, the word immediately preceding the chunk and the word immediately following the chunk are always reserved for the exclusive use of PMM. Once a client is through using a chunk, the chunk can be "liberated" by specifying its address to PMM. When a chunk is liberated, its memory space can be reused by subsequent allocate operations. Managed memory is partitioned completely into "nodes". Each node consists of several contiguous memory words; the number of words is called the "size" of the node. Each node is either "free" (i.e., available to be allocated) or "non-free" (i.e., reserved for use by the program). A non-free node contains a chunk that has been allocated but not yet liberated by the PMM client. The first word of a node is its "header word"; a node is identified by the address of its header word. The header word contains information that is manipulated by PMM, and is not meant to be used by a client. In a non-free node, the header word is followed by the chunk that that node contains; the size of a non-free node is one greater than the size of the chunk that it contains. In a free node, the header word is followed by another PMM-defined word; the rest of the words in the node are unused. In addition to the basic "allocate" and "liberate" operations, PMM provides an "initialization" operation and also several operations that support "alternative heap management" (see HEAP chapter of the Pascal writeup). __________________________________ +4.1. SUMMARY OF MEMORY MANAGER ROUTINES The memory manager routines can be logically divided into four groups. 1. Initialization of the memory management package. This requires the allocation of an initial block of allocatable memory for use by the Pascal program, the creation of dummy nodes in that block of memory to 30 1 Pascal-6000 Internal Reference Manual 27 May 86 simplify boundary condition checks in the memory manager, and the initialization of a table that contains information required by the memory manager. 2. Simple allocation and deallocation procedures that can be used to implement both the standard procedures NEW and DISPOSE, and a dynamic stack frame. 3. Routines to support "alternative heap management" extensions. 4. Subroutines used by the above. The following table summarizes the externally-called routines. Routine External Pascal Name Name Deck Name Description ------- -------- ---- ------ ----------- ALM P.ALM PMM NEW Allocate a "chunk" of managed memory. INM P.INM PMM Initialize memory manager. LIM P.LIM PMM DISPOSE Liberate a "chunk" of managed memory. MND P.MND AHM MNEW Allocate checked marked heap storage. MNW P.MNW AHM MNEW Allocate marked heap storage. MRK P.MRK AHM MARK Start a new mark level. RLS P.RLS AHM RELEASE Free marked nodes, reset mark level. The following routines are internal to the memory manager, but have external entry points for use by other routines. AFL P.AFL PMM Alter field length. CMR P.CMR PMM Check for memory reduction. _______________________________________ +4.2. MEMORY MANAGER PARAMETERS AND VARIABLES The state of the memory manager is determined by several parameters and variables, together with all the nodes in managed memory. The memory manager parameters are located in a table contained within the code space of the main program block. This table is called the Program Information Table (PIT), and is accessed through the entry point P.PIT. The memory manager variables are located in a table called TMEM, which is known outside the memory manager as P.TMEM. Each variable is denoted by a name which represents an offset into TMEM, as follows. Variable Name Description -------- ----------- MEMFL Current field length. MEMFF Address of first free node. MEMLF Address of last free node. MEMHLF Highest address of last free node. MEMHFL Highest field length used by memory manager. 31 1 Pascal-6000 Internal Reference Manual 27 May 86 ______________ +4.3. NODE STRUCTURE Each free node in managed memory has a two-word header, as follows. 1/1, 23/, 18/PREV, 18/SIZE 24/, 18/PREVFREE, 18/NEXTFREE PREV Link to adjacent node at lower address. SIZE Size of free node, in words. PREVFREE Link to previous free node. NEXTFREE Link to next free node. Each non-free node in managed memory has a one-word header, as follows. 1/0, 5/MARK, 18/, 18/PREV, 18/SIZE MARK Mark level of node. Non-zero only in nodes created by the non-standard procedure MNEW. PREV Link to adjacent node at lower address. SIZE Size of allocated node, in words. The size of every node includes the one or two header words. To ensure that there is space in each node for the header words, there is a lower bound on the size of a node. This bound is set by the constant MINSIZE. ___________________________ +4.4. ALTERNATIVE HEAP MANAGEMENT The Pascal-6000 run-time system provides two methods of managing dynamically allocated variables. Under the standard method, the routines NEW and DISPOSE are used to create and destroy dynamic variables. However, some Pascal programs, most notably the Pascal-6000 compiler, would benefit if there were a way to cheaply dispose many chunks at a single time. Therefore, since the first release of the Pascal-6000 compiler, a routine called RELEASE has been provided to perform this function. In Release 4, this mechanism has been changed to coexist with a standard implementation of NEW and DISPOSE. This package implements the mechanism described in the Pascal-6000 Release 4 documentation chapter HEAP. 32 1 Pascal-6000 Internal Reference Manual 27 May 86 _____________________________________________ +4.5. MEMORY MANAGER ALGORITHMS AND DATA STRUCTURES The state of the memory manager is determined by several variables together with all the nodes in managed memory. These variables are as follows. var fl: memaddr; { TMEM+MEMFL } { program Field Length } ff: memaddr; { TMEM+MEMFF } { first free node in memory } lf: memaddr; { TMEM+MEMLF } { last free node in memory } hlf: memaddr; { TMEM+MEMHLF } { highest last free node } hfl: memaddr; { TMEM+MEMHFL } { highest field length } ml: markrange; { TMEM+MEMML } { current mark-level } The memory space that is managed runs from address ff up to fl-1. ff and fl are determined during the initialize operation; in addition, fl may increase during an allocate operation or it may decrease during a liberate or release operation. We will denote memory by a variable m. var m: array [memaddr] of word; There are at least two kinds of words in which we are interested. One is a node header -- i.e, the first word of a node. The other kind is a data word. The type and values of a data word are irrelevant to the memory manager. type wordkind = (dataword, nodehead); word = record case wordkind of dataword: ( { arbitrary } ) ; nodehead: ( size: memsize; { number of words in node } prev: memaddr; { address of adjacent node at lower address } mark: markrange; { the mark-level of this node } case free: Boolean of { indicates whether free or non-free } false: ( ); true: ( nextfree, { address of next free node } prevfree: { address of previous free node } memaddr ) ) { nodehead } end { word } ; The astute reader will recognize that a nodehead for a free node cannot fit in one 60-bit word. This is dealt with in the following ways. (1) The nextfree and prevfree links in a free node header actually occupy the second word of the node. (2) In order to make this possible in all situations, the smallest node that may be allocated has size = 2. (3) In order to define this in Pascal, a new wordkind is introduced to contain the nextfree and prevfree fields. Thus, the following more nearly reflects the physical structure. 33 1 Pascal-6000 Internal Reference Manual 27 May 86 type wordkind = (dataword, nodehead, freelink); word = record case wordkind of dataword: ( { arbitrary } ) ; nodehead: ( size: memsize; { number of words in node } prev: memaddr; { address of adjacent node at lower addres } mark: markrange; { the mark-level of this node } free: Boolean { indicates whether free or non-free } ) { nodehead } ; freelink: { occurs only immediately after a free nodehead } ( nextfree, { address of next free node } prevfree: { address of previous free node } memaddr ) { freelink } end { word } ; For convenience we define: function next(p: memaddr): memaddr; { m[p] must be a nodehead word. } begin next := p + m[p].size end { next } ; Let a be an address of a nodehead word in m (memory). Then the following are invariant over the memory manager operations (except initialize). (1) a = ff implies m[a].free and (m[a].size = 2) and not m[next(a)].free and (m[next(a)].size = 1) (2) a = lf implies m[a].free and (m[a].size = fl-lf-1) and not m[next(a)].free and (m[next(a)].size = 1) (3) a <> ff implies next(m[a].prev) = a (4) a <> fl-1 implies m[next(a)].prev = a (5) m[a].free implies (m[ m[a+1].prevfree + 1 ].nextfree = a) and (m[ m[a+1].nextfree + 1 ].prevfree = a) and (not m[next(a)].free) (6) m[a].free and (a <> ff) implies (m[a+1].prevfree < a) and (not m[ m[a].prev ].free) (7) a = ff implies (m[a+1].prevfree = lf) (1) provides that there is a dummy free node located at ff and that it is 34 1 Pascal-6000 Internal Reference Manual 27 May 86 followed immediately by a dummy non-free node of size 1. Similarly, (2) requires a dummy non-free node of size 1 at fl-1, immediately preceded at lf by a free node of size fl-lf-1. These four dummy nodes always exist. The two non-free dummy nodes are the only nodes that can exist with size = 1. (3) and (4) show that all of memory from ff up to fl-1 consists entirely of nodes that are linked together in both directions. (5) indicates that free nodes are also doubly linked, and that a free node is always immediately followed by a non-free node. One can deduce therefore that no two free nodes are ever immediately adjacent. Further, it is apparent that all free space immediately adjacent to fl is represented by the two dummy nodes at the high end of memory. (6) provides that the freelist is sorted by address -- the "previous" free node (prevfree) is at a lower address except at the ends of the list which, according to (7), is circular. This structure of the dummy nodes is schematically represented below. address free mark prev size prevfree nextfree fl-1 false 0 lf 1 . . . lf+1 ? ff lf+0 true 0 ? (fl-lf-1) . . . ff+2 false 0 ff 1 ff+1 lf ? ff+0 true 0 0 2 The algorithms and data structures are more clearly described by the following Pascal code. { PMM - Pascal-6000 Memory Manager } const maxaddr = 1310{71}; maxfl = maxaddr; { maximum fl for job. } ReduceAllowed = true; { program option, = $R+ . } minrequest = 512; { minimum words to be requested at one time. } minreduce = 512; { minimum words to be returned at one time. } quantum = 64; { operating system unit of memory allocation. } minsize = 2; { minimum size of non-dummy node. } maxmark = 31; { maximum depth of mark nesting. } type markrange = 0 .. maxmark; memaddr = 0 .. maxaddr; 35 1 Pascal-6000 Internal Reference Manual 27 May 86 memsize = memaddr; wordkind = (dataword, nodehead, freelink); word = record case wordkind of dataword: ( data: { arbitrary } integer ) ; nodehead: ( free: Boolean; { indicates whether free or non-free } mark: markrange; { the mark-level of this node } prev: memaddr; { address of adjacent node at lower addres } size: memsize; { number of words in node } ) { nodehead } ; freelink: { occurs only immediately after a free nodehead } ( nextfree, { address of free node following in freelist } prevfree: { address of free node preceeding this in freelist } memaddr ) { freelink } end { word } ; marker = record lev: markrange end; memory = array [memaddr] of word; var fl: memaddr; { lwa+1 of memory } ff: memaddr; { address of first free node } lf: memaddr; { address of last free node } hlf: memaddr; { highest value of lf } hfl: memaddr; { highest value of fl } ml: markrange; { current mark level } m: memory; { central memory } procedure AdjustFieldLength(newfl: memaddr); begin fl := newfl; if fl > hfl then hfl := fl end { AdjustFieldLength } ; procedure Initialize(low, high: memaddr); { Initialize memory manager to manage area between low and high. } begin { Initialize } ml := 0; { assume low + 6 <= high } ff := low; lf := ff+3; hlf := lf; hfl := 0; AdjustFieldLength(high); with m[ff] do begin 36 1 Pascal-6000 Internal Reference Manual 27 May 86 free := true; size := 2; prev := 0; mark := 0 end; with m[ff+1] do begin nextfree := lf; prevfree := lf end; with m[ff+2] do begin free := false; size := 1; prev := ff; mark := 0 end; with m[lf] do begin free := true; size := fl-lf-1; prev := ff+2; mark := 0 end; with m[lf+1] do begin nextfree := ff; prevfree := ff end; with m[fl-1] do begin free := false; size := 1; prev := lf; mark := 0 end; end { Initialize } ; function next(p: memaddr): memaddr; { returns address of next node after p. Assumes p is address of a header word. } begin next := p + m[p].size end { next } ; function Allocate(s: memsize; var actsize: memsize): memaddr; { Allocate at least s words (plus PMM header); return actual size of space in actsize and the FWA of the space as the function result. } var p1, p2, p3: memaddr; need, excess: memsize; begin { Allocate } { add one to size for node header word } s := s + 1; { ensure minimal node size } if s < minsize then s := minsize; { search free list } p1 := m[ff+1].nextfree; m[lf].size := s; while m[p1].size < s do p1 := m[p1+1].nextfree; m[lf].size := fl - lf - 1; { check for use of last free node } if p1 = lf then begin if m[lf].size < s + minsize then begin { expand last free node } need := s+minsize - m[lf].size; 37 1 Pascal-6000 Internal Reference Manual 27 May 86 need := ((need-1) div quantum + 1) * quantum; { (need mod quantum = 0) and (need >= s+minsize-m[lf].size) } if need > maxfl-fl then Halt(' Memory required exceeds specified MFL.'); if need < minrequest then { need := min( minrequest, maxfl-fl ) } if minrequest < maxfl-fl then need := minrequest else need := maxfl-fl; AdjustFieldLength(fl + need); m[lf].size := fl-lf-1; m[fl-1] := m[fl-1-need]; { move dummy last node up. } end; lf := lf + s; { address of last free after current one gets split } if lf > hlf then hlf := lf end; { Allocate a node } { m[p1].size >= s } p2 := m[p1+1].prevfree; excess := m[p1].size - s; if excess < minsize then begin { use all of node p1 } m[p2+1].nextfree := m[p1+1].nextfree; m[m[p1+1].nextfree+1].prevfree := p2 end else begin { split node p1 } p3 := p1 + s; { fwa of new free node } { link p3 into free list. } m[p3+1] := m[p1+1]; { copy nextfree and prevfree. } m[p2+1].nextfree := p3; m[m[p3+1].nextfree+1].prevfree := p3; { link p3 into node list. } m[next(p1)].prev := p3; with m[p3] do begin size := excess; prev := p1; free := true; mark := 0 end; m[p1].size := s; end; m[p1].free := false; m[p1].mark := 0; actsize := m[p1].size; Allocate := p1+1 end { Allocate } ; procedure CheckMemoryReduction; { Returns memory to the operating system if enough is available. } var residue: 0..quantum; reduction: memsize; begin { CheckMemoryReduction } if ReduceAllowed then begin residue := (fl-lf-3) mod quantum; reduction := (fl-lf-3) - residue; if reduction >= minreduce then begin m[lf].size := residue+2; 38 1 Pascal-6000 Internal Reference Manual 27 May 86 m[fl-reduction-1] := m[fl-1]; { move dummy last node down. } AdjustFieldLength(fl-reduction); end end end { CheckMemoryReduction } ; procedure Liberate(p: memaddr); { Cause the non-free node starting at address p to become free. } var p1, p2: memaddr; begin { Liberate } { check p for validity. } p1 := m[p].prev; p2 := next(p); if (p <= ff) or (p >= lf) then Halt(' Inconsistent node reference.'); if m[p2].prev <> p then Halt(' Inconsistent node reference.'); if next(p1) <> p then Halt(' Inconsistent node reference.'); if m[p].free then Halt(' Inconsistent node reference.'); if m[p2].free then begin if m[p1].free then begin m[p1+1].nextfree := m[p2+1].nextfree; p := p1 end else begin m[p+1] := m[p2+1]; m[m[p2+1].prevfree+1].nextfree := p; m[p].free := true end; m[p].size := next(p2) - p; m[m[p2+1].nextfree+1].prevfree := p; m[next(p2)].prev := p; if p2 = lf then { combined with last free node } begin lf := p; CheckMemoryReduction end end else if m[p1].free then begin { p1 <> ff } m[p1].size := p2 - p1; m[p2].prev := p1; p := p1 end else { neither next nor previous node is free } begin p1 := ff; { search free list for place to insert. } while m[p1+1].nextfree < p do p1 := m[p1+1].nextfree; p2 := m[p1+1].nextfree; { (p1 < p) and (p < m[p1+1].nextfree) } m[p2+1].prevfree := p; m[p+1].nextfree := p2; m[p+1].prevfree := p1; m[p1+1].nextfree := p; m[p].free := true; end; end { Liberate } ; 39 1 Pascal-6000 Internal Reference Manual 27 May 86 procedure Mark(var x: marker); { Start a new mark level, and return the marker that identifies it. } begin { Mark } if ml = maxmark then Halt(' Maximum mark level exceeded.'); ml := ml + 1; x.lev := ml end { Mark } ; procedure Release(x: marker); { Reset mark-level (ml) to x.lev-1, and liberate all nodes having mark > ml. } var p1, p2: memaddr; begin { Release } ml := x.lev - 1; p1 := ff; while p1 <> lf do begin p2 := next(p1); { assume m[fl-1].mark = 0 } while m[p2].free or (m[p2].mark > ml) do begin if not m[p2].free then m[p2+1].data := 0; { zero out pointer-test word. } p2 := next(p2) end; if p2 <> next(p1) then { previous loop got entered } begin m[p1].size := p2 - p1; m[p2].prev := p1 end; if p2 > lf then { last free node was enlarged. } begin lf := p1; m[lf+1].nextfree := ff; m[ff+1].prevfree := lf; CheckMemoryReduction end else begin { (m[p2].mark <= ml) and not m[p2].free and (p2 < lf) } repeat p2 := next(p2) until m[p2].free or (m[p2].mark > ml); m[p2].free := true; m[p1+1].nextfree := p2; m[p2+1].prevfree := p1; p1 := p2 end end end { Release } ; 40 1 Pascal-6000 Internal Reference Manual 27 May 86 __________ +REFERENCES (1) "The Design of a Pascal Compiler" by Niklaus Wirth. "Software Practice and Experience", (1:4), 1971. [Describes the design steps taken to implement and test the first Pascal compiler on the CDC 6400. Code generation and performance information is also given.] (2) "On Pascal, Code Generation, and the CDC 6000 Computer" by Niklaus Wirth. Stanford University, "Computer Science Dept. Technical Report" No. 257, February, 1972. (also NTIS No. PB208519.) [general comments about the first implementation of Pascal on the CDC 6400 computer, with an assessment of the hardware architecture from the point of view of compiling.] (3) "On Code Generation in a Pascal Compiler" by Urs Ammann. "Software Practice and Experience", (7:3), June-July, 1977, pp 391-423. [Originally appeared as an E. T. H. Technical Report in March, 1976. A description of the run-time organization of data and the use of hardware registers in the second CDC-6000 implementation of Pascal. The work was completed in Spring, 1974. Details are given for register-remembrance strategies and local optimization.] (4) "Yet Another Look at Code Generation for Pascal on CDC-6000 and Cyber Machines" by Lawrence Liddiard. "Pascal Newsletter", No. 7, February, 1977, pp 17-23. [A project to reduce the memory requirements of the Pascal compiler for interactive use at the University of Minnesota led to substantial savings in 13 areas of the compiler. Experience from the MNF FORTRAN compiler shows that even further improvements are possible, especially in code-generation procedures.] (5) "The Zurich Implementation" by Urs Ammann. "Pascal--The Language and its Implementation", Wiley, 1978. [A history of the CDC-6000 Pascal compiler is given with a description of syntax-analysis and error-recovery procedures, semantic-analysis, and the treatment of context-sensitive errors. The internal representation of Pascal data structures, identifiers, and their associated attributes are also discussed.] (6) "Error Recovery in Recursive Descent Parsers" and "Run-Time Storage Organization" by Urs Ammann. "E. T. H., Institut fuer Informatik Techical Report No. 25", May, 1978, 46 pages. [The first paper discusses an effective method of error recovery adaptable to recursive descent parsers with examples from the Pascal-6000 compiler. The second paper surveys the various approaches to dynamic data storage supported by a language like Pascal; examples are given.] 41 1 Pascal-6000 Internal Reference Manual 27 May 86 _______ +HISTORY The first CDC Pascal processors were compile-to-core versions which contained their own loader and library. They were developed by the Computer Science Department of E. T. H. (Federal Institute of Technology) in Zuerich, Switzerland during 1970 to 1972. These compilers were referred to by the dates of their release (e.g. Pascal-Dec.72), or as Pascal 6000-3.2, or as PASCAL1. When the revised report for Pascal was published in 1972, work began on a new compiler which was called Pascal 6000 3.4 and PASCAL2. The compiler was released after the project was completed in 1974. Urs Ammann was chief implementor, and was aided by Kathleen Jensen, Helmut Sandmayr, and Niklaus Wirth. This compiler (which we will refer to as Pascal-6000 Release 1) generated standard relocatable binaries and so was compatible with CDC loaders. Release 2 of Pascal-6000 appeared in early 1976 after work done by Urs Ammann, and Svend Knudsen of E. T. H., Zuerich and John Strait of the University of Minnesota. Other individuals aided with reports of bugs detected in Release 1. In January of 1977, the University of Minnesota Computer Center assumed maintenance of Pascal-6000 in a signed agreement with E. T. H., Zuerich. Our efforts were directed towards an improved compiler and run-time system, as well as enhanced library, tools, documentation, and installation procedures. Release 3 of Pascal-6000 was previewed by 11 sites for testing in August 1978. It was officially released in January 1979. In October 1981, the International Organization for Standardization (ISO) reached consensus on an international standard for the programming language Pascal. We then worked to bring Pascal-6000 into compliance with the ISO standard, supported in part by a development contract with Control Data Corporation. Control Data Corporation has a non-exclusive right to distribute the resulting processor, which CDC calls Pascal 170 Version 1.1. We have subsequently made numerous refinements to Pascal-6000. The compiler is the property of the Institut fuer Informatik, E.T.H., Zuerich, Switzerland. 42 1 Pascal-6000 Internal Reference Manual 27 May 86 The following list summarizes the releases of the current compiler and their updates. May 1974 Release 1 Urs Ammann. Original Release implementing the revised Pascal report. Known as Pascal 6000-3.4. Generate relocatable code; remember registers. 1974-1975 Updates 1-10 Urs Ammann. Correct errors. Mar 1976 Release 2 Urs Ammann and John P. Strait. Improve performance and provide a summary of diagnostics. 1976 Updates 1-2 Urs Ammann. Correct errors. Jan 1977 Maintenance assumed by Andy Mickel and John P. Strait. Jan 1979 Release 3 John P. Strait. Implement changes which will become standard: new type-compatibility rules, etc. Improve run-time checks, usability; correct errors. Jun 1979 Update 1 John P. Strait. Correct errors. Apr 1980 Update 2 Andy Mickel. Correct errors. Oct 1981 Update 3 Rick L. Marcus. Error corrections, small performance changes. Feb 1982 Update 4 Daniel E. Germann. Correct errors. Jun 1984 Release 4 Dave Bianchi, Daniel E. Germann, Andy Mickel, and Jim Miner. Implement changes for ISO 7185 Pascal standard; correct errors; add memory management and other enhancements. May 1986 Version 4.1 Dave Bianchi, Jim Miner. | Add: command parameters, CMM interface, | extensions, library routines; correct errors; | simplify installation. | Other contributors included: Carsten Koch | (DHI), R. V. van Zanten (SARA), Patrick Ward | (UMTL), and Larry Daasch and Mike Frisch | (MINN). | 43 1 Pascal-6000 Internal Reference Manual 27 May 86 The original version of the run-time system was authored by: H. Sandmayr circa June 1974. N. Wirth circa June 1974. S. Knudsen circa March 1976. The run-time system was rewritten for Release 3 by: J. P. Strait January 20, 1977. J. J. Drummond January 20, 1977. Major revisions and enhancements were made to the run-time system for Release 4 by: D. J. Bianchi 1982..1984. D. E. Germann 1982..1983. J. F. Miner 1982..1984. The revisions necessary to run Pascal-6000 under SCOPE 2 (mainly revisions to the run-time system) were performed by the following persons. H. Joraandstad (CERN) Release 1, October 1975. A. P. Hayes (MNCH) Release 2, October 1976. A. G. Hay (MNCH) Release 3, January 1980. D. J. Legge (MNCH) Release 4, March 1983. These revisions were integrated into the regular Pascal-6000 installation procedures by Dave Bianchi and Jim Miner in October 1983. Many other people from around the world have contributed improvements to Pascal-6000. 44