next up previous
Nächste Seite: Optionen der Kommandozeile Aufwärts: Der Compiler Vorherige Seite: Compiler-Ausgaben im Quelltext

Bedeutung der Optionen

Jede Option wird im folgenden in der Form


Bedeutung
Name interaktiv Typ Vorgabe


dargestellt. Hierbei bezeichnet

Name
den Namen der Option, mit dem sie im Quelltext ansprechbar ist.
interaktiv
ist der Buchstabe, der die Option von der Kommandozeile (oder interaktiv) beeinflusst. Nicht alle Optionen sind von der Kommandozeile beeinflussbar. Für sie erscheint die Zeichenkette ,,n.a.`` (nicht anwendbar).
Typ
bezeichnet den Typ und Änderungsbereich der Option, d.h. ob sie stapelbar oder bereichsbezogen ist.
Vorgabe
gibt den Vorgabewert (Default) der Option an:

Es folgt nun eine genaue Beschreibung der Optionen im einzelnen:


Stapelkontrolle
StackChk s stapelbar TRUE


Das Betriebssystem kontrolliert nicht, ob ein Prozess den ihm zugewiesenen Stapelbereich überschreitet. Ist dies der Fall, stellt sich meist ein unerklärlicher Laufzeitfehler ein, dessen Ursache kaum feststellbar ist. Der Compiler generiert Code zur Überprüfung des Stackbereichs. Diese Überprüfung muss zu Beginn jeder Prozedur, sowie manchmal auch innerhalb der Prozedur durchgeführt werden. Dies vergrössert den Code und verlangsamt das Programm. Werden keine Prozeduren rekursiv aufgerufen, und ist sonst ein Stacküberlauf unwahrscheinlich, kann die Option ausgeschaltet werden.

Die Option wird zu Beginn jeder Prozedur eingefroren und am Ende wieder freigegeben. Der Änderbarkeitsbereich ist identisch mit dem der bereichsbezogenen Optionen.


Bereichskontrolle
RangeChk r stapelbar TRUE


Wird auf einen Unterbereich (``subrange`` wie [0..31] oder ein Feld wie a[3]) zugegriffen, generiert der Compiler Code, um die Einhaltung der Bereichsgrenzen zu überprüfen. Unter- oder Überschreiten eines solchen Bereichs bricht das Programm mit einem Laufzeitfehler ab. Ist das Programm vorsichtig ausgetestet (und nur dann), kann die Kontrolle mit (*$ RangeChk:=FALSE *) ausgeschaltet werden, um etwas Geschwindigkeit zu gewinnen.


\begin{example}
\begin{verbatim}VAR i: INTEGER;
zwerg: ARRAY[1..7] OF INTEGE...
... und anschliessend wieder auf den alten Wert
zur\uml {u}ckgesetzt.
\end{example}

Aber auch während der Compilation hat diese Option eine Wirkung. Der Compiler kann konstante Werte bereits zu dieser Zeit auf die Einhaltung von Bereichsgrenzen überprüfen.


\begin{example}
So f\uml {u}hrt beispielsweise der folgende Text normalerweise
z...
...zeit auf 7, sowie die Variable {\tt i} auf
den Wert 5678H gesetzt.
\end{example}


\begin{warning}
Die Laufzeit\uml {u}berpr\uml {u}fung von Zuweisungen zweier Var...
...be;
a:=b; (* hier KEIN Laufzeittest! *)\end{verbatim}\end{example}\end{warning}


Über-, Unterlaufskontrolle
OverflowChk v stapelbar TRUE


Die interne Zahlenrepräsentation kennt keine zu grossen oder zu kleinen Zahlen. Jede Über- oder Unterschreitung bei der Berechnung von Ausdrücken lässt sich jedoch durch das Testen eines speziellen Prozessor-Registers (CCR, ``condition code register``) feststellen. Der Compiler generiert Überprüfungscode, der im Fehlerfall zur Laufzeit das Programm abbricht. Ist das Programm vorsichtig ausgetestet, kann diese Kontrolle durch

