Schnelles Compiler-Gerät. Teil 1


Swift ist nicht nur eine Programmiersprache. Dies ist ein Projekt, das neben dem Compiler viele andere Komponenten enthält. Und der Compiler selbst ist keine große und schreckliche Box, die mit Hilfe von Magie Ihren Code in eine Reihe von Anweisungen verwandelt, die für die Maschine verständlich sind. Es kann auch in Komponenten zerlegt werden. Wenn Sie daran interessiert sind, willkommen bei cat.


Ich bin kein Spezialist für Compiler und habe keine Erfahrung auf diesem Gebiet. Aber ich fragte mich, wie es funktioniert, und begann, den Swift-Compiler zu studieren. Da sich der Artikel als zu groß herausstellte, musste ich ihn in 4 Teile teilen:


  • allgemeine Übersicht der Komponenten
  • Parsen der Quelldatei,
  • Schnelle Zwischensprache,
  • LLVM IR und Codegenerierung.

Schnell


Swift ist seit über zwei Jahren ein Open Source-Projekt. In dieser Zeit wurden viele Verbesserungen aus der Community hinzugefügt. Sie können ihnen auf einer speziellen Website sowie im Forum folgen. Dort können Sie Vorschläge zur Verbesserung der Sprache diskutieren oder Ihre Ideen darlegen. Dazu müssen Sie jedoch zunächst herausfinden, wie das Projekt funktioniert.


Schnelle Standardbibliothek





Die Hauptteile von Swift sind natürlich der Compiler und die Standardfunktionsbibliothek. Sie entwickeln sich parallel und sind praktisch untrennbar miteinander verbunden.


Der Compiler ist in C ++ geschrieben und der Hauptteil von stdlib ist in Swift. Die darin verwendete Sprache weist jedoch mehrere Funktionen auf:


  • Die Standardbibliothek über das Builtin-Modul hat direkten Zugriff auf die Compilerfunktionen. Dies ermöglicht ihr den Zugriff auf einfache Sprachdarstellungen und Rohzeiger.
  • Die Standardbibliothek verwendet nicht den Modifikator für den privaten Zugriff. Stattdessen beginnen nicht öffentliche Entitätsnamen mit einem Unterstrich. Lesen Sie hier mehr.
  • Es verwendet die Codegenerierung mit dem Dienstprogramm " Generate Your Boilerplate" (GYB), um Wiederholungen im Code der Standardbibliothek zu reduzieren.

Die Standardbibliothek ist normalerweise mit Containern und nützlichen Funktionen verknüpft, die das Leben des Entwicklers vereinfachen. Dies ist jedoch nur ein Teil. Insgesamt lassen sich 3 interessanteste Komponenten unterscheiden:


  • Kern Ein Kernel mit all seinen Protokollen, Datentypen und Funktionen. Quellen .
  • Laufzeit Eine Zwischenschicht zwischen der Standardbibliothek und dem Compiler. Er ist verantwortlich für das Typ Casting, die Arbeit mit Gedächtnis, Reflexion und anderen dynamischen Merkmalen der Sprache. Geschrieben in C ++ und Objective-C. Quellen .
  • SDK-Overlays. Wrapper über Foundation und andere System-Frameworks, die den Zugriff von Swift aus bequemer machen. Quellen .

Andere Teilprojekte





Neben dem Compiler und der Standardbibliothek gibt es viele weitere öffentlich zugängliche Teilprojekte. Einige von ihnen sind unten aufgeführt.


Sourcekit


IDE-Unterstützungsframework : Indizierung, Syntaxhervorhebung, Code-Vervollständigung usw.


SourceKit-LSP


Eine Implementierung von LSP für Swift basierend auf SourceKit. Hier können Sie nachlesen, was es ist.


Schneller Paketmanager


Paketmanager für Projekte auf Swift.


Stiftung


Port der Foundation-Bibliothek , die einer der Kernpunkte für Apples Betriebssystem für Plattformen von Drittanbietern ist.


