Slide 1

Slide 1 text

(c) 2025 Kouji Matsui chibiccを CILに移植した結果 2025.01.18 NGK2025S LT - KOUJI MATSUI

Slide 2

Slide 2 text

(c) 2025 Kouji Matsui Kouji Matsui – kozy, kekyo NAGOYA city, AICHI pref., JP https://github.com/kekyo https://mi.kekyo.net/@kekyo Center CLR organizer. .NET OSS: IL2C RelaxVersioner Epoxy GitReader FlashCap etc… Bicycle rider

Slide 3

Slide 3 text

(c) 2025 Kouji Matsui Attention! 1ページあたり10秒

Slide 4

Slide 4 text

(c) 2025 Kouji Matsui Attention! スライドはアップします。 この発表の詳細は、後日「第9回 Center CLR 勉強会」でやります。 質疑応答がある場合は、是非ご参加ください。 connpass: https://centerclr.connpass.com/ Discord: https://discord.gg/JMA4uzNUKj

Slide 5

Slide 5 text

(c) 2025 Kouji Matsui (c) 2025 Kouji Matsui Agenda chibiccとは chibicc-cilとは 移植の過程 移植した結果 ラスボス

Slide 6

Slide 6 text

(c) 2025 Kouji Matsui chibiccとは Rui Ueyama氏のプロジェクト “A small C compiler” https://github.com/rui314/chibicc chibicc は、C11 のほとんどの機能を実装した、もう 1 つの小さな C コ ンパイラです。 他の小さなコンパイラと同様に、おそらく「おもちゃのコンパイラ」のカ テゴリに分類されるかもしれませんが、chibicc は、コンパイルされたプ ログラムに変更を加えることなく、Git、 SQLite、 libpng、chibicc 自体 を含むいくつかの実際のプログラムをコンパイルできます。

Slide 7

Slide 7 text

(c) 2025 Kouji Matsui (c) 2025 Kouji Matsui Agenda chibiccとは chibicc-cilとは 移植の過程 移植した結果 ラスボス

Slide 8

Slide 8 text

(c) 2025 Kouji Matsui .NET、 ネイティブライブラリとの 連携つらいよね ある日、 思いました

Slide 9

Slide 9 text

(c) 2025 Kouji Matsui .NETのバイナリが吐ける 「素直な」C言語処理系があれば 様々な問題が解決するのでは? C++/CLIはいらないです (言語仕様は変態チックで好きですが)

Slide 10

Slide 10 text

(c) 2025 Kouji Matsui .NET/.NET Core/.NET Frameworkで使われる、CIL (Common Intemediate Language)の事です。 CILは.NETにおけるJava Bytecodeのような中間言語仕様で、 ECMA-335で定義されています。 https://ecma-international.org/publications-and- standards/standards/ecma-335/ CILとは

Slide 11

Slide 11 text

(c) 2025 Kouji Matsui chibicc-cilとは chibiccをCILに移植するプロジェクトです。 .NETのコードを吐ける C言語処理系を作ろう!

Slide 12

Slide 12 text

(c) 2025 Kouji Matsui (c) 2025 Kouji Matsui Agenda chibiccとは chibicc-cilとは 移植の過程 移植した結果 ラスボス

Slide 13

Slide 13 text

(c) 2025 Kouji Matsui 移植の過程 しかし、話はそう簡単ではありません。大きくは: ◦ chibiccはx86-64のコードを出力するので、これをCILを出力するように コードジェネレータを変更する。 ◦ CILアセンブラが必要(ilasmが使える?) ◦ CILで書かれたCランタイムライブラリ(例えばprintf()の実装)が必要。

Slide 14

Slide 14 text

