\chapter{Native code versions of gpm\label{native}}
This chapter describes the differences between native code versions of \gpm\
and the {\em classic\/} \gpm.

In many cases, these differences reflect the fact that the development of
the native code versions is converging on the draft international standard
for Modula-2 more rapidly than the classic versions.  In cases where
the features of the native code versions are unlikely to be duplicated in the
future releases of the classic version this is specifically noted.

\section{Semantic Differences in Native Code Versions}
\subsection{Arithmetic overflow trapping}
Classic versions of \gpm\ perform stringent checking of index expressions,
and of assignments to subrange types. As well as these index and range
checks, native code versions of \gpm\ perform full trapping of arithmetic 
overflows.  
It is possible to turn off overflow checking using the \verb!(* $T- *)!
pragma, or the {\bf --t} command line switch.  Any decision to do so should
be made on a carefully considered basis.

Whole number arithmetic is checked for overflow, in both the
signed and unsigned case in all versions.  
For some machine architectures, such as those
based on the  {\em MIPS\/} chip, there is no hardware support for the 
detection of unsigned overflow. The time penalty in such cases may be
significant for procedures which perform intensive unsigned arithmetic.

Floating point arithmetic does not trap, but returns the hardware default
{\em NaNs\/} specified by {\em IEEE Std 754}.  Conversions to whole numbers
are trapped, and result in the expected whole number overflow messages.

It is unlikely that future versions of classic \gpm\ will support overflow
trapping.

\subsection{Numeric conversions and VAL\label{valinfo}}
Native code versions support a wider range of numeric conversions, using the
semantics in the ISO draft standard.  In addition, non-standard
system functions have been added to {\em SYSTEM\/} so as to provide a wider
range of conversions for the numerical programmer.  All conversions are
fully range and overflow checked by default, with trapping controlled by
the \$T pragma as for other tests.

Classic \gpm\ did not implement the {\em INT\/} function, and did not allow
{\em VAL\/} to be used for real to whole number conversions.

The table gives a summary of the real-to-whole number conversions. Note
that converting 32-bit integers to {\em SHORTREAL\/} or converting
64-bit integers to {\em REAL\/} involves rounding to the nearest valid
floating point number.  

The conversions induced by {\em ENTIER, ROUND\/} are built in as system
functions in order to allow applications to directly access the hardware
instructions which most contemporary floating point implementations provide.
They are thus much faster than the semantically equivalent functions calls
in module {\em RealMath\/}, but are, or course, specific to \gpm.

\begin{table}
\begin{center}
{\small
\begin{tabular}{ | r p{7cm} p{3.2cm} | }
\hline
{\bf Function} & {\bf\hfill Description \hfill} & {\bf\hfill Comment \hfill} \\
\hline
{\tt VAL(REAL,i)}       &{\raggedright
			returns the real number
			equal in value to the integer $i$
		        --- same as {\tt FLOAT(i)} }
		        & rounds to nearest fp-number\\
{\tt VAL(REAL,c)}       &{\raggedright
			returns the real number
			equal in value to the cardinal $c$ 
		        --- same as {\tt FLOAT(r)} }
		        & rounds to nearest fp-number\\
{\tt VAL(CARDINAL,r)} 	&{\raggedright
			round $r$ toward zero, and return as
			a cardinal value if in range
		        --- same as {\tt TRUNC(r)}} 
		        & rounds toward zero \\
{\tt VAL(INTEGER,r)}    &{\raggedright
			round $r$ toward zero, and return as 
			an integer value if in range
			--- same as {\tt INT(r)}}
		        & rounds toward zero \\
{\tt INT(r)} 		&{\raggedright
			--- same as {\tt VAL(INTEGER,r)} }
			& rounds toward zero \\
{\tt FLOAT(i)} 		&{\raggedright
			converts integer $i$ to real --- \\
			same as {\tt VAL(REAL,i)} }
		        & rounds to nearest fp-number\\
{\tt FLOAT(c)} 		& {\raggedright
			converts cardinal $c$ to real --- \\
			same as {\tt VAL(REAL,c)} }
		        & rounds to nearest fp-number\\
{\tt TRUNC(r)}		&{\raggedright
		        --- same as {\tt VAL(CARDINAL,r)} }
			& rounds toward zero \\
{\tt SYSTEM.ENTIER(r)} 	&{\raggedright
			returns the greatest integer   
			not greater than the real $r$}
			& rounds toward $- \infty $  \\
{\tt SYSTEM.ROUND(r)}	&{\raggedright
			returns the nearest integer   
			to the real $r$}
			& rounds to nearest \\
\hline
\end{tabular}
} % end small
\end{center}
\end{table}

