Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als...

55
Diplomarbeit Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks. zur Erlangung des akademischen Grades Diplom-Informatiker (FH) vorgelegt dem Fachbereich Mathematik, Naturwissenschaften und Informatik der Fachhochschule Gießen-Friedberg Sven Wagner im August 2007 Referent: Prof. Dr. Hellwig Geisse Korreferent: Prof. Dr. Thomas Letschert

description

Diplomarbeit von Sven Wagner

Transcript of Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als...

Page 1: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

Diplomarbeit

Konzeption und Entwicklung eines neuenCompiler „CESC“ zur Implementierung

von Prozeduren als atomare Tasks.

zur Erlangung des akademischen GradesDiplom-Informatiker (FH)

vorgelegt dem Fachbereich Mathematik,Naturwissenschaften und Informatik der

Fachhochschule Gießen-Friedberg

Sven Wagner

im August 2007

Referent: Prof. Dr. Hellwig GeisseKorreferent: Prof. Dr. Thomas Letschert

Page 2: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

Inhaltsverzeichnis

1. Zusammenfassung 6

2. Einleitung 82.1. Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92.2. Zielsetzung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92.3. Aufbau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

3. Grundlagen 113.1. Die Prozedur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113.2. Der Task . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113.3. Der Frame Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123.4. Der Current Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123.5. Programmbeispiel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

4. Die Sprache CES 204.1. Einführung in die Sprache von CES . . . . . . . . . . . . . . . . . . . . . . 20

4.1.1. Eigenschaften von CES . . . . . . . . . . . . . . . . . . . . . . . . 204.1.2. Einordnung der Programmiersprache CES . . . . . . . . . . . . . . 214.1.3. Lexikalische Konventionen . . . . . . . . . . . . . . . . . . . . . . . 214.1.4. Beispielprogramme . . . . . . . . . . . . . . . . . . . . . . . . . . . 224.1.5. Datentypen und Variablen . . . . . . . . . . . . . . . . . . . . . . . 234.1.6. Der Präprozessor . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

4.2. Die CES Prozedur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234.2.1. Definition einer CES Prozedur . . . . . . . . . . . . . . . . . . . . 234.2.2. Die Parameter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

4.3. Der CES Aufruf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 254.3.1. Vorsicht Falle! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

4.4. Die CES Variable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

5. Das Backend 275.1. Die Run Time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275.2. Datenstrukturen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

5.2.1. Der Task Frame . . . . . . . . . . . . . . . . . . . . . . . . . . . . 275.2.2. Der Storage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

5.3. Die Header Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 345.4. Der von CESC generierte C Code . . . . . . . . . . . . . . . . . . . . . . . 35

5.4.1. C Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

2

Page 3: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

5.4.2. CES Prozedur Aufruf . . . . . . . . . . . . . . . . . . . . . . . . . 385.4.3. Verwendung einer CES Variablen . . . . . . . . . . . . . . . . . . . 395.4.4. Den Storage erzeugen . . . . . . . . . . . . . . . . . . . . . . . . . 405.4.5. Kopie des Current Stack auf den Frame Stack . . . . . . . . . . . . 415.4.6. Die Print Funktion . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

6. Der CES Compiler 436.1. Der Scanner . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 436.2. Der Parser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 446.3. Der abstrakte Syntaxbaum . . . . . . . . . . . . . . . . . . . . . . . . . . 446.4. Die semantische Analyse . . . . . . . . . . . . . . . . . . . . . . . . . . . . 446.5. Die Codegenerierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 446.6. Der Pretty Printer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

7. Ausblick 47

A. CESC Handbuch 50A.1. Dateien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50

A.1.1. Makefile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50A.1.2. CESC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51A.1.3. Scanner . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52A.1.4. Parser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52A.1.5. Run Time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52A.1.6. Pretty Printer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52A.1.7. Beispielprogramm . . . . . . . . . . . . . . . . . . . . . . . . . . . 52

B. Testumegbung 53B.1. Dateien im Verzeichnis CESC/Tests . . . . . . . . . . . . . . . . . . . . . 53

3

Page 4: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

Abbildungsverzeichnis

2.1. Activation Frames[1] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92.2. Task Frames[1] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

3.1. Frame Stack mit Tasks und Storages . . . . . . . . . . . . . . . . . . . . . 133.2. Frame Stack während der Ausführung von TaskA . . . . . . . . . . . . . . 143.3. Frame Stack nach der Ausführung von TaskA . . . . . . . . . . . . . . . . 143.4. Frame Stack während der Ausführung des CES Programms . . . . . . . . 163.5. Pretty Printer Ausgabe . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

4.1. Ablaufdiagramm eines Kompiliervorgangs . . . . . . . . . . . . . . . . . . 204.2. Informationsaustausch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

5.1. Pretty Printer Ausgabe mit dem „ancestor“ Task program(;;) . . . . . . . 315.2. Frame Stack nach der Ausführung von program(;;) . . . . . . . . . . . . . 335.3. Pretty Printer Ausgabe mit dem „ancestor“ Task program(;;) . . . . . . . 345.4. Frame Stack nach der Ausführung von program(;;) . . . . . . . . . . . . . 36

6.1. Der abstrakte Syntaxbaum . . . . . . . . . . . . . . . . . . . . . . . . . . 45

4

Page 5: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

Listings

2.1. Pseudoprogrammbeispiel . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

3.1. Beispiel if Anweisung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123.2. TaskA wird ersetzt durch TaskB und TaskC . . . . . . . . . . . . . . . . . 133.3. C Programm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143.4. CES Programm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

4.1. CES Programm Hallo, Welt! . . . . . . . . . . . . . . . . . . . . . . . . . . 224.2. CES Programm Euklid’scher Algorithmus . . . . . . . . . . . . . . . . . . 224.3. Beispiel mit Fehlerquelle . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

5.1. Funktion aus der Run Time zur Ausfürung eines Task . . . . . . . . . . . 275.2. TASK_FRAME Datenstruktur aus der run_time.h . . . . . . . . . . . . . 275.3. Beispiel einer von CESC generierten Task Struktur im Header File . . . . 285.4. Beispiel zur Parameterprüfung . . . . . . . . . . . . . . . . . . . . . . . . 295.5. Datenstruktur des Tasks euclid(b,c;;double erg2) . . . . . . . . . . . . . . 295.6. STORAGE_FRAME Datenstruktur . . . . . . . . . . . . . . . . . . . . . 315.7. Storage Funktion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325.8. CES Programm zur Storage Erzeugung . . . . . . . . . . . . . . . . . . . . 325.9. Datenstruktur eines Storage für double a . . . . . . . . . . . . . . . . . . . 335.10. CES Prozedur printVar(double a;;) . . . . . . . . . . . . . . . . . . . . . . 345.11. Datenstruktur des Tasks print_Var(double a;;) . . . . . . . . . . . . . . . 355.12. CES Programmbeispiel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

6.1. C Quellcode des Pretty Printers . . . . . . . . . . . . . . . . . . . . . . . . 45

5

Page 6: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

1. Zusammenfassung

Die vorliegende Diplomarbeit mit dem Titel Konzeption und Entwicklung einesneuen Compiler „CESC“ zur Implementierung von Prozeduren als atomareTasks beschreibt eine Neuimplementierung von Prozeduren als atomare Tasks.

Als Grundlage für diese Diplomarbeit dient die Veröffentlichung Task Frames [1] vonDr. Burkhard Steinmacher-Burow (IBM Deutschland Entwicklung GmbH) sowie die Po-werPoint Präsentation The Execution of Computer Applications[2] (bei Interesse bitteEmail an [email protected]). In der Arbeit Task Frames[1] wird das Konzept vonTask Frames beschrieben sowie eine grobe Implementierung von Prozeduren als atomareTasks. Diese Diplomarbeit greift das von Dr. Steinmacher-Burow entwickelte Konzeptauf und zeigt, dass es möglich ist die beschriebene Theorie und den praktischen Ansatzfür das Execution System in eine weiterbenutzbare Neuimplementierung umzusetzen.

Der entwickelte Compiler CESC (C with Execution System Compiler) basiert auf derImplementierung des Compilers für die Sprache SPL von Dr. Hellwig Geisse, Professor ander Fachhochschule Giessen-Fiedberg, der zu Lehrzwecken entwickelt wurde. Ziel war esden Aufwand für die Entwicklung des Compilers zu minimieren, deswegen wurde auf einealtbewährte Entwicklung im Compilerbau zurückgegriffen und eine getestete Struktur desSPL Compilers benutzt.

Die Programmiersprache C wurde durch ein neues Sprachkonzept erweitert und alsneue Sprache CES definiert. Das C in CES steht für die Programmiersprache C, dadiese als Basis dient, um die Sprache CES zu entwickeln. Es ist weiterhin möglich dieProgrammiersprache C zu benutzen. ES bedeutet Execution System. Das Execution Sys-tem steuert die Ausführung einer Prozedur als Task, hierzu ist für die Ausführung deratomaren Tasks eine Verwaltung nötig, die ebenfalls vom ES übernommen wird.

Der im Rahmen dieser Arbeit entwickelte Compiler CESC generiert aus CES Quelltexteinen C Quelltext. Alle in CES definierten Prozeduren werden als atomare Tasks von demCES Compiler übersetzt, das heisst sie werden als C Funktion implementiert. Durch eineeigens entwickelte Run Time, die zusammen mit dem vom CES Compiler generierten CFile zum ausführbaren Programm kompiliert wird, werden die erzeugten Tasks als neuimplementierte Funktionen ausgeführt.

Nach einer Einführung in das Thema in Kapitel 2 beinhaltet die Diplomarbeit in Kapi-tel 3 eine Beschreibung der neu definierten und verwendeten Begriffe für die Entwicklungvon CES und dem Compiler CESC. Eine genaue Beschreibung der Erweiterung von Czu CES erfolgt in Kapitel 4. Das Kapitel 5 ist der Kern dieser Diplomarbeit. In diesemKapitel wird genaustens beschrieben wie die Ausführung der Tasks erfolgt und welcheStrukturen dazu nötig sind. Kapitel 6 umfasst wie der CES Compiler entwickelt wur-de und welche Phasen zur Übersetztung nötig sind. Zusätzlich wird in diesem Kapitelbeschrieben welche Konstrukte nötig waren um das beschriebene Konzept der Neuimple-

6

Page 7: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

mentierung durch CESC zu ermöglichen.Das Ziel dieser Diplomarbeit ist nicht eine neue Programmiersprache zu entwickeln,

sondern das Prinzip einer Neuimplementierung einer Prozedur als atomarer Task zuverdeutlichen.

7

Page 8: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

2. Einleitung

Programmiersprachen beinhalten in ihrem Quellcode mitunter Befehle, Definitionen vonFunktionen und Aufrufe von Funktionen. Zur Komplexitätsbewältigung wird das Kon-zept der Modularisierung verwendet. Das heisst, dass ein komplexes Programm durchkleinere Teilprogramme (Funktionen) beschrieben wird. Diese können unabhängig von-einander definiert werden, funktionieren aber als Ganzes. CES benutzt genau diese Artvon Vereinfachung. In CES ist es wie in C möglich aus mehreren Dateien ein Programmzu erstellen. Das Teilprogramm wird in CES als CES Prozedur definiert. Die Implemen-tierung der CES Prozedur erfolgt durch eine C Funktion.

