At the centre of most Fortran systems is some form of relocatable binary subroutine enabling subroutines which have previously been compiled to be used again without subsequent recompilation. To be satisfactory, such a form must retain sufficient symbolic content from the original Fortran routine to enable cross references between subroutines to be made. A further development is to allow array storage to be allocated at load time, in order to avoid recompilation just because data alters the sizes and shapes of arrays. These requirements are all satisfied in the system of relocatable binary subroutines used on Atlas. It is known as BAS or in full Binary and Arbitrarily Symbolic. The particular form of BAS used in conjunction with the S3 Fortran compiler on Atlas 2 is a development of that used originally with the NIRNS Fortran compiler on Atlas 1.
This note describes the BAS form of each routine as it exists in store immediately after relocation, and the subsequent processing of that routine. Descriptions will be found elsewhere (eg. "Fortran Loader on Atlas Two") of the external binary card format generally used, and of the complete system.
Each BAS routine is introduced by a symbolic program card which states
Item (e) is used only to check the validity of the loading of a series of routines. It will not be discussed further in this paper.
It is also possible for the program card to contain other information of interest to the user. Any such information is not inspected by the loader.
The basic routine is augmented by up to three special tables. These tables are known as the Routine Symbol Table (RST) , the Parameter Use Table (PUT) and the External Reference Table (ERT). The tables occur in the order given, and follow the routine itself, with no gaps in between.
They normally form part of the relocatable binary card sequence, and are initially loaded and relocated, just like the routine itself and immediately following it in store. The next routine will, when loaded, overwrite the tables of the preceding routine.
The RST is used to define auxilliary symbols which are to have significance outside this routine, for example, a subsidiary entry point. It can be used similarly for private symbols.
Each entry occupies two full words and consists of an 8 character name followed by two halfwords. The first specifies the length to be associated with the symbol, and gives its node in the octal fraction. Possible modes are; 0 private, 1 public, 2 global, 3 block. The second halfword gives the value to be associated with the symbol name.
The length of the RST was defined on the program card.
This table provides a means for the evaluation at load time of various quantities, and of inserting these values in the program. A null table is indicated by an empty full word.
Each entry in the table starts at a whole word address, and consists of a list of parameters to be multiplied together, and a list of addresses into which the product is to be added or subtracted. The product may consist of just one parameter. Each parameter may be specified explicitly (high half zero), by address (high half 0.1) or by name. The product list is terminated by a number with even low half. Whilst this restricts the use of parameter names, the limitation is not felt by existing Fortran compilers.
The address list consists of one halfword per member. Each halfword contains an address. If the address is flagged odd, the contents of the specified halfword is reduced by the product value. Otherwise it is augmented by that value. The address list is terminated by a negative marker halfword. The last PUT entry has the marker halfword even. For all other entries it is odd.
This table indicates the positions of every halfword to be adjusted because of store assigned at load time. It is used for private arrays, public arrays and routine calls. An empty ERT is indicated by a zero full word.
Each entry starts at a whole word address and begins with the 8 character name of a symbol. The next halfword gives the expected length (zero if a routine) and mode associated with the required symbol. The mode, may be 0 (private), 1 (public), 2 (global), 3 (block).
In the case of arrays with parametric length, difficulty in compiler production of the BAS tables may be overcome by preceding an entry by a special full word whose high half is zero and whose low half contains the address of a quantity to be added into the length mode cell of the next entry proper. In the case of the NIRNS compiler the RST is used. This device is not used by the AWRE S3 compiler.
Each entry heading is followed immediately by a list of addresses into which the value of the symbol referred to is to be added. Each list is terminated just like the PUT entries, i.e. by a negative halfword. The last ERT entry has the marker half word even. For all other entries it is odd.
In order to describe the processing properly, it is necessary to explain the form of the Loader Symbol Table (LST). This table is of computed entry type, and has room for a total of 2048 entries. Each entry consists of two full words, the first containing the 8 character name, whilst the second is regarded in two halves. The first half word contains the length and mode, where the mode = 0 (parameter), 1 (public), 2( global), 3( block). The second half word contains the value of the symbol.
The LST has an initial state such that the first word of each position is clear. An entry can be deleted (by *RENAME or when a chapter of a chain job is completed). A deletion is marked by the first half of the keyword being all ones (-0.1).
When a symbol which is not defined is referred to, it is necessary for the loader to remember the symbol name and its address list until the references can be satisfied. The LST entry for an undefined symbol consists of its name in the usual way, but the length is flagged negative. The value is replaced by a (negated) pointer to the Forward Reference Table (FRT). The FRT is stored just below the library area, and is used in descending order. Each entry consists of a list of addresses (as in the ERT) and is terminated by a negative halfword. The terminator, when negated, points to the next FRT entry for the current symbol. The end of a string of entries is marked by the terminator J4.
A note is kept of the next available position in the FRT. No attempt is made to condense the table. To speed library searches, a count of the number of required symbol values is maintained.
The PUT is the first of the BAS tables to be processed. Its start is given by summing the length of the routine and twice the number of entries in the RST. Since the PUT is processed first, it can, and often does, modify the RST and ERT.
The processing method is generally clear from the description of the form. However when a parameter is specified by name, the name is first compared, with those in the RST. If this search fails, then the main LST is consulted.
The ERT is the second table to be processed. Private arrays are assigned storage and the first address of the array added to the specified locations. All other symbol names are referred to the LST. If they are already defined, then the modes are checked for compatibility. The mode specified in the ERT must never be greater than that in the LST. If the check is passed, then the value of the symbol as given in the LST is added to the specified locations.
When a symbol value is not defined, and the ERT indicates an array (length non-zero) then store is immediately assigned in the appropriate region, and the value inserted in the LST and added to the specified locations. If the length is zero, then an entry is made in the LST (if one was not there already) and a pointer to the ERT inserted. The list of addresses in the ERT is copied across to the FRT.
Note that if a routine is being loaded into the global region, then any symbols of mode public in the ERT are automatically upgraded to global status.
The last table to be processed is the RST. All symbols other than private ones are inserted into the LST, together with their modes and values. If they are already there, they should be undefined and the corresponding forward reference chain is processed. If the routine is being loaded into the global region, then RST symbols are forced to global mode. Otherwise they are of public mode. The main entry point to the routine is processed in the same way as the RST entries.