Oberon || Library || Module Index || Search Engine || Definition || Module

Ulm's Oberon Library:


Compilers - general interface for two-pass compilers


TYPE Result = POINTER TO ResultRec;
TYPE ResultRec =
         header: CompilerObjects.Header;
         object: CompilerObjects.Object;

TYPE Compiler = POINTER TO CompilerRec; TYPE CompilerRec = RECORD (Services.ObjectRec) END;

TYPE Context = POINTER TO ContextRec; TYPE ContextRec = RECORD (Disciplines.ObjectRec) keys: CompilerKeys.Set; mtab: CompilerObjects.ModuleTable; tab: ModularizedStructures.ObjectTable; db: CompilerDatabases.Database; cachemode: CompilerObjects.CacheMode; log: CompilerLogs.Log; END;

TYPE Pass1Proc = PROCEDURE (compiler: Compiler; context: Context; source: CompilerSources.Source; VAR definition, module: Result) : BOOLEAN; TYPE Pass2Proc = PROCEDURE (compiler: Compiler; context: Context; definition, module: CompilerObjects.Object; arch: Architectures.Architecture; updatesPermitted: BOOLEAN; VAR archdef, code: Result; errors: RelatedEvents.Object) : BOOLEAN; TYPE DefineArgsProc = PROCEDURE (compiler: Compiler; args: Args.Arguments); TYPE Pass1Interface = POINTER TO Pass1InterfaceRec; TYPE Pass1InterfaceRec = RECORD (Objects.ObjectRec) pass1: Pass1Proc; defineArgs: DefineArgsProc; (* may be NIL *) END; TYPE Pass2Interface = POINTER TO Pass2InterfaceRec; TYPE Pass2InterfaceRec = RECORD (Objects.ObjectRec) pass2: Pass2Proc; defineArgs: DefineArgsProc; (* may be NIL *) END;

PROCEDURE Init(compiler: Compiler; if: Pass1Interface); PROCEDURE Register(compiler: Compiler; arch: Architectures.Architecture; if: Pass2Interface);

PROCEDURE DefineArgs(compiler: Compiler; args: Args.Arguments);

PROCEDURE CreateCopyOfContext(VAR newcontext: Context; orig: Context); PROCEDURE SynchronizeContext(context, ext: Context);

PROCEDURE Pass1(compiler: Compiler; context: Context; source: CompilerSources.Source; VAR definition, module: Result) : BOOLEAN;

PROCEDURE Pass2(compiler: Compiler; context: Context; definition, module: CompilerObjects.Object; arch: Architectures.Architecture; updatesPermitted: BOOLEAN; VAR archdef, code: Result; errors: RelatedEvents.Object) : BOOLEAN;

PROCEDURE Supported(compiler: Compiler; arch: Architectures.Architecture) : BOOLEAN;

PROCEDURE GetSupportedArchitectures(compiler: Compiler; VAR it: Iterators.Iterator);


Compilers provides a general interface for two-pass compilers. The first pass is strictly architecture-independent and its results may be passed in case of success to one of the back-ends that generate code for a selected architecture.

This interface supports the separation of interface descriptions (called definitions) from module implementations (called modules) as known by Modula-2 and classic Oberon. Variants where both, the interface and its implementation, are derived from one source (as in newer variants of Oberon) are supported as well.

Program texts are represented by CompilerSources. Note that source objects have already their compilation options associated with. Modules that create source objects for a particular compiler are obliged to include all possible compilation options into their set of options using DefineArgs.

A compilation process is set into a context that consists of

Contexts can be cloned using CreateCopyOfContext and a branch can be synchronized back using SynchronizeContext. Note, however, that synchronization requires both contexts to be compatible to each other. Otherwise an assertion will fail. Cloning and resynchronization is useful if an attempt is to be made to load an imported module and where in case of failures the original context should remain unchanged.

Compilation results are of type Result and consist of a header object (CompilerObjects.Header) and an object that represents the entire result (CompilerObjects.Object).

Using a compiler

Pass1 passes source to compiler, and returns in case of a successful compilation architecture-independent results in definition and/or module. The to be expected results depend on the source kind (CompilerSources.SourceKind) of source:
Just definition will be returned, module is set to NIL.
Just module will be returned, definition is set to NIL.
Both, definition and module will be returned and are non-NIL.

Pass2 generates, if successful, compilation results for the architecture arch. If just an architecture-dependent definition object is to be generated, an architecture-independent definition is to be given and module is to be set to NIL. For the generation of machine code (represented by the code result object) definition and module must be non-NIL where definition may be either architecture-independent, or, if it already available for arch, architecture-dependent. Pass2 is allowed to update a architecture-dependent definition if updatesPermitted is TRUE. However, if updates are permitted, definition must neither be a member of context.mtab and its key must not be a member of context.keys. Note that updatesPermitted must be set to TRUE if definition is architecture-independent.

Supported return TRUE if arch is supported by compiler. The list of supported architectures by a compiler can be retrieved using GetSupportedArchitectures.

Implementing a compiler

For each compiler an architecture-independent pass has to be implemented. Its interface is of type Pass1Interface which is to be passed to Init. Afterwards, the architecture-dependent passes of a compiler can be registered by Register using an interface of type Pass2Interface. Both interfaces consist of an interface procedure similar to the signatures of Pass1 and Pass2 which share the same semantics. In addition, an optional interface procedure defineArgs can be defined or set to NIL. This interface procedure, if non-NIL, can be used to register compilation flags and options to args (see Args).


In case of failures, Pass1 relates all errors to source while Pass2 related all errors to errors (see RelatedEvents). As long as errors are genuine compilation errors, they are of type CompilerErrors.Error. However, occasional errors related to the compiler database or access to source objects may result in other error objects. Pass1 and Pass2 return TRUE in case of success and FALSE in case of failures.


classification of hardware architectures and operating systems
general abstraction for flags and options
interface to a persistent database where sources and compilation results are found and stored to
standardized events for compilation errors
keys that identify dependencies of compiler-generated objects
filter and formatting tool for logs of compilation processes
base type for compiler objects that represent compiler results and header structures
objects that represent program text sources
modularized byte sequences of persistent objects
implementation of this interface for Oberon
general object loader on base of Compilers

Edited by: borchert, last change: 2004/06/24, revision: 1.1, converted to HTML: 2004/06/24

Oberon || Library || Module Index || Search Engine || Definition || Module