2013-07-11 6 views
10

私はllvmを学んでおり、私が持っているアイデアの概念の証明をしたかったのです。ExecutionEngineのC/C++関数を呼び出す

基本的に、コンパイラとランタイムを分割したいと考えています。コンパイラは.bcを与え、ランタイムはそれをParseBitcodeFile経由でロードし、ExecutionEngineを使用して実行します。この部分は機能しています。

システムコールを簡単にするために、すべてのシステムコール(ファイルio、stdoutの印刷など)を実行するC/C++ランタイムで実装することができます。私の質問は、llvmの別のステップでコンパイルされたtoyコンパイラのコードから、これらの関数をどのように呼び出すことができ、実行時にその関数を使用できるようにすることです。

答えて

9

良いニュース:JIT ExecutionEngineを使用する場合、これはとなります。です。 JIT-erがIRで使用されているIRが使用している外部シンボルを検出すると、JIT-ingプロセス自体が調べられ、ホストプログラムから見えるシンボルを呼び出すことができます。

これはpart 4 of the LLVM tutorialに直接説明します

おっと、どのようにJITは罪とCOSについて知っていますか?答えは で、意外に単純です。この例では、JITは 関数の実行を開始し、関数呼び出しを取得しました。関数がまだ であり、まだJITがコンパイルされておらず、 ルーチンの標準セットが呼び出されて関数が解決されていることが分かりました。この場合、 関数に定義されているボディが存在しないため、JITは万華鏡プロセス自体の で "dlsym(" sin ")"という呼び出しを終了しました。 「sin」はJITの アドレス空間内で定義されているため、モジュールの呼び出しをパッチするだけで、 libmバージョンのsinを直接呼び出すことができます。

詳細については、lib/ExecutionEngine/JIT/JIT.cppをご覧ください。具体的には、DynamicLibraryです。

8

エリの答えは素晴らしいですし、それを受け入れるべきです。ただし、ランタイムソースファイルをLLVMモジュール(Clangなど)に個別にコンパイルし、ExecutionEngine::addModule()を使用して追加することもできます。

これはあまり便利ではなく、同じファイルを2回コンパイルすることです(ホストプログラムでは1回、別のファイルではModulesを取得します)。ただし、JITtedコードからのインライン化やその他のクロス関数の最適化が可能です。