(c) 2025 Kouji Matsui 移植の過程 CILレベルではメタデータがあるので、単純すぎるC言語関数との整合性を 持たせることを考える必要がある: ◦ ポインタの扱いはCILにポインタ型があるので、1:1で対応できる。 ◦ しかし、ポインタは実行時環境で32/64bitが決定されるので、コンパイル時にサイズが確定できない(intptr_tが実行時 にサイズ決定される感じ) ◦ この機能(問題?)のため、構造体オフセット計算やsizeofの扱いなど、元のchibiccでは素直な実装だったところも複雑化。 ◦ CILには構造体(ValueType)が存在するので、C言語構造体はだいたい1:1に対応出来る。 ◦ 共用体に対応するものは無いので、ValueTypeで代用する。どちらにしてもchibiccは自力でオフセット計算を行うので、 CIL側でそれっぽくメタデータ生成(フィールド群定義)を行うけど、ガン無視でポインタ演算でアクセスする。 ◦ CILにはP/Invokeという、ネイティブライブラリ(*.so)を呼び出せる機能があるので、これを使えばシームレスにネイ ティブライブラリと結合できるかも? (少なくともC#よりは簡単に) ◦ CILアセンブラは.NET標準のilasmがあるけど、これが色々扱いにくい。CILアセンブラ作るのはそれほど難易度が高い わけではないので、chibiccのバックエンドとして扱いやすいchibiasを作るか… ◦ P/Invokeでネイティブライブラリをリンクできるようなナチュラルさを実現するには、リンカ側でコード生成能力とか 多少必要になるかもしれない… ◦ POSIX環境処理系として違和感を与えたくないので、普通に想定されるldやarも必要だよね… うんたらかんたら…

Slide 15

Slide 15 text

(c) 2025 Kouji Matsui 移植の過程 https://github.com/kekyo/chibicc-cil-toolchain chibiccの移植以外にも やるべきことは多い libc.a アセンブラ リンカ ランタイム ライブラリ chibicc本体

Slide 16

Slide 16 text

(c) 2025 Kouji Matsui 移植の過程 他にも山のように検討事項がありましたが、 chibiccがステップバイステップで実装するのだから、 途中で少しずつ問題と解決に取り組むことが出来る! きっと!

Slide 17

Slide 17 text

(c) 2025 Kouji Matsui (c) 2025 Kouji Matsui Agenda chibiccとは chibicc-cil 移植の過程 移植した結果 ラスボス

Slide 18

Slide 18 text

(c) 2025 Kouji Matsui 移植した結果 最初の山場(セルフホスト試行・総コミット316個の約半分ぐ らい) Stage1(gccでビルドしたchibicc-cil) Stage2(Stage1 chibicc-cilを使ってビルドしたchibicc-cil) Stage3(Stage2 chibicc-cilを使ってビルドしたchibicc-cil) でテスト結果が一致する事を確認!! chibiccはC言語で書かれているので 自分自身をコンパイルできる

Slide 19

Slide 19 text

(c) 2025 Kouji Matsui 移植した結果 当然、Hello worldなど問題なくコンパイル可能:

Slide 20

Slide 20 text

(c) 2025 Kouji Matsui 移植した結果 そして… chibicc: 305/316 chibicc-cil: 367 増えているのはCILへの 対応分です。 移植 残り11コミット

Slide 21

Slide 21 text

(c) 2025 Kouji Matsui 移植した結果 残11コミット gitとかsqliteをビルドする。 まともなCランタイムラ イブラリが必要

Slide 22

Slide 22 text

(c) 2025 Kouji Matsui 移植した結果 ◦ ポインタサイズ: 32/64bitの計算を実行時に行うために、計算式をそのままemitすると非常に効率の悪いコードにな る(100倍近く遅いことも) ◦ 関数ポインタを構造体のメタデータに出力すると、ランタイムに無視される ◦ ランタイムはスタックマシンなので、関数の戻り値がvoidの場合にこれを考慮に入れる必要があるが、元のchibicc はそうではない。 ◦ newlibが複素数型への対応を要求する。 ◦ C言語の配列は、ValueType arrayに相当するが、対応するCILの型が無い。 ◦ VLA (Variable length array)への対応。スタックマシンだとこれを安全に対応するのは非常に難しい。 ◦ 全く同じ構造体型が、CILメタデータ上では区別されてしまう。C言語では構造体のアイデンティティはヘッダファ イルの定義が全て。 ◦ アライメントの指定と計算。ランタイムがどのように配置するのかは不透明なので。 ◦ MMX, SSE, AVXなどのintrinsic ◦ まともなデバッグ情報を出したい ◦ ランタイムライブラリの用意 ◦ 関数の可変引数への対応(vararg) ◦ POSIXシグナル・スレッドの扱い

Slide 23

Slide 23 text

(c) 2025 Kouji Matsui 移植した結果 他にも細かい問題は山のように存在しましたが… newlibの移植を開始して、libc.a/libm.aが生成できるところま でたどり着いた… ざっくりしたまとめ: https://gist.github.com/kekyo/d3bec6e1427bc8c0d459f7fcb7a1fcac

Slide 24

Slide 24 text

(c) 2025 Kouji Matsui (c) 2025 Kouji Matsui Agenda chibiccとは chibicc-cil 移植の過程 移植した結果 ラスボス

Slide 25

Slide 25 text

(c) 2025 Kouji Matsui ラスボス ほぼほぼ動作するようになって、Stage2コンパイラで実験した 結果: .NETのランタイムはかなり遅い。 実行時最適化はたいしたことがない (まあしってた)

Slide 26

Slide 26 text

(c) 2025 Kouji Matsui ラスボス もし、 「ネイティブライブラリを呼び出せるようにする。 それもchibildで*.soライブラリ指定するだけで」 が実現できれば、もういっそnewlibも捨ててlibc.soを直接呼び 出した方が少しはマシかも? memcpy()とかstrlen()とか、絶対にネイティブコードの方が 速い。

Slide 27

Slide 27 text

(c) 2025 Kouji Matsui ラスボス libc呼び出し可能にするには、関数の可変引数への対応が必要 ◦ CILのvarargメタデータと専用命令を使うようにする。これのemitは chibildで行う必要がある。 ◦ 最初、varargを使うもうまく動かない事があった。これはnetstandard TFMでのみ発生し、.NETランタイムのissueにも上がっていない問題で、 どうしようもないことから、vararg命令を使わず独自の実装で回避。こ れは動作した。 ◦ しかし、P/Invokeでネイティブライブラリの可変引数関数を呼び出した りコールバックで呼び出し可能にするには、やはり.NETランタイムが varargを処理できる必要がある…

Slide 28

Slide 28 text

(c) 2025 Kouji Matsui ラスボス “Initial thoughts on Native Vararg support on Unix platforms for RyuJit” https://github.com/dotnet/runtime/issues/10478 意訳: 「varargはWindowsにしか対応してないよーん」 うそだ!うそだと言ってくれ…!!!

Slide 29

Slide 29 text

(c) 2025 Kouji Matsui ラスボス Issueにping打ちましたがスルーされたところを見ると、まあ 対応は絶望的です。 個人的にはあと少しだったので、これですべてがぽっきり折れ ました。 だから、この話はここで終いです

Slide 30

Slide 30 text

(c) 2025 Kouji Matsui ご清聴ありがとうございました! 成果物を公開します: ◦ chibicc-cil-build: https://github.com/kekyo/chibicc-cil-build この発表の詳細は、後日「第9回 Center CLR勉強会」でやります。質疑 応答がある場合は、是非ご参加ください。 類似プロジェクト: Cesium(ForNeVerさん/JBの中の人) 同じ問題がIssueで上がっています(もちろん未解決) https://github.com/ForNeVeR/Cesium