Warum gibt es so wenige C-Compiler?

72

C ist eine der am häufigsten verwendeten Sprachen der Welt. Es macht einen großen Teil des vorhandenen Codes aus und wird weiterhin für eine große Menge neuen Codes verwendet. Es ist bei seinen Benutzern sehr beliebt, es ist so weit verbreitet, dass die Fähigkeit, C auszuführen, für viele die informelle Definition einer Plattform ist , und es wird von seinen Fans als "kleine" Sprache mit relativ sauberen Funktionen gelobt.

Wo sind also alle Compiler?

Auf dem Desktop gibt es (realistisch gesehen) zwei : GCC und Clang. Wenn Sie ein paar Sekunden darüber nachdenken, werden Sie sich wahrscheinlich daran erinnern, dass Intel ebenfalls existiert. Es gibt eine Handvoll anderer, die für den Durchschnittsbürger viel zu dunkel sind, um sie zu nennen, und die sich im Allgemeinen nicht die Mühe machen, eine neuere Sprachversion (oder oft sogar eine genau definierte Sprachuntermenge, nur "eine Untermenge") zu unterstützen. Die Hälfte der Mitglieder dieser Liste sind historische Fußnoten. Die meisten anderen sind sehr spezialisiert und implementieren immer noch nicht die vollständige Sprache. Sehr wenige scheinen Open Source zu sein.

Scheme and Forth - andere kleine Sprachen, die von ihren Fans geliebt werden - haben wahrscheinlich mehr Compiler als tatsächliche Benutzer. Sogar etwas wie SML hat "ernstere" Implementierungen zur Auswahl als C. Während die Ankündigung eines neuen (unvollendeten) C-Compilers, der auf Verifikation abzielt, tatsächlich einige ziemlich negative Reaktionen hervorruft und erfahrene Implementierungen Schwierigkeiten haben, genügend Mitwirkende zu bekommen, um überhaupt aufzuholen C99.

Warum? Ist die Implementierung von C so schwierig? Es ist nicht C ++. Haben Benutzer einfach eine sehr verzerrte Vorstellung davon, in welche Komplexitätsgruppe sie fallen (dh, dass sie tatsächlich näher an C ++ als an Schema liegt)?


quelle
61
MSVC zählt immer noch, zumindest als C89-Compiler. Wahrscheinlich sogar beliebter als Intel.
Rufflewind
22
Wikipedia listet einige C-Compiler auf. Sie bekommen sehr häufig , wenn man sich im eingebetteten Bereich finden.
113
Wie viele Compiler benötigen Sie, um Ihren C-Code zu kompilieren?
Bryan Chen
76
Die Frage basiert auf einer falschen Prämisse. Analog Devices, armcc, Bruce's C-Compiler, der Bare-C-Cross-Compiler, der Borland-Compiler, der Clang-Compiler, der Cosmic C-Compiler, der CodeWarrior-Compiler, der Dokto-Compiler, der Ericsson-Compiler, und ich bin noch nicht einmal dabei Die ersten fünf Buchstaben des Alphabets noch. Es gibt eine wahnsinnig große Anzahl von C-Compilern. Die Frage ist: "Warum gibt es so wenige C-Compiler, wenn wir diese Dutzende nicht als echte C-Compiler betrachten?" Sie haben die überwiegende Mehrheit der C-Compiler als nicht interessant eingestuft, weshalb es nicht sehr viele von ihnen gibt.
Eric Lippert
19
"Warum" -Fragen sind im besten Fall schlechte Fragen für diese Site, und "warum nicht?" Fragen sind schlimmer. Wenn ich Sie auf einer Party treffen und fragen würde: "Warum rennst du nicht mit Segelbooten?" Ich denke, Sie würden es zu Recht als seltsame Frage empfinden. Sie müssen keine Rechtfertigung dafür vorlegen, sich NICHT auf ein technisch schwieriges, physisch riskantes und sehr teures Hobby einzulassen. Das Schreiben einer nicht trivialen Software ist teuer, schwierig und riskant und erfordert daher einen enormen Motivator. Eine bessere Frage wäre "Warum gibt es so viele C-Compiler?" Es ist überraschend, dass es mehr als eine gibt.
Eric Lippert