(*$ OverflowChk:=FALSE *)
ausgeschaltet werden.


Zeigerkontrolle
NilChk n stapelbar TRUE


Die Verwendung nicht-initialisierter Zeiger kann bei ihrer Dereferenzierung zu unvorhersehbaren Ergebnissen und Programm-Abstürzen führen. Der Compiler erzeugt Code, der zur Laufzeit testet, ob ein Zeiger auf die Adresse 0 (NIL) verweist. Dadurch kann zur Laufzeit das Programm abgebrochen werden. Ist das Programm vorsichtig ausgetestet, kann diese Überprüfung durch

(*$ NilChk:=FALSE *)
ausgeschaltet werden.


\begin{warning}
Globale Variablen sind beim Programmstart immer mit 0 initialisi...
...ar}
unterbunden, kann die
\uml {U}berpr\uml {u}fung nicht greifen!
\end{warning}


Nullinitialisierung
EntryClear e stapelbar TRUE


Da der Anfangswert einer lokalen Variablen nicht bestimmt ist, werden diese explizit auf Null gesetzt. Somit kann die Zeigerkontrolle richtig gut greifen. Soll diese Operation nicht durchgeführt werden, muss die Option mit

(*$ EntryClear:=FALSE *)
ausgeschaltet werden.


\begin{warning}
Dies gilt jedoch {\em nicht\/} f\uml {u}r Register-Variablen und...
...,
wenn die Anzahl der lokalen Variablen 32kByte \uml {u}bersteigt!
\end{warning}


Fallüberprüfung
CaseChk c stapelbar TRUE


Wenn innerhalb einer CASE-Anweisung der aktuelle Wert ausserhalb aller angegebenen Teilbereiche liegt und kein ELSE-Teil angegeben wurde, wird das Programm mit einem Laufzeitfehler abgebrochen. Für diese Überprüfung wird dazu vom Compiler Code generiert, der durch die Option

(*$ CaseChk:=FALSE *)
vermieden wird. Die Wirkung ist identisch mit der Angabe eines leeren ELSE-Teiles.


Funktionsrückgabe
ReturnChk f stapelbar TRUE


Am Ende jeder Funktionsprozedur generiert der Compiler Code, der im Falle einer fehlenden RETURN-Anweisung ausgeführt wird und das Programm mit einem Laufzeitfehler abbricht. Ist bei einer Funktionsprozedur die ordnungsgemässe Beendigung garantiert (und nur dann), kann die Generierung des Überprüfungscodes mit

(*$ ReturnChk:=FALSE *)
abgeschaltet werden.


\begin{note}
Da der Sprungoptimierer (siehe Seite \pageref{refOpti}) auch unbenu...
...uml {u}r den Fall {\tt i\char93 1} ben\uml {o}tigt wird.
\end{example}\end{note}


Ein-/Ausgangs-Code
EntryExitCode n.a. bereichsbezogen TRUE


Jede Prozedur führt zu Beginn einen speziellen Code aus, der eine Stapelüberprüfung vornimmt, Platz für die lokalen Variablen auf dem Stapel alloziert, den dynamischen Link erstellt, die innerhalb der Prozedur benutzten Register auf dem Stack ablegt, und bei Bedarf die offenen Feldparameter auf den Stack kopiert. Am Ende der Prozedur werden (bei Funktionsprozeduren) der Code zur Rückgabekontrolle generiert, die zu Beginn geretteten Register vom Stapel geholt, die lokalen Variablen und die Parameter abgebaut und eine Rückkehranweisung ausgeführt.

Diese beiden Codeteile werden nach

(*$ EntryExitCode:=FALSE *)
nicht erzeugt. Dies wird vor allem bei reinen Assembler-Prozeduren, bei denen der Programmierer für alle oben genannten Aktionen selbst verantwortlich ist, oder bei Prozeduren, die lediglich als ,,Verpackung`` für Daten dienen, benötigt.


\begin{example}
\begin{verbatim}PROCEDURE Ret0():LONGINT;
(*$ EntryExitCode:=F...
....W 1,2,3
DC.B 'Moin, Moin!',0 EVEN
END);
END Daten;\end{verbatim}\end{example}


