This file documents the mechanism how information is transferred from the exporting Modules and Units to the Program, Module or Unit which imports (uses) the information.
The GPI mechanism is not (yet :-) as stable as it should be. If you encounter problems with your Modules or Units, please do the following:
A GPI file contains a precompiled GNU Pascal Interface. "Precompiled" means in this context that the Interface already has been parsed (i.e the front-end has done its work), but that no assembler output has been produced yet.
The GPI file format is an implementation-dependent (but not too implementation-dependent ;-) file format for storing GNU Pascal Interfaces to be exported--Extended Pascal and PXSC module interfaces as well as interface parts of Borland Pascal Units compiled with GNU Pascal.
To see what information is stored in or loaded from a GPI file, run
GPC with an additional command-line option --debug-gpi
. Then, GPC
will write a human-readable version of what is being stored/loaded
to stderr.
While parsing an Interface, GPC stores the names of exported objects
in tree lists--in gpc-parse.y, the bison (yacc) source of GPC's parser,
search for handle_autoexport
. At the end of the Interface, everything
is stored in one or more GPI files. This is called in gpc-parse.y--search
for create_gpi_files ()
.
Everything else is done in gpc-module.c. Here you can find the source
of create_gpi_files () which documents the file format: First, a header
of 33 bytes containing the string GNU Pascal Module/Unit Interface\n
is stored, then the name of the primary source file of the module as a
string, then the name of the exported interface as a tree node (see
below), after that all exported names in the order as they were stored
while parsing.
The names and the objects (i.e. constants, data types, variables and
functions) they refer to are internally represented as so-called
tree nodes as defined in the files tree.h and tree.def from the GCC
source (i.e. the source of the GNU C compiler). The names are stored
as IDENTIFIER_NODE
s, their meanings as IDENTIFIER_GLOBAL_VALUE
s
of these nodes. The main problem when storing tree nodes is that they
form a complicated tree in memory with a lot of circular references
making it hard to decide which information must be stored and which
mustn't.
The functions load_tree and store_tree are intended to load/store a tree node in a GPI file.
Each tree node has a TREE_CODE
indicating what kind of information
it contains. Each different tree node must be stored in a different
way. See the source of load_tree
and store_tree
for details.
Most tree nodes contain pointers to other tree nodes; therefore
load_tree
and store_tree
are recursive functions.
The --debug-gpi
debugging informations contains the recursion
level in parantheses, e.g. loaded (2):
means that the loaded
information was requested by a pointer contained in a tree node
requested by a pointer contained in a tree node representing an
exported symbol.
Since this recursion can be circular (think of a record containing
a pointer to a record of the same type), we must resolve references
to tree nodes which already have been loaded. For this reason, and
for saving disk space, I have introduced a gpi_contents
list
containing pointers to all nodes so far loaded from / stored in the
GPI file under consideration. When storing a node which already is
in the gpi_contents list, a (normally invalid) TREE_CODE
of 255
`(0xFF)' followed by the (int) index of the node in the
gpi_contents
list is stored instead. Like this, the reference
uses 1 byte plus the size of an int (normally 4) in the GPI file.
In the debugging information, this method of storing/loading is
indicated as via gpi_contents
.
There are some special tree_nodes (e.g. integer_type_node
or
NULL_TREE
) which are used very often. I have assigned (normally
invalid) unique TREE_CODES
for them, so they can be stored in a
single byte.
That's it. Now you should be able to "read" GPI files using GPC's
--debug-gpi
option. If you encounter a case where the loaded
information differs too much from the stored information, you
have found a bug--congratulations! What "too much" means, depends
on the object being stored in / loaded from the GPI file. Remind
that the order things are loaded from a GPI file is the reversed
order things are stored when considering different recursion levels,
but the same order when considering ths same recursion level.