Upgrade to Pro — share decks privately, control downloads, hide ads and more …

BareRuby ~組み込み向けRubyAOTコンパイラ~

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for すぎうり すぎうり
August 13, 2026
7

BareRuby ~組み込み向けRubyAOTコンパイラ~

Avatar for すぎうり

すぎうり

August 13, 2026

Transcript

  1. 自己紹介 すぎうり • • • • • • • •

    • • • • Twitter:@uproad3 Ruby歴20年 VRChat歴7年 仕事:Rails | AWS | LT芸人 趣味:アーキテクト | リファクタリング | 電子工作 言語:Ruby | C# | C | JS | ほかいろいろ 技術:Terraform | Unity | Ubuntu | MySQL | RaspberryPi 悲しきフルスタックエンジニア 案外アホなFableに絶望している 最近はスキルを磨く日々 実は電子回路とか低レイヤーって結構好きなんだよね VRChat.rb登壇8回目
  2. BareRuby とは — 背景と狙い 課題 着想元 : Ruby AOT “Spinel”

    帰結: 独自実装 • PicoRuby / R2P2 はマイコン上で mruby/c VM を動かすため低速 • 動的機能を切り捨て、全プログラム 型推論で最適化しネイティブコード化 • Spinel の設計思想のみを継承 • VM のオーバーヘッドが性能の上 限を決めてしまう • そのまま載せる案は却下: ランタイム が POSIX 依存 (ucontext.h / sys/mman.h 等) でベアメタル不可 → → • PicoRuby よりさらに機能を絞った マイコン向け Ruby サブセット言語 を新規定義 • 独自 AOT コンパイラを作る BareRuby = マイコン向け Ruby サブセット言語 + AOT コンパイラ • Ruby ソース → C コード → 標準 C コンパイラ (arm-none-eabi-gcc 等) でネイティブバイナリ (.uf2) • 対象環境: RP2040 / RP2350 (Raspberry Pi Pico 系) を基準 • 想定利用者: 既に PicoRuby / R2P2 を使っている組み込み開発者 (移行コスト最小化を重視)
  3. 根本思想 — 全設計判断に先立つ 3 つの軸 1. 高速・省メモリ最優先 2. 怠惰の自由 3.

    想定利用者を絞る • 実行速度とメモリ使用量を最重要 視 • 型注釈を強制しない。注釈なしで 全コードが書ける • 主対象は PicoRuby / R2P2 の既 存ユーザ • 「10倍ルール」: 他案より 10 倍を 超える性能劣化をもたらす案は原 則採用しない • ただし書いた注釈は最優先で尊重 する • ペリフェラル API を独自設計せず PicoRuby と共通化 → 移行コスト 最小化 • 「なんとなく遅い案」を無自覚に積 み上げないための明示的な歯止 め • 「書かない自由の保障」と「書いた 人の意図の尊重」を両立 • 後のペリフェラル API 標準準拠の 判断に直結 第 4 の原則 : コンパイル時にできることはコンパイル時に行う — 定数畳み込み・範囲チェック・型解決は可能な限りコン パイル時に解決する
  4. メモリモデル — GC を捨て、三層で管理する GC を持たない (却下: mark-and-sweep GC) 三層メモリモデル

    • GC pause (数ms〜数十ms) はモーター 制御・オーディオ等のハードリアルタイム 用途で許容できない 層 名称 配置 用途 • Pico の RAM は約 264KB。GC ヒープの 確保自体が負担 層1 Static .bss / .data (RAM) または Flash (ROM) グローバル定数、静的 データ、ペリフェラルバイ ンディング 層2 Capacity-bound スタック / 固定容量バッ ファ 容量上限が決まったデー タ (固定長配列・固定長文 字列) 層3 Arena 明示的 arena { } ブロック 内 動的サイズが必要な処理 (パース等) • 「すべてのメモリ操作のコストを静的に予 測可能にする」ことを優先 核心の緊張 : ハードリアルタイムと動的データ 構造の両立 → 「動的アロケーションをリアルタ イム部分から隔離する」設計で解決 • 着想は Zig のアロケータ明示や TigerBeetle のメモリモデルに近い • 却下案: Stack-only (表現力不足) / Region-based のみ (仕様が複雑化) / Rust 風 所有権 (実装が重く Ruby らしさから遠い)
  5. Arena と Realtime context — リアルタイム性を言語で 担保 Arena (リージョンアロケータ )

    Realtime context • bump pointer で確保 O(1)、ブロック終了時に一括解放、フラ グメンテーションなし • 割り込みハンドラ等の「リアルタイム実行文脈」では層3 (Arena) の使用を禁止 • 満杯時は panic。自動拡張は却下 (O(1) 性と無フラグメン テーションが崩れる) • Realtime context 内での動的アロケーションはコンパイルエ ラー • アリーナ外への持ち出しは明示的コピー(dup) を要求 (初期 は簡易チェック) • 使えるのは層1・層2 のみ • 例外安全: 例外で脱出しても必ず解放 (Rust の Drop 相当) arena(size: 8192) do |a| data = parse_something(input, allocator: a) end # ここで a 全体が一括解放される • リアルタイム保証を言語レベルで担保する— 実行時ではなく コンパイル時に検査 ライフタイムはブロックスコープが基本。長寿命用に Arena.new(size:) とネストも許可
  6. 型システム — 注釈任意の whole-program 型推論 採用: whole-program 推論 (Spinel 式)

    却下案 • 全変数・式の型はコンパイル時に確定(静的型付け) • 完全静的型 (注釈必須): 「怠惰の自由」に反する • 動的ディスパッチを排除しているため型が常に一意に確定→ 注釈なし推論が現実的に成立 • 局所推論 + 注釈 (Crystal 風): 実装コストでは優位だが、注 釈を強制する方式は採らないと決定 • 実装は最も重いが「注釈なしで書ける」一線を最優先 注釈の強制は永久に不採用 型情報源の優先順位 • 推論が通らないコードに「注釈を書け」というエラーでは解決し ない 1. インライン型注釈 • 推論エンジンの改善、または書き方の変更で対処 2. RBS 風別ファイル (ライブラリの型供給用) • 逃げ道を断つことで、推論器の賢さ= 書けるコードの範囲にな る設計 3. whole-program 型推論 (普段のデフォルト) Crystal / TypeScript 風の「: 型」。組み込み開発者に馴染む構文
  7. アーキテクチャ (1) — 実装の土台とデータフロー 実装の土台 • コンパイラ実装言語: Ruby • パーサ:

    Prism (ruby/prism、公式 gem) • コンパイル方式: AOT。Ruby ソースを C コードに変換し、外部 C コンパイラ (arm-none-eabi-gcc 等) でネイティブ バイナリを生成 • クロスコンパイルで .uf2 を生成し pico-sdk と連携 Ruby ソース (.rb) ↓ Prism.parse Prism AST ↓ AST → HIR 変換 HIR — 複数のパスがこの IR を変換 ↓ lowering (HIR → LIR) LIR — 複数のパスがこの IR を変換 ↓ C コード生成 C ソース + ランタイムヘッダ ↓ arm-none-eabi-gcc 等 (外部ツール) ネイティブバイナリ (.uf2)
  8. アーキテクチャ (2) — 中核概念は IR・パス・パイプライン の3つ IR (中間表現 ) パス

    (pass) パイプライン • コンパイラがプログラムを保持するメ モリ上のデータ構造 • IR を変換する処理の単位 • パスの列 • パスからパスへ受け渡される • 入力 IR を受け取り、変換し、出力 IR を返す • 先頭から順に実行され、前のパスの 出力が次のパスの入力になる • 常に可読形式に出力できる構造を持 つ • 後続パスは前段パスの内部状態に 依存しない 2 種類の IR 定義 IR 水準 表現する世界 HIR 高水準 クラス・メソッド・インスタンス変数・ブロックがある LIR 低水準 クラスが関数と構造体に変換済み。メモリ・ポインタ・アリーナ操作が顕在化する
  9. アーキテクチャ (3) — 12 パス構成と IR ダンプ機構 順 パス 入力

    → 出力 IR 1 AST → HIR 変換 Prism AST → HIR 2 desugar / 正規化 HIR → HIR 3 継承 / Module フラット展開 HIR → HIR 4 型推論: 制約収集 HIR → HIR 5 型推論: 単一化 HIR → HIR 6 ブロックのインライン展開 HIR → HIR 7 Symbol → 整数 ID 変換 HIR → HIR 8 定数畳み込み HIR → HIR 9 lowering HIR → LIR 10 アリーナ解析 + cleanup 挿入 LIR → LIR 11 realtime context 検査 LIR → LIR 12 C コード生成 LIR → C ソース IR ダンプ機構 (コア機能) • 任意のパス境界の IR を可読形式で出力 (パスが N 個なら出力地点は N+1 個) • 地点は複数指定・全指定が可能。既定では出力し ない • 型情報・ノード構造が読み取れる形式 パス 1〜8 は HIR、パス 9 の lowering を境に、パ ス 10〜12 は LIR を扱う