Antworten:

153

Heutzutage benötigen Sie einen echten C-Compiler, um einen optimierenden Compiler zu sein , insbesondere, weil C keine hardwarenahe Sprache mehr ist, da aktuelle Prozessoren unglaublich komplex sind ( außer Betrieb , Pipeline , superskalar , mit komplexen Caches und TLBs) . daher wird eine Befehlsplanung benötigt , etc ...). Die heutigen x86-Prozessoren sind keine i386-Prozessoren des vorigen Jahrhunderts, auch wenn beide in der Lage sind, denselben Computercode auszuführen. Siehe, das C ist kein Low-Level- Papier (Ihr Computer ist kein schnelles PDP-11) von David Chisnall.

Nur wenige Leute verwenden naive, nicht optimierende C-Compiler wie tinycc oder nwcc , da sie Code erzeugen, der um ein Vielfaches langsamer ist als der, den optimierende Compiler liefern können.

Das Codieren eines optimierenden Compilers ist schwierig. Beachten Sie, dass sowohl GCC als auch Clang eine "quellensprachenneutrale" Codedarstellung optimieren (Gimple für GCC, LLVM für Clang). Die Komplexität eines guten C-Compilers befindet sich nicht in der Analysephase!

Insbesondere ist das Erstellen eines C ++ - Compilers nicht viel schwieriger als das Erstellen eines C-Compilers: Das Parsen von C ++ und das Umwandeln in eine interne Codedarstellung ist komplex (da die C ++ - Spezifikation komplex ist), aber gut verstanden, aber die Optimierungsteile sind noch viel komplexer Komplex (innerhalb von GCC: Die Middle-End-Optimierungen, quellensprachlich und zielprozessorneutral, bilden die Mehrheit des Compilers, wobei der Rest zwischen Frontends für mehrere Sprachen und Backends für mehrere Prozessoren ausgeglichen wird ). Daher sind die meisten optimierenden C-Compiler auch in der Lage, einige andere Sprachen wie C ++, Fortran, D, ... zu kompilieren. Die C ++ - spezifischen Teile von GCC machen etwa 20% des Compilers aus.

Außerdem wird C (oder C ++) so häufig verwendet, dass die Benutzer erwarten, dass ihr Code kompilierbar ist, auch wenn er nicht genau den offiziellen Standards entspricht, die die Semantik der Sprache nicht genau genug definieren (sodass jeder Compiler möglicherweise seine eigene Interpretation hat) davon). Schauen Sie sich auch den von CompCert bewährten C-Compiler und den statischen Analysator Frama-C an , die sich um eine formalere Semantik von C kümmern .

Und Optimierungen sind ein Long-Tail- Phänomen: Ein paar einfache Optimierungen zu implementieren ist einfach, macht einen Compiler jedoch nicht wettbewerbsfähig! Sie müssen viele verschiedene Optimierungen implementieren und sie geschickt organisieren und kombinieren, um einen echten Compiler zu erhalten, der wettbewerbsfähig ist. Mit anderen Worten, ein Compiler zur Optimierung der Realität muss eine komplexe Software sein. Übrigens haben sowohl GCC als auch Clang / LLVM mehrere interne spezialisierte C / C ++ - Codegeneratoren. Und beide sind riesige Bestien (mehrere Millionen Quellcodezeilen, mit einer Wachstumsrate von mehreren Prozent pro Jahr) mit einer großen Entwicklergemeinschaft (einige hundert Personen, die meistens in Vollzeit oder mindestens in Halbzeit arbeiten).

