web-dev-qa-db-ja.com

llvmでマシンコードを生成する方法

私は現在、llvmを使用してコンパイラプロジェクトに取り組んでいます。構文ツリーを作成するためのパーサーがあり、提供されたIRBuilderを使用してツリーがllvmモジュールに変換されるまで、さまざまなチュートリアルに従いました。

私の目標は実行可能ファイルを作成することですが、次に何をすべきか混乱しています。私が見つけたすべてのチュートリアルは、llvmモジュールを作成し、Module.dump()を使用してアセンブリを印刷するだけです。さらに、私が見つけることができる唯一のドキュメントはllvm開発者向けであり、プロジェクトのエンドユーザー向けではありません。

マシンコードを生成したい場合、次のステップは何ですか? llvm-mcプロジェクトは、私が望むことを実行できるように見えますが、ドキュメントが見つかりません。

おそらく、llvmが実行しないことを実行することを期待しています。私の期待は、モジュールを構築できることです。その後、モジュールで呼び出すことができるAPIがあり、ターゲットトリプルとオブジェクトファイルが生成されます。 JITの作成に関するドキュメントと例を見つけましたが、興味はありません。コンパイルされたバイナリを作成する方法を探しています。

影響がある場合は、OSXに取り組んでいます。

22
David Mason

使用する llc -filetype=objIRからリンク可能なオブジェクトファイルを発行します。 llcのコードを見ると、そのようなコードを発行するためにLLVMAPI呼び出しが行われていることがわかります。少なくともMacOS XとLinuxの場合、そのような方法で出力されたオブジェクトはかなり良いはずです(つまり、これは今のところ「アルファ品質」オプションではありません)。

ただし、LLVMにはリンカーが含まれていません(まだ!)。したがって、このオブジェクトファイルを実行可能ファイルまたは共有ライブラリに実際にリンクするには、システムリンカーを使用する必要があります。単一のオブジェクトファイルで構成される実行可能ファイルがある場合でも、後者はとにかくリンクする必要があることに注意してください。 LLVMコミュニティの開発者は、lldと呼ばれるLLVMの実際のリンカーに取り組んでいます。 そのページ にアクセスするか、メーリングリストのアーカイブを検索して進行状況を確認できます。

16
Eli Bendersky

llcガイド で読むことができるように、それは確かにアセンブリを生成することだけを目的としており、「アセンブリ言語の出力をネイティブアセンブラとリンカに渡してネイティブ実行可能ファイルを生成できます」-例えばgnuアセンブラ(as)とリンカー(ld)。

したがって、ここでの主な答えは、アセンブルとリンクにネイティブツールを使用することです

ただし、llcを介して、IRファイルから直接ネイティブオブジェクトを生成するための実験的なサポートがあります。

-filetype      - Choose a file type (not all types are supported by all targets):
    =asm         -   Emit an Assembly ('.s') file
    =obj         -   Emit a native object ('.o') file [experimental]

または、llvm-mcを使用して、.sファイルからアセンブルすることもできます。

-filetype      - Choose an output file type:
    =asm         -   Emit an Assembly ('.s') file
    =null        -   Don't emit anything (for timing purposes)
    =obj         -   Emit a native object ('.o') file

リンカーについてはわかりませんが。

さらに、tools/bugpoint/ToolRunner.hファイルをチェックすることをお勧めします。このファイルは、llcとプラットフォームのネイティブCツールチェーンを組み合わせてマシンコードを生成するラッパーを公開しています。そのヘッダーコメントから:

このファイルは、Cおよびアセンブリコードのコンパイルに使用されるプラットフォームCコンパイラに関する抽象化を公開します。

15
Oak

llvm-c/TargetMachine.hでこれらの関数を確認してください。

/** Emits an asm or object file for the given module to the filename. This
  wraps several c++ only classes (among them a file stream). Returns any
  error in ErrorMessage. Use LLVMDisposeMessage to dispose the message. */
LLVMBool LLVMTargetMachineEmitToFile(LLVMTargetMachineRef T, LLVMModuleRef M,
  char *Filename, LLVMCodeGenFileType codegen, char **ErrorMessage);

/** Compile the LLVM IR stored in \p M and store the result in \p OutMemBuf. */
LLVMBool LLVMTargetMachineEmitToMemoryBuffer(LLVMTargetMachineRef T, LLVMModuleRef M,
  LLVMCodeGenFileType codegen, char** ErrorMessage, LLVMMemoryBufferRef *OutMemBuf);
5
andrewrk

サンプルのBrainFプログラムを実行するには、それをコンパイルして実行します。

echo ,. > test.bf
./BrainF test.bf -o test.bc
llc -filetype=obj test.bc
gcc test.o -o a.out
./a.out

次に、1文字を入力して、Enterキーを押します。それはあなたにその手紙をエコーバックするはずです。 (それが,.します。)

上記はLLVMバージョン3.5.0でテストされました。

1