**「私たちが望むルストの呼び出し規約(2024)」**

2026/03/02 2:25

**「私たちが望むルストの呼び出し規約(2024)」**

RSS: https://news.ycombinator.com/rss

要約

Japanese Translation:

著者はRustのデフォルト呼び出し規約―実質的にLLVMの汎用C ABI―を批判しており、

[i32;3]
のような複雑な型がポインタで渡されることを強いるため、レジスタ使用が制限され保守的なコードになると指摘しています。
彼らは
-Zcallconv=fast
と呼ばれるRust専用の新規呼び出し規約を提案します。この方式では引数を再配置し、最大値が最初にレジスタに収まるよう(ナップサック型ヒューリスティック)、可能な限りプリミティブをレジスタに詰め込み、オーバーフローしたものは「参照」ポインタへ降格させます。
LLVM の poison 値を利用して未使用のレジスタの初期化を回避し、戻り値はフラット化(パディングと小型型のビットパッキングを除去)され、値で返すか参照で返すかが決定されます。
実装にはカスタム LLVM IR シグネチャと、詰められたレジスタを SSA 値へ復号するプロローグ/エピローグロジックが必要であり、同じ関数本体は規約にかかわらず使用できます。関数ポインタや
extern "Rust"
ブロックはまだ旧規約を使い、必要に応じてシムが規約間の変換を行います。
プロファイルガイド付きヒューリスティクスをオプションで導入すれば、未使用引数の除外やホットパスで参照を値として渡すことで更なる最適化が可能です。
この ABI を採用すると、特に複雑な引数型を持つ関数に対して Rust のバイナリが高速化され、C ライブラリとの後方互換性も維持できます。ただし LLVM の複雑さが増しビルド時間が長くなる可能性があるため、LLVM に精通していない開発者には導入が難しいというトレードオフがあります。

本文

C ABI とより優れた呼び出し規約 ― Rust の呼び出し規約を深掘りする

「C ABI は複雑な型の渡し方に向いていない」とよく不満を漏らします。
代わりに何を使うかと聞かれると、私は Go のレジスタABI(register ABI)を紹介しますが、多くの人はまだその意味が掴めていません。この記事では私の考えを詳細に説明します。


1. 呼び出し規約とは何か?

呼び出し規約(Calling Convention, CC)は ABI の一部で、次のことを定義します。

  • 引数はどのレジスタまたはスタック領域へ渡すか
  • 戻り値はどこに配置されるか
  • 関数プロローグ/エピローグ、アンワインディングなど

本稿では主に x86 を例に挙げますが、ARM や RISC‑V でも同様の考え方が適用できます。x86 アセンブリ、LLVM IR、および Rust(rustc の内部は想定していません)に慣れている前提で進めます。


2. 問題点

Rust のデフォルト CC は「未指定の 0‑呼び出し規約」であり、最終的には LLVM の組み込み C 呼び出し規約へ落とし込まれます。この保守的アプローチは次のような利点があります。

  1. デバッグサポートが良好 – DWARF が ELF 上で機能する
  2. LLVM のバグを誘発しにくい – Rust は Clang と同じコード生成経路を使う

しかし、結果として簡単な関数でも悪質なコード生成になってしまいます。

fn extract(arr: [i32; 3]) -> i32 {
    arr[1]
}

デフォルト CC でコンパイルすると:

extract:
    mov   eax, dword ptr [rdi + 4]   ; 2 番目の要素をロード
    ret

12 バイトの配列がポインタ経由で渡されてしまい、レジスタに収まるはずなのにそうなりません。

extern "C"
を付ければもっと良い結果になります:

extract:
    mov   rax, rdi
    shr   rax, 32
    ret

Clang は

[i32;3]
をレジスタで値渡しできることをすでに知っているのに、Rust はそうしてくれません。


3.
-Zcallconv
の導入

アイデア

  • 現在の
    extern "Rust"
    CC(後方互換性保持)を維持
  • 新しいレジスタ中心の規約に切り替えるフラグ
    -Zcallconv=fast
    を追加
  • -O
    で最適化するときは自動的に
    fast
    を有効にする

トレードオフ

  • デバッグビルド
    fast
    はコードが悪くなる可能性があるので避けるべき
  • 関数ポインタ & extern ブロック:これらはレガシーのまま。必要に応じて実装へ tail‑call するシムを用意
  • クレート単位で設定:フラグはクレート全体に適用されるため、関数ごとに使用 CC を宣言できる