Beachten Sie, dass es (meines Wissens nach) keinen Multithread-C-Compiler gibt, auch wenn einige Teile eines Compilers parallel ausgeführt werden könnten (z. B. prozedurale Optimierung, Registerzuweisung, Befehlsplanung ...). Und paralleles Bauen mit make -jist nicht immer ausreichend (besonders bei LTO ).

Außerdem ist es schwierig, einen C-Compiler von Grund auf neu zu programmieren, und ein solcher Aufwand muss mehrere Jahre dauern. Schließlich sind die meisten C- oder C ++ - Compiler heute freie Software (es gibt keinen Markt mehr für neue proprietäre Compiler, die von Startups verkauft werden) oder zumindest monopolistische Produkte (wie Microsoft Visual C ++ ), und für Compiler ist eine freie Software fast erforderlich ( weil sie Beiträge von vielen verschiedenen Organisationen benötigen).

Ich würde mich sehr freuen, wenn ich finanzielle Unterstützung für die Arbeit an einem C-Compiler von Grund auf als freie Software erhalten könnte, aber ich bin nicht naiv genug, um zu glauben, dass dies heute möglich ist!

Basile Starynkevitch
quelle
14
(there is no more a market for proprietary compilersSagen Sie das dem Visual Studio-Team ...
Mason Wheeler
18
Microsoft hat ein Monopol. Ich habe gemeint, dass kleine Unternehmen, die neue C-Compiler entwickeln, nicht viele davon verkaufen werden. Können Sie einen neuen proprietären Konkurrenten von MSVC nennen?
Basile Starynkevitch
12
Es gibt viele proprietäre Compiler in der HPC-Welt. PGCC, NAG und ICC werden am häufigsten verwendet.
Davidmh
37
@MasonWheeler: VS wird heutzutage kostenlos verschenkt (wie in Bier). In den nicht-freien Versionen werden Tools hinzugefügt, aber der C-Compiler in VS2013 ist in allen Versionen gleich. Es gibt einfach keinen Markt, nicht einmal für sie.
MSalters
3
Aber beide GCC & LLVM arbeiten mit viel niedrigeren Darstellungen und optimieren ebenfalls C ++ & C (& Ada & Fortran, für GCC) Code. Ich würde im Gegenteil sagen, dass C ++ mehr Optimierung erfordert (insbesondere beim Kompilieren von Code mit seiner STL) als C!
Basile Starynkevitch
70

Ich möchte Ihre zugrunde liegende Annahme, dass es nur eine kleine Anzahl von C-Implementierungen gibt, in Abrede stellen.

Ich kenne C nicht einmal, ich benutze C nicht, ich bin kein Mitglied der C-Community, und dennoch kenne ich weit mehr als die wenigen Compiler, die Sie erwähnt haben.

In erster Linie gibt es den Compiler, der wahrscheinlich sowohl GCC als auch Clang auf dem Desktop völlig in den Schatten stellt: Microsoft Visual C. Trotz der Fortschritte, die sowohl OSX als auch Linux auf dem Desktop gemacht haben, und des Marktanteils, den iOS und Android "gestohlen" haben Windows ist nach wie vor das dominierende Desktop-Betriebssystem, und die meisten Windows-Desktop-C-Programme werden wahrscheinlich mit Microsoft-Tools kompiliert.

Traditionell hatte jeder Hersteller von Betriebssystemen und Chips eigene Compiler. Microsoft als Betriebssystemanbieter verfügt über Microsoft Visual C. IBM als Betriebssystemanbieter und als Chipanbieter verfügt über XLC (dies ist der Standardsystemcompiler für AIX und der Compiler, mit dem sowohl AIX als auch i / OS kompiliert werden). . Intel hat einen eigenen Compiler. Sun / Oracle hat einen eigenen Compiler in Sun Studio.

Hinzu kommen die leistungsstarken Compiler-Anbieter PathScale und The Portland Group, deren Compiler (und OpenMP-Bibliotheken) für die Zahlenverarbeitung verwendet werden.

Digital Mars ist auch noch im Geschäft. Ich glaube, Walter Bright hat die einzigartige Auszeichnung, der einzige Mensch auf dem Planeten zu sein, der es geschafft hat, einen C ++ - Compiler in Produktionsqualität (meistens) selbst zu erstellen.

Last but not least haben wir alle proprietären Compiler für eingebettete Mikrocontroller. Im IIRC werden jedes Jahr mehr Mikrocontroller verkauft als Desktop-, Mobil-, Server-, Workstation- und Mainframe-CPUs in der gesamten Computergeschichte. Das sind also definitiv keine Nischenprodukte.

Eine Auszeichnung geht an TruffleC , einen C - Interpreter (!), Der auf der JVM (!) Läuft und mit dem Truffle AST - Interpreter - Framework geschrieben wurde, das nur 7% langsamer ist als GCC und Clang (je nachdem, welches auf einem bestimmten Benchmark am schnellsten ist) Computersprachen-Benchmark-Spiel und schneller als beide auf Mikrobenchmarks. Mit TruffleC konnte das Truffle-Team seine Version von JRuby + Truffle dazu bringen, Ruby C-Erweiterungen schneller als die eigentliche C-Ruby-Implementierung auszuführen!

Das sind also 6 Implementierungen zusätzlich zu den von Ihnen aufgelisteten, die ich auf den ersten Blick benennen kann, ohne überhaupt etwas über C zu wissen.

Jörg W. Mittag
quelle
1
Außerhalb von Microsoft Visual C werden die meisten C-Compiler, die Sie erwähnen, selten verwendet.
Basile Starynkevitch
6
MSVC ist der große C ++ - Compiler, aber für C ist es schwer zu verwenden und bleibt dauerhaft in C89 stecken. Mikrocontroller-Compiler sind normalerweise zielspezifisch, hängen in C89 fest und sind schrullig. TruffleC scheint noch nicht verfügbar zu sein (ist aber interessant, danke). Pathscale und Digital Mars scheinen eher die Art von Gegenbeispielen zu sein, nach denen ich gesucht habe.
Leushenko
8
@ Mario Meiner Meinung nach ist C89 nicht defekt, aber C89 ist nicht die aktuelle Form der Sprache. und das bedeutet, dass weniger Compiler vorhanden sind, die aktuell sind.
Leushenko
6
@ Leushenko MSVC ist nicht dauerhaft in C89 stecken. Es gab einige Diskussionen und es sollten weitere C99-Funktionen hinzugefügt werden. Für den Anfang wird der größte Teil der C99-Bibliothek ab MSVC 2015 und einige Sprachfunktionen unterstützt (hauptsächlich jedoch die für C ++ 11 erforderlichen Funktionen).
Morwenn
5
@ Morwenn: Die Microsoft-Richtlinie scheint zu lauten, dass C99 keine Probleme behebt, die C ++ noch nicht gelöst hat, und dass Sie bei der Systemprogrammierung die C-ähnliche Teilmenge von C ++ verwenden sollten (alles, was keine Laufzeit benötigt oder wo Sie nicht steuern können, wo der Compiler die Dinge ablegen wird - wichtig, wenn Sie sicherstellen möchten, dass Code oder Daten nicht aus Staaten ausgelagert werden, in denen Paging deaktiviert ist). Die einzigen Features von C99 werden Dinge sein, die in späteren C ++ - Spezifikationen erforderlich sind, und solche, die keine Ahnung haben, was zu implementieren ist.
Mike Dimmick
8

Wie viele Compiler benötigen Sie?

Wenn sie unterschiedliche Funktionssätze haben, erstellen Sie ein Portabilitätsproblem. Wenn es sich um Ware handelt, wählen Sie entweder die "Standardeinstellung" (GCC, Clang oder VS). Wenn Sie sich für die letzten 5% interessieren, haben Sie einen Benchmark-Off.

Wenn Sie in Ihrer Freizeit oder zu Forschungszwecken in Programmiersprachen arbeiten, ist die Sprache wahrscheinlich moderner. Daher die Verbreitung von Toy Compilern für Scheme und ML. Obwohl OCaml für nicht-akademische Zwecke eine gewisse Zugkraft zu bekommen scheint.

Beachten Sie, dass dies je nach Sprache sehr unterschiedlich ist. Java hat im Wesentlichen die Sun / Oracle-Toolchain und die GNU-Toolchain. Python hat verschiedene Compiler, von denen keiner im Vergleich zum Standardinterpreter wirklich respektiert wird. Rust und Go haben jeweils genau eine Implementierung. C # hat Microsoft und Mono.

pjc50
quelle
1
Es ist offensichtlich, dass es interessantere Gründe gibt, einen ML-Compiler zu entwickeln ... Ich dachte nur, dass die C-Community, die wahrscheinlich drei Größenordnungen größer ist, diesen Effekt ausgleichen würde. Aber Sie könnten Recht haben, 1000 * 0ist immer noch 0.
Leushenko
Das Erstellen eines neuen Compilers ist häufig mit einer Fragmentierung der Community verbunden (entweder verursacht durch oder verursachend). Zum Beispiel die Aufteilung von egcs gegen gcc Betreuer. Außerdem liegt die Kompatibilität mit C-Quellen in der Regel unter 100%.
pjc50
@ pjc50: Die Art und Weise, wie der Standard geschrieben wird, unterteilt C in eine Reihe von disjunkten Dialekten, die auf Dingen wie dem Basistyp von basieren int, und erfordert, dass verschiedene Compiler denselben Quellcode auf sehr unterschiedliche Weise interpretieren.
Supercat
5
Ich glaube, Go hat zwei Implementierungen (die 6g/ 8g/… Toolchain und gccgo). Es gab auch eine sehr interessante proprietäre kommerzielle Implementierung namens erGo, die a) eine native Windows-Implementierung von Go zu einer Zeit war, als weder gccgo noch der ursprüngliche Go-Compiler unter Windows sehr gut funktionierten, b) eine Firma, die lange auf Go setzte bevor es überhaupt 1.0 wurde, und c) die erste Implementierung von Go in Go (gccgo und 6g / 8g sind beide in C geschrieben). Sowohl das Projekt als auch das Unternehmen verschwanden jedoch, bevor sie die Closed Beta verlassen hatten.
Jörg W Mittag
6

