% Copyright (C) 1989, Digital Equipment Corporation % All rights reserved. % See the file COPYRIGHT for a full description. % % Last modified on Tue Jul 10 02:33:45 1990 by muller % modified on Thu Feb 22 08:58:12 1990 by kalsow \chapter{How to use the system} This section describes each of the tools in the \srcmodula distribution and how to use them. Briefly, the tools include a compiler, a linker, a pretty printer, a profiler and an inter-module dependency checker. See also chapter~\ref{local} for tools that are local to your installation. \section{Compiling} %================== To compile a \modula program, invoke \verb|m3|(1). This driver is much in the style of \verb|cc|(1); the output is an object file or an executable program, according to the options. \verb|m3| parses the command line and invokes the compiler and linker as required. \verb|m3| tells the compiler where to seek imported interfaces and where to find the \modula runtime library. Arguments ending in \verb|.m3| or \verb|.i3| are assumed to name Modula-3 source files to be compiled. Arguments ending in \verb|.mo|, \verb|.io| or \verb|.o| are assumed to name object files, possibly created by other language processors, that are to be linked with the object files created by \verb|m3|. Arguments ending in \verb|.mc|, \verb|.ic|, or \verb|.c| are assumed to name C source files to be compiled. Arguments ending in \verb|.ms|, \verb|.is|, or \verb|.s| are assumed to name assembly language files to be translated into object files by the assembler. Arguments starting with \verb|-| specify compiler options. Other arguments are assumed to name library files, and are simply passed along to the linker. The source for a module named \verb|M| is normally in a file named \verb|M.m3|. The source for an interface named \verb|I| must be in a file named \verb|I.i3|. The main program is the module that implements the interface \verb|Main|. There are options to compile without linking, stop compiling after producing C, emit debugger symbols, generate profiling hooks, retain intermediate files, override search paths, select non-standard executables for the various passes, and pass arguments to individual passes. For the full details, see the \verb|m3|(1) man page. In a source file, an occurrence of \verb|IMPORT Mumble| causes the compiler to seek an interface named \verb|Mumble|. The compiler will step through a sequence of directories looking for the file \verb|Mumble.i3|. It will parse the first such file that it finds, which is expected to contain an interface named \verb|Mumble|. If no file \verb|Mumble.i3| exists, or if the parse fails, the compiler will generate an error. The particular sequence of directories to be searched is determined by the options passed to \verb|m3|. See the \verb|m3(1)| manual page for full details. \section{An example} %=================== Here's a simple program composed of a main module, an imported interface and its implementation. \noindent In the file \verb|Main.m3|: \begin{verbatim} MODULE Main; IMPORT A; BEGIN A.DoIt (); END Main. \end{verbatim} \noindent In the file \verb|A.i3|: \begin{verbatim} INTERFACE A; PROCEDURE DoIt (); END A. \end{verbatim} \noindent In the file \verb|A.m3|: \begin{verbatim} MODULE A; IMPORT Wr, Stdio; PROCEDURE DoIt () = BEGIN Wr.PutText (Stdio.stdout, "Hello world.\n"); Wr.Close (Stdio.stdout); END DoIt; BEGIN END A. \end{verbatim} \noindent And finally, in \verb|Makefile|: \begin{verbatim} OBJECTS = Main.mo A.io A.mo M3FLAGS = -g program: $(OBJECTS) m3 -o program $(OBJECTS) .SUFFIXES: .m3 .mo .i3 .io .m3.mo: ; m3 -c $(M3FLAGS) $*.m3 .i3.io: ; m3 -c $(M3FLAGS) $*.i3 \end{verbatim} If \srcmodula is installed properly, running \verb|make| will compile the three compilation units and link them with the standard libraries. The result will be left in the executable file named \verb|program|. \section{Language restrictions} %------------------------------ With a few exceptions, \srcmodula implements the \modula language as defined in the revised report of November 1989. Send a note to \verb|m3-request@src.dec.com| to receive paper copies of the report. A PostScript version of the report is available via {\tt ftp}; see section 4.1. \paragraph{Arithmetic checking.} \srcmodula does not generate any special checking for arithmetic overflow or underflow. You get whatever checking your C compiler gives you. We decided that the runtime checking was too expensive in a compiler that was constrained to produce C. Future versions of this compiler that generate native machine code will perform the checking. \paragraph{Packed types.} Packed types are restricted. \verb|BITS n FOR T| is treated as \verb|T| everywhere except when applied to a field of an ordinal type in a record. In that case, the field is implemented by a {\em field} of width \verb|n| in a C{} \verb|struct|. Otherwise, a \modula field is implemented as a {\em member} of a C{} \verb|struct|. Consequently, the C representation of a packed field cannot span word boundaries and padding may be added by the C compiler to respect this constraint. \paragraph{Stack overflow checking.} \srcmodula does not reliably detect thread stack overflows. Stacks are only checked for overflow on procedure entry. No checking is done on external procedures. Thread stacks are allocated in fixed size chunks. The required \verb|Thread| interface has been augmented with the |SizedClosure| type to allow arbitrary sized stacks. The default size is given by \verb|Thread.DefaultStackSize|, \paragraph{Exception semantics.} \srcmodula uses C's {\tt setjmp}/{\tt longjmp} mechanism to unwind the stack when raising an exception. A problem can occur: assignments may appear to be undone. For example, consider \begin{verbatim} TRY i := 3; P (); EXCEPT E: j := i; END; \end{verbatim} where {\tt P} raises exception {\tt E}. The compiler generates a {\tt setjmp} at the beginning of the try statement. If the C compiler allocates variable {\tt i} to a register, the assignment of {\tt 3} may be lost during the {\tt longjmp} and branch that gets to the handler. \section{Language extensions} %---------------------------- \srcmodula implements some features not defined in the \modula report. \paragraph{Inlined procedures.} The compiler recognizes the \verb|<*INLINE*>| pragma before procedure declarations. The pragma is allowed in interfaces and modules. At the moment, \srcmodula ignores the pragma. Future versions will implement inline procedures. For example: \begin{verbatim} INTERFACE X; <*INLINE*> PROCEDURE P (i: INTEGER); <*INLINE*> PROCEDURE Q (); END X. \end{verbatim} declares \verb|X.P| and \verb|X.Q| to be inlined procedures. \paragraph{External language interface.} The compiler also recognizes the \verb|<*EXTERNAL*>| pragma. The pragma may appear immediately prior to a variable or procedure declaration. A variable or procedure that is declared to be external is assumed to be implemented outside the \modula world. The names of external procedures and variables are passed through to the C compiler unchanged. The types of external variables and the formals to external procedures are assumed to be correct and are not checked against their external implementation. Standard calling conventions are used when calling external procedures. For example: \begin{verbatim} INTERFACE OS; <*EXTERNAL*> VAR errno: INTEGER; <*EXTERNAL*> PROCEDURE exit (i: INTEGER); END OS. \end{verbatim} allows importers of \verb|OS| to access the standard \unix symbols \verb|errno| and \verb|exit| through the names \verb|OS.errno| and \verb|OS.exit| respectively. If several variables are declared within a single \verb|<*EXTERNAL*> VAR| declaration, they are all assumed to be external. The external pragma may optionally specify a name different from the \modula name. The form \verb|<*EXTERNAL |id\verb|*>| will use ``id'' as the external name and the form \verb|<*EXTERNAL "|s\verb|"*>| will use the text literal ``s'' as the external name. For example: \begin{verbatim} INTERFACE Xt; <*EXTERNAL "_XtCheckSubclassFlag" *> PROCEDURE CheckSubclassFlag (...); ... \end{verbatim} defines a procedure named \verb|Xt.CheckSubclassFlag| in \modula and named \verb|_XtCheckSubclassFlag| in the generated C. %%% Procedures declared as external within a module cannot include a body. \paragraph{The character type.} The report defines \verb|CHAR| as an enumeration of at least 256 elements that includes the ISO-Latin-1 alphabet. The report gives a lexical method for naming each of the elements of the enumeration (e.g. \verb|'A'| or \verb|'\012'|). Unfortunately the report does not give names to the elements of this enumeration. \srcmodula defines these names: \begin{quote} \begin{tabular}{lllllllllll} name & value & & name & value & & name & value & & name & value \\ \hline NUL & \verb|\000| & & SOH & \verb|\001| & & STX & \verb|\002| & & ETX & \verb|\003| \\ EOT & \verb|\004| & & ENQ & \verb|\005| & & ACK & \verb|\006| & & BEL & \verb|\007| \\ BS & \verb|\010| & & HT & \verb|\011| & & NL & \verb|\012| & & VT & \verb|\013| \\ NP & \verb|\014| & & CR & \verb|\015| & & SO & \verb|\016| & & SI & \verb|\017| \\ DLE & \verb|\020| & & DC1 & \verb|\021| & & DC2 & \verb|\022| & & DC3 & \verb|\023| \\ DC4 & \verb|\024| & & NAK & \verb|\025| & & SYN & \verb|\026| & & ETB & \verb|\027| \\ CAN & \verb|\030| & & EM & \verb|\031| & & SUB & \verb|\032| & & ESC & \verb|\033| \\ FS & \verb|\034| & & GS & \verb|\035| & & RS & \verb|\036| & & US & \verb|\037| \\ SP & \verb|\040| & & DEL & \verb|\177| & & \end{tabular} \end{quote} Hence, \verb|CHAR.NL| and \verb|'\n'| denote the same value. Each of the alphabetic characters a-z and A-Z are also defined in the enumeration, so \verb|CHAR.A| and \verb|'A'| denote the same value. \paragraph{Assertions.} \srcmodula implements an \verb|ASSERT| pragma. The pragma may appear anywhere a statement may appear. It has the form \verb|<*ASSERT expr *>| where \verb|expr| is a boolean expression. At runtime the expression is evaluated. It is a checked runtime error if the result is \verb|FALSE|. Assertion checking can be disabled with the \verb|-a| compiler switch. \paragraph{Warnings.} \srcmodula generates several types of warning messages (e.g. unused variables, incomplete case statements, and use of non-standard features.) Two pragmas are available to control these warning messages: \verb|<*NOWARN*>| and \verb|<*UNUSED*>|. No warning messages are emitted for lines containing \verb|<*NOWARN*>|. No ``unused variable'' warnings are emitted for variables declared where \verb|VAR| is immediately preceded by \verb|<*UNUSED*>|. The kinds of warnings emitted can also be controlled by the \verb|-w| switch. See the \verb|m3| man page for the full details. \paragraph{Obsolete.} \srcmodula implements an \verb|<*OBSOLETE*>| pragma. \verb|<*OBSOLETE*>| may appear before any declaration (e.g. \verb|<*OBSOLETE*> PROCEDURE P ();|). A warning is emitted in any module that references an obsolete symbol. This feature is used to warn clients of an interface that is evolving that they are using features that will disappear in the future. \section{Linking} %================ \srcmodula requires a special two-phase linker. The \modula linker is normally invoked by \verb|m3|, but may be invoked directly as \verb|m3ld|. The \verb|m3ld|(1) man page describes the arguments and options recognized by the linker. The first phase of the linker invokes the standard \unix linker to construct a single object containing everything required by the program except a tiny bit of entry code. The second phase generates the entry code (as C), compiles it and produces the final linked program. At runtime the generated entry code initializes the program's modules. For every symbol \verb|X.Z| exported or imported by a module, the compiler generates an auxiliary symbol \verb|VS_X__Z__xx|. This extra symbol, \verb|X.Z|'s version stamp, is used to ensure that all modules linked into a single program agree on the type of \verb|X.Z|. The \verb|xx|'s are a string of 16 hexadecimal digits that encode the signature of \verb|X.Z|. Modules that export \verb|X.Z| also define its version stamp. Modules that import \verb|X.Z| also import its version stamp. Modules that import different versions of \verb|X.Z| will require different version stamps. But, since only a single instance of \verb|X.Z| can be linked into the program, only a single version stamp can be defined. \section{Garbage Collection} %=========================== A crucial fact for clients of the garbage collector to know is that {\em objects in the heap move}. If all references to a traced heap object are from other traced heap objects, the collector may move the referent. Hence, it is a bad idea to hash pointer values. References from the stack or untraced heap into the traced heap are never modified. \section{Debugging} %================== Since an intermediate step of the \modula compiler is to produce C code, you may use any debugger for which your C compiler can produce debugging information; in most cases, this means {\tt dbx} or {\tt gdb}. However, this mechanism has limitations: the C compiler generates source-level information that relates the executable program to the intermediate C code, not to the \modula source code. We attempted to reflect as much as possible of the source-level \modula information into the intermediate C code. But there are still some shortcomings that you should know about. \subsection{Names} %----------------- Every \modula name is prefixed with an underscore. This mutation prevents name clashes between \modula names, names used by the runtime system, and C reserved words. Global names (i.e. top-level procedures, constants, types, variables, and exceptions) are also prefixed by their module's name. For example, in an interface or module named \verb|X|, the C name of a top-level procedure \verb|P| would be \verb|_X__P|. Note, there is one underscore before \verb|X| and two between \verb|X| and \verb|P|. Local names (i.e. ones defined within a procedure or block statement) are simply prefixed by an underscore. \subsection{Types} %----------------- \modula is based on structural type equivalence, C is not. For this reason, the compiler maps all structurally equivalent \modula types into a single C type. These C types have meaningless names like \verb|t182|. The \modula type names are equated to their corresponding C type. The bad news is that variables are declared with the C type names. So, if you ask your debugger ``what is the type of \verb|v|?'', it will most likely answer, ``\verb|t137|''. But, if you ask ``what is \verb|t137|?'' it will most likely give you a useful type description. The following table indicates the C type corresponding to a \modula type. \begin{center} \begin{tabular}{p{1.3in}|p{4.6in}} \multicolumn{1}{c}{\modula} & \multicolumn{1}{|c}{C}\\ \hline enumeration & \verb|unsigned char|, \verb|unsigned short| or \verb|unsigned int| depending on the number of elements in the enumeration. \\ \\ \verb|INTEGER| & \verb|int| \\ \\ %% \end{tabular} %% %% \vv %% \begin{tabular}{p{1.3in}|p{4.6in}} %% \multicolumn{1}{c}{\modula} & \multicolumn{1}{|c}{C}\\ \hline subrange & \verb|char|, \verb|short| or \verb|int|, possibly \verb|unsigned|, depending on the base type of the subrange. Subranges of enumerations are implemented by the same type as the full enumeration. Subranges of \verb|INTEGER| are implemented by the smallest type containing the range. For example, the type \verb|[0..255]| is mapped to \verb|unsigned char| and \verb|[-1000..1000]| is mapped to \verb|short|. \\ \\ \verb|REAL| & \verb|float| \\ \\ \verb|LONGREAL| & \verb|double| \\ \\ $\verb|ARRAY I OF T|$ & \verb|struct { tT elts[n] }|, where \verb|tT| is the C type of \verb|T| and \verb|n| is \verb|NUMBER(I)|. \\ \\ $\verb|ARRAY|^n \verb| OF T|$ & \verb|struct { char* elts; int size[n] }|, where \verb|elts| is a pointer to the first element of the array. \\ \\ \verb|RECORD ... END| & \verb|struct{ ... }| with the same collection of fields as the original record, except that their names are prefixed by a \verb|_|. \\ \\ \verb|BITS n FOR T| & Usually \verb|tT| where \verb|tT| is the the C type of \verb|T|. When \verb|T| is an ordinal type and the packed type occurs within a record, it generates a C bit field. \\ \\ \verb|SET OF T| & \verb|struct { int elts[n] }| where \verb|n| is $\lceil\verb|NUMBER (T)| / \verb|sizeof(int)|\rceil$. \\ \\ \begin{tabular}[t]{@{}l@{}} \verb|REF T| \\ \verb|UNTRACED REF T| \\ \verb|OBJECT ... END| \end{tabular} & \verb|ADDRESS|, a {\tt typedef} for \verb|char*| defined in \verb|M3RuntimeDecls.h|. Each use of a reference is cast into a pointer of the appropriate type at the point of use. \\ \\ \verb|PROCEDURE (): T| & Usually \verb|tT *(proc)()| where \verb|tT| is the C type of \verb|T|. If \verb|T| is a record or array, an extra \verb|VAR| parameter is passed to the procedure which it uses to store the return result. %% \\ \\ \end{tabular} \end{center} Despite the fact that all references turn into \verb|char*|, traced references and objects can be examined with the debugger. To print the referent of a reference or object \verb|ref|, call \verb|print_object (ref)|. Note that using this feature requires your debugger to be able to call procedures in the target address space. Examining untraced \verb|REF|s requires loopholing. % It is possible for a stack overflow to occur during a call to % \verb|print_object|; even while debugging. If this overflow checking % is a problem during debugging and must be prevented, set the variable % \verb|ThreadAs.stackLimit| to zero. Beware! Once you've clobbered the % stack limit, anything can happen. \subsection{Procedures} %---------------------- \modula procedures are mapped as closely as possible into C procedures. Two differences exist: ``large'' results and nested procedures. First, procedures that return structured values (i.e. records, arrays or sets) take an extra parameter. The last parameter is a pointer to the memory that will receive the returned result. This parameter was necessary because some C compilers return structured results by momentarily copying them into global memory. The global memory scheme works fine until it's preempted by the \modula thread scheduler. Second, nested procedures are passed an ``extra'' parameter. The first parameter to a nested procedure is a pointer to the local variables of the enclosing block. To call a nested procedure from the debugger, pass the address of the enclosing procedure's local variable named \verb|frame|. When a nested procedure is passed as parameter, the address of the corresponding C procedure and its ``extra'' parameter are packaged into a small closure record. The address of this record is actually passed. Any call through a formal procedure parameter first checks to see whether the parameter is a closure or not and then makes the appropriate call. Likewise, assignments of formal procedure parameters to variables perform runtime checks for closures. \verb|<*EXTERNAL*>| procedures have no extra parameters. \subsection{File names and line numbers} %--------------------------------------- Due to liberal use of the \verb|#line| mechanism of C, the \modula file names and line numbers are preserved. Your debugger should give you the right names and line numbers and display the correct \modula source code (if it includes facilities to display source code). \subsection{Threads} %------------------- There is no support for debugging threads. That is, there is no mechanism to force the debugger to examine any thread other than the one currently executing. Usually you can get into another thread by setting a breakpoint that it will hit. There is no mechanism to run a single thread while keeping all others stopped. \section{Profiling} %================== \srcmodula provides two types of profiling: count profiling and time profiling. \subsection{Count profiling} %--------------------------- This type of profiling reports the number of times each procedure has been called and/or the number of times each statement or line of source code has been executed. \unix provides two tools to gather the number of executions of a procedure, but no tool to measure the number of executions of a statement. However, these tools also gather time-profiling information and are somewhat problematic in our case (see the next section). We provide an alternate set of programs that collect both kinds of data. To enable collection of data during the execution of programs, give the \verb|-Z| option to the \verb|m3| command. To interpret the result, run \verb|analyze_coverage|(1). % The \srcmodula profiling tools may be used with programs written in % other languages or compiled with other compilers. All that is % required is the presence of function/procedure and statement location % information in the assembly file produced by your favorite compiler; % this information must be in the format suitable for \verb|dbx|. See % \verb|install_coverage|(1) for a discussion of the collection. Note that because of the extensive data collection performed by this mode of profiling, the execution time of the program can be significantly larger when collection is enabled; thus, simultaneous time profiling can produce erroneous results. For the same reason, the profiling data file is rather large; furthermore, as it is augmented by each execution of the program, you may want to compress it from time to time (see \verb|analyze_coverage|(1) for more details). \subsection{Time profiling} %-------------------------- The standard method to construct time profiles uses a \unix timer to periodically interrupt the execution of the program and collect the current program counter. We have another use for that timer interrupt (to schedule the execution of threads). Hence, it is generally not possible to gather time profiles. But, programs that have only one thread (and thus, do not use \verb|Thread.Fork|, either directly or indirectly via a library routine), have no scheduling to do. On such programs, using the \verb|-pg| compilation option will gather a time profile that can be interpreted using \verb|gprof|(1). This situation is only temporary; we plan to offer the full time profiling capabilities standard in \unix in a forthcoming release. \section{Pretty printing} %======================== \srcmodula includes a pretty-printer for \modula programs. It is accessible as \verb|m3pp|(1). Read its man page to find out how to use it. (This version may not accept some of the programs that the compiler accepts, in particular because of pragmas. A feature release will fix that.) \section{Inter-module Dependencies} %================================== \srcmodula includes an inter-module dependency checker. This tool determines if a \modula source file needs to be recompiled, either because the object file is out-of-date or because one of the interfaces that is imported has been modified in an incompatible way. It is accessible as {\tt m3imc(1)}. Read its man page to find out how to use it. \section{Keeping in touch} %======================= Mail sent to \verb|m3@src.dec.com| will be forwarded to all registered users of \srcmodula. (You're registered if you sent us a note asking to be added to this list or returned a signed copy of the licensing agreement.) We hope that this mailing list will provide a useful forum for the exchange of ideas, problems and solutions when using \srcmodula. You can contact the \srcmodula implementers at the following address: \begin{center} \begin{tabular}{l} System Research Center\\ Digital Equipment Corporation\\ 130 Lytton Avenue\\ Palo Alto, CA 94301-1044 \\ \\ \verb|m3-request@src.dec.com| \\ \end{tabular} \end{center} Needless to say, this implementation probably has many bugs. We are quite happy to receive bug reports. We don't promise to fix them, but we will try. When reporting a bug, please send us a short program that demonstrates the problem.