= 手を動かせばできるLLVMバックエンド チュートリアル 艮 鮟鱇 :toc: left :icons: font :stem: latexmath == FIXME AsciiDocのコメントを用いて文中にFIXMEを仕込む。 その他のFIXME(全般的なものなど)をここにリストにする。 * だ・である調をです・ます調に変える。 * 実際にやってみる。 ** 現状過去の作業ログを切り貼りしながら書いているので通してちゃんと動くかは良くわからない。 ** ついでにLLVM v10.0.0に対応させる。 == この文書について この文書はAsciiDocを用いて執筆されています。 この文書はGitによって管理されています。 https://github.com/ushitora-anqou/write-your-llvm-backend[リポジトリはGitHubにて 公開しています]。 この文書に(おおよそ)則って開発されたLLVMバックエンドのソースコードを https://github.com/virtualsecureplatform/llvm-cahp[GitHubリポジトリにて公開しています]。 この作品は、クリエイティブ・コモンズの 表示 4.0 国際 ライセンスで提供されています。ライセンスの写しをご覧になるには、 http://creativecommons.org/licenses/by/4.0/ をご覧頂くか、Creative Commons, PO Box 1866, Mountain View, CA 94042, USA までお手紙をお送りくださいfootnote:[この 段落はクリエイティブ・コモンズより引用。]。 本文書の内容は筆者が独自に調査したものです。 **疑う余地なく誤りが含まれます**。誤りに気づかれた方はGitHubリポジトリなどを通じて ご連絡ください。 == LLVMバックエンド概略 本書ではRISC-V風味の独自ISAを例にLLVMバックエンドを開発します。 // FIXME: そのうち10がでそう。 使用するLLVMのバージョンはv9.0.0です。 // FIXME: 人がLLVMバックエンドを書きたくなるような文章をここに書く。 == ところで 一度もコンパイラを書いたことがない人は、この文書を読む前に 『低レイヤを知りたい人のためのCコンパイラ作成入門』<>などで一度 フルスクラッチからコンパイラを書くことをおすすめします。 また<>などを参考に、 LLVMではなくGCCにバックエンドを追加することも検討してみてはいかがでしょうか。 == 参考にすべき文献 LLVMバックエンドを開発する際に参考にできる書籍やWebサイトを以下に一覧します。 なおこの文書では、RISC-Vバックエンド及びそれに関する技術資料を**大いに**参考しています。 === Webページ * Writing an LLVM Backend<> ** 分かりにくく読みにくい。正直あんまり見ていないが、たまに眺めると有益な情報を見つけたりもする。 * The LLVM Target-Independent Code Generator<> ** <>よりもよほど参考になる。LLVMバックエンドがどのようにLLVM IRをアセンブリに落とすかが明記されている。必読。 * TableGenのLLVMのドキュメント<> ** 情報量が少ない。これを読むよりも各種バックエンドのTableGenファイルを読むほうが良い。 * LLVM Language Reference Manual<> ** LLVM IRについての言語リファレンス。LLVM IRの仕様などを参照できる。必要に応じて読む。 * Architecture & Platform Information for Compiler Writers<> ** LLVMで公式に実装されているバックエンドに関するISAの情報が集約されている。Lanaiの言語仕様へのリンクが貴重。 * RISC-V support for LLVM projects<> ** **どちゃくそに参考になる**。以下の開発はこれに基づいて行う。 ** LLVMにRISC-Vサポートを追加するパッチ群。バックエンドを開発するためのチュートリアルも兼ねているらしく `docs/` 及びそれと対応したpatchが参考になる。 ** またこれについて、開発者が2018 LLVM Developers' Meetingで登壇したときの動画は<>より閲覧できる。スライドは<>より閲覧できる。 ** そのときのCoding Labは<>より閲覧できる。 * Create an LLVM Backend for the Cpu0 Architecture<> ** Cpu0という独自アーキテクチャのLLVMバックエンドを作成するチュートリアル。多少古いが、内容が網羅的で参考になる。英語が怪しい。 * FPGA開発日記<> ** Cpu0の資料<>をもとに1からRISC-Vバックエンドを作成する過程がブログエントリとして公開されている。GitHubに実装も公開されている<>。 * ELVMバックエンド<> ** 限られた命令でLLVM IRの機能を達成する例として貴重。でも意外とISAはリッチだったりする。 ** 作成者のスライドも参考になる<>。 * 2018年度東大CPU実験で開発されたLLVM Backend<> ** これについて書かれたAdCのエントリもある<>。 * Tutorial: Building a backend in 24 hours<> ** LLVMバックエンドの大まかな動きについてざっとまとめたあと、 `ret` だけが定義された最低限のLLVMバックエンド ("stub backend") を構成している。 ** Instruction Selection の説明にある *Does bunch of magic and crazy pattern-matching* が好き。 * 2017 LLVM Developers’ Meeting: M. Braun "Welcome to the back-end: The LLVM machine representation"<> ** スライドも公開されている<>。 ** 命令選択が終わったあとの中間表現であるLLVM MIR ( `MachineFunction` や `MachineInstr` など)や、それに対する操作の解説。 RegStateやframe index・register scavengerなどの説明が貴重。 * Howto: Implementing LLVM Integrated Assembler<> ** LLVM上でアセンブラを書くためのチュートリアル。アセンブラ単体に焦点を絞ったものは珍しい。 * Building an LLVM Backend<> ** 対応するレポジトリが<>にある。 * [LLVMdev] backend documentation<> ** llvm-devメーリングリストのバックエンドのよいドキュメントは無いかというスレッド。Cpu0とTriCoreが挙げられているが、深くまで記述したものは無いという回答。 * TriCore Backend<> ** TriCoreというアーキテクチャ用のバックエンドを書いたという論文。スライドもある<>。ソースコードもGitHub上に上がっているが、どれが公式かわからないfootnote:[論文とスライドも怪しいものだが、著者が一致しているので多分正しいだろう。]。 * Life of an instruction in LLVM<> ** Cコードからassemblyまでの流れを概観。 * LLVM Backendの紹介<> ** 「コンパイラ勉強会」footnote:[これとは別の発表で「コンパイラ開発してない人生はFAKE」という名言が飛び出した勉強会<>。]での、LLVMバックエンドの大きな流れ(特に命令選択)について概観した日本語スライド。 === 書籍 * 『きつねさんでもわかるLLVM〜コンパイラを自作するためのガイドブック〜』<> ** 数少ない日本語資料。Passやバックエンドの各クラスについて説明している。<>と合わせて大まかな流れを掴むのに良い。 ** ただし書籍中で作成されているバックエンドは機能が制限されており、またコードベースも多少古い。 なおLLVMについてGoogleで検索していると"LLVM Cookbook"なる謎の書籍(の電子コピー)が 見つかるが、内容はLLVM公式文書のパクリのようだ<>。 === バックエンド * RISC-V<> ** パッチ群が開発ドキュメントとともに公開されている<>。以降の開発はこれをベースに行う。 * Lanai<> ** Googleが開発した32bit RISCの謎アーキテクチャ。全く実用されていないが、バックエンドが単純に設計されておりコメントも豊富のためかなり参考になるfootnote:[LLVMバックエンドの開発を円滑にするためのアーキテクチャなのではと思うほどに分かりやすい。]footnote:[後のSparcについて<> にて指摘されているように、商業的に成功しなかったバックエンドほどコードが単純で分かりやすい。]。 * Sparc ** <>でも説明に使われており、コメントが豊富。 * x86 ** みんな大好きx86。貴重なCISCの資料であり、かつ2オペランド方式を採用する場合に実装例を与えてくれる。あと `EFLAGS` の取り回しなども参考になるが、全体的にコードは読みにくい。ただLLVMの命名規則には従うため、他のバックエンドからある程度推論をして読むのが良い。 == ISAの仕様を決める 本書で使用するISAであるCAHPv3について説明します。 cahpv3.pdfを参考のこと。 // FIXME: 書く == スケルトンバックエンドを追加する https://github.com/virtualsecureplatform/llvm-cahp/commit/d0b8dd14570dc9efac09d3c5fd6e8512980fd7b7[d0b8dd14570dc9efac09d3c5fd6e8512980fd7b7] CAHPのためのビルドを行うために、中身のないバックエンド(スケルトンバックエンド)を LLVMに追加します。 === CAHPをTripleに追加する <>を参考にして CAHPをLLVMに認識させます。LLVMではコンパイル先のターゲットをTripleという単位で 管理しています。そのTripleの一つとしてCAHPを追加します。 `llvm/include/llvm/ADT/Triple.h` や `llvm/lib/Support/Triple.cpp` などの ファイルにTripleが列挙されているため、そこにCAHPを追加します。 また `llvm/unittests/ADT/TripleTest.cpp` にTripleが正しく認識されているかをチェックする テストを書きます。 === CAHPのELFフォーマットを定義する <>を参考にして、CAHPのためのELFフォーマットを定義します。 具体的にはCAHPのマシンを表す識別コードや再配置情報などを記述し、 ELFファイルの出力が動作するようにします。 ただし独自ISAではそのような情報が決まっていないため、適当にでっちあげます。 === バックエンドを追加する <>を参考に `llvm/lib/Target` ディレクトリ内に `CAHP` ディレクトリを作成し、最低限必要なファイルを用意します。 まずビルドのために `CMakeLists.txt` と `LLVMBuild.txt` を用意します。 またCAHPに関する情報を提供するために `CAHPTargetInfo.cpp` や `CAHPTargetMachine.cpp` などを記述します。 `CAHPTargetMachine.cpp` ではdata layoutを文字列で指定します。 詳細はLLVM IRの言語仕様<>を参考してください。 // FIXME: ここで指定するdata layoutが結局の所どの程度影響力を持つのかは良くわからない。 // ツール間でのターゲットの識別程度にしか使ってなさそう。要確認。 以上で必要最小限のファイルを用意することができました。 == LLVMをビルドする LLVMは巨大なプロジェクトで、ビルドするだけでも一苦労です。 以下では継続的な開発のために、高速にLLVMをデバッグビルドする手法を紹介します。 <>・<>・<>を 参考にしています。 ビルドの際には以下のソフトウェアが必要になります。 * `cmake` * `ninja` * `clang` * `clang++` * `lld` まずLLVMのソースコードをGitを用いて取得します。 前述したように、今回の開発ではLLVM v9.0.0をベースとします。 そこでブランチ `llvmorg-9.0.0` から独自実装のためのブランチ `cahp` を生成し、 以降の開発はこのブランチ上で行うことにします。 $ git clone https://github.com/llvm/llvm-project.git $ cd llvm-project $ git switch llvmorg-9.0.0 $ git checkout -b cahp 続いて、ビルドを行うための設定をCMakeを用いて行います。 大量のオプションはビルドを早くするためのものです<>。 $ mkdir build $ cd build $ cmake -G Ninja \ -DLLVM_ENABLE_PROJECTS="clang;lld" \ -DCMAKE_BUILD_TYPE="Debug" \ -DBUILD_SHARED_LIBS=True \ -DLLVM_USE_SPLIT_DWARF=True \ -DLLVM_OPTIMIZED_TABLEGEN=True \ -DLLVM_BUILD_TESTS=True \ -DCMAKE_C_COMPILER=clang \ -DCMAKE_CXX_COMPILER=clang++ \ -DLLVM_USE_LINKER=lld \ -DLLVM_TARGETS_TO_BUILD="" \ -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD="CAHP" \ ../llvm Ninjaを用いてビルドを行います。直接Ninjaを実行しても構いません( `$ ninja` )が、 CMakeを用いて間接的に実行することもできます。 $ cmake --build . 手元の環境(CPUはIntel Core i7-8700で6コア12スレッド、RAMは16GB)では 30分弱でビルドが完了しました。 また別の環境(CPUはIntel Core i5-7200Uで2コア4スレッド、RAMは8GB)では 1時間半程度かかりました。以上から類推すると、 stem:[n]コアのCPUを使用する場合およそstem:[\frac{180}{n}]分程度かかるようです。 ビルドが終了すると `bin/` ディレクトリ以下にコンパイルされたバイナリが生成されます。 例えば次のようにして、CAHPバックエンドが含まれていることを確認できます。 .... $ bin/llc --version LLVM (http://llvm.org/): LLVM version 9.0.0 DEBUG build with assertions. Default target: x86_64-unknown-linux-gnu Host CPU: skylake Registered Targets: cahp - CAHP .... [NOTE] ==== ここでは開発用にデバッグビルドを行いました。 一方で、他人に配布する場合などはリリースビルドを行います。 その際は次のようにCMakeのオプションを指定します。 // FIXME: LLVM_BUILD_TESTS=False で良い気がする。要確認。 $ cmake -G Ninja \ -DLLVM_ENABLE_PROJECTS="lld;clang" \ -DCMAKE_BUILD_TYPE="Release" \ -DLLVM_BUILD_TESTS=True \ -DCMAKE_C_COMPILER=clang \ -DCMAKE_CXX_COMPILER=clang++ \ -DLLVM_USE_LINKER=lld \ -DLLVM_TARGETS_TO_BUILD="" \ -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD="CAHP" \ ../llvm ==== == LLVMをテストする `llvm-lit` を使用してLLVMをテストできます。 $ bin/llvm-lit test -s # 全てのテストを実行する。 $ bin/llvm-lit -s --filter "Triple" test # Tripleに関するテストを実行する。 $ bin/llvm-lit -s --filter 'CAHP' test # CAHPを含むテストを実行する。 $ bin/llvm-lit -as --filter 'CAHP' test # テスト結果を詳細に表示する。 $ bin/llvm-lit -as --filter 'CAHP' --debug test # デバッグ情報を表示する。 == アセンブラを作る https://github.com/virtualsecureplatform/llvm-cahp/commit/2c31c0a80020cc50bba6df1c35da228905190d97[2c31c0a80020cc50bba6df1c35da228905190d97] この章ではLLVMバックエンドの一部としてアセンブラを実装します。 具体的にはLLVMのMCLayerを実装し、アセンブリからオブジェクトファイルへの変換を可能にします。 一度にアセンブラ全体を作るのは難しいため、まずレジスタのみを使用する演算命令に絞って実装し、 その後メモリを使用する命令をカバーします。 === TableGenファイルを追加する LLVM coreは基本的にC++ によって記述されています。一方で、多くの箇所で共通する処理などは 独自のDSL(ドメイン固有言語)であるTableGenを用いて記述し `llvm-tblgen` という ソフトウェアを用いてこれをC++ コードに変換しています。 こうすることによって記述量を減らし、ヒューマンエラーを少なくするという考え方 のようです<>。 LLVMバックエンドでは、アーキテクチャが持つレジスタや命令などの情報をTableGenによって 記述します。大まかに言って、TableGenで書ける場所はTableGenによって書き、 対応できない部分をC++ で直に書くというのがLLVM coreの方針のようです。 // FIXME: 単なる印象。ほんまか? ここでは、簡単なアセンブラを実装するために最低限必要なTableGenファイルを追加します。 内訳は次のとおりです。 * `CAHP.td`: 下のTableGenファイルをincludeし、その他もろもろを定義。 * `CAHPRegisterInfo.td`: レジスタを定義。 * `CAHPInstrFormats.td`: 命令形式を定義。 * `CAHPInstrInfo.td`: 命令を定義。 順に説明します。 `CAHP.td` がTableGenファイル全体をまとめているTableGenファイルで、 内部では `include` を使って他のファイルを読み込んでいます。 include "llvm/Target/Target.td" include "CAHPRegisterInfo.td" include "CAHPInstrInfo.td" また同時に、今回想定するプロセッサを表す `ProcessorModel` や、 現在実装しているターゲットの `CAHP` について定義しています。 // FIXME: ここの定義が具体的にC++コードにどう反映されるかの確認が必要。 // まぁこう書いておけば問題ないという認識でもとりあえず良い気もするけど……。 `CAHPRegisterInfo.td` ではCAHPに存在するレジスタを定義します。 まず `Register` を継承して `class CAHPReg` を作り、これに基本的なレジスタの性質をもたせます。 ついで `class CAHPReg` の実体として `X0` から `X15` を作成します。 `alt` にはレジスタの別名を指定します。 // FIXME: ABIRegAltName がどういう役割を果たしてるのか要検証。 // 多分 `getRegisterName` の第二引数に何も渡さなかったときにAltNameを表示 // させるのに必要なんだと思うけど、裏をとってない。 最後に、レジスタをまとめて `RegisterClass` である `GPR` (General Purpose Register; 汎用レジスタの意)を定義します。 このあと命令を定義する際にはこの `RegisterClass` 単位で指定します。 ここでレジスタを並べる順番が先であるほどレジスタ割り付けで割り付けられやすいため、 caller-savedなもの(使ってもspill outが起こりにくいもの)を先に並べておきます。 `GPR` と同様に `SP` という `RegisterClass` も作成し、 `X1` 、 つまりスタックポインタを表すレジスタのみを追加しておきます。 この `RegisterClass` を命令のオペランドに指定することで `lwsp` や `swsp` などの「スタックポインタのみを取る命令」を表現することができます。 命令は `CAHPInstrFormats.td` と `CAHPInstrInfo.td` に分けて記述します。 `CAHPInstrFormats.td` ではおおよその命令の「形」を定義しておき、 `CAHPInstrInfo.td` でそれを具体化します。言葉で言ってもわかりにくいので、コードで見ます。 例えば24bit長の加算命令は次のように定義されます。 まずCAHPの命令全体に共通する事項を `class CAHPInst` として定義します。 .... class CAHPInst pattern = []> : Instruction { let Namespace = "CAHP"; dag OutOperandList = outs; dag InOperandList = ins; let AsmString = opcodestr # "\t" # argstr; // Matching patterns used when converting SelectionDAG into MachineDAG. let Pattern = pattern; } .... 次に、CAHPの24bit命令に共通する事項を `class CAHPInst` を継承した `class CAHP24Inst` として定義します。 .... // 24-bit instruction format. class CAHPInst24 pattern = []> : CAHPInst { let Size = 3; bits<24> Inst; } .... さらに、24bit長加算命令の「形」である24bit R形式(オペランドにレジスタを3つとる)を `class CAHPInst24R` として定義します。 `class CAHPInst24` を継承します。 .... // 24-bit R-instruction format. class CAHPInst24R opcode, dag outs, dag ins, string opcodestr, string argstr> : CAHPInst24 { bits<4> rd; bits<4> rs1; bits<4> rs2; let Inst{23-20} = 0; let Inst{19-16} = rs2; let Inst{15-12} = rs1; let Inst{11-8} = rd; let Inst{7-0} = opcode; } .... 最後にこれを使って加算命令 `ADD` を定義します。 .... def ADD : CAHPInst24R<0b00000001, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), "add", "$rd, $rs1, $rs2">; .... 上記の継承による構造を展開すると、結局 `class Instruction` を使って 次のような定義を行ったことになります。 // FIXME: 要確認。 .... def ADD : Instruction { let Namespace = "CAHP"; let Pattern = []; let Size = 3; // 命令長は8bit * 3 = 24bit bits<24> Inst; bits<4> rd; // オペランドrdは4bit bits<4> rs1; // オペランドrs1は4bit bits<4> rs2; // オペランドrs2は4bit // 命令のエンコーディングは次の通り。 let Inst{23-20} = 0; let Inst{19-16} = rs2; let Inst{15-12} = rs1; let Inst{11-8} = rd; let Inst{7-0} = 0b00000001; // 出力はレジスタクラスGPRのrdに入る。 dag OutOperandList = (outs GPR:$rd); // 入力はレジスタクラスGPRのrs1とrs2に入る。 dag InOperandList = (ins GPR:$rs1, GPR:$rs2); // アセンブリ上では「add rd, rs1, rs2」という形で与えられる。 let AsmString = "add\t$rd, $rs1, $rs2"; } .... // FIXME: `AsmString` は出力とパーズの両方に使われるっぽい。要確認。 // FIXME: 即値の取り回しについて書く === `MCTargetDesc` を追加する === `CAHPAsmParser` を追加する === `CAHPInstPrinter` を実装する === テストを書く === メモリ演算を追加する === 属性を指定する === ディスアセンブラを実装する === relocationとfixupに対応する === `%hi` と `%lo` に対応する === `li a0, foo` をエラーにする === llvm-objdump の調査 === `hlt` 疑似命令を追加する == コード生成部を作る === コンパイラのスケルトンを作成する === 基本的な演算に対応する === 定数の実体化に対応する === メモリ演算に対応する === relocationに対応する === 条件分岐に対応する === 関数呼び出しに対応する === 関数プロローグ・エピローグを実装する === frame pointer eliminationを実装する === `select` に対応する === `FrameIndex` をlowerする。 === 大きなスタックフレームに対応する === `SETCC` に対応する === `ExternalSymbol` に対応する === jump tableを無効化する === インラインアセンブリに対応する === fastccに対応する == Cコンパイラに仕立てる === LLDにCAHPバックエンドを追加する === ClangをCAHPに対応させる === `crt0.o` と `cahp.lds` の導入 === `--nmagic` の有効化 === libcの有効化 == まともなコードを生成する === 分岐解析に対応する === branch relaxationに対応する === 16bit命令を活用する === `jal` を活用する === 命令スケジューリングを設定する === 末尾再帰に対応する == 落ち穂拾い === スタックを利用した引数渡し === `byval` の対応 === 動的なスタック領域確保に対応する === emergency spillに対応する === 可変長引数関数に対応する === 単体の `sext/zext/trunc` に対応する === 乗算に対応する === 除算・剰余に対応する === `frameaddr/returnaddr` に対応する === `ROTL/ROTR/BSWAP/CTTZ/CTLZ/CTPOP` に対応する === 32bitのシフトに対応する === 間接ジャンプに対応する === `BlockAddress` のlowerに対応する [bibliography] == 参考文献 - [[[github_riscv-llvm_docs_01,1]]] https://github.com/lowRISC/riscv-llvm/blob/master/docs/01-intro-and-building-llvm.mkd - [[[llvm_getting-started,2]]] https://llvm.org/docs/GettingStarted.html - [[[clang_gettings-started,3]]] https://clang.llvm.org/get_started.html - [[[asciidoctor_user-manual,4]]] https://asciidoctor.org/docs/user-manual/ - [[[riscv,5]]] https://riscv.org/ - [[[riscv_specifications,6]]] https://riscv.org/specifications/ - [[[fox-llvm,7]]] 『きつねさんでもわかるLLVM〜コンパイラを自作するためのガイドブック〜』(柏木 餅子・風薬・矢上 栄一、株式会社インプレス、2013年) - [[[github_riscv-llvm_docs_02,8]]] https://github.com/lowRISC/riscv-llvm/blob/master/docs/02-starting-the-backend.mkd - [[[github_riscv-llvm_patch_02,9]]] https://github.com/lowRISC/riscv-llvm/blob/master/0002-RISCV-Recognise-riscv32-and-riscv64-in-triple-parsin.patch - [[[github_riscv-llvm,10]]] https://github.com/lowRISC/riscv-llvm - [[[youtube_llvm-backend-development-by-example,11]]] https://www.youtube.com/watch?v=AFaIP-dF-RA - [[[msyksphinz_try-riscv64-llvm-backend,12]]] http://msyksphinz.hatenablog.com/entry/2019/01/02/040000_1 - [[[github_riscv-llvm_patch_03,13]]] https://github.com/lowRISC/riscv-llvm/blob/master/0003-RISCV-Add-RISC-V-ELF-defines.patch - [[[github_riscv-llvm_patch_04,14]]] https://github.com/lowRISC/riscv-llvm/blob/master/0004-RISCV-Add-stub-backend.patch - [[[github_riscv-llvm_patch_06,15]]] https://github.com/lowRISC/riscv-llvm/blob/master/0006-RISCV-Add-bare-bones-RISC-V-MCTargetDesc.patch - [[[github_riscv-llvm_patch_10,16]]] https://github.com/lowRISC/riscv-llvm/blob/master/0010-RISCV-Add-support-for-disassembly.patch - [[[llvm-writing_backend-operand_mapping,17]]] https://llvm.org/docs/WritingAnLLVMBackend.html#instruction-operand-mapping - [[[llvm-writing_backend,18]]] https://llvm.org/docs/WritingAnLLVMBackend.html - [[[github_riscv-llvm_patch_07,19]]] https://github.com/lowRISC/riscv-llvm/blob/master/0007-RISCV-Add-basic-RISCVAsmParser.patch - [[[github_riscv-llvm_patch_08,20]]] https://github.com/lowRISC/riscv-llvm/blob/master/0008-RISCV-Add-RISCVInstPrinter-and-basic-MC-assembler-te.patch - [[[llvm-tablegen,21]]] https://llvm.org/docs/TableGen/index.html - [[[github_riscv-llvm_patch_09,22]]] https://github.com/lowRISC/riscv-llvm/blob/master/0009-RISCV-Add-support-for-all-RV32I-instructions.patch - [[[llvm_dev_ml-tablegen_definition_question,23]]] http://lists.llvm.org/pipermail/llvm-dev/2015-December/093310.html - [[[llvm_doxygen-twine,24]]] https://llvm.org/doxygen/classllvm_1_1Twine.html - [[[llvm-tablegen-langref,25]]] https://llvm.org/docs/TableGen/LangRef.html - [[[github_riscv-llvm_docs_05,26]]] https://github.com/lowRISC/riscv-llvm/blob/master/docs/05-disassembly.mkd - [[[github_riscv-llvm_patch_11,27]]] https://github.com/lowRISC/riscv-llvm/blob/master/0011-RISCV-Add-common-fixups-and-relocations.patch - [[[github_riscv-llvm_docs_06,28]]] https://github.com/lowRISC/riscv-llvm/blob/master/docs/06-relocations-and-fixups.mkd - [[[github_riscv-llvm_patch_13,29]]] https://github.com/lowRISC/riscv-llvm/blob/master/0013-RISCV-Initial-codegen-support-for-ALU-operations.patch - [[[speakerdeck-llvm_backend_development,30]]] https://speakerdeck.com/asb/llvm-backend-development-by-example-risc-v - [[[llvm-code_generator,31]]] https://llvm.org/docs/CodeGenerator.html - [[[llvm-code_generator-target_independent_code_gen_alg,32]]] https://llvm.org/docs/CodeGenerator.html#target-independent-code-generation-algorithms - [[[llvm-code_generator-selectiondag_instruction_selection,33]]] https://llvm.org/docs/CodeGenerator.html#selectiondag-instruction-selection-process - [[[github_riscv-llvm_patch_15,34]]] https://github.com/lowRISC/riscv-llvm/blob/master/0015-RISCV-Codegen-support-for-memory-operations.patch - [[[cpu0,35]]] https://jonathan2251.github.io/lbd/ - [[[elvm-llvm_backend,36]]] https://github.com/shinh/llvm/tree/elvm - [[[elvm-slide,37]]] http://shinh.skr.jp/slide/llel/000.html - [[[github_riscv-llvm_patch_16,38]]] https://github.com/lowRISC/riscv-llvm/blob/master/0016-RISCV-Codegen-support-for-memory-operations-on-globa.patch - [[[github_riscv-llvm_patch_17,39]]] https://github.com/lowRISC/riscv-llvm/blob/master/0017-RISCV-Codegen-for-conditional-branches.patch - [[[todai_llvm_backend,40]]] https://github.com/cpu-experiment-2018-2/llvm/tree/master/lib/Target/ELMO - [[[todai_llvm_backend-article,41]]] http://uenoku.hatenablog.com/entry/2018/12/25/044244 - [[[github_riscv-llvm_patch_18,42]]] https://github.com/lowRISC/riscv-llvm/blob/master/0018-RISCV-Support-for-function-calls.patch - [[[llvm-langref,43]]] http://llvm.org/docs/LangRef.html - [[[fpga_develop_diary,44]]] http://msyksphinz.hatenablog.com/ - [[[llvm-anton_korobeynikov_2012,45]]] https://llvm.org/devmtg/2012-04-12/Slides/Workshops/Anton_Korobeynikov.pdf - [[[llvm-welcome_to_the_back_end_2017,46]]] https://www.youtube.com/watch?v=objxlZg01D0 - [[[ean10-howto-llvmas,47]]] https://www.embecosm.com/appnotes/ean10/ean10-howto-llvmas-1.0.html - [[[lowrisc-devmtg18,48]]] https://www.lowrisc.org/llvm/devmtg18/ - [[[LLVMBackend_2015_03_26_v2,49]]] http://www.inf.ed.ac.uk/teaching/courses/ct/other/LLVMBackend-2015-03-26_v2.pdf - [[[rui-compilerbook,50]]] https://www.sigbus.info/compilerbook - [[[krister-writing_gcc_backend,51]]] https://kristerw.blogspot.com/2017/08/writing-gcc-backend_4.html - [[[llvm-ml-129089,52]]] http://lists.llvm.org/pipermail/llvm-dev/2019-January/129089.html - [[[llvm-langref-datalayout,53]]] https://llvm.org/docs/LangRef.html#langref-datalayout - [[[github-frasercrmck_llvm_leg,54]]] https://github.com/frasercrmck/llvm-leg/tree/master/lib/Target/LEG - [[[llvm_doxygen-InitMCRegisterInfo,55]]] https://llvm.org/doxygen/classllvm_1_1MCRegisterInfo.html#a989859615fcb74989b4f978c4d227a03 - [[[llvm-programmers_manual,56]]] http://llvm.org/docs/ProgrammersManual.html - [[[llvm-writing_backend-calling_conventions,57]]] https://llvm.org/docs/WritingAnLLVMBackend.html#calling-conventions - [[[riscv-calling,58]]] https://riscv.org/wp-content/uploads/2015/01/riscv-calling.pdf - [[[llvm_dev_ml-how_to_debug_instruction_selection,59]]] http://lists.llvm.org/pipermail/llvm-dev/2017-August/116501.html - [[[fpga_develop_diary-20190612040000,60]]] http://msyksphinz.hatenablog.com/entry/2019/06/12/040000 - [[[llvm_dev_ml-br_cc_questions,61]]] http://lists.llvm.org/pipermail/llvm-dev/2014-August/075303.html - [[[llvm_dev_ml-multiple_result_instrs,62]]] https://groups.google.com/forum/#!topic/llvm-dev/8kPOj-_lbGk - [[[stackoverflow-frame_lowering,63]]] https://stackoverflow.com/questions/32872946/what-is-stack-frame-lowering-in-llvm - [[[llvm_dev_ml-selecting_frame_index,64]]] https://groups.google.com/d/msg/llvm-dev/QXwtqgau-jA/PwnHDF0gG_oJ - [[[fpga_develop_diary-llvm,65]]] https://github.com/msyksphinz/llvm/tree/myriscvx/impl90/lib/Target/MYRISCVX - [[[llvm-github_cd44ae,66]]] https://github.com/llvm/llvm-project/commit/cd44aee3da22f9a618f2e63c226bebf615fa8cf8 - [[[llvm_phabricator-d43752,67]]] https://reviews.llvm.org/D43752 - [[[llvm-compilerwriterinfo,68]]] https://llvm.org/docs/CompilerWriterInfo.html - [[[wikipedia-The_Gleaners,69]]] https://en.wikipedia.org/wiki/The_Gleaners - [[[github_riscv-llvm_patch_20,70]]] https://github.com/lowRISC/riscv-llvm/blob/master/0020-RISCV-Support-and-tests-for-a-variety-of-additional-.patch - [[[llvm_phabricator-d47422,71]]] https://reviews.llvm.org/D47422 - [[[llvm-extendingllvm,72]]] https://llvm.org/docs/ExtendingLLVM.html - [[[llvm_dev_ml-001264,73]]] http://lists.llvm.org/pipermail/llvm-dev/2004-June/001264.html - [[[llvm_phabricator-d42958,74]]] https://reviews.llvm.org/D42958 - [[[compiler_rt,75]]] https://compiler-rt.llvm.org/ - [[[github-riscv_compiler_rt,76]]] https://github.com/andestech/riscv-compiler-rt - [[[github_riscv-llvm_patch_27,77]]] https://github.com/lowRISC/riscv-llvm/blob/master/0027-RISCV-Support-stack-frames-and-offsets-up-to-32-bits.patch - [[[llvm_phabricator-d44885,78]]] https://reviews.llvm.org/D44885 - [[[llvm_phabricator-d45859,79]]] https://reviews.llvm.org/D45859 - [[[llvm-langref-poison_value,80]]] http://llvm.org/docs/LangRef.html#poisonvalues - [[[github-emscripten-issues-34,81]]] https://github.com/emscripten-core/emscripten/issues/34 - [[[switch_lowering_in_llvm,82]]] http://fileadmin.cs.lth.se/cs/education/edan75/part2.pdf - [[[github-avr_llvm-issues-88,83]]] https://github.com/avr-llvm/llvm/issues/88 - [[[asciidoctor-quickref,84]]] https://asciidoctor.org/docs/asciidoc-syntax-quick-reference/ - [[[llvm_phabricator-d56351,85]]] https://reviews.llvm.org/D56351 - [[[hatenablog-rhysd-230119,86]]] https://rhysd.hatenablog.com/entry/2017/03/13/230119 - [[[llvm_dev_ml-115805,87]]] http://lists.llvm.org/pipermail/llvm-dev/2017-July/115805.html - [[[github_riscv-llvm_patch_29,88]]] https://github.com/lowRISC/riscv-llvm/blob/master/0029-RISCV-Add-support-for-llvm.-frameaddress-returnaddre.patch - [[[github-riscv_llvm-clang,89]]] https://github.com/lowRISC/riscv-llvm/tree/master/clang - [[[github-elvm_clang,90]]] https://github.com/shinh/clang/tree/elvm - [[[github_riscv-llvm_patch_22,91]]] https://github.com/lowRISC/riscv-llvm/blob/master/0022-RISCV-Support-lowering-FrameIndex.patch - [[[llvm_dev_ml-087879,92]]] http://lists.llvm.org/pipermail/llvm-dev/2015-July/087879.html - [[[stackoverflow-27467293,93]]] https://stackoverflow.com/questions/27467293/how-to-force-clang-use-llvm-assembler-instead-of-system - [[[github-riscv_llvm-clang-03,94]]] https://github.com/lowRISC/riscv-llvm/blob/master/clang/0003-RISCV-Implement-clang-driver-for-the-baremetal-RISCV.patch - [[[github_riscv-llvm_patch_25,95]]] https://github.com/lowRISC/riscv-llvm/blob/master/0025-RISCV-Add-custom-CC_RISCV-calling-convention-and-imp.patch - [[[llvm_dev_ml-106187,96]]] http://lists.llvm.org/pipermail/llvm-dev/2016-October/106187.html - [[[llvm_phabricator-d39322,97]]] https://reviews.llvm.org/D39322 - [[[cpu0-lld,98]]] http://jonathan2251.github.io/lbt/lld.html - [[[youtube-how_to_add_a_new_target_to_lld,99]]] https://www.youtube.com/watch?v=FIXaeRU31Ww - [[[llvm-smith_newlldtargetpdf,100]]] https://llvm.org/devmtg/2016-09/slides/Smith-NewLLDTarget.pdf - [[[llvm-lld,101]]] https://lld.llvm.org/index.html - [[[note-n9948f0cc3ed3,102]]] https://note.mu/ruiu/n/n9948f0cc3ed3 - [[[lanai-isa,103]]] https://docs.google.com/document/d/1jwAc-Rbw1Mn7Dbn2oEB3-0FQNOwqNPslZa-NDy8wGRo/pub - [[[github-blog_os-issues-370,104]]] https://github.com/phil-opp/blog_os/issues/370 - [[[llvm_phabricator-d61688,105]]] https://reviews.llvm.org/D61688 - [[[man-xtensa_linux_gnu_ld,106]]] https://linux.die.net/man/1/xtensa-linux-gnu-ld - [[[man-elf,107]]] https://linuxjm.osdn.jp/html/LDP_man-pages/man5/elf.5.html - [[[llvm_phabricator-d45385,108]]] https://reviews.llvm.org/D45385 - [[[llvm_phabricator-d47882,109]]] https://reviews.llvm.org/D47882 - [[[llvm_dev_ml-128257,110]]] https://lists.llvm.org/pipermail/llvm-dev/2018-December/128257.html - [[[github_riscv-llvm_patch_31,111]]] https://github.com/lowRISC/riscv-llvm/blob/master/0031-RISCV-Implement-support-for-the-BranchRelaxation-pas.patch - [[[github_riscv-llvm_patch_30,112]]] https://github.com/lowRISC/riscv-llvm/blob/master/0030-RISCV-Implement-branch-analysis.patch - [[[stackoverflow-5789806,113]]] https://stackoverflow.com/questions/5789806/meaning-of-and-in-c - [[[compiler_study_report,114]]] https://proc-cpuinfo.fixstars.com/2018/11/compiler_study_report/ - [[[github-llvm-bcb36be8e3f5dced36710ba1a2e2206071ccc7ba,115]]] https://github.com/llvm/llvm-project/commit/bcb36be8e3f5dced36710ba1a2e2206071ccc7ba - [[[llvm_dev_ml-059799,116]]] http://lists.llvm.org/pipermail/llvm-dev/2013-February/059799.html - [[[tricore-llvm-slides,117]]] https://reup.dmcs.pl/wiki/images/7/7a/Tricore-llvm-slides.pdf - [[[tricore-llvm,118]]] https://opus4.kobv.de/opus4-fau/files/1108/tricore_llvm.pdf - [[[llvm_dev_ml-111697,119]]] http://lists.llvm.org/pipermail/llvm-dev/2017-April/111697.html - [[[takayuki-no09,120]]] http://www.ertl.jp/~takayuki/readings/c/no09.html - [[[hwenginner-linker,121]]] https://hwengineer.github.io/linker/ - [[[koikikukan-000300,122]]] http://www.koikikukan.com/archives/2017/04/05-000300.php - [[[stackoverflow-57735654_34997577,123]]] https://stackoverflow.com/questions/34997577/linker-script-allocation-of-bss-section#comment57735654_34997577 - [[[redhat-ld_simple_example,124]]] https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/4/html/Using_ld_the_GNU_Linker/simple-example.html - [[[llvm_phabricator-d45395,125]]] https://reviews.llvm.org/D45395 - [[[llvm_phabricator-d45395-398662,126]]] https://reviews.llvm.org/D45395#inline-398662 - [[[llvm-langref-inline_asm,127]]] http://llvm.org/docs/LangRef.html#inline-assembler-expressions - [[[hazymoon-gcc_inline_asm,128]]] http://caspar.hazymoon.jp/OpenBSD/annex/gcc_inline_asm.html - [[[github_riscv-llvm_patch_28,129]]] https://github.com/lowRISC/riscv-llvm/blob/master/0028-RISCV-Add-basic-support-for-inline-asm-constraints.patch - [[[llvm-langref-inline_asm-asm_template_argument_modifier,130]]] http://llvm.org/docs/LangRef.html#asm-template-argument-modifiers - [[[github-llvm-0715d35ed5ac2312951976bee2a0d2587f98f39f,131]]] https://github.com/llvm/llvm-project/commit/0715d35ed5ac2312951976bee2a0d2587f98f39f - [[[github_riscv-llvm_patch_32,132]]] https://github.com/lowRISC/riscv-llvm/blob/master/0032-RISCV-Reserve-an-emergency-spill-slot-for-the-regist.patch - [[[github_riscv-llvm_patch_26,133]]] https://github.com/lowRISC/riscv-llvm/blob/master/0026-RISCV-Support-for-varargs.patch - [[[github-fracture-wiki-how-dagisel-works,134]]] https://github.com/draperlaboratory/fracture/wiki/How-TableGen%27s-DAGISel-Backend-Works - [[[welcome_to_the_back_end-slides,135]]] http://llvm.org/devmtg/2017-10/slides/Braun-Welcome%20to%20the%20Back%20End.pdf - [[[life_of_an_instruction,136]]] https://eli.thegreenplace.net/2012/11/24/life-of-an-instruction-in-llvm/ - [[[shinh-blog-010637,137]]] http://shinh.hatenablog.com/entry/2014/10/03/010637 - [[[llvm_backend_intro,138]]] https://www.slideshare.net/AkiraMaruoka/llvm-backend - [[[amazon-llvm_cookbook-customer_review,139]]] https://www.amazon.co.jp/dp/178528598X#customer_review-R28L2NAL8T9M2H - [[[llvm_dev_ml-117139,140]]] https://lists.llvm.org/pipermail/llvm-dev/2017-September/117139.html - [[[github_riscv-llvm_patch_85,141]]] https://github.com/lowRISC/riscv-llvm/blob/master/0085-RISCV-Set-AllowRegisterRenaming-1.patch - [[[llvm_dev_ml-135337,142]]] https://lists.llvm.org/pipermail/llvm-dev/2019-September/135337.html - [[[wikipedia-weak_symbol,143]]] https://en.wikipedia.org/wiki/Weak_symbol - [[[wikipedia-remat,144]]] https://en.wikipedia.org/wiki/Rematerialization - [[[llvm_phabricator-d46182,145]]] https://reviews.llvm.org/D46182 - [[[nakata-compiler,146]]] 『コンパイラの構成と最適化(第2版)』(中田育男、朝倉書店、2009) - [[[fpga_develop_diary-to_llvm9,147]]] http://msyksphinz.hatenablog.com/entry/2019/08/17/040000 - [[[llvm_phabricator-d60488,148]]] https://reviews.llvm.org/D60488 - [[[llvm_phabricator-rl364191,149]]] https://reviews.llvm.org/rL364191 - [[[llvm_phabricator-d64121,150]]] https://reviews.llvm.org/D64121 - [[[llvm-codingstandards,151]]] https://llvm.org/docs/CodingStandards.html - [[[llvm_dev_ml-134921,152]]] https://lists.llvm.org/pipermail/llvm-dev/2019-September/134921.html - [[[llvm_phabricator-d43256,153]]] https://reviews.llvm.org/D43256 - [[[llvm_dev_ml-114675,154]]] http://lists.llvm.org/pipermail/llvm-dev/2017-June/114675.html - [[[llvm_phabricator-d42780,155]]] https://reviews.llvm.org/D42780 - [[[llvm_phabricator-d51732,156]]] https://reviews.llvm.org/D51732 - [[[llvm_devmtg-schedmachinemodel,157]]] http://llvm.org/devmtg/2014-10/Slides/Estes-MISchedulerTutorial.pdf - [[[llvm_dev_ml-098535,158]]] https://lists.llvm.org/pipermail/llvm-dev/2016-April/098535.html - [[[llvm_devmtg-writinggreatsched,159]]] https://www.youtube.com/watch?v=brpomKUynEA - [[[anandtech-11441,160]]] https://www.anandtech.com/show/11441/dynamiq-and-arms-new-cpus-cortex-a75-a55/4 - [[[llvm_devmtg-larintrick,161]]] https://llvm.org/devmtg/2012-11/Larin-Trick-Scheduling.pdf - [[[llvm-schedinorder,162]]] https://llvm.org/devmtg/2016-09/slides/Absar-SchedulingInOrder.pdf