C / C ++ ist einzigartig in kompilierten Sprachen, da es drei Hauptimplementierungen einer gemeinsamen Spezifikation enthält.

Nach der Regel, alles zu verwerfen, was nicht oft verwendet wird, hat jede andere kompilierte Sprache 0 zu 1.

Und ich denke, Javascript ist der einzige Grund, warum Sie "kompiliert" angeben müssen.

Soru
quelle
2
Die Bezeichnung "C" wird auf eine Reihe verschiedener Sprachen angewendet. Einige definieren den Code uint16_t a=48000u; unsigned uint32_t b=(a*a)/2;als Zuweisung zum bWert 8192. Einige definieren ihn als Zuweisung zu 1152000000. Die meisten betrachten ihn heutzutage als undefiniertes Verhalten und speichern wahrscheinlich 3299483648, versprechen dies jedoch nicht.
Supercat
1
@supercat: Ah, eine gute verrückte mit Überläufen und ganzzahligen Beförderungsregeln. Es hängt von der Verwendung 2oder 2uanscheinend.
Zan Lynx
1
@ZanLynx: Ich glaube nicht, dass es Fälle gibt, in denen 2 gegen 2u eine legitime Rolle spielen. Der einzige Fall, von dem ich weiß, wo es darauf ankommt, ist Undefiniertes Verhalten mit 2 und 2u.
Supercat
3
@supercat: wie würdest du undefiniertes Verhalten bekommen /2u? Überlauf ohne Vorzeichen ist definiert (als Modulo 2 ^ N für implementierungsdefiniertes N), aber Division kann nicht einmal überlaufen.
MSalters
2
Das Undefinierte Verhalten würde aus der Multiplikation von Werten resultieren, die zu signiert befördert würden int, deren Produkt jedoch nicht zu diesem Typ passen würde. Das Erzwingen dieses Ergebnisses auf int ohne Vorzeichen würde wahrscheinlich die Interpretation des resultierenden Werts ändern, das undefinierte Verhalten aus der vorhergehenden Berechnung jedoch nicht negieren.
Supercat
5

