Open Source im professionellen Einsatz

GCC erweitern und effizient nutzen

Schneller rufen

Das Beispiel der Call-Optimierung zeigt, dass auch einzelne Entwickler dem Millionen-Zeilen-Monster GCC Beine machen können. Der Autor hat indirekte Endaufrufe beschleunigt und deren Stack-Konsum eingeschränkt. Der Trick: Die gerufene Funktion recycelt den Stack-Frame der rufenden Funktion.

Die GNU Compiler Collection (GCC)[1] unterstützt viele Sprachen, Betriebssysteme und Hardwareplattformen. Besonders beim Optimieren des erzeugten Codes entwickelt sich die Übersetzersuite kontinuierlich weiter. Was das für Compileranwender und Mitentwickler in der Praxis bedeutet, zeigt dieser Artikel anhand einer neuen Erweiterung: der Optimierung indirekter Endaufrufe.

Die GCC besteht aus einem in C implementierten Kern (dem Backend), der rund eine halbe Million Codezeilen umfasst. Dazu kommen weitere fest integrierte Frontends beispielsweise für Java, Ada oder Fortran, die es zusammen auf mehrere Millionen Zeilen Code bringen. Die Anzahl unterstützter Plattformen ist ebenfalls beeindruckend. Kombiniert man die Betriebssysteme (Linux, Windows, Solaris, HP-UX ...) mit den Hardware-Architekturen (i386, Alpha, Sparc ...), ergeben sich über 100 Zielplattformen. Kurzum: Die GCC ist riesig und erfordert viel Entwicklungsaufwand für Experten aller Sprachen, Betriebssysteme und Prozessoren.

GCC-Interna: Kompilieren in vielen Stufen

Der Übersetzungsvorgang der GCC ist strikt in Verarbeitungsstufen unterteilt (siehe Abbildung 1). Welche Schritte innerhalb dieser Stufen tatsächlich abzuarbeiten sind, variiert allerdings je nach benutztem Frontend und je nach gewählter Optimierungsstufe. Die eigentliche Optimierungsphase kann sehr kurz ausfallen oder auch viel Zeit beanspruchen, wenn der Anwender besonders performante oder speicherschonende Programme benötigt.

Wichtig ist, dass fast alle Code-Optimierungen auf einer Zwischensprache aufbauen, der Register Transfer Language (RTL). Diese Sprache ist nahezu Hardware-unabhängig. Sie modelliert einen abstrakten Prozessor. Dieser stellt beispielsweise eine Vielzahl Pseudo-Register zur Verfügung, die das Backend am Ende seiner Arbeit auf die physische Zielplattform abbildet.

Ausblick auf GCC 3.4

Die kommenden GCC-Versionen enthalten - neben den optimierten Endaufrufen - viele interessante Neuerungen. Wer große Softwareprojekte entwickelt, wird die Unterstützung für vorkompilierte Header-Dateien gespannt erwarten. Sie verkürzt die Übersetzungszeit von C- und C++-Projekten mit vielen Include-Anweisungen drastisch. Der Compiler übersetzt die einzubindenden Dateien nur ein einziges Mal - solange sie niemand verändert.

Sogar der gesamte C++-Parser wurde neu geschrieben, um Fehler des alten zu umgehen und zudem bessere Sprachunterstützung zu garantieren. Das gilt auch für künftige Versionen des ISO-Sprachstandards.

Sehr ambitionierte Teilprojekte

Hinter den Kulissen gibt es noch weitaus ambitioniertere Erweiterungen zu bestaunen, die jedoch vermutlich nicht mehr den Weg in die kommenden GCC-Versionen finden werden. Red Hat arbeitet beispielsweise an dem Ersatz für eine Vielzahl der RTL-Optimierungen. Mit dem neuen SSA-Backend (Single Static Assignment) sollen Programmtransformationen möglich sein, die die RTL an ihre Leistungsgrenze gebracht hätten.

Gemeint sind vor allem Optimierungen auf Programm-Kontrollflussgraphen, die sich gegenwärtig nur mühsam aus RTL und den abstrakten Syntax-Bäumen (AST) extrahieren lassen. Sie werden im Zeitalter von Garbage Collection und neuer Sprachen immer wichtiger, finden in der eher Low-Level-orientierten RTL-Schicht der Übersetzersuite aber keine adäquaten Konstrukte.

Lisp-artige Syntax zur Plattform-Beschreibung

Die Zielplattformen sind in einer Lisp-artigen Syntax beschrieben. Aus dieser Spezifikation wird der Code ganzer Teile der Compilersuite generiert - das Übersetzen des Compilers selbst läuft in mehreren Stufen ab. Dieses flexible Design hat den besonderen Vorteil, dass die GCC weitgehend sprach- und plattformunabhängig ist und sich sehr gut als Crosscompiler eignet.

Einen Crosscompiler benötigen Entwickler immer dann, wenn sie zwar auf einer bestimmten Plattform arbeiten, jedoch nativen Code für eine inkompatible Architektur erzeugen müssen. Mit der GCC steht ihnen hierbei für jede Zielplattform ein einheitlicher Compiler zur Verfügung.

Eine der Neuerungen in der GCC- Version 3.4 ist die Optimierung von indirekten Endaufrufen (Tail Calls) auf Intel-kompatiblen Systemen. Bei dieser Technik überführt der Compiler alle Funktionsaufrufe über Zeiger, die am logischen Ende eines Funktionsrumpfs stehen (siehe Listing 1), in eine Jump-Reuse-Sequenz.

Abbildung 1: Die GNU Compiler Collection übersetzt Sourcecode in mehreren Schritten. Als Zwischensprache verwendet sie die Register Transfer Language (RTL). GCC optimiert den Code beim Übergang von RTL in Maschinensprache.

Abbildung 1: Die GNU Compiler Collection übersetzt Sourcecode in mehreren Schritten. Als Zwischensprache verwendet sie die Register Transfer Language (RTL). GCC optimiert den Code beim Übergang von RTL in Maschinensprache.

Diesen Artikel als PDF kaufen

Als digitales Abo

Als PDF im Abo bestellen

comments powered by Disqus

Ausgabe 07/2013

Preis € 6,40

Insecurity Bulletin

Insecurity Bulletin

Im Insecurity Bulletin widmet sich Mark Vogelsberger aktuellen Sicherheitslücken sowie Hintergründen und Security-Grundlagen. mehr...

Linux-Magazin auf Facebook