ネイティブ・イメージのLLVMバックエンド

ネイティブ・イメージには、LLVM中間表現およびLLVMコンパイラを使用してネイティブ実行可能ファイルを生成する代替バックエンドが含まれています。これを使用するには、ネイティブ・イメージの呼出しに-H:CompilerBackend=llvmオプションを追加します。

LLVMバックエンドを使用するには、GraalVMのLLVMツールチェーンがインストールされている必要があります(gu install llvm-toolchainを使用)。

コード生成オプション

デバッグ・オプション

バッチについて: LLVMコンパイルは次の4つのフェーズで実行されます:

  1. 関数ごとにLLVMビットコード・ファイル(f0.bcf1.bcなど)が作成されます。
  2. ビットコード・ファイルがバッチ(b0.bcb1.bcなど)にリンクされます。-H:LLVMMaxFunctionsPerBatch=1が指定されている場合、このフェーズはスキップされます。
  3. バッチが(b0o.bcb1o.bcなどに)最適化され、(b0.ob1.oなどに)コンパイルされます。
  4. コンパイルされたバッチが単一のオブジェクト・ファイル(llvm.o)にリンクされ、そのファイルが最終実行可能ファイルにリンクされます。

LLVMバックエンドを使用したGraalVMへのターゲット・アーキテクチャの追加方法

LLVMバックエンドの興味深いユース・ケースは、ネイティブ・イメージ用にまったく新しいバックエンドを実装することなく、新しいアーキテクチャをターゲットにすることです。現時点でこれを実現するために必要なステップは次のとおりです。

ターゲット固有のLLVM設定

場合によっては、GraalVMコードでLLVMのターゲット非依存の性質よりも深い部分を処理することが必要になります。これらの代表例は、直接レジスタ・アクセスおよび直接レジスタ・ジャンプ(トランポリンの場合)と、LLVMによって発行されるコードのスタック・フレームの構造に関する精度を実装するための、インライン・アセンブリ・スニペットです。一般的に、このことは、十数個に満たない単純な値が新しいターゲットごとに設定されることを表します。将来的には、これが新しいターゲットをサポートするために唯一必要な追加になるようにすることが目標です。

(AArch64の完全な値セット)

LLVMステートポイントのサポート

LLVMバックエンドでは、LLVMの一般的で十分にサポートされている機能が使用されますが、ガベージ・コレクション・サポートでは、LLVMの試験段階の機能であるステートポイント組込み関数が暗黙的に使用されます。現在、この機能はx86_64でのみサポートされており、現在、コード・ベースにAArch64のGraalVM実装を追加するよう要求しているところです。つまり、LLVMコミュニティの多大な努力が実らないかぎり、新しいアーキテクチャをサポートするには、要求されたターゲットのLLVMにステートポイントを実装する必要があります。ほとんどのステートポイント・ロジックはビットコード・レベル、つまりターゲット非依存のステージで処理されることから、これには、ステートポイント組込み関数を弱める正しいタイプのコールの発行が大きく関係します。AArch64のステートポイント実装は100行未満のコードで構成されます。

(AArch64のステートポイント実装)

オブジェクト・ファイルのサポート

GraalコンパイラのLLVMバックエンドで作成されたプログラムのデータ・セクションは、現在、LLVMによって処理されるコードから独立して発行されます。つまり、LLVMでコンパイルされたコードをGraalVMで生成されたデータ・セクションにリンクできるようにするには、Graalコンパイラでターゲット・アーキテクチャのオブジェクト・ファイルの再配置が認識されている必要があります。LLVMビットコードとしてコードを使用してデータ・セクションを発行することはLLVMバックエンドの次の優先事項であるため、これは将来のターゲットでは問題になりません。

(例はELFMachine$ELFAArch64Relocationsを参照)