2013-07-11 9 views
10

Ich llvm lernen und wollte eine Proof of Concept einer Idee, die ich habe.Call C/C++ Funktionen von der ExecutionEngine

Grundsätzlich möchte ich meinen Compiler und meine Laufzeit teilen. Der Compiler würde ein .bc geben und die Laufzeit würde es über ParseBitcodeFile laden und die ExecutionEngine verwenden, um es auszuführen. Dieser Teil funktioniert.

Nun, um Systemaufrufe leicht zu machen, möchte ich in der Lage sein, in meiner Laufzeit C/C++ Funktionen zu implementieren, die alle Systemaufrufe (Datei io, stdout Druck usw.) ausführen. Meine Frage ist, wie kann ich diese Funktionen aus dem Code von meinem Spielzeug-Compiler, der in einem anderen Schritt von llvm kompiliert wird, aufrufen und erlauben, dass es bei der Ausführung verwendet wird.

Antwort

9

Gute Nachrichten: Wenn Sie die JIT ExecutionEngine verwenden, wird dies nur arbeiten. Wenn der JIT-er ein vom IR verwendetes externes Symbol findet, das nicht im IR selbst gefunden wird, sieht es im JIT-in-Prozess selbst aus, so dass alle Symbole, die von Ihrem Host-Programm sichtbar sind, aufgerufen werden können.

Dies wird direkt in part 4 of the LLVM tutorial erklärt:

Whoa, woher weiß der JIT über Sünde und cos? Die Antwort ist überraschend einfach: In diesem Beispiel startete das JIT die Ausführung einer Funktion und kam zu einem Funktionsaufruf. Es stellte sich heraus, dass die Funktion noch nicht JIT kompiliert wurde und den Standardsatz von Routinen auf löste, um die Funktion aufzulösen. In diesem Fall ist kein Körper für die -Funktion definiert, so dass das JIT letztendlich "dlsym (" sin ")" auf dem Kaleidoscope-Prozess aufgerufen hat. Da "sin" innerhalb des JIT-Adressraums definiert ist, führt es einfach Aufrufe im Modul durch, um die libm-Version von sin direkt aufzurufen.

Für die blutigen Details schauen Sie auf lib/ExecutionEngine/JIT/JIT.cpp - insbesondere die Verwendung von DynamicLibrary.

8

Elis Antwort ist großartig und Sie sollten es akzeptieren. Es gibt jedoch eine andere Alternative, die Quelldateien Ihrer Laufzeitumgebung zu LLVM-Modulen (z. B. mit Clang) separat zu kompilieren und ExecutionEngine::addModule() zu verwenden, um sie hinzuzufügen.

Es ist weniger praktisch, und es bedeutet, die gleichen Dateien zweimal kompilieren (einmal für Ihr Host-Programm, ein anderes, um Module s von ihnen zu bekommen), aber der Vorteil ist, dass es Inlining und andere funktionsübergreifende Optimierungen von Ihrem JITted-Code ermöglicht .