4. LLVM に望む規約を書き出す方法

  1. ターゲットごとの「レジスタ渡し可能最大値」を決定(例:x86 なら整数 6 個、SSE ベクトル 8 個)
  2. 戻り値の戦略を決める
    • 出力レジスタに収まればそれを使う
    • そうでなければ追加ポインタ(
      sret
      属性)を渡し、戻り値としてそのポインタを返す
  3. 大きい引数は「by‑reference」に昇格させる(例:x86 では 176 バイト超)
  4. レジスタに入れる引数を選択(ナップサック問題;ヒューリスティックを使用)
  5. LLVM IR シグネチャを生成し、レジスタ入力を列挙、その後にスタック引数
  6. プロローグ/エピローグブロックでレジスタ値を SSA フォームへデコードし、戻り値も同様にエンコード
  7. 既存呼び出し側が関数アドレスを取得した場合はシムを用意

5. レジスタ容量の決定

小さな LLVM プログラムをターゲット上で実行して、レジスタに渡せる引数数を調べます。

%InputI = type [6 x i64]
%InputF = type [0 x double]
%InputV = type [8 x <2 x i64>]

define void @inputs({ %InputI, %InputF, %InputV }) {
  ...
}

x86 上で実行すると整数 6 個、SSE ベクトル 8 個がレジスタに渡せることがわかります。AArch64 では整数 8 個+ベクトル 8 個です。

重要なのは すべての関数が同じ数のレジスタ引数を使う という点です。未使用のレジスタは poison 値で埋められ、LLVM は「そこに何があっても良い」とみなしますので追加作業は不要です。


6. Rust の型とレジスタパッキング

戻り値

構造体を padding を除いた非ゼロ要素でフラット化し、サイズ順に並べます。例:

[(u64, u32); 2] → (u64, u64, u32, u32)   // 24 バイト

実効サイズが利用可能な出力レジスタ数(x86 なら 88 バイト)未満であればそれを使い、そうでなければポインタ経由で返す。