Offene Felder
CopyDyn n.a. bereichsbezogen TRUE


Eine Prozedur, die offene Feldparameter als Werteparameter besitzt, muss diese zu Beginn auf den Stack kopieren, damit die übergebene Variable oder Konstante nicht verändert werden kann (siehe auch 5.5.5, Seite [*]). Für die Herstellung der Kopie muss Code erzeugt werden. Falls der Parameter innerhalb der Prozedur nicht verändert wird, kann das Kopieren mit der Option

(*$ CopyDyn:=FALSE *)
unterbunden werden, was Code und Laufzeit spart. Danach wird der Parameter wie ein VAR-Parameter behandelt, behält aber den Vorteil, dass auch Konstanten übergeben werden können.


\begin{example}
\begin{verbatim}(*$ CopyDyn:=FALSE *)
PROCEDURE Show(s:ARRAY O...
...
Write(''''); WriteString(s); Write('''');
END Show;\end{verbatim}\end{example}


\begin{warning}
Besonders, wenn mehrere Parameter \uml {u}bergeben werden, sollt...
...\ ...
\\ Swap(name,name);
\\ ...
\\ \relax \end{alltt}\end{example}\end{warning}


Parameter-Abbau
ParDealloc n.a. bereichsbezogen TRUE


In dealloziert jede Prozedur ihre Parameter selbst wieder, da sie aus der Vereinbarung genau weiss, mit wievielen Parametern sie aufgerufen wurde. In der Sprache C werden die Parameter vom Aufrufer dealloziert, da nur dieser weiss, wieviele Parameter er übergeben hat. Einige Betriebssystem-Prozeduren benötigen eine Prozedur als Parameter. Diese dürfen ihre Parameter dann allerdings nicht selbst abbauen, da dies ja die aufrufende Prozedur des Betriebssystems tut. Der Parameter-Abbau kann mit

(*$ ParDealloc:=FALSE*)
unterbunden werden.


\begin{example}
% latex2html id marker 2556Ein Beispiel aus der Graphik-Biblio...
...Collision(0,CAST(PROC,ADR(BorderPatrol)),GInfo);
...\end{verbatim}\end{example}


Sichere und lade A4
LoadA4 n.a. bereichsbezogen FALSE


Normalerweise wird das Register A4 von unserem -Laufzeitsystem zu Beginn des Programmes einmal mit der Basis der globalen -Variablen initialisiert und während des Programmlaufs nicht verändert. Falls jedoch -Prozeduren vom Betriebssystem aufgerufen werden, z.B. Interrupt-Handler, ist A4 zu Beginn der Prozedur ,,zerstört`` und muss neu ,,beschafft`` werden. Näheres steht in 6.2.2, Seite [*]. Dort befindet sich auch ein ausführliches Beispiel für den Nutzen dieser Option. Die Angabe

(*$ LoadA4:=TRUE *)
gilt für die nächste Prozedur und bewirkt, dass Register A4 mit den anderen Registern auf den Stack gerettet und mit der Basis der -Variablen (,,_LinkerDB``) geladen wird. Am Ende der Prozedur wird A4 wiederhergestellt. Damit ist ein Programm nicht mehr residentfähig, da jeder Aufruf eines residentfähigen Programms seine eigenen globalen Daten bekommt. Sie in diesem Fall die folgende Option!


Sichere A4
SaveA4 n.a. bereichsbezogen FALSE


Diese Option ist fast identisch mit LoadA4. Die Angabe

(*$ SaveA4:=TRUE *)
gilt für die nächste Prozedur und bewirkt, dass das Register A4 mit den anderen Registern auf den Stack gerettet und am Prozedurende wiederhergestellt wird. Hier wird also - im Gegensatz zu LoadA4 -- das Register nicht explizit mit einem Wert geladen, sondern nur gerettet. Es muss nun innerhalb der Prozedur vom Programmierer ,,per Hand`` gesetzt werden. Dadurch kann die Residentfähigkeit eines Programmes erhalten werden. Auch hier findet sich ein Beispiel im Abschnitt 6.2.2.


Implementation
Implementation n.a. pro Modul TRUE


Zu jeder Symboldatei erwartet der Linker auch eine Objektdatei. Besteht jedoch die Definition nur aus Typen- und Konstanten-Vereinbarungen oder der Deklaration absoluter oder externer Variablen und ist kein Code beim Import dieses Moduls auszuführen -- vom Compiler nur beim Implementations-Modul feststellbar --, erübrigt sich eine Objektdatei. In diesem Fall ist vor dem ersten Import oder der ersten Deklaration die Compiler-Anweisung

(*$ Implementation:=FALSE *)
zu schreiben. Dies spart also des Schreiben eines ,,leeren`` ImplementationsModuls und die Ausführung unnützen Codes. Ein wenig Code muss sonst auch bei leeren Moduln erzeugt und durchlaufen werden.


Bezeichnerkontrolle
NameChk n.a. pro Modul TRUE


In einer Symboldatei werden alle Bezeichner der Prozedurparameter abgelegt und deren Übereinstimmung in der Implementation überprüft. Stimmen die Namen nicht überein, erfolgt eine Fehlermeldung. Sollen die Bezeichner nicht vermerkt werden, kann in einem Definitionsmodul das Ablegen der Bezeichner mit

(*$ NameChk:=FALSE *)
unterbunden werden. Der Nutzen liegt in kleineren und schneller einzulesenden Symboldateien. Sollen nur die abgelegten Bezeichner nicht überprüft werden, kann die Option zu Beginn des Implementationsmoduls angegeben werden.


Langwortgrenzen
LongAlign l stapelbar TRUE


Normalerweise werden globale Variablen, die mehr als ein Byte belegen, auf Langwortgrenzen abgelegt. Dies ist manchmal zwingend notwendig (z.B. DosD.FileInfoBlock), lässt aber auch die Programme auf Prozessoren mit 32-Bit Datenbus -- 68020 und höher -- schneller laufen. Falls dies nicht nötig ist, kann durch die Angabe

(*$ LongAlign:=FALSE *)
eine dichteres Aufeinanderfolgen der Variablen erreicht werden. Sie liegen dann auf Wortgrenzen. Näheres ist im Abschnitt 5.5.7, Seite [*] zu finden.


Zeiger vergessen
Volatile h stapelbar TRUE


Falls diese Option durch

(*$ Volatile:=FALSE *)
auf FALSE gesetzt wird, versucht der Compiler, möglichst viele Zeiger in Adressregistern zu halten und wiederzubenutzen, was enorm Code sparen kann. Näheres kann man in Abschnitt 6.2.8, Seite [*] nachlesen.


StackParameter
StackParms z stapelbar TRUE


Normalerweise müssen Parameter, welche die Register D0 oder D1 belegen, bis zum endgültigen Prozeduraufruf zunächst auf dem Stack zwischengelagert werden, weil sie sonst durch andere Operationen zerstört werden könnten. Durch

(*$ StackParms:=FALSE *)
wird erreicht, dass sie gleich, ohne Umweg über den Stack, in diesen Registern abgelegt werden, was Code und Laufzeit spart. Hierbei können jedoch Probleme auftreten; lesen Sie bitte Abschnitt 6.2.5, Seite [*]!


Zeichenketten-Konstanten
CStrings n.a. stapelbar TRUE


Da die Sonderbehandlung des Zeichens ,,\`` in Zeichenketten-Konstanten (siehe 5.1.6, Seite [*]) zu Inkompatibilitäten führen kann, kann durch

(*$ CStrings:=FALSE *)
auf die normale Bedeutung dieses Zeichens umgeschaltet werden.


Entwickler-Option
Joker j stapelbar TRUE


Diese Option ist den Entwicklern des -Systems zu Testzwecken vorbehalten. Sie kann in jeder neuen Revision des Compilers eine andere Bedeutung haben und sollte deshalb vom Anwender keinesfalls eingesetzt werden!


-Modell
LargeVars y pro Modul TRUE


Um die Anzahl und Grösse der globalen Variablen eines Moduls nicht einzuschränken, wird jedes Modul standardmässig im -Modell kompiliert. Durch die Angabe

(*$ LargeVars:=FALSE *)
wird erreicht, dass es im -Modell kompiliert wird, also alle globalen Variablen dieses Moduls sind, was die Codegrösse verringert, das Programm beschleunigt und vor allem Bedingung für residentfähige Programme ist. Was hierbei zu beachten ist, wird in Abschnitt 5.1.12, Seite [*] näher erklärt.
\begin{note}
Es wird empfohlen, alle Moduln mit der Option ,,{\tt -y}\lq\lq  zu
kompi...
...on in ,,{\tt ENV:m2c}\lq\lq
(z.B. durch ,,{\tt SetEnv m2c -y}\lq\lq ) mit auf.
\end{note}


\begin{warning}
Werden in einem Definitionsmodul globale Variablen deklariert, s...
...f\uml {u}r den Benutzer nicht
zugreifbare Variable darin befindet!
\end{warning}


Daten in Chip
ChipDATA n.a. pro Modul FALSE


Mit ist es möglich, globale Variablen mit einem vorinitialisierten Wert zu versehen:

VAR i:=INTEGER2;
Diese Option entspricht in der Wirkungsweise der Option ChipCODE. Mit der Option ChipDATA werden die so vorinititialisierten globalen Variablen (5.1.8) im Chip-Memory abgelegt.

Daten müssen dann im Chip-Memory liegen, wenn die Custom Chips des Amigas darauf zugreifen müssen.


\begin{warning}
Diese Option \uml {u}berlagert {\em stillschweigend\/} die Optio...
...ten im Chip-Memory alloziert man den Speicher
besser zur Laufzeit!
\end{warning}


Daten in Chip
ChipBSS n.a. pro Modul FALSE


Normalerweise wird für die nicht vorinitialisierten globalen Variablen eines Moduls kein bestimmter Speichertyp verlangt, das Betriebssystem vergibt den bestmöglichen. Durch die Anweisung

(*$ ChipBSS:=TRUE *)
werden die globalen Daten des gesamten Moduls im Chip-Memory angelegt.

Der Einsatz dieser Option unterliegt den gleichen Einschränkungen wie die Option ChipDATA.


Code in Chip
ChipCODE n.a. pro Modul FALSE


Hier gilt das gleiche wie unter ChipDATA und ChipBSS gesagte. Durch die Anweisung

(*$ ChipCODE:=TRUE *)
wird der gesamte Code- und Konstanten-Bereich des Moduls im Chip-Memory abgelegt.


Zielprozessor
m68000...m68881 0...8 pro Modul 0


Diese Optionen sind ausschliesslich von der Kommandozeile durch die Ziffern 0, 1, 2, 3, 4 und 8 zu setzen. Sie dienen dazu, den Zielprozessor für den erzeugten Code festzulegen und so den optimalen Code zu erzeugen. Der Zielprozessor muss dabei nicht unbedingt identisch mit dem Prozessor des eigenen Amigas sein.

Standardeinstellung ist ,,0``, d.h. der Compiler generiert Code, der auf allen Prozessoren der MC68000er-Familie lauffähig ist.


\begin{warning}
Die jeweils letzte Ziffer auf der Kommandozeile hat das ,,letzte...
...st ---
kann der Compiler f\uml {u}r Sie nur 68010-Code
generieren.
\end{warning}

Bei der bedingten Kompilierung sind die in der Tabelle angegebenen Namen in IF-Abfragen erlaubt. Dabei ist zu beachten, dass all diese Optionen in gegenseitiger Abhängigkeit stehen, wie in Tabelle 2.5 zu sehen und unter 5.1.11, Seite [*] beschrieben ist.



Unterabschnitte
next up previous
Nächste Seite: Optionen der Kommandozeile Aufwärts: Der Compiler Vorherige Seite: Compiler-Ausgaben im Quelltext
Claudio Nieder 2000-11-12