\subsubsection{Extensions to VAL}
According to the standard, any numeric type may be converted to any other
numeric type using {\em VAL\/}, while ordinal types may be converted
only to and from the whole-number types.  

\gpm\ extends these semantics by allowing conversion between
any numeric or ordinal type and any other numeric or ordinal type.
Conversions which are technically illegal according to the standard\footnote{
For example, conversions between one enumeration type and another, or 
conversions from enumeration values to real types are illegal in the 
standard.  Thus portable code cannot say~---
\par
\verb!  VAL(REAL,enumVal);                (* non-standard, but ok for gpm *)!
\par\noindent
but may use the equivalent but clumsy~---
\par
\verb!  VAL(REAL,VAL(CARDINAL,enumVal));  (* this version is standard     *)!
\par\noindent
or better~---
\par
\verb!  FLOAT(ORD(enumVal));              (* this is also standard        *)!
}
are flagged with warning~510.

\subsection{Non-constant constructors} 
The current release allows constructors to be used for either constant or
variable values.  The syntax is the same in either case, and is described in
the language reference manual. 

Constructors provide a simple mechanism for specifying a new value for an 
entire variable.  In general, \gpm\ will construct the new value in a temporary
location, and then assign the entire variable.  Thus it is safe to use 
constructs such as~---
\begin{verbatim}
    TYPE Thing  = RECORD left,right : REAL END;
    VAR  aThing : Thing;

    BEGIN
      aThing := Thing{aThing.right, aThing.left};
      ...
\end{verbatim}
which logically require a temporary location.

In the opinion of the \gpm\ development team the syntax for value constructors
has a number of undesirable features.  In principle, records provide a method
of associating the components of a value with individual identifiers. 
There is no
inherent notion of ``ordering'' of record fields, and a change in order of the
fields of a type declaration should leave the meaning of any correct program
unaltered.  However, in defiance of this principle, value constructors provide
a {\em positional association\/} between the elements of the original 
declaration of the type and the expressions in the constructor body. For
example, in the above program fragment a change in the declaration of 
the type {\em Thing\/} might change the semantics of the constructor without 
invalidating its type compatability. 
Similarly, constructors for arrays which
are indexed on an enumeration type are vulnerable to any change in the order
of the enumeration constants.  Please be careful with value constructors.

\subsection{Functions returning arrays}
Functions may return arbitrary types, including arrays. In combination with
the use of value constructors, this allows a very functional style of 
programming.  As with value constructors, the returned value is usually
constructed in a temporary location and then copied to the destination
location.

\subsection{Multi-dimensional open arrays\label{multidim}}
Formal parameters may now be declared to be of multidimensional array types.
The syntax is~---
\[\mbox{FormalType} \rightarrow 
	\mbox{{\tt ARRAY OF} \{{\tt ARRAY OF}\} {\em TypeName}}\]
The dimensionality of the array is the number of times {\em ARRAY OF\/}
is repeated.  

An array of $n$-dimensions has $n$ high values associated with it. These
are accessed as 
\mbox{{\em HIGH\/}($f$)},
\mbox{{\em HIGH\/}($f[e]$)},
\mbox{{\em HIGH\/}($f[e_1,e_2]$)}, 
and so on, where $f$ is the name of the formal parameter and 
$e_1, e_2, \cdots$
are cardinal value expressions of arbitrary value.\footnote{In fact, \gpm\ 
doesn't even check the semantic correctness of these expressions, it just 
{\em counts\/} the number of index expressions.}

These high values correspond to the maximum values of the indices
in a designator $a[i, j, k, \cdots]$ where \mbox{{\em HIGH}($a$)} is the
maximum of the index corresponding to $i$, and so on respectively.