引数

  1. 大きすぎる引数はポインタに昇格
  2. 列挙型は discriminant + union のペアに置き換える(例:
    Option<i32>
    (i32, bool)
  3. ユニオンは、単一バリアントしかない場合を除いてバイト配列として渡す
  4. すべてをプリミティブ型(ptr、i64、double 等)にフラット化
  5. 効率的サイズ順でソートし、レジスタに収まる最大プレフィックスを選び、残りはスタックへ
  6. 論理値はビット単位でパック(1 レジスタにつき最大 64 個まで)

この方法で Rust 型からレジスタ/スタック位置への決定論的マッピングが得られます。


7. 実例:
do_thing

struct Options {
    colorize: bool,
    verbose_debug: bool,
    allow_spurious_failure: bool,
    retries: u32,
}

フラット化後、x86 上の LLVM シグネチャは次のようになります。

define %Out @do_thing(
  i64 %rdi, ptr %rsi, ptr %rdx,
  ptr %rcx, i64 %r8, i64 %r9,
  <4 x i32> %xmm0, <4 x i32> %xmm1,
  ; 未使用レジスタ
  ...
) {
  ; プリミティブをアンパック …
  ; Rust の値へ再構築 …
}

すべての引数がレジスタに収まり、スタック経由で渡す必要はありません。


8. 最適化依存 ABIs

コンパイラは関数本体を知っているので次のような最適化が可能です。

  • 未使用パラメータの除去
  • 参照渡しされた小構造体で、実際には保存されない場合に直接インライン展開
  • プロファイルガイド付きで「ホット」引数をレジスタ優先度高く割り当て

これらは

-Zcallconv=fast
と最適化が有効なときのみ意味があります。


9. 結論

Rust は固定 ABI に縛られないため、各関数に合わせた CC をカスタマイズできる点で C++ を凌駕します。Go はすでに同様の手法を採用していますが、Rust が広く取り入れていない理由は次の通りです。

  • LLVM の ABI コード生成の複雑さ
  • rustc 側の LLVM 実装への専門知識不足
  • コンパイル時間への懸念(ただし
    fast
    はリリースビルド向けに設計)

Rust の ABI 改善に関心がある方は、LLVM が望むレジスタ配置を出力する方法から始めると良いでしょう。さらに深掘りしたい場合は遠慮なくご相談ください!

同じ日のほかのニュース

一覧に戻る →

2026/03/04 23:16

マックブック・ネオ

## Japanese Translation: *いくつかの重要な詳細が省略され、いくつかの推論が導入されているため、以下に改善された要約を示します。* --- ## 改善された要約 Appleは**MacBook Neo**を発表しました。これは2026年3月4日に公開された、これまでで最も低価格なMacBookです。デバイスの価格は米国では**$599**(教育機関向けは$499)で、3月11日(水)に出荷されます。3月4日に予約注文が開始されます。Neoは**ブリッシュ、インディゴ、シルバー、シトラス**の四色で提供され、apple.com/store、Apple Storeアプリ(30か国/地域)、およびApple認定販売店を通じて購入できます。 Neoの重量は**2.7 lb**で、アルミニウムエンクロージャーから作られ、**60 %がリサイクル素材**です(アルミニウムの90 %、コバルト電池の100 %が再利用されています)。13インチのLiquid Retinaディスプレイは**2408×1506**解像度で、**500 nits**の輝度を持ち、**10億色**に対応し、反射防止コーティングがあります。 内部には新しい**Apple A18 Pro**チップ(6コアCPU、5コアGPU、16コアNeural Engine)が搭載されています。Appleは、Intel Core Ultra 5を搭載したPCと比べて日常タスクが最大**50 %高速化**し、オンデバイスAIワークロードが最大**3倍速く**なると主張しています。このラップトップは**ファンレス**で静かに動作し、1回の充電で**最大16時間**のバッテリー寿命を提供します。 接続性にはUSB‑Cポート2つ(左側がUSB 3、右側がUSB 2)があり、充電と外部ディスプレイをサポートしています。ヘッドフォンジャック、Wi‑Fi 6E、およびBluetooth 6も備えています。ハードウェア機能としては、Apple Magic Keyboard(Touch ID付き)、大きなマルチタッチトラックパッド、1080p FaceTime HDカメラ、デュアルビームフォーミングマイクロフォン、デュアルサイドファイリングスピーカーがあり、Spatial Audio/Dolby Atmosをサポートします。 MacBookは**macOS Tahoe**で動作し、Safari、Photos、Messagesなどの標準アプリと、Writing ToolsやLive TranslationなどのApple Intelligence機能を含むパッケージです。これらは業界最高レベルのプライバシー保護に支えられています。 追加サービスには**Apple Trade In**クレジット、**AppleCare+**または**AppleCare One**保護プラン、**Personal Setupセッション**、およびApple Cardを利用する米国顧客向けの0 % APRと3 % Daily Cashバックがある**Apple Card Monthly Installments**があります。

2026/03/05 5:30

「それが何を指しているか」によりますが、一般的に多くの共通した活動は相当量のエネルギーを消費します。 | 活動 | 一般的なエネルギー使用量 | |------|---------------------------| | **電気自動車** | 100 kmあたり10–20 kWh(約35–70 MJ)。30日間で約3,000 km走行すると、約300 kWhが消費されます。 | | **航空輸送** | 人員1人あたり距離1 kmで約2–5 kg CO₂を排出し、典型的な長距離フライトでは約200–500 kWh相当のエネルギーが使われます。 | | **家庭用電気暖房** | 1 m²あたりの床面積で、冬季は1日あたり約10 kWh必要です。大きな住宅になるとさらに多く消費します。 | | **データセンター** | 世界全体のIT産業が年間で約200–300 TWh(総電力使用量のおよそ2%)を消費しています。 | 特定の機器やサービスについて言及されている場合は、正確な数値は異なります。しかし、燃焼エンジン・電動モーター・大規模コンピューティングなど、大量のエネルギーを移動させる活動であれば、必ずしも相当量の電力が使用され、全体の消費に寄与します。

## Japanese Translation: > 文章は、日常のデバイスや活動が電力をどのように消費するかを説明し、一般的な家電製品・電子機器・交通手段の典型的なワット時(Wh)値を提示しています。電力使用量は「パワー(W) × 時間(h)」で計算されることが示されており、各アイテムの平均消費電力とそれに伴う Wh/時間または Wh/サイクルの具体例が挙げられています。 > > 比較対象は以下の通りです: > * 電球 – 白熱灯 25–100 W(標準値60 W)対 LED 約10 W;1時間で白熱灯は60 Wh、LEDは10 Whを消費します。 > * 携帯電話充電にはフルチャージあたり約20 Whが必要です(15–20 %の損失)。 > * テレビ消費 – 中効率 40–50″ LED 約60 W、最新大型 55–60″ 4K 約90 W。 > * MacBook ノートパソコン平均電力約20 W、デスクトップ平均約50 W(ゲーミングPCは数百 Wに達することも)。 > * ゲーム機 – Xbox Series S 約70 W、Xbox Series X 遊び中で約150 W。 > * ストリーミングサービスは1時間あたり約0.2 Whを追加;Wi‑Fi ルーターの継続使用は約15 W。 > * ChatGPT GPT‑4o の中央値クエリ消費量は約0.3 Wh、Kindle e‑reader は1時間に1 Wh未満。 > * キッチン家電 – ケトル 1500–2000 W(3 分沸騰で約100 Wh)、電子レンジ 1000 W ×5 分 ≈83 Wh、オーブン 2500 W の稼働率55 %。 > * 洗濯&食器洗い – 洗濯機は1回のロードあたり約800 Wh、乾燥機 2000–4500 Wh/サイクル、食器洗い機 約1250 Wh/サイクル、アイロン 10 分で417 Wh。 > * 暖房 – 電気シャワー 9500 W ×10 分 ≈1583 Wh;COP 3 のヒートポンプ式シャワーは約3000 Wh/hを使用;ガス式シャワー相当は10 分で約1759 Wh。 > * ドライブ – e‑bike 15 Wh/mi、e‑スクーター 25 Wh/mi、電動バイク 150 Wh/mi、ガソリンバイク ≈530 Wh/mi;電気自動車 約300 Wh/mi 対 ガソリン車約1000 Wh/mi。 > > このデータは、技術や活動によってエネルギー消費がどのように変化するかを示しています。LED 照明や高 COP ヒートポンプなどより効率的な機器はタスクあたりの Wh を削減し、一方でゲーム機や AI サービスの利用増加は総需要を押し上げる可能性があります。これらの洞察は、消費者が習慣を調整したり低電力機器へアップグレードする手助けとなり、メーカーに効率向上を促す指針となり、ユーティリティーは負荷シフトを予測しやすくなり、政策立案者は高消費セクターの削減策を検討する際の情報源となります。

2026/03/04 20:43

「単純さだけを理由に昇進する者は存在しません。」

## Japanese Translation: --- ## Summary エンジニアリングチームは、複雑なシステムが昇進パッケージや面接パネルで印象的に見えるため、過剰設計を報奨する傾向があります。短く迅速に配備できる単純なソリューションは、キャリアの進展議論では目立たず、報酬が少なくなることが多いです。面接官や設計レビューは、追加サービス、キュー、シャーディング、抽象化を求めることで、複雑さをスケーラビリティの代理指標として扱います。この「将来性確保」マインドセットは、不要な層を生み出し、コードを理解しにくく保守しづらくしてしまい、見た目の洗練感が実際には無意味になる原因となります。 根本的な問題は、影響力を機能規模と等価化する昇進基準です。これに対抗するために、エンジニアは意思決定プロセスを文書化すべきです(「X のアプローチを評価し、現在の要件に合わせて Y を選択した」など)ので、ミニマリズムがレビューで認識されやすくなります。リーダーはインセンティブ構造を調整する必要があります:例えば「私たちが配備できる最も単純なバージョンは何か?」と質問し、昇進議論の際に不要な複雑さを挑戦します。公的認知は、大規模プロジェクトと同等にコード削除やミニマリズムを報奨することで、最適化インセンティブを転換すべきです。 チームが単純さの価値付与努力にもかかわらず複雑なシステム構築者を昇進させ続ける場合、それは文化的不一致を示し、エンジニアが派手なアーキテクチャよりも健全な判断を重視する組織へ流れる可能性があります。インセンティブをシンプルで保守しやすい解決策に向けることで、昇進と実際の影響力を一致させ、技術的負債を減らし、ユーザーと企業双方に対して製品の信頼性を向上させます。