inkwell

LLVM C API を安全にラップした Rust の LLVM バインディングクレート。トイ言語コンパイラ toy-llvm-compiler (ipulang) で LLVM IR 生成に使用 (LLVM 12 系)。生成した .llclang で実行ファイルへリンクする。

IR の階層と生成

  • LLVM IR は Module > Function > Block > Instruction の階層構造。Builder のメソッド呼び出しで手続き的に命令を組む。
  • 変数: build_alloca でスタック確保 → build_store / build_load。二項加算は build_int_add
  • 関数: i32_type.fn_type(args, is_vararg) で型宣言し、entry ブロックを作って引数を ptr に load。
  • 制御フロー: append_basic_block でブロックを作り、build_unconditional_branch / build_conditional_branch (build_int_comparecond != 0) で結線。各ブロック生成前に position_at_end を呼ぶ必要がある。
  • 組み込み関数 (putchar/getchar) は IR 内で 宣言だけ しておけばリンク時に解決され呼べる。
  • 最後に module.print_to_string() で IR 文字列を得る。

コード生成の状態管理

コンパイラ側は Env 構造体に module / ctx / 関数ごとの変数マップ / 一時変数カウンタ / 関数テーブル / 現在の builder・関数 を保持し、各 AST ノードに gen_code(&mut env) を実装して Program から再帰的に呼ぶ (後に trait CodeGen へ整理)。

関連