libdispatch (gcd)


GCD für Plattformen von Drittanbietern.


XCTest


XCTest für Plattformen von Drittanbietern.


LLDB


LLDB mit Swift- und REPL-Unterstützung.


Spielplatzunterstützung


Das Projekt umfasst zwei Frameworks - PlaygroundSupport und PlaygroundLogger. Sie bieten Interaktion mit Xcode bzw. eine schöne Anzeige von Daten.


llbuild


System erstellen .


Gyb


Dienstprogramm zur Codegenerierung.


libcxx


Implementierung der Standard-C ++ - Bibliothek.


Schneller Compiler





Ein Compiler im weitesten Sinne ist ein Programm, das Code von einer Sprache in eine andere konvertiert. In den meisten Fällen bezieht sich die Kompilierung auf die Konvertierung von Quellcode in Maschinencode (oder in eine andere Darstellung auf niedriger Ebene), die dann zum Erstellen einer ausführbaren Datei verwendet werden kann.


Der Compiler besteht häufig aus drei Teilen: Frontend, Middlend, Backend. Der erste ist für die Konvertierung des Quellcodes in eine Zwischendarstellung verantwortlich, mit der der Compiler bequem arbeiten kann. Middlend führt die Optimierung durch und das Backend generiert Maschinencode aus der optimierten Zwischendarstellung.


In Swift wird die Optimierung jedoch sowohl im Frontend als auch (größtenteils) im Backend durchgeführt. Daher ist der Zwischenschritt im Diagramm nicht gezeigt.


LLVM





Der Swift-Compiler verwendet LLVM als Backend. LLVM ist ein großes Projekt, das viele Technologien umfasst. Es basiert auf Intermediate Representation (IR). Dies ist eine universelle Zwischencodedarstellung, die auf jeder von LLVM unterstützten Plattform in ausführbaren Code konvertiert werden kann.



Wenn eine neue Architektur angezeigt wird, reicht es aus, in LLVM die Generierung von Maschinencode aus IR für diese Plattform hinzuzufügen. Danach unterstützen alle Sprachen, für die es einen Compiler mit IR-Generierung gibt, diese Architektur.


Um einen Compiler für eine neue Programmiersprache zu erstellen, reicht es jedoch aus, die Übersetzung des Quellcodes in IR zu schreiben, und LLVM kümmert sich um die verschiedenen Architekturen.


Ein weiterer Vorteil eines solchen Systems besteht darin, dass LLVM die Zwischenpräsentation optimieren kann und das Front-End möglicherweise nicht an der Optimierung beteiligt ist. Dies vereinfacht die Compilerentwicklung erheblich.


IR hat drei Arten von Anzeigen:


  • Ein Baum von Objekten im Speicher. Jedes Objekt entspricht einer bestimmten Entität im Quellcode: Funktion, Operator, Zeile, Zeiger usw. Dieser Baum wird vom Frontend in der Phase der IR-Generierung erstellt.
  • Textansicht. IR kann als Low-Level-Quellcode abgeleitet werden. Es kann in einer Datei gespeichert und mit dem Interpreter ausgeführt werden.
  • Das serialisierte Bitformat „Bitcode“ (nicht zu verwechseln mit dem Bytecode, der beispielsweise in Java verwendet wird). Es kann als Endergebnis des Backends verwendet und zur Optimierung auf Linkebene an den Linker übertragen werden. Die Konvertierung in Maschinencode erfolgt in diesem Fall durch den Linker.

Linker ist ein Programm, das eine ausführbare Datei generiert. Ihre Beschreibung geht über den Rahmen des Artikels hinaus.


Den Quellcode für die in Swift verwendete LLVM-Version finden Sie hier und die Dokumentation auf der offiziellen Website .


Wie Sie sehen können, hat Apple viele interessante Projekte zu Open Access veröffentlicht. Im nächsten Teil werde ich über das Parsen der Quelldatei und das Generieren des AST sprechen.

Source: https://habr.com/ru/post/de438204/


All Articles