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

# 発端

> 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を翻訳してちょっとコメント

http://llvm.org/docs/FAQ.html#can-i-compile-c-or-c-code-to-platform-independent-llvm-bitcode

### 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の扱い

https://github.com/apple/swift/blob/master/docs/SIL.rst#sil-in-the-swift-compiler

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コミュニティでの質問と回答

+ [Cross Platform: Rust to LLVM IR and is LLVM IR is portable?](https://users.rust-lang.org/t/cross-platform-rust-to-llvm-ir-and-is-llvm-ir-is-portable/7767)　
    + 私の気になってた話と回答がそのままここに
    + Rust特有の話っぽいのはあんまりちゃんと読んでません
    + LLVM公式のFAQへのリンクもあります

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

+ [Introducing MIR](https://blog.rust-lang.org/2016/04/19/MIR.html)
    + SwiftのSILのように、LLVM IRの手前に別の中間表現があるようです。
    + ほぼ図しか見てないので、そのうち読んで何か追記します。