Also, was ist Ihre Zielsprache?

SML-Compiler zielen häufig auf C oder so etwas wie LLVM (oder wie in Ihrem Link, der JVM oder JavaScript).

Wenn Sie C kompilieren, liegt das nicht daran, dass Sie zur JVM gehen. Du wirst etwas Schlimmeres als C. Weit schlimmer. Und dann können Sie diese kleine Hölle ein paar Mal für alle Ihre Zielplattformen duplizieren.

Und sicher, C ist nicht C ++, aber ich würde sagen, dass es näher an C ++ liegt als Schema. Es hat eine eigene Untergruppe von undefiniertem Verhalten Bösartigkeit (ich sehe Sie Größe der eingebauten Typen). Und wenn Sie diese Kleinigkeiten vermasseln (oder "richtig", aber unerwartet "machen"), verfügen Sie über jahrzehntelangen Code auf wichtigen Systemen, der Ihnen sagt, wie schrecklich Sie sind. Wenn Sie einen SML-Compiler vermasseln, funktioniert er einfach nicht - und jemand könnte es bemerken. Irgendwann mal.

Telastyn
quelle
SML / NJ und PolyML kompilieren beide zu Maschinencode ...
Basile Starynkevitch
2
Wie ist int size "Undefiniertes Verhalten"? Und warum sollte UB die Compiler-Anbieter überhaupt belasten? Die einzige wirkliche Belastung für Compiler-Schreiber besteht darin, dass die Int-Breiten durch die Implementierung definiert und nicht unbestimmt sind. Sie müssen also dokumentieren, was Sie getan haben.
MSalters
@MSalters In Wirklichkeit müssen Compiler-Autoren für eine etablierte Plattform die Anforderungen der anderen Plattformen erfüllen. Manchmal ist dies dokumentiert und standardisiert, manchmal nicht. Es ist einfach zu finden, wie groß ein int ist, aber schwieriger zu finden, was mit Registerwerten gemacht wird und wo Argumente gespeichert werden, wenn eine Funktion aufgerufen wird (die sich abhängig von den Argumenttypen und dem Rückgabetyp der Funktion ändern kann). etc.
Random832
@MSalters Die meisten Leute erwarten int32 oder 64 Bit, aber es kann so klein wie 16 Bit sein. Es ist überhaupt nicht schwer, eine Zahl außerhalb des Bereichs von zu produzieren, [−32767, +32767]und der intÜberlauf ist UB. Es gibt auch char/ shortzu gefördert zu werden int oder unsigned int je nachdem , ob intjeder Wert des ursprünglichen Typs darstellen kann, die weiter eine Umwandlung von auslösen können intzu , unsigned intwenn die Operanden hatten verschiedene Typen und wurde anders umgesetzt, und möglicherweise eine andere Umwandlung , wenn Sie das Ergebnis einer Variablen zuweisen .
Doval
@MSalters Es gibt genügend Spielraum bei der Größe der Standardtypen und genügend implizite Konvertierungen, sodass ich wetten würde, dass es für nahezu jedes nicht-triviale C-Programm eine Auswahl zulässiger ganzzahliger Größen gibt, die dazu führen, dass es das Falsche tut oder Undefinierte verursacht Verhalten.
Doval