LoginSignup
1
1

More than 3 years have passed since last update.

「LLVM bitcode はポータブルでない」ってどういう意味なの?

Posted at

発端

LLVM bitcode はポータブルでない
http://shinh.skr.jp/slide/elvm/002.html

これがどういう意味なのか分からなくてずっと気になってました。
LLVMのbitcodeってターゲット非依存なんじゃないの?みたいな感じで。

ここでは「ポータブルでない」というのを
(実行される)プラットフォームまたは(コンパイルの)ターゲット
依存している(dependent)または固有のもの(specific)を含むこと
ぐらいにふんわり理解してます。
「だから〇〇ができない」みたいなことは考えません。

結論あるいは感想

  • LLVM IRとそれをまとめたbitcode自体はターゲットに依存しない
  • 実際にはだいたい(?)ターゲットに依存したIRが出力される
    • C系の場合にはほぼ不可避
    • Swiftでもターゲット依存のIRっぽい
  • low levelな中間表現なんだからそりゃターゲット依存にもなるでしょ
    • 正しいのかは分からないけどそういう気持ちになった
    • ただしLLVMは何の略でもないことになってる

C/C++/Objective-C

Cとその上位互換たちの話のはずなので、Objective-Cもたぶん該当する

LLVM公式のFAQを翻訳してちょっとコメント

Question

Can I compile C or C++ code to platform-independent LLVM bitcode?

CやC++のコードをプラットフォームに依存しないLLVM bitcodeにコンパイルできますか?

Answer

3分割してタイトルを付けます。

コンパイル前(プリプロセッサ)

No. C and C++ are inherently platform-dependent languages. The most obvious example of this is the preprocessor. A very common way that C code is made portable is by using the preprocessor to include platform-specific code. In practice, information about other platforms is lost after preprocessing, so the result is inherently dependent on the platform that the preprocessing was targeting.

できません。CやC++は本質的にプラットフォーム依存な言語です。いちばん分かりやすい例としては、プリプロセッサがあります。Cのコードをポータブルにするためによくあるやり方は、プリプロセッサを使ってプラットフォーム固有のコードを含めることです。実際のところ、他のプラットフォームの情報はプリプロセスの後では失われ、その成果物はプリプロセスが対象としたプラットフォームに本質的に依存したものとなります。

要するに、LLVM IRを作るコンパイル以前に、既にプラットフォーム依存なコードになってるのが普通というわけです。

コンパイル時(sizeof)

Another example is sizeof. It’s common for sizeof(long) to vary between platforms. In most C front-ends, sizeof is expanded to a constant immediately, thus hard-wiring a platform-specific detail.

もう1つの例として、sizeofがあります。よく知られているように、sizeof(long)はプラットフォームごとに変わります。多くのC言語のフロントエンドでは、sizeofを定数値に直接展開して、プラットフォーム固有の詳細を埋め込みます。

ここでのフロントエンドは、clangとか、LLVMのフロントエンドのことですね。プリプロセッサのようにコンパイル前だけでなく、コンパイル過程でもプラットフォーム固有の値がそのまま入ってしまうのが普通、ということでしょう。

ABI

Also, since many platforms define their ABIs in terms of C, and since LLVM is lower-level than C, front-ends currently must emit platform-specific IR in order to have the result conform to the platform ABI.

また、多くのプラットフォームでABIはCレベルで定義され、そしてLLVMはCより低レベルなので、そのプラットフォームのABIに合わせた成果物を得るために、フロントエンドはプラットフォーム固有のIRを出力しなければならないのが現状です。

私はABIというものをちゃんと分かっていません。なので、それっぽい翻訳だけにとどめておきます。

Swift

SILのドキュメントでのLLVM IRの扱い

SILというのは、コンパイル過程でASTとLLVM IRの中間にあるやつで、raw SILとcanonical SILの2段階があります。それ以外のことは何も分かってませんが、LLVM IRとの対比で興味深い表現を見つけました。

In contrast to LLVM IR, SIL is a generally target-independent format representation that can be used for code distribution, but it can also express target-specific concepts as well as LLVM can.

LLVM IRとは対照的に、SILは専らターゲットに依存しないフォーマットの表現形態で、コード配布に使うことができます。しかし、LLVMと同様に、ターゲット特有の概念を表現することもできます。

ここではLLVM IRがターゲット依存なものとして扱われているように読めます。これがC系のように不可避の現実なのか、(例えば何らかの最適化のための?)選択なのかは分かっていませんが、high-levelなSILではターゲットに依存しない表現を扱い、ターゲット依存なものはlow levelなLLVM IRの担当になっているようです。

Rust

LLVMのフロントエンドとして、C系、Swiftの他にRustでの扱いも挙げておきます。なお、私はRustのことは何も知りません。

Rustコミュニティでの質問と回答

TODO MIRの記事から何か分かるといいな

  • Introducing MIR
    • SwiftのSILのように、LLVM IRの手前に別の中間表現があるようです。
    • ほぼ図しか見てないので、そのうち読んで何か追記します。
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1