Ein CES Quelltext ist ähnlich wie ein C Quelltext. Der Unterschied liegt in der Ausfüh-rung von CES Prozeduren gegenüber Prozeduren oder Funktionen aus anderen Sprachen.In anderen Sprachen wird ein Ausfruf einer Prozedur sofort ausgeführt. In CES, innerhalbder ausführenden Prozedur, werden alle CES Prozedur Aufrufe gesammelt. Am Ende derausführenden Prozedur werden die gesammelten Aufurfe dem Execution System überge-ben. Das Execution System führt dann den nächsten Aufruf aus. Der Ablauf einer CESProzedur ist somit ein atomarer Task, da er nicht von dem Ablauf anderer Prozedurenabhängig ist.

Eine CES Prozedur wird ausgeführt durch einen Task Frame. Eine Prozedur aus eineranderen Programmiersprache wird durch ein Activation Frame ausgeführt. Ein Beispiel[1] soll nochmal den Unterschied der Ausführung zwischen dem Konzept der ActivationFrames und dem der Task Frames verdeutlichen.

1 a ( ) { . . . }2 b ( ) { . . . }3 c ( ) { . . . a ( ) . . . }4 d ( ) { . . . b ( ) . . . c ( ) . . . }

Listing 2.1: Pseudoprogrammbeispiel

Die Prozedur „d“ wird ausgeführt. Bei dem bekannten Konzept der Activation Framesist die Prozedur „d“ von Anfang bis Ende auf dem Prozedurstack vorhanden. Betrachtetman das Konzept der Task Frames, so kann man sagen, dass ein Task durch andere„ersetzt“ wird. Tatsächlich ist es aber so, dass das Execution System speichert in welcherReihenfolge die Tasks ausgeführt werden müssen. Erst wenn ein Task beendet ist, wirdder nächste Task ausgeführt. In dem aufgeführten Beispiel wird der Task d durch dieTasks b und c „ersetzt“.

8

Page 9: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

Abbildung 2.1.: Activation Frames[1]

Abbildung 2.2.: Task Frames[1]

2.1. Motivation

Bewährte Systeme wie zum Beispiel Seti@home oder auch diverse Datenbanken zeigen,dass es bereits Anwendungsgebiete gibt, die das Konzept von atomaren Tasks verwendenund erfolgreich einsetzen.

Im Hinblick auf die aktuelle Entwicklung zu Mehrprozessorsystemen entwickelt dienachfolgende Diplomarbeit ein Execution System, dass die einzelnen Task Frames parallelauf mehreren CPUs ausführt.

2.2. Zielsetzung

Ziel ist es Prozeduren als atomare Tasks zu implementieren. Es wurde die Program-miersprache C erweitert und verwendet. Hierbei ist darauf geachtet worden, dass dieProgrammiersprache C weiterhin verwendet werden kann. Dies war Vorrausetzung fürdiese Arbeit, da es nicht Ziel ist in der vorgegebenen Zeit eine neue Sprache zu entwi-ckeln, sondern Vorteile der Programmiersprache C nutzen zu können. Zum Beispiel solles weiterhin möglich sein C Bibliotheken per Include-Anleitung für eine seperate Kompi-lierung benutzten zu können. C biete außerdem die Möglichkeit der Zeigerarithemtik mitder einfach Referenzen gebildet werden können. Es wurde auch bewusst eine dem Autorbekannte Programmiersprache gewählt damit ein zügiges Implementieren garantiert ist.Zur Präsentation des Programmablaufs soll ein Pretty Printer implementiert werden, der

9

Page 10: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

den Stack mit allen wichtigen Informationen zum Verstehen des aktuellen Status und derzukünftigen Ausführung des Programms ausgibt. Ergebnisse dieser Diplomarbeit dienenals Basis für die Weiterentwicklung von CES und dem Execution System (Kapitel „DasBackend“), um einmal atomare Tasks parallel auf mehreren Prozessoren ausführen zukönnen.

2.3. Aufbau

Zu Beginn der Diplomarbeit wurde ein Beispielprogramm entwickelt, welches die Aus-gabe des CES Compilers darstellt. Hierzu wurde aus der Veröffentlichung Task Frames[1] von Dr. Steinmacher-Burow die doch sehr einfach gehaltene Implementierung aufge-griffen und als Basis für eine erste Testimplementierung benutzt. Es sollte klar werdenwelche Codefragmente für die Neuimplementierung von Prozeduren als Tasks vom CESCompiler generiert werden sollen. Aus diesem Beispielprogramm wurde ersichtlich wie dieRun Time implementiert werden muss, um die gleiche Funktion zu beinhalten. Daraufhinerfolgte die Entwicklung des CES Compilers zur Generierung eines C Files, dass zusam-men mit der Run Time von einem C Compiler übersetzt, ein ausführbares Programmerzeugt, welches das gleiche Ergebnis liefert.

Im Konzept der Activation Frames dient der Activation Frame zur Übermittlung vonInformationen zwischen den Subfunktionen. Für diesen Mechanismus mußte eine Alter-native geschaffen werden. Im CES dienen sogenannte Storages als Vermittler zwischenden Subtasks.

Der Aufbau der Stacks zum Speichern und verwalten der Tasks wurde entwickelt. Die-ser Stack ist ähnlich dem Funktionsstack in C. Passende Strukturen für den Stack und dieStorages wurden anschliessend entwickelt. Es mussten Datenstrukturen definiert werdenund welche Daten diese Strukturen enthalten müssen, um die gewünschte Funktionalitäterbringen zu können.

Der nächste Schwerpunkt der Diplomarbeit beinhaltet die Entwicklung des CES Com-pilers. Dieser umfasst folgende Phasen: Der Scanner dient dazu den CES-Quelltext ein-zulesen und sogenannte Tokens für den Parser zu generieren. Die im Parser definiertekontexfreie Grammatik dient zur Überprüfung des Tokenstroms aus dem Scanner. Bei Zu-treffen eines eingelesenen Tokenstroms in den endlichen Automaten des Parsers wird einvordefinierte Aktion ausgeführt. Folge hiervon ist die Erstellung eines abstrakten Syntax-baums. Parallel kommt es zu einer Überprüfung der Semantik. Mit Hilfe des Syntaxbau-mes werden zuerst Symboltabellen für die einzelnen Prozeduren erstellt, um anschliessenddie Codegenerierung in C zu ermöglichen. Abschließend wird das vom CES-Compiler ge-nerierte C-File zusammen mit der Runtime als Eingabedatum für den C-Compiler einge-geben. Das Endprodukt ist ein ausführbares Programm, dass jeden Aufruf einer Prozedurals atomarer Task ausführt.

10

Page 11: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

3. Grundlagen

Diese Diplomarbeit baut auf altbewährte und bekannte Grundlagen aus der Informatikauf. Die Begriffe Prozedur und Task sind typische Begriffe aus der Informatik. In diesemKapitel werden die in der Arbeit verwendeten Begriffe beschrieben und erklärt um dieneu definierten Konzepte von CES verständlicher zu machen. Am Ende dieses Kapitelsverdeutlicht ein Programmbeispiel die beschriebenen Begriffe aus der vorliegenden Arbeitin dem dazugehörigen Kontext.

3.1. Die Prozedur

Eine Prozedur ist eine Spezifikation von aufeinanderfolgenden Befehlen, welche in ei-nem zusammenhängenden Kontext bearbeitet werden sollen und bei gleicher Eingabedieselbe Ausgabe liefern. In der Informatik ist dies einem Unterprogramm gleichzuset-zen. Funktionen sind ähnlich definiert, haben aber im Vergleich zu Prozeduren einenRückgabewert. Ein definierter CES Task entspricht einer Prozedur. Diese Prozedur isttransparent, eigenständig und kann durch die Neuimplementierung unabhängiger aus-geführt werden als Prozeduren aus bekannten Programmiersprachen. Diese Eigenschaf-ten bezeichnen eine atomare Prozedur. Eine Prozedur hat die Aufgabe ein vorliegendesProgramm in Module zu unterteilen. Diese Module fassen Teile eines Programms untereigenem Namen zusammen. Prozeduren arbeiten nach dem EVA Prinzip; sie können Pa-rameter als Eingabe erhalten, verarbeiten diese und liefern Ergebnisse. Diese Ergebnissekönnen berechnete Werte sein, sowie Ausgaben auf dem Bildschirm oder in einer Da-tei. Eine Prozedur wird aktiviert indem ihr definierter Name aufgerufen wird. Beinhalteteine Prozedur weitere Prozeduraufrufe, so werden diese je nach Implementierung derProzeduren sofort ausgeführt. Bei konventionellen Programmiersprachen, die nach demPrinzip der Sequentialisierung arbeiten, sind Funktionen Vermittler zwischen anderenFunktionen. In der Sprache C bedeutet diese eine starke Abhängigkeit der Funktionenuntereinander.

3.2. Der Task

Ein Task im herkömmlichen Sinne ist eine Zusammenfassung von Befehlen, die aus demSpeicher geladen und ausgeführt werden. In der Sprache CES ist ein Task eine Prozedurmit Befehlen. Ein Befehl kann ein Aufruf eines anderen Task sein. Der Task wird in denSpeicher geladen und kann als Ganzes ausgeführt werden. Beinhaltet ein Task andereTasks, so wird von dem Excution System gespeichert welche Tasks als nächstes ausgeführtwerden müssen. Es kann immer nur ein Task ausgeführt werden. Dies bedeutet es ist nicht

11

Page 12: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

wie bei Activation Frames möglich, dass ein Task einen anderen Task sofort aktiviert undausgeführt wird. Betrachtet man den Ablauf auf dem Stack so gewinnt man den Eindruck,dass der aktuelle Task durch seine Aufrufe ersetzt wird.

3.3. Der Frame Stack

Der Frame Stack ist ein Stapel mit dem LIFO Prinzip. Dieser Stapel beinhaltet sogenann-te Frames. Ein Frame hat immer die gleiche Speichergrösse. Dies wurde zur Vereinfachungder Implementierung des Frame Stacks gewählt. Die Verarbeitung der Frames auf demFrame Stack wurde somit vereinfacht. Es wird immer nur der oberste Frame auf dem Fra-me Stack von der Run Time ausgeführt. Dies ist die gewöhnliche depth-first Ausführungvon Prozeduren. Ist der oberste Frame ein Storage, so wird der Frame Stack Pointer nurauf den nächsten Task gesetzt. Die Abbildung 3.1 zeigt ein Beispiel des Frame Stacks mitTask Frames und Storage Frames. fsp ist der Frame Stack Pointer, der auf den oberstenFrame zeigt. fsp_bottom zeigt immer auf den „Boden“ des Frame Stacks und dient zurBerechnung der Indizes der einzelnen Frames auf dem Stack.

3.4. Der Current Stack

In der einfachen Implementierung dieser Diplomarbeit wurde ein zusätzlicher Stack er-zeugt, der sogenannte Current Stack. Der Current Stack ist ein Top Down Stack, d.h.jeder neue Task wird unter dem letzten Task erzeugt.

Der Current Stack dient dazu Aufrufe von CES Prozeduren als Task Frames zu sam-meln, solange der Eltern Task ausgeführt wird. Ist der Eltern Task beendet werden allegesammelten Kinder Task Frames auf den Frame Stack kopiert. Der Current Stack wirdeingesetzt, da durch Verzweigungen, zum Beispiel if Anweisungen, nicht bekannt ist wie-viele Tasks erzeugt werden.

Im folgenden Beispiel soll TaskA entweder durch TaskB oder TaskC ersetzt werden, dadiese in TaskA enthalten sind. Zum Zeitpunkt der Übersetzung ist nicht bekannt welchenWert a zur Laufzeit annehmen wird.