In the case of value-mode open arrays, the actual parameter must be an 
array value
which conforms in the number of dimensions, and has elements which are
elementwise {\em assignment compatible\/} with the formal parameter element
type.
For variable-mode open arrays the actual parameter must be an array variable
which conforms in the number of dimensions, and which is has elements of
{\em identical type\/} to the formal parameter.

In the case of open arrays of the system types {\em BYTE, WORD\/}, only
one dimensional arrays have the usual universally conformant property.
Thus it is possible to send a value of {\em any\/} type (and even arrays 
of an arbitrary number of dimensions) to an array of byte, but only a two 
dimensional array of bytes can be sent to a formal parameter which is a 
two dimensional open array of bytes.

\subsection{Parameter passing to open arrays\label{marshall}}
When actual arrays are passed to value-mode, open array formals, the
element types must be {\em assignment compatible}.  Originally, the
element types had to be identical.

A consequence of this change is that values passed to open arrays must
be {\em marshalled\/} in the stack frame of the calling procedure.
In some cases the value must be range-checked element by element.
Previously, implementations copied the entire value into the local space
of the called procedure, using a block copy operation.


\section{Modified Functionality}
\subsection{Organisation of the compiler}
The compiler driver program {\tt gpm} is a small process, which parses
the command line switches, and then forks and execs the main compiler 
components. 

The compiler frontend is called {\tt gpmd}.  This process reads the source file
passed to it, and a configuration file named {\tt gp2d.cfg}, which must be
readable on the M2SYM path.  The configuration file specifies such
things as the alignment constraints of the target machine, and the parameter
passing conventions.  The frontend writes an ascii file with extension
{\tt .dcf} which contains the intermediate form of the compilation 
unit\footnote{The format of the \dcode\ file has been placed in the public
domain.  The technical reference is updated to track the current versions
of native code \gpm.  This report is available by anonymous ftp from 
\mbox{\tt ftp.fit.qut.edu.au:/pub/papers}}.

Following a successful termination of {\tt gpmd}, the driver forks and
execs the code generator program {\tt dgen}.  This program produces an
assembly language file with extension {\tt .s}.  Future versions may
very well produce object code directly, in the interests of shortened 
compilation time, but current versions use a separate assembler.

Following a successful termination of {\tt dgen}, the driver forks and
execs the resident assembler with appropriate options. The assembler
produces the final object code file, with extension {\tt .o\/}.

The driver program repeats this procedure for each of the source files,
deleting the intermediate files after each compilation.

\subsection{New command line switch --D}
The command line switch --D abandons compilation of each file after the
{\em DCode\/} form has been created.  This allows the {\tt .dcf} files to
be examined. Similarly, the command line switch --S abandons compilation
after the assembler form has been created. This allows the {\tt .s} files
to be examined.

\subsection{Runtime Error Messages}
Runtime error messages in native code versions are more detailed than in
previous versions.  In particular,  range, index and overflow errors report
a module name and line-number, as does the default stack overflow test.

\subsection{Use of SOAP}
Classic versions of \gpm\ all use a separate $S$tack for $O$pen $A$rray 
$P$arameters.
This {\em SOAP\/} is unnecessary for native code versions which have a 
conventional frame pointer register.  In particular all versions of \gpm\
for the Intel architecture (including {\bf gpm-pc}) copy open array parameters
to the runtime stack, and do not use {\em SOAP}.

Given the changes to the parameter passing strategy for open arrays 
described on page~\pageref{marshall},  even versions which still use 
{\em SOAP\/} will only do so when an open formal array is passed as 
an open actual array.

\section{Calling Conventions}
\gpm\ will normally use standard $C$ calling conventions (parameters pushed in
reverse order, caller removes parameters from the stack).  For situations where
it is necessary to interface to modules expecting {\em Pascal calling
convention}
(callee removes parameters from stack), a new context sensitive mark has been
introduced.  It must precede the word {\em DEFINITION} at the head of the
callee's definition module and may be combined with the {\em FOREIGN} or
{\em INTERFACE} context sensitive marks (see Chapter 14 - Reference Manual).
The mark itself is defined in the configuration file {\tt gp2d.cfg} as
{\tt mark = calleeCutPars}.  (see the {\em DCode} technical reference for
details of the configuration file)