1 int a ;2 a = . . . ;3 TaskA ( ; ; ) { // E l t e rn Task4 i f ( a ) {5 TaskB ( ; ; ) ; // Kind Task6 TaskC ( ; ; ) ; // Kind Task7 } else8 TaskD ( ; ; ) ; // Kind Task9 }

Listing 3.1: Beispiel if Anweisung

Ein zusätzliches Beispiel soll verdeutlichen wie der Kopiervorgang vom Current Stackauf den Frame Stack erfolgt.

12

Page 13: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

fsp // 8 Task E(;x;)

7 Storage(x)

6 Task D

5 Task C

4 Task B(;;a,b)

3 Storage(b)

2 Storage(a)

fsp_bottom // 1 Task A

Abbildung 3.1.: Frame Stack mit Tasks und Storages

1 TaskA ( ; ; ) { // E l t e rn Task2 TaskB ( ; ; ) ; // Kind Task3 TaskC ( ; ; ) ; // Kind Task4 }

Listing 3.2: TaskA wird ersetzt durch TaskB und TaskC

Zuerst wird TaskB und dann TaskC auf dem Current Stack erzeugt.Danach wird der komplette Current Stack auf den Frame Stack kopiert.

3.5. Programmbeispiel

Das in diesem Abschnitt gezeigte Programmbeispiel verdeutlicht die Ausführung einesCES Programms. Es sollte eindeutig zu erkennen sein, wo der wesentliche Unterschied

13

Page 14: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

Frame Stack Current Stack

2 1 TaskB

1 TaskA

22

112 TaskC

Abbildung 3.2.: Frame Stack während der Ausführung von TaskA

Frame Stack Current Stack

2 TaskB 1 TaskBqq

1 TaskC 2 TaskCqq

Abbildung 3.3.: Frame Stack nach der Ausführung von TaskA

zum Ablauf eines vergleichbaren C Programms liegt. Beide Programme haben die gleicheDefinition und das gleiche Ergebnis: Den Wert 100.0 der Variable a auf dem Monitorauszugeben. Die Ausführung des Programms ist allerdings unterschiedlich.

Bei dem bekannten C Programm wird zuerst die Funktion main() ausgeführt. In dermain() wird eine Variable mit dem Bezeichner a definiert und an die Funktion setVal(;;)per Call by Reference übergeben. In der Funktion setVal wird dann a der Wert 100.0zugewiesen. Danach wird die Funktion printVar() aufgerufen, zu beachten ist, dass dieFunktion main weiterhin im Arbeitsspeicher vorhanden ist. Die printf Anweisung wirdalso ausgeführt und die Funktion printVar wird beendet. Danach wird die Funktionmain() wieder reaktiviert um sich letztendlich mit dem return Befehl zu beenden.

1 #include <s td i o . h>2

3 void setVal (double ∗a ) {4 p r i n t f ( "we i se ␣a␣den␣wert ␣ 100 .0 ␣zu\n" ) ;5 ∗a = 100 ;6 }7

8 void printVar (double a ) {9 p r i n t f ( "Die␣Var iab le ␣a␣hat␣den␣Wert␣%f \n" , a ) ;

10 }11

14

Page 15: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

12 int main (void ) {13

14 double a ;15

16 setVal (&a ) ; // c a l l by r e f e r ence17 printVar ( a ) ; // c a l l by va lue18

19 return 0 ;20 }

Listing 3.3: C Programm

Bei dem CES Programm ist der Ablauf ähnlich, aber es gibt doch einen wesentlichenUnterschied. Der CES Compiler generiert ein C File, dass die definierten Prozeduren alsTask implementiert. Das vorliegende Beispiel verdeutlicht den Ablauf bei der Ausführungdes Programms.

1 #include <s td i o . h>2

3 $program ( ; ; ) {4 $setVal ( ; ; double a ) ; $5 $printVar ( a ; ; ) ; $6 }$7

8 $setVal ( ; ; double a ) {9 p r i n t f ( "we i se ␣a␣den␣wert ␣ 100 .0 ␣zu\n" ) ;

10 $a$ = 100 . 0 ;11 }$12

13 $printVar (double a ; ; ) {14 p r i n t f ( "Die␣CES␣Var iab le ␣a␣hat␣den␣Wert␣%f \n" , $a$ ) ;15 }$

Listing 3.4: CES Programm

Abbildung 3.4 zeigt nochmal den Frame Stack während der Ausführung des CES Pro-gramms.

Die Run Time erzeugt auf dem Frame Stack den ersten Task program(;;) und beginntmit der Ausführung der Prozedur program(;;).

FrameStack CurrentStack

program(; ; )

Der Task program(;;) wird auf dem Frame Stack erzeugt

15

Page 16: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

Abbildung 3.4.: Frame Stack während der Ausführung des CES Programms

Nun wird der Task program(;;) ausgeführt. Der Kinder Task setVal(;;a) wird auf demCurrent Stack erzeugt.

FrameStack CurrentStack

program(; ; ) setV al(; ; a)

Der Task setVal(;;a) wird auf dem Current Stack angelegt

Aber es erfolgt keine Ausführung von setVal(;;a)! Der in dem Task definierteOutput Parameter erzeugt als nächstes ein Storage Frame a auf dem Frame Stack derdiesen Parameter beinhaltet. Dieser Outputparameter referneziert nun auf den Storagea. Dieser Storage ist mit dem Wert 0 initialisiert, damit die Ausgabe des Pretty Printerskeine undefinierten Zeichenketten ausgibt.

FrameStack CurrentStack

Storage(a) = 0

program(; ; ) setV al(; ; a)

hhQQQQQQQQQQQQ

Der Storage für die variable a wird auf dem Frame Stack erzeugt

Als nächstes wird der Task printVar(a;;) auf dem Current Stack erzeugt und alle Refe-renzen werden aufgelöst, d.h. in diesem Fall wird eine Referenz von dem Input Parametera auf den Storage a gebildet.

16

Page 17: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

FrameStack CurrentStack

Storage(a) = 0 // printV ar(a; ; )

program setV al(; ; a)

hhQQQQQQQQQQQQ

Der Task printVar(a;;) wird auf dem Current Stack erzeugt

Zuletzt werden alle von program(;;) erzeugten Tasks, die auf dem Current Stack liegen,auf den Frame Stack kopiert. Man kann sagen, dass program(;;) durch setVal(;;a) undprintVar(a;;) ersetzt wird. Der Current Stack ist nun leer.

FrameStack CurrentStack

setV al(; ; a)

yy

printV ar(a; ; )

Storage(a) = 0

OO

Der Current Stack wurde auf den Frame Stack kopiert

Der Task program(;;) ist somit zu Ende und es kann der zuvor belegte Speicherbereichfreigegeben werden. Die Run Time führt den nächsten Task aus. In diesem Beispiel istdas der Task setVal(;;a). Beim Ausführen von setVal(;;a) wird nun dem Storage a derWert 100.0 zugewiesen.

17

Page 18: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

FrameStack CurrentStack

setV al(; ; a)

yy

printV ar(a; ; )

Storage(a) = 100.0

OO

Der Task setVal(;;a) wird ausgeführt

Danach wird der Task setVal(;;a) beendet und printVar(a;;) wird als nächstes ausge-führt.

FrameStack CurrentStack

printV ar(a; ; )

Storage(a) = 100.0

OO

Der Task printVar(a;;) wird ausgeführt.

Der Task printVar(a;;) erzeugt die Ausgabe auf dem Monitor und endet.

FrameStack CurrentStack

Storage(a) = 100.0

Der Task printVar(a;;) erzeugt die Ausgabe und endet.

Der Storage hat keine weitere Bedeutung bzw. wird nicht mehr von einem anderenTask benötigt und kann somit freigegeben werden. Das Programm ist somit beendet. DerPretty Printer erzeugt die Ausgabe aus der folgenden Abbildung 3.5. Die Nummerierungan der linken Seite der Ausgabe bezeichnet die Nummer des Frames auf dem Frame Stack.Es kann somit nochmal der genaue Ablauf des CES Programms nachvollzogen werden.

18

Page 19: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

*****************EXECUTE 1****************1 program(;;)

*****************EXECUTE 2****************3 setVal(;;double a_1=0.000000)2 printVar(double a_1=0.000000;;)

weise a den wert 100.0 zu*****************EXECUTE 3****************

2 printVar(double a_1=100.000000;;)Die CES Variable a hat den Wert 100.000000

Abbildung 3.5.: Pretty Printer Ausgabe

19

Page 20: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

4. Die Sprache CES

Die Sprache CES ist eine Erweiterung der Programmiersprache C, die als neues Featureeine Prozedur als Task implementiert. Für diese neu implementierten Prozeduren wurdeeine neue Syntax eingeführt. Es kann weiterhin die Programmiersprache C benutzt wer-den. Im folgenden werden die neueingeführten Sprachkonzepte von CES aufgeführt undanhand einiger Beispiele deutlich gemacht.

4.1. Einführung in die Sprache von CES

4.1.1. Eigenschaften von CES

Die Sprache CES unterstützt die getrennte Kompilierung von Programmeinheiten wiein C bekannt. Es ist somit möglich bereits geschriebene Bibliotheken einzubinden undzu benutzen. Der in CES geschriebene Quellcode eines Programms kann aus mehrerenDateien bestehen. Die generierten C Dateien werden dann zusammen mit der runTime.cund der debug.c mit einem C Compiler kompiliert.

program.ces foo.ces

CES Compiler

�� ((QQQQQQQQQQQQQCES Compiler

��vvmmmmmmmmmmmmm

program.c

''PPPPPPPPPPPPHeaderF iles

��

foo.c

wwoooooooooooo

CESProgrammPräprozessorC Compiler

oo runTime.cdebug.c

oo

Abbildung 4.1.: Ablaufdiagramm eines Kompiliervorgangs

Die getrennte Kompilierbarkeit bietet die üblichen Vorteile, zum Beispiel:

• Bei Änderung müssen nur bestimmte Dateien bearbeitet werden, alle anderen Da-teien bleiben stabil.

• Außerdem kann der Kompilierlauf des gesamten Programms verkürzt werden, in-dem nur die veränderten Dateien kompiliert werden.

20

Page 21: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

4.1.2. Einordnung der Programmiersprache CES

CES gehört zu den imperativen und deklarativen Programmiersprachen, wie auch dieProgrammiersprache C.

4.1.3. Lexikalische Konventionen

Lexikalischer Zeichenvorrat

Der Zeichenvorrat in CES umfasst alle benutzbaren Zeichen aus C und zusätzlich dasDollarzeichen $. Dieses Zeichen wurde zur Vereinfachung des CES Compilers eingeführt.Der Scanner, der Teil des CES Compilers ist, kann somit leichter CES Code und CCode getrennt voneinander erkennen. Das Dollarzeichen wir am Anfag einer Prozedurvorrangestellt und am Ende mit einer geschweiften Klammer }$ beendet. Bei einemAufruf einer CES Prozedur muss am Anfang ein Dollarzeichen vorhanden sein und amEnde des Aufrufs muss ein Semikolon ;$ stehen.

Lexikalische Einheiten

Zu Beginn der Kompilierung eines CES Quellprogrammes liegt das Programm in Formder anschließenden lexikalischen Einheiten, auch Token genannt vor.

• Namen (Bezeichner, speziell für CES Prozedur Definition und Aufruf, sowie Varia-blennamen)

• reservierte Wörter

• C Code

Reservierte Wörter

program Zur Vereinfachung der Implementierung beginnt ein CES Programm mit derAusführung der Prozedur program(;;). Andere Prozeduren können mit selbstge-wähltem Namen bezeichnet werden. Hierbei sind gewisse Konventionen für dieNamensbildung einzuhalten (siehe Abschnitt Die CES Prozedur). Der Name pro-gram(;;) ist natürlich exklusiv für das Hauptprogramm reserviert und darf in einemCES Programm nicht ein zweites Mal als Prozedur definiert werden. Die Prozedurprogram(;;) dient als „Einsprung“ in das CES Programm und wird von der RunTime im Backend erzeugt. Diese Prozedur ist der Anfangspunkt wie die Funktionmain() aus der Programmiersprache C.

parallel Dieses Schlüsselwort dient dazu Prozeduraufrufe als parallel ausführbar zu mar-kieren. Die Möglichkeit der Funktion hierzu wurde noch nicht umgesetzt; alle CESProgramme laufen somit noch sequentiell ab. Die technische Umsetzung ist für eineerweiterte Version von CESC und dem Execution System geplant.

21

Page 22: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

4.1.4. Beispielprogramme

Aufbau eines CES-Programmes

Ein CES Programm besteht aus CES Prozeduren, deren Aufrufen, Variablen und C Code.Die Prozeduren nehmen die Rolle von Haupt- und Unterprogrammen ein. Sie haben dabeidie Aufgabe Teile eines Programmes unter eigenem Namen zusammenzufassen. Mit Hilfedes Prozedurnamens werden CES Prozeduren innerhalb eines Programmes aufgerufen.Dabei besteht die Möglichkeit der Prozedur beim Aufruf Argumente zu übergeben. DerAustausch von Informationen kann zum Beispiel in den CES Ausgabeparametern erfolgenoder auch über globale C Variablen. Bei der Ausführung wird der Task durch seine KinderTasks ersetzt. Wie bei C Funktionen können in CES die Prozeduren nicht geschachteltdefiniert werden. Dies bedeutet, dass es in CES nicht möglich ist eine Prozedur innerhalbeiner Prozedur zu definieren.

Programmbeispiel 1 Hallo, Welt!

1 #include <s td i o . h>2

3 $program ( ; ; ) {4 p r i n t f ( "Hallo , Welt ! " ) ; /∗ C Code ∗/5 }$

Listing 4.1: CES Programm Hallo, Welt!

Programmbeispiel 2 Euklid’scher Algorithmus

1 #include <s td i o . h>2

3 $program ( ; ; ) {4 int a ;5 int b ;6 int e rg ebn i s = 0 ;7 p r i n t f ( "\ tEuc l id ( a , b ) \n" ) ;8 p r i n t f ( "␣a␣ e ingeben ␣" ) ;9 s can f ( "%d" , &a ) ;

10 p r i n t f ( "␣b␣ e ingeben ␣" ) ;11 s can f ( "%d" , &b) ;12 $ euc l i d ( int a , int b ; int e rg ebn i s ; ) ; $13 $pr in tResu l t ( int e rg ebn i s ; ; ) ; $14 }$15 $pr in tResu l t ( int erg ; ; ) {16 p r i n t f ( "␣Ergebnis ␣=␣%d\n" , $erg$ ) ;17 }$

22

Page 23: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

18 $ euc l i d ( int a , int b ; int erg ; ) {19 i f ( $b$ == 0)20 $erg$ = $a$ ;21 else {22 int c = $a$ % $b$ ;23 $ euc l i d (b , int c ; erg ; ) ; $24 }25 }$

Listing 4.2: CES Programm Euklid’scher Algorithmus

4.1.5. Datentypen und Variablen

Datentypen, die zur Definition von Parameter oder Argumenten benutzt werden dürfennur aus einem Bezeichner bestehen. Es ist also nicht direkt möglich den Datentyp unsi-gned char zu benutzten. Eine Lösung wäre zuvor einen zusammengesetzten Datentyp zudefinieren:

1 typedef unsigned char UCHAR;

Alle Datentypen aus C, die aus einem Bezeichner bestehen können verwendet wer-den, zum Beispiel char, int, float, double, sowie zusammengesetzte bzw. selbstdefinierteDatentypen aus C.

Variabeln können als Parameter oder C-Variable definiert werden. Die Sichtbarkeitund Lebensdauer einer CES-Variable bezieht sich immer auf die CES Prozedur in der dieVariable definiert wurde. Somit vergleichbar mit dem Prinzip der lokalen Variablen ausdiversen anderen Programmiersprachen.

4.1.6. Der Präprozessor

Das Präprozessing wird von dem C Präprozessor übernommen. Unter anderem werden beider Übersetzung vom C Compiler die von CESC generierten Header Files eingebunden.

4.2. Die CES Prozedur

Eine CES Prozedur wird als ein Task Frame auf dem Frame Stack aufgerufen. Benötigtwerden ein Bezeichner für den Task, Parameter und einen Task Body. Zur Vereinfachungder Implementierung ist es nicht möglich einen Prototypen zu deklarieren. Der Austauschvon Informationen zwischen den Prozeduren erfolgt über die Parameter oder auch überMöglichkeiten, die C bietet wie z.B. globale Variablen.

4.2.1. Definition einer CES Prozedur

Eine CES Prozedur ist definiert durch das Zeichen „$“ am Anfang der Definition, denNamen der Prozedur und die Parameter. Der Name der CES Prozedur darf nur aus

23

Page 24: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

Buchstaben, Ziffern und einem „Unterstrich“ bestehen (diese Konvention wurde aus derProgrammiersprache C übernommen). Der reguläre Ausdruck hierfür ist in der scanner.lzu finden. Die drei Arten von Parameter Input, InOutput und Output müssen durchSemikolons getrennt werden. Durch diese Trennung können Abhängigkeiten zwischenden Prozeduren besser deutlich gemacht werden. Beinhaltet zum Beispiel ein Task Aeinen Parameter x als Ausgabeparameter, so erkennt man bei anderen definierten Taskswelche diesen Parameter als Eingabeparameter benutzen (siehe Abbildung 4.2).

$ProzedurName(inputParamListe;inOutputParamListe;outputParamListe){...}$

Zu beachten sind die Dollarzeichen am Anfang und Ende der Prozedurdefinition.

4.2.2. Die Parameter

Ein Parameter ist definiert durch seinen Typ und Bezeichner. Die Deklaration einesParameters sieht wie in C aus:

int parameter

Die folgende Abbildung 4.2 soll deutlich machen in welche Richtungen Informationenausgetauscht werden können und welche Parameter dazu benutzt werden müssen.

C Code ProzedurA ProzedurB

OutputA // InputB

C Variable // InOutputA // InputB

C Variable InputParameterAoo

Abbildung 4.2.: Informationsaustausch

Input Parameter

Die hier definierten Parameter dürfen nur lesend benutzt werden. Es ist möglich mehrereParameter als Liste zu definieren.

InOutput Parameter

Auf die hier definierten Parameter darf lesend und schreibend zugegriffen werden, dasheißt es ist möglich innerhalb dieser CES Prozedur den Wert der Variablen zu verändern.

24

Page 25: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

Output Parameter

Die hier definierten Parameter dürfen nur schreibend benutzt werden.

4.3. Der CES Aufruf

Der Aufruf eines CES Prozedur erfolgt durch folgende Syntax.

$ProzedurName(inputArgListe;inOutputArgListe;outputArgListe);$

Zu beachten sind die Dollarzeichen am Anfang und Ende des Prozeduraufrufs. In dereinfachen CESC Implementierung ist es nur möglich eine Variable als Argument zu über-geben. Es ist also nicht möglich einen Ausdruck zu übergeben. Der CES Aufruf kann auchohne Argumente erfolgen. Sollte der Fall eintreten, dass mehr oder weniger Argumenteübergeben werden, als in der CES Prozedur definiert, so wird es eine Fehlermeldung vomC Compiler geben. Die einfache CESC Implementierung überprüft dies nicht.

Wird dem CES Aufruf eine C Variable als Argument übergeben so muss darauf geachtetwerden den zugehörigen Datentyp davor zu setzen um dem CES Compiler mitzuteilenwelchen Datentyp diese C Variable hat. Handelt es sich bei dem Argument um eine zuvordefinierte CES Variable so ist dies nicht nötig, da dem CES Compiler diese Variable (als Symbol) bekannt ist.

4.3.1. Vorsicht Falle!

Ein Programmierer, der das Konzept der Activation Frames gewohnt ist, wird wahr-scheinlich nicht daran denken, dass ein CES Aufruf nicht sofort ausgeführt wird. Einkleines Beispiel soll verdeutlichen welche Umgewöhnung nötig ist.

1 $program ( ; ; ) {2 $setVal ( ; ; int a ) $ ;3 p r i n t f ( "Der␣Wert␣von␣a␣ i s t ␣%d\n" , $a$ ) ; // und e f i n i e r t e

Ausgabe ! ! !4 }$5

6 $setVal ( ; ; int a ) {7 $a$ = 100 ;8 }$

Listing 4.3: Beispiel mit Fehlerquelle

Die Ausgabe der printf Anweisung in Zeile 3 ist undefiniert. Der CES Aufruf setval(;;a)in Zeile 6 bewirkt nur ein Erzeugen des Task Frames auf dem Current Stack. setVal(;;a)wird nicht ausgeführt! Dies ist zu beachten.

25

Page 26: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

4.4. Die CES Variable

Als CES Variable werden Variablen bezeichnet, die als InOutput oder nur Output Ar-gument oder Parameter deklariert sind. Soll eine CES Variable benutzt werden, müssenvor und nach dem Bezeichner Dollarzeichen gesetzt werden. Es ist möglich eine CESVariable wie eine C Variable im C Code zu benutzen. Beispielsweise ist es möglich durchZuweisungen Werte zwischen C und CES Variablen auszutauschen oder CES Variablenkönnen auch als Argumente an eine C Funktion übergeben werden. Die Syntax siehtfolgendermaßen aus.

$var$

In den vorgehenden CES Quelltexten sind viele Beispiele, die eine CES Variable in CCode benutzten.

26

Page 27: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

5. Das Backend

Das Backend setzt sich zusammen aus der Run Time, das vom CES Compiler generierteC Files, einem C Compiler und anderen C Entwicklungstools. Der CES Compiler wirdim nächsten Kapitel im Detail besprochen.

5.1. Die Run Time

Die Run Time beinhaltet eine Funktion zur Ausführung des obersten Tasks auf demFrame Stack. Es wird immer nur ein Task von der Run Time ausgeführt. Erst wenndieser beendet ist wird der nächste Task ausgeführt.

1 void exec_top_of_fs ( ) {2 while ( f sp >= frame_stack ) {3 i f ( fsp−>ance s to r == 0 && fsp−>func_ptr != func_storage ) {4 i f ( show_stack == 1) {5 show_fs ( ) ;6 }7 (∗ ( ( void (∗∗ ) (void ) ) f sp ) ) ( ) ; /∗ execu te top o f s t a c k ∗/8 } else {9 f s p −= 1 ; /∗ s e t frame s t a c k po in t e r to next t a s k ∗/

10 }11 }12 }

Listing 5.1: Funktion aus der Run Time zur Ausfürung eines Task

Der ausführbare Task ist immer eine C Funktion ohne Parameter mit dem Rückgabe-wert void. Diese C Funktion wurde vom CES Compiler generiert. Die Codegenerierungwird in einem späteren Abschnitt dieses Kapitels erklärt.

5.2. Datenstrukturen

5.2.1. Der Task Frame

Die Datenstruktur eines Task Frame auf dem Stack ist in der run_time.h folgendermassendefiniert:

1 typedef struct {2 void (∗ func_ptr ) (void ) ;3 void (∗ print_func ) (void ) ;

27

Page 28: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

4 int numIn ;5 int numInOut ;6 int numOut ;7 void ∗parameter [ARG_SIZE ] ;8 int ance s to r ; // benu t z t von der Run Time9 char ∗name ; // benu t z t vom Pre t t yPr in t e r

10 int p a r a l l e l ; // benu t z t vom Pre t t yPr in t e r ( nur fü r Ausgabe ,ke ine Implementat ion bzw Funktion )

11 } TASK_FRAME;

Listing 5.2: TASK_FRAME Datenstruktur aus der run_time.h

Für jeden Task wird ein taskspezifischer Frame generiert, der auf der aufgeführtenTASK_FRAME Datenstruktur aufbaut. Dieser taskspezifische Frame wird speziell ineinem eigenen Header File <Task Name>.h generiert. Da für diese taskspezifische Struk-tur die Variablen ancestor, parallel und *name nicht verwendet werden, sind diese nichtim eigenen Header File deklariert.

1 typedef struct {2 void (∗ func_foo ) (void ) ; // Neuimplementierung des Task a l s

Prozedur bzw C Funktion3 void (∗ print_func ) (void ) ; // Print Funktion zur

S e l b s t d a r s t e l l u n g fü r den Pre t ty Pr in te r4 int numIn2 ; // Anzahl der Input Parameter5 int numInOut1 ; // Anzahl der InOutput Parameter6 int numOut0 ; // Anzahl der Output Parameter7 int ∗ in1 ; // 1 . Input Parameter8 . . . // e v e n t u e l l e z u s ä t z l i c h e Input Parameter9 int ∗ inOut1 ; // 1 . InOutput Parameter

10 . . . // e v e n t u e l l e z u s ä t z l i c h e InOutput Parameter11 int ∗out1 ; // 1 . Output Parameter12 . . . // e v e n t u e l l e z u s ä t z l i c h e Output Parameter13 // maximal ARG_SIZE Parameter14 } Struct_foo ;

Listing 5.3: Beispiel einer von CESC generierten Task Struktur im Header File

Da Struct_foo auf der Struktur von TASK_FRAME aufbaut, kann die Run Time dieseals Task Frame TASK_FRAME benutzten.

Alle Frames auf dem Frame Stack haben die gleiche Grösse. Die Strukturgrösse wurdekonstant gehalten um eine Vereinfachung bei der Implementierung zu haben. Diese ge-wählte Lösung bietet den Vorteil Schwierigkeiten bei der Zeigerarithmetik zu vermeiden.Es ist also zu jedem Zeitpunkt einfach bekannt wo sich alle Informationen über einenTask im Speicher befinden. Da der Frame Stack wie ein Array aufgebaut ist kann übereinen Index direkt auf jeden Frame zugegriffen werden. Ein weiterer Vorteil ist beim De-bugging zu erkennen. Der Pretty Printer kann sehr leicht alle Frames ausgeben. Ziel ist es

28

Page 29: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

nicht an Ressourcen und Performance zu sparen sondern das Prinzip und die Abfolge imSpeicher klar und deutlich zu präsentieren. Daher wurde eine einfache Struktur gewählt.

Der Funktionszeiger func_ptr

Dieser Funktionszeiger ist der eigentliche Kern eines Task Frames. Der in Zeile 2 definierteFunktionszeiger zeigt auf die auszuführende C Funktion in dem generierten C File, derden CES Task als Prozedur repräsentiert. Die Namen des Task und der C Funktion sindidentisch. Da die Parameter im Frame sind, wurde der Rückgabewert und die Parameterdes Funktionszeigers als void definiert.

Der Funktionszeiger print_func

Zu Debugzwecken wurde ein zweiter Funktionszeiger print_func definiert. Dieser zeigtauf die generierte Print Funktion. Jeder Task beinhaltet eine eigene Print Funktion, dieden Task im Pretty Printer ausgibt. Die Anzahl und Typen der Parameter ist von Taskzu Task unterschiedlich. Der Pretty Printer führt dann diese spezielle Print Funktionaus.

Überprüfung der Parameteranzahl

Die drei Integervariablen numIn, numInOut und numOut in Zeile 4, 5 und 6 dienenzur Überprüfung der Anzahl von Parametern in dem definierten Task Frame. Allerdingswird der Wert der Variablen nicht benutzt, sondern der Name der Variable gibt an wievielParameter definiert sind.

Hier ein Beispiel um die genaue Funktion der Parameterüberprüfung zu verdeutlichen.Der Task

$euclid(int a, int b; int erg){...}

1 $ euc l i d ( int a , int b ; int erg ; ) {2 int c ;3 i f ( $b$ == 0)4 $erg$ = $a$ ;5 else {6 c = $a$ % $b$ ;7 $ euc l i d (b , c ; erg ; ) ; $8 }9 }$

Listing 5.4: Beispiel zur Parameterprüfung

erzeugt folgende Struktur.

1 typedef struct {

29

Page 30: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

2 void (∗ func_euc l id ) (void ) ; // Neuimplementierung des Task a l sProzedur bzw C Funktion

3 void (∗ print_func ) (void ) ; // Print Funktion zurS e l b s t d a r s t e l l u n g fü r den Pre t ty Pr in te r

4 int numIn2 ; // Anzahl der Input Parameter5 int numInOut1 ; // Anzahl der InOutput Parameter6 int numOut0 ; // Anzahl der Output Parameter7 int ∗ in1 ; // 1 . Input Parameter8 int ∗ in2 ; // 2 . Input Parameter9 int ∗ inout1 ; // 1 . InOutput Parameter

10 } Struct_euc l id ;

Listing 5.5: Datenstruktur des Tasks euclid(b,c;;double erg2)

Da der Task euclid(a,b;;c) 2 Input Parameter definiert hat befindet sich hinter derVariablen numIn die Zahl 2. So kann später bei einem Task Aufruf durch den C Com-piler festgestellt werden ob die Definition mit der tatsächlichen Anzahl an Parameterübereinstimmt. Würde dem Task Aufruf ein Argument fehlen $euclid(int c;erg ;) ;$ sohätte dies folgende Fehlermeldung zur folge.

ces_program.c: In function ‘euclid’:ces_program.c:168: structure has no member named ‘numIn1’make: *** [gcc] Error 1

Warum diese doch etwas umständliche Art der Überprüfung von Parameter? Um dieImplementierung des CES Compiler zu vereinfachen wurde die Überprüfung an den CCompiler weitergegeben. Die nötigen Informationen, die der C Compiler braucht ist je-weils der Bezeichner der drei Variablen numIn, numInOut und numOut.

Das Zeigerarray parameter[ARG_SIZE]

Die hier definierten Zeiger zeigen auf die im Task definierten Parameter, diese referenzie-ren auf ein vorher angelegtes Storage. ARG_SIZE wurde in der run_time.h deklariertund ist eine Konstante die die Anzahl der maximalen Parameter oder Argumente ineinem Task vorgibt. Für das Parameter Array wurde bewusst eine konstanten Grössegewählt, da eine Struktur mit variabler Grösse einen zu grossen Aufwand bei der CESCImplementierung mit sich bringen würde. Zum Beispiel bei der Ausgabe im Pretty Prin-ter müsste jedesmal der Offset im Frame Stack berechnet werden. Bei konstanter Grösseder Frames im Frame Stack ist es einfacher zu berechnen an welcher Position sich derZeiger auf den Parameter befindet. Da nicht bekannt ist welcher Typ von Parameterndefiniert werden, muss hier ein void Zeiger verwendet werden. So ist gesichert, dass dieZeiger in dem Array auf jeden Parametertyp zeigen kann.

Die Variable ancestor

Um ausgeführte Tasks auf dem Frame Stack anzeigen zu können, wurde eine Variableancestor angelegt, die mit dem Wert 1 einen noch auszufühenden Task repräsentiert

30

Page 31: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

und mit dem Wert 0 einen schon ausgeführten Task anzeigt. Dies dient lediglich zurAnzeige beim Pretty Printer. ancestor wird nicht im Frame, dass im Header File fürden zugehörigen Task generiert wurde, definiert. ancestor hat keine Auswirkung auf dasProgramm, sondern dient lediglich der Ausgabe des Pretty Printers.

*****************EXECUTE 1****************1 program(;;)

*****************EXECUTE 2****************4 setVal(;;double a_2=0.000000)3 printVar(double a_2=0.000000;;)1 ANCESTOR program(;;)

*****************EXECUTE 3****************3 printVar(double a_2=100.000000;;)1 ANCESTOR program(;;)

Die CES Variable a hat den Wert 100.000000

Abbildung 5.1.: Pretty Printer Ausgabe mit dem „ancestor“ Task program(;;)

Der String name

Der String name beinhaltet den Namen des Tasks. Diese ist für die Ausgabe des PrettyPrinters wichtig.

Die Variable parallel

Steht parallel vor einem Task Auruf so kann dieser unabhängig von anderen CES Proze-dur Aufrufen ausgeführt werden. Diese Funktion wurde allerdings noch nicht umgesetzt.Die Variable parallel enthält bei der Ausführung des Programms den Wert 1, wenn derCES Aufrufmit dem Schlüsselwort parallel gekennzeichnet wurde. Ansonsten ist der Wert0. Der Pretty Printer zeigt welche Task Frames auf verschiedenen Prozessoren ausgeführtwerden könnten.

5.2.2. Der Storage

Eine Speichereinheit für eine CES Variable auf dem Frame Stack wird als Storage bezeich-net. Dieser beinhaltet den Wert und Namen der Variable sowie einen Funktionszeiger aufdie Storage C Funktion. Der Wert der Variable, die der Storage verwaltet, wird in demgenerierten Member value gespeichert. Der Datentyp von value wird automatisch vomCES Compiler generiert und ist somit von der Definition der Variablen abhängig.

Ein Storage hat folgende Struktur.

1 typedef struct {2 void (∗ func_storage ) (void ) ; // Funk t i ons z e i g e r auf d i e s t o rag e

Funktion

31

Page 32: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

3 char ∗name ; // Name der Var iab l e4 <type> value ; // Datentyp <type> abhängig von der De f i n i t i on

der Var iab l e5 } STORAGE_FRAME;

Listing 5.6: STORAGE_FRAME Datenstruktur

Die maximale Grösse eines selbstdefinierten Datentyps ist 4 Byte * ARG_SIZE. DieseGrösse darf nicht überschritten werden. Ansonsten würden Daten vom nächsten Frameüberschrieben werden. Dieses Problem ist allerdings abhängig von der Implementierungund nicht fundamental.

Der Funktionszeiger func_storage

Der Zeiger func_storage zeigt auf die C Funktion storage, die in der run_time.c imple-mentiert ist. Wird die storage Funktion ausgeführt, so wird der Frame Stack Pointer aufden nächsten Frame gesetzt.

1 void func_storage ( ) {2 f s p −= 1 ; // f s p auf nächsten Frame se t z en3 }

Listing 5.7: Storage Funktion

Der String name

Der String name beinhaltet den Namen der CES Variable. Diese ist für die Ausgabe desPretty Printers wichtig. Die Variable *name wird nicht in der taskspezifischen Strukturim Header File erzeugt.

Die Variable value

Ein Storage wird bei der Ausführung eines Task angelegt, sobald eine CES Variable ineiner Prozedur deklariert wurde und der Task auf den Frame Stack kommt. Die Rei-henfolge ist hier sehr wichtig, damit alle nachkommenden Prozeduren auf den Storagezugreifen können. Bei der Ausführung eines Tasks werden immer zuerst alle Storagesauf dem Stack erzeugt und dann die Task Frames der Kinder Tasks. Der CES Compilergeneriert somit C Code, der ein Storage erzeugt. Erst bei der Ausführung der Prozedur,die den Storage erzeugt bzw. benutzt wird der Wert geschrieben oder ausgelesen. DieseLösung wurde gewählt um eine Vereinfachung der Implementierung im CES Compiler zubekommen.

Im folgendem Beispiel soll ersichtlich werden wie ein Storage erstellt wird.

1 #include <s td i o . h>2

3 $program ( ; ; ) {4 $setVal ( ; ; double a ) ; $

32

Page 33: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

FrameStack CurrentStack

setV al(; ; a)

yy

printV ar(a; ; )

Storage(a) = 100.0

OO

Abbildung 5.2.: Frame Stack nach der Ausführung von program(;;)

5 $printVar ( a ; ; ) ; $6 }$7

8 $setVal ( ; ; double a ) {9 $a$ = 100 . 0 ;

10 }$11

12 $printVar (double a ; ; ) {13 p r i n t f ( "Die␣CES␣ va r i ab l e ␣a␣hat␣den␣Wert␣%f \n" , $a$ ) ;14 }$

Listing 5.8: CES Programm zur Storage Erzeugung

CESC generiert aus dem CES Quelltext folgenden C Code als Storage Struktur.

1 /∗ CREATE STORAGE FOR OUTPUT ARGUMENT ’a ’ ∗/2 typedef struct {3 void (∗ func_storage ) (void ) ;4 char ∗name ;5 double value ;6 } Struct_storage_a_ptr ;

Listing 5.9: Datenstruktur eines Storage für double a

CESC erzeugt einen Storage für die CES Variable a. Der Scope dieser Struktur be-zieht sich nur auf die C Funktion, in der die Struktur definiert wurde. Die Struktur istsomit lokal. Dies ermöglicht bei verschiedenen CES Prozeduren gleiche Bezeichner fürParameter zu benutzen. Innerhalb einer CES Prozedur dürfen keine gleichen Bezeichnerfür Variablen benutzt werden; auch nicht wenn sie unterschiedliche Typen hätten.

Die Abbildung 5.3 zeigt die Ausgabe des Pretty Printers. Die Nummerierung an derlinken Seite der Ausgabe bezeichnet die Nummer des Frames auf dem Frame Stack.

33

Page 34: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

*****************EXECUTE 1****************1 program(;;)

*****************EXECUTE 2****************4 setVal(;;double a_2=0.000000)3 printVar(double a_2=0.000000;;)1 ANCESTOR program(;;)

*****************EXECUTE 3****************3 printVar(double a_2=100.000000;;)1 ANCESTOR program(;;)

Die CES Variable a hat den Wert 100.000000

Abbildung 5.3.: Pretty Printer Ausgabe mit dem „ancestor“ Task program(;;)

Frame 2, der nicht vom Pretty Printer angezeigt wird, beinhaltet den Storage für dieCES Variable a. Erst bei Ausführung der Prozedur setVal bekommt a den Wert 100zugewiesen.

Damit die Ausgabe vom Pretty Printer keine undefinierten Werte in den Storage Fra-mes anzeigt wurde bei der Codegenerierung der Wert auf 0 initialisiert.

5.3. Die Header Files

Der CES Compiler erzeugt ein Header File für jede definierte CES Prozedur. Jedes gene-rierte Header Files beinhaltet die taskspezifische Struktur. Diese Struktur ist notwendig,um einen Task, der aufgerufen wurde, auf dem Stack zu erzeugen, sowie Operationenbezüglich der Parameter durchführen zu können. Diese Struktur ist auf die StrukturTASK_FRAME (siehe Abschnitt Datenstruktur) aufgebaut.

Das nächste Beispiel zeigt im CES Quellcode die definierte Prozedur printVar(doublea;;). Zur Vereinfachung der Implementierung werden die Namen der Parameter hier nichtmehr verwendet, da zu diesem Zeitpunkt der Übersetztung die Header Files bei fremdenProzeduren vom CES Compiler gescannt werden müssten, um den Namen der Parameterbenutzen zu könenn. Als einfache Lösung werden die Parameter vom CES Compilerdurchnummeriert. Ein Beispiel zum besseren Verständnis: der erste Input Parameter hatden Namen in1, der dritte Output Parameter out3 und der sechste InOutput Parameterden Namen inOut6. Die Struktur bekommt den Typennamen Struct_<NameDesTask>.Es ist nun möglich mit diesem Datentyp z.B. einen Zeiger zu definieren. Die Anweisung

1 $printVar (double a ; ; ) {2 p r i n t f ( "Die␣CES␣ va r i ab l e ␣a␣hat␣den␣Wert␣%f \n" , $a$ ) ;3 }$

Listing 5.10: CES Prozedur printVar(double a;;)

im CES Quelltext führt bei der Codegenerierung durch den CES Compiler zu fol-gendem Eintrag in der ces_print.h. Der Name des Header Files wird definiert durch

34

Page 35: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

ces_<NameDesTask>.h.

1 #ifndef CES_printVar_H2 #define CES_printVar_H3

4 typedef struct {5 void (∗ func_printVar ) (void ) ;6 void (∗ print_func ) (void ) ;7 int numIn1 ;8 int numInOut0 ;9 int numOut0 ;

10 double ∗ in1 ;11 } Struct_printVar ;12

13 void printVar (void ) ;14

15 #endif

Listing 5.11: Datenstruktur des Tasks print_Var(double a;;)

5.4. Der von CESC generierte C Code

Das vom CES Compiler generierte C File ergibt zusammen mit der Run Time das aus-führbare Programm. Ist die Kompilierung des CES Source Code Files durch den CESCompiler efolgreich gewesen, so wird ein C File generiert welches die Tasks als Prozedurenimplementiert und den C Code so übernimmt, wie er im CES Quellcode definiert wurde.In diesem Abschnitt werden die Inhalte des vom CES Compiler generierten C Files undderen Zwecke erläutert und im Detail besprochen. Das C File ist nur zusammen mit derRun Time ausführbar.

Die in diesem Kapitel beschriebene Codegenerierung bezieht sich auf folgendes CESBeispiel:

1 #include <s td i o . h>2

3 $program ( ; ; ) {4 $setVal ( ; ; double a ) ; $5 $printVar ( a ; ; ) ; $6 }$7

8 $setVal ( ; ; double a ) {9 $a$ = 100 . 0 ;

10 }$11

12 $printVar (double a ; ; ) {

35

Page 36: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

13 p r i n t f ( "Die␣CES␣ va r i ab l e ␣a␣hat␣den␣Wert␣%f \n" , $a$ ) ;14 }$

Listing 5.12: CES Programmbeispiel

FrameStack CurrentStack

setV al(; ; a)

yy

printV ar(a; ; )

Storage(a) = 100.0

OO

Abbildung 5.4.: Frame Stack nach der Ausführung von program(;;)

Im generierten C File werden zuerst alle benötigten Standard C Bibliotheken und Hea-der Files aus der Run Time eingebunden. Diese sind für spätere Anwendungen notwendig.

1 #include <s td i o . h>2 #include <s t r i n g . h>3 #include "debug . h"4 #include "run_time . h"

Die extern definierten Variablen aus der Run Time werden zusätzlich gebraucht. Dazugehören der Frame Stack Zeiger zusammen mit dem Frame Stack, Current Stack Zeigerzusammen mit dem Current Stack und zusätzliche Zeiger auf den Anfang der beidenStacks.

1 extern TASK_FRAME ∗ f s p ; /∗ frame s t a c k po in t e r ∗/2 extern TASK_FRAME ∗ csp ; /∗ curren t s t a c k po in t e r ∗/3 extern TASK_FRAME ∗ptr ; /∗ the a c t ua l t a s k frame ∗/ \TODO4 extern TASK_FRAME ∗ fs_bottom ; /∗ bottom of the frame s t a c k ∗/5 extern TASK_FRAME ∗cs_top ; /∗ top o f the curren t s t a c k ∗/

Der oben gezeigte Code wird unabhängig vom CES Quelltext erzeugt.Danach werden alle Prototypen der Print Funktionen einer jeden definierten CES Pro-

zedur erzeugt. Diese sind für die Ausgabe des Tasks durch den Pretty Printer nötig.Die Print Funktion wird an den dazugehörigen Funktionszeiger print_func in der TaskStruktur, die im Header File erzeugt wurde, übergeben.

1 void ces_print_program (void ) ;

36

Page 37: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

2 void ces_print_setVal (void ) ;3 void ces_print_printVar (void ) ;

Dann wird C Code aus dem CES Quelltext in das C File kopiert bis die erste CESProzedur erreicht ist. Danach wird das Header File der erreichten Prozedur durch ei-ne include Anweisung eingebunden. Im Anschluss folgen die Header Files der von dererreichten Prozedur aufgerufenen Prozeduren.

1 //CES Que l l t e x t2 $program ( ; ; ) {3 setVal ( . . . ) ;4 printVar ( . . . ) ;5 }$

1 // g en e r i e r t e r C Code zum CES Que l l t e x t2 . . .3 #include "program . h"4 #include " setVal . h"5 #include " pr intVar . h"6 void program (void ) {7 . . .8 }9 . . .

Nun wird für die erreichte CES Prozedur die C Funktion generiert. Jede CES Proze-durdefinition erzeugt eine gleichnamige C Funktionen.

In der gleichnamigen C Funktion wird zuerst der Frame Stack Zeiger kopiert. Hierzuwird ein Zeiger definiert, der auf die passende Datenstruktur des Tasks zeigen kann. DerWert des Zeigers wird auf die Adresse des Frame Stack Zeigers gesetzt. Dieser Zeigerwird später benötigt, um die Referenzen auf die Parameter des Tasks, die auf dem FrameStack vorhanden sind, setzen zu können.

1

2 void program (void ) {3 /∗ d i e Funktion program braucht ke ine Sicherung des f s p ∗/4 . . .5 }6

7 #include " ces_setVal . h"8

9 void setVal (void ) {10 /∗ SAVE ME se tVa l ∗/11 Struct_setVal ∗me = ( Struct_setVal ∗) f sp ; // Kopie der Adresse

auf dem Frame Stack12 . . .

37

Page 38: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

13 }14

15 #include " ces_pr int . h"16

17 void printVar (void ) {18 /∗ SAFE ME printVar ∗/19 Struct_printVar ∗me = ( Struct_printVar ∗) f sp ;20 . . .21 }

Danach wird aus dem CES Quelltext weiter C Code kopiert bis die nächste CES Pro-zedur erreicht wird. Diese Prozedur wird gleich behandelt wie die Erste. Dieser Vorgangwiederholt sich bis zum Ende des CES quelltextes.

Zuletzt werden die Print Funktionen für die definierten Tasks generiert. Der hier aufge-führte Quellcode ist abhängig vom Prozedurnamen und deren definierten Parameter. Aufdie Berechnung der Storage Frames für die Ausgabe wird hier nicht genauer eingegangen.

1 void ces_print_setVal (void ) {2 int ∗value_out1 = ( ( ( Struct_setVal ∗) ptr )−>out1 ) ;3 int storage_index_out1 = ( ( ( char∗) value_out1 −(char∗) fs_bottom

) / s izeof (TASK_FRAME) )+1;4

5 p r i n t f ( " setVal ( " ) ; //Bezeichner der CES Prozedur6 p r i n t f ( " ; " ) ;7 p r i n t f ( " ; " ) ;8 p r i n t f ( "%s_%d" , ∗(char∗∗) ( ( char∗) ( ( ( Struct_setVal ∗) ptr )−>

out1 ) −(((char∗)&( s to rage . va lue ) )−((char∗)&( s to rage . name) )) ) , storage_index_out1 ) ; //Berechnung des Storage fü r d i ee r s t e Output Var iab l e

9 p r i n t f ( "=%d" ,∗ ( ( Struct_setVal ∗) ptr )−>out1 ) ;10 p r i n t f ( " ) " ) ;11 }

5.4.1. C Code

Das oben beschriebene Kopieren des C Codes in das generierte C File bewirkt, dass dieReihenfolge und die Semantik des kopierten C Codes nicht beeinflusst ist von generiertenCodefragmenten des CES Compilers.

5.4.2. CES Prozedur Aufruf

Ist im CES Quelltext ein CES Aufruf vorhanden, so wird daraus folgender C Code ge-neriert:

1 //CES Que l l t e x t

38

Page 39: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

2 $program ( ; ; ) {3 . . .4 setVal ( ; ; double a ) ;5 . . .6 }$

1 void program (void ) {2 . . .3 /∗ PUSH TASK TO CURRENT STACK ∗/4 csp −= 1 ;5 csp−>ance s to r = 0 ;6 csp−>p a r a l l e l = 0 ;7 csp−>name = " setVal " ;8 ( ( Struct_setVal ∗) csp )−>numIn0 = 0 ;9 ( ( Struct_setVal ∗) csp )−>numInOut0 = 0 ;

10 ( ( Struct_setVal ∗) csp )−>numOut1 = 1 ;11 ( ( Struct_setVal ∗) csp )−>func_setVal = &setVal ; //

Funk t i ons z e i g e r auf d i e C Funktion12

13 ( ( Struct_setVal ∗) csp )−>print_func = &ces_print_setVal ; //Funk t i ons z e i g e r auf d i e Print Funktion

14

15 /∗ CREATE REFERENCE FROM OUTPUT ARG ’a ’ TO STORAGE ∗/16 ( ( Struct_setVal ∗) csp )−>out1 = &(storage_a_ptr−>value ) ;17 . . .18 }

Zuerst wird der Current Stack Zeiger auf den nächsten Frame gesetzt. Die Memberancestor und parallel werden initialsiert. ancestor mit dem Wert 0 bedeutet dass dertask nocht nicht ausgeführt wurde. parallel mit dem Wert 0 bedeutet, dass der Tasknicht parallel ausgeführt werden kann. Der Name des Tasks wird in den Member namegeschrieben. Nun werden die Variablen für die Argumentenanzahl des Task initialisiert.Die Funktionszeiger func_setVal und print_func werden auf die Adressen der C Funk-tionen gesetzt. Zuletzt wird C Code generiert der Referenzen für die Argumente auf dieStorages erzeugt. Output Argument out1 auf den Storage für die Variable a. Dies istabhängig der Parameterdefinitionen in der CES Prozedur.

5.4.3. Verwendung einer CES Variablen

Tritt der Fall auf, dass auf eine CES Variable schreibend zugegriffen wird,

1 // CES Que l l t e x t2 $setVal ( ; ; double a ) {3 p r i n t f ( "we i se ␣a␣den␣wert ␣ 100 .0 ␣zu\n" ) ;4 $a$ = 100 . 0 ;

39

Page 40: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

5 }$

so sieht der generierte Code folgendermaßen aus:

1 // g en e r i e r t e r C Code2 void setVal (void ) {3 . . .4 p r i n t f ( "we i se ␣a␣den␣wert ␣ 100 .0 ␣zu\n" ) ;5 ∗(me−>out1 ) = 100 . 0 ;6 . . .7 }

Die Variable out1 ist das erste Output Argument aus dem dazugehörigen CES Task.Diese wurde im dazugehörigen Header File setVal.h definiert. Bei lesendem Zugriff wirddieser Code generiert.

1 void printVar (void ) {2 . . .3 p r i n t f ( "Die␣CES␣Var iab le ␣a␣hat␣den␣Wert␣%f \n" , ∗(me−>in1 ) ) ;4 . . .5 }

Die Variable in1 ist das erste Input Argument aus dem dazugehörigen CES Task setVal.Diese Variable ist ebenfalls im Header File definiert worden.Der Zeiger me zeigt auf denaktuellen Task Frame auf dem Frame Stack.

5.4.4. Den Storage erzeugen

Gibt es CES Aufrufe deren Argumente eine CES Variable erzeugen sollen so muss einStorage angelegt werden. Hierzu wird vom CES Compiler die Datenstruktur für daspassende Storage generiert. Der Name der Struktur des Storages und der Name desZeigers der auf den Storage Frame sind folgendermaßen definiert.

Name der Datenstruktur Struct_storage_<Name der CES Variable>_ptrName des Zeiger *storage_<Name der CES Variable>_ptrDie Referenzen können danach aufgelöst werden. Zuerst wird der Storage Zeiger auf

den Storage Frame gesetzt. Der Funktionszeiger func_storage wird der Storage Funktionaus der Run Time zugewiesen. Diese Storage Funktion sorgt dafür, dass der Frame StackPointer bei der Ausführung auf den nächsten Frame gesetzt wird. Der Wert der MemberVariable value des Storages wird mit 0 initialisiert. Diese verhindert bei der Ausgabedurch den Pretty Printer unnötig lange Ausgaben. Der Name des Storage wird an denMember name der Struktur übergeben. Zuletzt wird der Frame Stack Pointer auf dennächsten Frame gesetzt.

Der generierte Code im C File für die Datenstruktur des Storages ist folgendermaßenaufgebaut:

1 void program (void ) {2 . . .

40

Page 41: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

3 /∗ CREATE STORAGE FOR OUTPUT ARGUMENT ’a ’ ∗/4 typedef struct {5 void (∗ func_storage ) (void ) ;6 char ∗name ;7 double value ; // Datentyp abhängig von der De f i n i t i on8 } Struct_storage_a_ptr ;9

10 /∗ SET STORAGE PTR TO STORAGE FRAME ON FRAME STACK ∗/11 Struct_storage_a_ptr ∗ storage_a_ptr = (

Struct_storage_a_ptr ∗) f sp ;12 storage_a_ptr−>func_storage = &func_storage ;13 storage_a_ptr−>value = 0 ;14 storage_a_ptr−>name = "double ␣a" ;15 f s p += 1 ;16 . . .17 }

5.4.5. Kopie des Current Stack auf den Frame Stack

Als letztes generiert der CES Compiler in der C Funktion C Code um den gesamtenCurrent Stack auf den Frame Stack zu kopieren.

1 /∗ COPY CURRENT STACK TO FRAME STACK ∗/2 memcpy( fsp , csp , ( cs_top − csp ) ∗ s izeof (TASK_FRAME) ) ;3 f s p += ( cs_top−csp )−1;4 csp = cs_top ;

5.4.6. Die Print Funktion

Für die Ausgabe der Tasks auf dem Frame Stack generiert CESC C Code, der die PrintFunktion für den Pretty Printer darstellt. Die Anzahl der Parameter ist hier Abhängig vonder Definition in der CES Prozedur. Zusätzlich wurde jedem Frame ein Index zugewiesen.Die Variable heisst storage_index_<Name_des_Parameters>. Auf die Berechnung wirdhier nicht näher eingegangen.

1 void ces_print_setVal (void ) {2 int ∗value_out1 = ( ( ( Struct_setVal ∗) ptr )−>out1 ) ; // Ze iger auf

Parameter3 int storage_index_out1 = ( ( ( char∗) value_out1 −(char∗) fs_bottom

) / s izeof (TASK_FRAME) )+1; // Index des Frames auf dem FrameStack

4

5 p r i n t f ( " setVal ( " ) ; //Bezeichner der CES Prozedur6 p r i n t f ( " ; " ) ;

41

Page 42: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

7 p r i n t f ( " ; " ) ;8 p r i n t f ( "%s_%d" , ∗(char∗∗) ( ( char∗) ( ( ( Struct_setVal ∗) ptr )−>

out1 ) −(((char∗)&( s to rage . va lue ) )−((char∗)&( s to rage . name) )) ) , storage_index_out1 ) ; //Berechnung des Storage fü r d i ee r s t e Output Var iab l e

9 p r i n t f ( "=%d" ,∗ ( ( Struct_setVal ∗) ptr )−>out1 ) ;10 p r i n t f ( " ) " ) ;11 }

42

Page 43: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

6. Der CES Compiler

Der CES Compiler übersetzt den CES Quelltext in Form einer einzigen Eingabedateiin eine C Datei, die alle definierten Prozeduren als Task implementiert. Der Compilerdurchläuft folgenden Phasen:

lexikalische Analyse Der Scanner liest die Eingabedatei, den CES Quelltext, ein underzeugt einen Tokenstrom für den Parser.

syntaktische Analyse Der Parser überprüft den Tokenstrom vom Scanner und erzeugtdaraus einen abstrakten Syntaxbaum.

semantische Analyse Der abstrakte Syntaxbaum wird durchlaufen und prüft auf se-mantische Korrektheit. Zusätzlich wird eine Symboltabelle für die Verwaltung derdefinierten Variablen im Quelltext erzeugt.

Codegenerierung Aus dem abstrakten Syntaxbaum und der Symboltabelle wird C Codegeneriert der die CES Prozeduren als Tasks implementiert.

Nachdem der CES Compiler das C File generiert hat wird dieses zusammen mit der RunTime von einem C Compiler übersetzt und in ein ausführbares Programm erstellt. Es istmöglich mit mehreren vom CESC generierten C Files und der Run Time ein ausführbaresProgramm zu erzeugen.

Der Compiler CESC wurde unter dem Betriebssystem Windows XP Professional mitHilfe von MinGW (www.mingw.org), flex 2.5.4, bison 1.28, gcc 3.2.3 entwickelt. make3.78.1 wurde verwendet, um die Kompilierung durch den C und CES Compiler zu steuernund zu automatisieren.

6.1. Der Scanner

Ziel des Scanners ist es Tokens zu erzeugen, die an den Parser weitergereicht werden. Diestrikte Trennung zwischen C und CES stand dabei im Vordergrund. Der C Code wirdnur an den Parser weitergereicht. Der Scanner überprüft nur CES auf die Richtigkeitder Syntax. Der Scanner beinhaltet zum Einen die regulären Ausdrücke zur Erkennungder CES spezifischen Code Fragmente in der CES Quellcodedatei, die auch C spezifischeCode Fragmente beinhalten kann und zum Anderen reguläre Ausdrücke die den als nichterkannten CES Code als C Code Token an den Parser weiterreicht. Damit der Scannerleichter zwischen C und CES unterscheiden kann, ist ein zusätzliches Zeichen „$“ benutztworden, um den Anfang und das Ende von CES Code anzuzeigen. Das benutzte Toolheisst flex. Dieses generiert aus der eigens erstellten scanner.l ein C File lex.yy.c . Bei

43

Page 44: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

dem Kompiliervorgang wird die Eingabedatei, also der CES Quelltext, analysiert und dieregulären Ausdrücke verwendet, um die Tokens für den Parser zu erzeugen. Die Dateiscanner.l ist in den Anlagen zu finden. Auf den Code der scanner.l wird in dieser Diplom-arbeit nicht weiter eingegangen, da der Quelltext der scanner.l bekannte Konstrukte ausdem Compilerbau aufweist und somit keine neue Konzepte beinhaltet.

CESC bietet die Möglichkeit den Tokenstrom ausgeben zu lassen (siehe Anhang A).

6.2. Der Parser

Der Parser beinhaltet Regeln, welche Aktionen bei einem bestimmten Tokenstrom durch-geführt werden. Die sogenannten Aktionen sind C Funktionen, die den abstrakten Syn-taxbaum generieren. Die Datei parser.y beschreibt alle definierten Tokens und Aktionen.Hierzu wurde das Konzept verschachtelte Listen benutzt. Das verwendete Tool heisstbison.

6.3. Der abstrakte Syntaxbaum

Der abstrakte Syntaxbaum repräsentiert den Quelltext der Eingabedatei als Baum. DieBlätter sind Parameter, Argumente, C Code, Variablen oder Typinformationen. Der ab-strakten Syntaxbaum dient später zur Generierung des gewünschten C Codes, der demCES Quelltext als C Quelltext entspricht. Die entwickelten Funktionen sind in der Dateiabsyn.c definiert und implementiert. Es können Knoten erzeugt werden, die C oder CESKonstrukte beinhalten können. Ein C Code Knoten beinhaltet den im CES Quelltext ge-schriebenen C Code ohne irgendwelche Veränderungen. Die definierten CES Definitionenoder Aufrufe werden als eigens angelegte Knoten im abstrakten Syntaxbaum gespeichert.

CESC bietet die Möglichkeit den abstrakten Syntaxbaum ausgeben zu lassen (sieheAnhang A). Die Abbildung 6.1 zeigt nochmal ein Beispiel einer Baumstruktur der Im-plementierung.

6.4. Die semantische Analyse

Bei der semantischen Analyse wird der abstrakte Syntaxbaum systematisch von der Wur-zel bis zu allen Blättern auf semantische Fehler geprüft. Zusätzlich wird die Symboltabelleerstellt.

6.5. Die Codegenerierung

Die Codegenerierung erfolgt in der letzten Phase des Kompiliervorgangs. C Code wirdgeneriert, der den vorhandenen CES Quellcode als C Programm darstellt und die definier-ten Prozeduren als Task implementiert. Die Codegenerierung erfolgt mittels der fprintfFunktion in das generierte C File. C Code zu generieren ist relativ einfach und portierbar

44

Page 45: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

�� ���� ��ast

��_ _ _ _ _�

�_ _ _ _ _listNode

value��

next //_ _ _ _ _�

�_ _ _ _ _listNode

value��

cCodeNode cesDefNode

params

��

body //_ _ _ _ _�

�_ _ _ _ _listNode

value

��

next //_ _ _ _ _�

�_ _ _ _ _listNode

value

��paramNode paramsNode

inoo

inOutwwnnnnnnnnnnnnout

��

cesCallNode

args

��

cCodeNode

paramNode

type

��

paramNode argsNodeout //

in��

inOut

''PPPPPPPPPPPPargNode

typeNode typeNode argNodetype

oo argNode

Abbildung 6.1.: Der abstrakte Syntaxbaum

gegenüber Assembler. Welche Codefragmente erzeugt werden, ist im Kapitel 5 Abschnitt„Das generierte C File“ zu finden.

6.6. Der Pretty Printer

Der Pretty Printer dient zur Ausgabe des Frame Stack, zum Beispiel zum Debuggen undum die neue Implementierung von Prozeduren darzustellen. Somit ist es möglich denaktuellen Status eines Tasks auszugeben und die Referenzen auf Storages und andereTasks nachvollziehen zu können. Hierfür wurden in der Codegenerierung Print Funktionenerzeugt, die dann die Ausgabe des Tasks erzeugen. Die Generierung des Quelltextes derPrint Funktionen ist im Kapitel 5 zu finden.

1 #inc lude "run_time . h"2

3 extern TASK_FRAME ∗ fs_bottom ;4 extern TASK_FRAME ∗ f s p ;5

6 extern TASK_FRAME ∗cs_top ;7 extern TASK_FRAME ∗ csp ;8

9 TASK_FRAME ∗ptr ;10

45

Page 46: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

11 extern int show_stack ;12

13 void show_fs ( ) {14 int frame_index ;15

16 i f ( show_stack == 0) return ;17

18 for ( ptr = f sp ; ptr >= fs_bottom ; ptr−−) {19

20 i f ( !SHOW_ANCESTOR && ptr−>ance s to r == 1) continue ;21 i f ( ptr−>func_ptr == func_storage ) continue ;22

23 frame_index = ( ( ( char∗) ptr−(char∗) fs_bottom ) / s izeof (TASK_FRAME) )+1;

24

25 p r i n t f ( "\ t%3d␣" , frame_index ) ;26

27 i f ( ptr−>ance s to r == 1) p r i n t f ( "\tANCESTOR␣" ) ;28 (void ) ( ptr−>print_func ) ( ) ; /∗ execu te t a s k ∗/29 i f ( ptr−>p a r a l l e l == 1) p r i n t f ( "\tPARALLEL␣" ) ;30 p r i n t f ( "\n" ) ;31 }32 }

Listing 6.1: C Quellcode des Pretty Printers

46

Page 47: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

7. Ausblick

Die Ergebnisse dieser Diplomarbeit zeigen, dass der theoretische Ansatz von Dr. Burk-hard Steinmacher-Burow in eine funktionierende Implementierung umgesetzt werdenkonnte. Die zu Anfangs gesteckten Ziele konnten erfolgreich erreicht werden. Der entwi-ckelte CES Compiler erzeugt die geforderten Daten zur Implementierung von Prozedurenals atomare Tasks. Auftretende Probleme wurden gelöst und trugen bei der Erkenntnis-findung des Themas bei. Mit Hilfe der Veröffentlichung Task Frames [1] wurde ein leichterEinstieg in das Thema ermöglicht. Die gewonnene Erkenntnisse dieser Arbeit bieten dieMöglichkeit Tasks parallel ausführen zu können. Um dies zu erreichen muss ein erwei-tertes Execution System entwickelt werden, dass die Verwaltung der Tasks übernimmt.Diese Diplomarbeit bietet ebenfalls einen pädagogischen Aspekt zur Verdeutlichung desThemas. Die Strukturen wurden einfach gehalten. Die Pretty Printer Ausgabe des FrameStack kann leicht nachvollzogen werden und verdeutlicht mit einfachen Details den Ablaufeines CES Programms. Der modulare Aufbau gibt die Möglichkeit die Implementierungzu erweitern und zukünftige auftretende Probleme zu lösen.

Ich hoffe, dass die vorliegende Arbeit viele Menschen inspiriert und auch motiviert dasKonzept der Task Frames weiterzuentwickeln und zu nutzen.

47

Page 48: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

Literaturverzeichnis

[1] Dr. Burkhard Steinmacher-Burow. Task Frames, 2000.http://www-zeus.desy.de/~funnel/TSIA/index.htm.

[2] Dr. Burkhard Steinmacher-Burow. The execution of computer applications. Kontakt:[email protected], 2006.

48

Page 49: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

Benutzte Internetquellen

www.wikipedia.org

49

Page 50: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

A. CESC Handbuch

A.1. Dateien

A.1.1. Makefile

folgende Regeln sind möglich:

all kompiliert das ausführbare Programm aus dem CES Quelltext

cesc erzeugt das Programm cesc, den Compiler

compile benutzt das Programm cesc und erzeugt aus der Datei program.ces das C Fi-le ces_program.c. Der Name der Eingabedatei (CES Quelltext) muss immer pro-gram.ces lauten, möchte man dieses Makefile benutzen. Der Name der Ausgabedateiwird immer ces_program.c heissen.

print gibt das Beispielprogramm program.ces als Text auf der Konsole aus (das Pro-gramm cat muss vorhanden sein)

gcc der C Compiler kompiliert zusammen mit der Run Time das ausführbare Programmces_program

exe führt das kompilierte Programm ces_program aus

fs gibt den Frame Stack während der Ausführung des Programms durch den PrettyPrinter auf der Konsole aus

tokens, absyn, tables siehe Optionen von CESC

ancestor zeigt zusätzlich die bereits ausgeführten Tasks auf dem Frame Stack

fstests führt nacheinander alle Testprogramme aus dem Verzeichnis Tests aus und gibtzusätzlich den Frame Stack auf der Konsole aus

tests führt nacheinander alle Testprogramme aus dem Verzeichnis Tests aus

clean löscht alle vom C Compiler erzeugten Dateien

dist-clean löscht alle vom C und CES Compiler erzeugten Dateien

50

Page 51: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

A.1.2. CESC

abstrakter Syntaxbaum

absyn.c Funktionen zur Erzeugung des abstrakten Syntaxbaumesabsyn.h Datenstrukturen für den Syntaxbaum, Prototypen

Codegenerierung

codegen.c Funktionen zur Codegenerierungcodegen.h Prototypen

Hauptprogramm CESC

main.c Das Hauptprogramm von CESCfolgende Optionen bietet CESC:

• —tokens zeigt den Tokenstrom

• —absyn zeigt den abstrakten Syntaxbaum

• —version zeigt die Compilerversion

• —ancestor zeigt bei der Ausgabe die schon ausgeführten Tasks

• —help zeigt die Hilfe für CESC Optionen

Symbole

symbol.c Funktionen zur Erzeugung von Symbolen und deren Verwaltung in einer HashTabellesymbol.h Datenstruktur eines Symbols für die Symboltabelle

Symboltabelle

table.c Funktionen zur Erstellung der Symboltabelle und zur Ausgabe der Symboltabel-letable.h Datenstrukturen der Symboltabelle und Definitionen von Konstanten, Prototy-pen

Utils

utils.c Funktionen zur Fehlerausgabe, Speicherreservierung und Speicherfreigabeutils.h Prototypencommon.h Definitionen für den eigenen Datentyp boolean

51

Page 52: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

Semantiküberprüfung

semant.c Funktionen zur Überprüfung der Semantiksemant.h Prototypen

A.1.3. Scanner

scanner.l Scanner Eingabedatei für flexscanner.h Datenstrukturen zur Erzeugung der Tokens

A.1.4. Parser

parser.y Parser Eingabedatei für bisonparser.h Prototypen

A.1.5. Run Time

run_time.c Die Run Timerun_time.h Datenstrukturen für Task Frame sund Storage Frames

A.1.6. Pretty Printer

debug.c Der Pretty Printerdebug.h Definitionen für Konstanten zum Debuggen

A.1.7. Beispielprogramm

program.ces Ein einfaches Beispielprogramm

52

Page 53: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

B. Testumegbung

B.1. Dateien im Verzeichnis CESC/Tests

Alle Dateien von test01.ces bis test26.ces testen die richtige Definition von CES Proez-duren und deren Verwendung durch CES Aufrufe. In der Excel Tabelle ist aufgelistet wieder Informationsaustausch zwischen verschiedenen Prozeduren möglich ist.

53

Page 54: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

Danksagung

Ich danke besonders Dr. Burkhard Steinmacher-Burow, der mir die Möglichkeit gegebenhat diese sehr interessante Arbeit durchführen zu können. Ausserdem danke ich Ihmfür seine Unterstützung und den vielen wissenschaftlichen Ratschlägen zur Fertigstel-lung dieser Diplomarbeit. Ebenfalls bedanke ich mich bei Prof. Dr. Hellwig Geisse fürseine persönliche Hilfe bei Fragen bezüglich dieser Arbeit. Der Firma IBM DeutschlandEntwicklung GmbH danke ich für die Bereitstellung der Ressourcen und der Räumlichkei-ten. Meinem Nachfolger Jens Remus danke ich für wichtige Tipps und das Korrekturlesenbezüglich der technischen Korrektheit dieser Arbeit. Meiner Freundin Maike Schmelterdanke ich für die Motivierung und Unterstützung bei dieser Arbeit, ohne Sie wäre es niemöglich gewesen diese Arbeit in dem angesetzten Zeitraum zu Ende zu bringen.

54

Page 55: Konzeption und Entwicklung eines neuen Compiler „CESC“ zur Implementierung von Prozeduren als atomare Tasks

Eidesstattliche Erklärung

Hiermit versichere ich, die vorliegende Arbeit selbstständig und unter ausschließlicherVerwendung der angegebenen Literatur und Hilfsmittel erstellt zu haben.

Die Arbeit wurde bisher in gleicher oder ähnlicher Form keiner anderen Prüfungsbehördevorgelegt und auch nicht veröffentlicht.

Böblingen, 8. August 2007Unterschrift

55