Slide 1

Slide 1 text

(c) 2025 Kouji Matsui chibiccを CILに移植した結果 (完全版) 2025.01.25 CENTER CLR #9 MEETUP - 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 Self employed Center CLR organizer. .NET OSS: IL2C RelaxVersioner Epoxy GitReader FlashCap etc… Bicycle rider

Slide 3

Slide 3 text

(c) 2025 Kouji Matsui Attention! NGK2025Sで発表したのでオチはつ いてるけど 濃密にやります 要所要所でデモやります

Slide 4

Slide 4 text

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

Slide 5

Slide 5 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 6

Slide 6 text

(c) 2025 Kouji Matsui chibiccとは chibiccの特徴は、ステップバイステップでCコ ンパイラの機能を実装していくところを、Git のコミットで表現しているところです。 だから、言語処理系の実装方法が分からなく ても、コミットを追っていけば理解が容易です。

Slide 7

Slide 7 text

(c) 2025 Kouji Matsui chibiccとは 乗算・除算・優先順位 returnが使えるようにする 比較演算子を使えるようにする ifが使えるようにする whileが使えるようにする

Slide 8

Slide 8 text

(c) 2025 Kouji Matsui chibiccとは 興味深い、最初のコミット: 与えられた整数をコンパイルしてコマンドの戻り値 (プロセス終了コード)として返す

Slide 9

Slide 9 text

(c) 2025 Kouji Matsui chibiccとは 与えられた整数をコンパイルしてコマンドの戻り値 (プロセス終了コード)として返す 42 chibicc gcc (gas) tmp.s tmp ソースコード (整数) アセンブリコード コンパイル処理 アセンブル処理 実行コード

Slide 10

Slide 10 text

(c) 2025 Kouji Matsui chibiccとは 与えられた整数をコンパイルしてコマンドの戻り値 (プロセス終了コード)として返す $ chibicc 42 $ ./tmp $ echo $? 42 引数に与えた整数(ソースコード)を 戻り値として返す実行ファイルを 生成する chibiccが `tmp` 実行 ファイルを生成する 「ソースコード」は整数限定です。 こんなのC言語とは呼べませんが、 それは第一歩だからです

Slide 11

Slide 11 text

(c) 2025 Kouji Matsui chibiccとは x86_64アセンブラコードを ベタに出力 コマンドラインに指定されたた 数値を埋め込む 「指定された整数を 終了コードとして返す 実行ファイルにコンパイルする」

Slide 12

Slide 12 text

(c) 2025 Kouji Matsui chibiccとは テストコードは単純な シェルスクリプト 式を指定してchibiccを実行して 出力を(gccを使って)アセンブルする “0”を入力して0に “42”を入力して42になればOK 出来たバイナリを実行して結果を得る

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

(c) 2025 Kouji Matsui ネイティブコードとの連携がつらいよね。 扱いやすいP/Invokeがあるけど… .NET Coreになって、Linuxや*BSDへの移植が進むにつれて、こ の部分が不満点として爆発してた (N=1) .NETって

Slide 15

Slide 15 text

(c) 2025 Kouji Matsui 有用なOSSライブラリがネイティブコードだと、実行環境に合 わせてバイナリを全部パッケージに含めなければならない (x86, x86-64, armel, aarch64, …) これを避けるために、ライブラリを.NETに移植しようとすると、 C言語で書かれたコードをC#に移植する必要がありますが、こ れが出来る技術者はそうそう居ないので… ◦ FlashCapで非常に苦労しましたもうやりたくないです .NETって

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

(c) 2025 Kouji Matsui C言語処理系を一から書くのはしんどいけど この前見たchibiccを移植すれば、 自分でも行けるかも?! C++/CLIが出来てるんだから、不可能では無い だろうきっと…

Slide 18

Slide 18 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 19

Slide 19 text

(c) 2025 Kouji Matsui chibicc-cilとは chibiccをCILに移植する プロジェクトです。

Slide 20

Slide 20 text

(c) 2025 Kouji Matsui chibicc-cilとは つまり? chibiccのコードジェネレータがCILを出力する事で、 C言語で書いたコードが .NET環境で動くようになる ことを意味します。

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

(c) 2025 Kouji Matsui 移植の検討 C言語関数との整合性を持たせることを考える必要がある: ◦ ポインタの扱いはCILにポインタ型があるので、1:1で対応できる。 ◦ CILには構造体(ValueType)が存在するので、C言語構造体はだいたい 1:1に対応出来る。共用体に対応するものは無いので、ValueTypeで代 用する。 ◦ CILにはP/Invokeという、ネイティブライブラリ(*.so)を呼び出せる機 能があるので、これを使えばシームレスにネイティブライブラリと結合 できるかも? (少なくともC#よりは簡単に)

Slide 24

Slide 24 text

(c) 2025 Kouji Matsui 移植の検討 ◦ CILアセンブラは.NET標準のilasmがあるけど、これが色々扱いにくい。 CILアセンブラ作るのはそれほど難易度が高いわけではないので、 chibiccのバックエンドとして扱いやすいchibiasを作るか… ◦ POSIX環境処理系として違和感を与えたくないので、普通に想定される chibildやchibiarも必要だよね。これらがないと、そもそもOSSのコード とかビルドできそうにない(Cの世界において、MSBuild周りのツール チェインは全く必要とされない) 。

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

(c) 2025 Kouji Matsui 移植の検討 ◦ P/Invokeでネイティブライブラリをリンクできるようなナチュラルさを 実現するには、リンカ側でコード生成能力とか多少必要になるかもしれ ない… ◦ 本格的なCランタイムライブラリを用意したい。newlibとか。

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

(c) 2025 Kouji Matsui 移植した結果 残11コミット gitとかsqliteを ビルドする

Slide 33

Slide 33 text

(c) 2025 Kouji Matsui 移植した結果 最低限必要な事前知識

Slide 34

Slide 34 text

(c) 2025 Kouji Matsui 移植した結果 chibiccの元のコードはx86-64を想定しています。 CPU内のレジスタ一覧 (一時的な値を保存する場所) これらに自由に出し入れできる https://commons.wikimedia.org/wiki/File:X86_64-registers.svg

Slide 35

Slide 35 text

(c) 2025 Kouji Matsui 移植した結果 CLIが想定するランタイム(CLR)は、「スタックマシン」と呼 ばれる構造になっています。一時的な値は「評価スタック」に 保存します(スタック操作に縛られます)。 (空) 10 10 20 30 スタックとしての 操作のみ許される

Slide 36

Slide 36 text

(c) 2025 Kouji Matsui 移植した結果 CLRにはポインタ型があり、これは仮想メモリ空間のアドレス を指し示すことが出来る。 マジックではない。なので、ガベージコレクタが対象を移動す るような状況では使えない(C#で言う所のunsafeと同じ)。 chibicc-cilでは、最近はやりの「ref」ではなく、全面的にポイ ンタ型を使う。理由はポインタ型の透明性(裏でCLRが勝手に 何かする事がない)と、C言語セマンティクスとの一致。

Slide 37

Slide 37 text

(c) 2025 Kouji Matsui 移植した結果 ldc.i4 %d で評価スタックに 数値をpushし、retする ilasm向けのCLIコードを出力 public static class Program public static int Main(string[] args) chibiccの最初のコミットの 移植

Slide 38

Slide 38 text

(c) 2025 Kouji Matsui 移植した結果 遭遇した難易度の高い問題

Slide 39

Slide 39 text

(c) 2025 Kouji Matsui 移植した結果 構造体のメンバーアクセスは、ポインター計算で処理する。 ◦ 元のchibicc (x86-64)は、当たり前ですが「型消去」を行います。つま り、コンパイル後のバイナリに型情報は含まれません。 ◦ 従って、構造体のメンバーにアクセスするには、コンパイル時にオフ セットを計算しておき、オフセットを信じてアクセスします。

Slide 40

Slide 40 text

(c) 2025 Kouji Matsui 移植した結果 ◦ この手法を大きく変えないようにするために、chibicc-cilでもメンバー アクセスはオフセット計算で行います。 コンパイル時に オフセットを計算する コードジェネレータの構造が、ポインタとオフ セットアクセスに強く依存しているので、 逸脱すると大幅に変更する必要がある

Slide 41

Slide 41 text

(c) 2025 Kouji Matsui 移植した結果 CILには、フィールドアクセス命令 ldfldやstfldがあるが、それらを使わず 全部ポインタで計算する

Slide 42

Slide 42 text

(c) 2025 Kouji Matsui 移植した結果 構造体のメンバーアクセスは(特にポインター型を含む場合)、 コンパイル時ではなく実行時に解決する必要がある。 ◦ “void*”や”intptr_t”は、普通のC言語処理系では「コンパイル時にター ゲット環境に合わせて32/64bit(4/8バイト)」と仮定出来るが、.NETの 場合は実行時までわからない。 ◦ オフセット計算をコンパイラ内部で行うのではなく、オフセット計算式 をコードとして出力し、実行時にこのコードを計算することによってオ フセットを確定させる。

Slide 43

Slide 43 text

(c) 2025 Kouji Matsui 移植した結果 ポインターがあると、 実行時環境によって オフセットが異なる 実行時に計算を 行う必要がある

Slide 44

Slide 44 text

(c) 2025 Kouji Matsui 移植した結果 関連する問題として、アライメントの指定と計算: ◦ CLRがどのようにメンバーをメモリ上に配置するのかは不透明なので、 必ずchibiccが出力するオフセット計算と一致するようにしなければなら ない。 ◦ 構造体メンバーのオフセット計算は行う。グローバル変数とかのアライ メント計算は無視する(常にオフセット0から始まると仮定する)。 ◦ 多分、SSEやAVX intrinsicで、グローバル変数__int128を128バイト境界に配置したいという ような要求。.NETでintrinsicを想定するのは意味不明だと思うので、出来なくても問題なさそ う。

Slide 45

Slide 45 text

(c) 2025 Kouji Matsui 移植の過程 chibiccを.NETに移植する (56): Align struct members ◦ https://youtu.be/Yg5gF-I0khY?si=6Wvygz3orjrqhfQU

Slide 46

Slide 46 text

(c) 2025 Kouji Matsui 移植した結果 パフォーマンスが悪すぎる: ◦ オフセット計算式をそのまま出力しても動作するが、非常にパフォーマ ンスが悪い。 ◦ タイプイニシャライザで一度だけ計算して、結果をスタティックフィールドに保持するような コードを出力することでキャッシュし、構造体メンバーにアクセスするときはその値を使用す るようなコードを出力する。 後続フィールドの計算は式が増 えていくのでコストが高い

Slide 47

Slide 47 text

(c) 2025 Kouji Matsui 移植した結果 ◦ オフセット計算式自体も、コンパイラ内部で計算可能な部分は計算して おく。このために簡約器(一種のインタプリタ)を実装した。 ◦ 直値の検出と、直値同士の計算をコンパイラ内で行う。 ◦ 直値が条件となる分岐式(例えば “1 != 0 ? o1 : o2”)は、判定もコンパイラ内で行う。 ◦ おそらくこれを発展させれば、オプティマイザ機能に昇華出来ると思われる(未実施)。 ◦ これでかなりパフォーマンスが向上した(恐らく5倍から20倍程度)。 但し、現在の実装はそこ まで万能でもない…

Slide 48

Slide 48 text

(c) 2025 Kouji Matsui 移植の過程 chibiccを.NETに移植する (67): Reducerの説明と課題 https://youtu.be/McpFR217QaI?si=8Gk_Az1HPq4zXM8y

Slide 49

Slide 49 text

(c) 2025 Kouji Matsui 移植した結果 関数ポインターを構造体のメタデータに出力すると、ランタイ ムの構造体サイズ計算で無視される ◦ 仕方がないので、”void*”と同じように扱うように修正 ◦ CoreCLRのバグっぽいが、Issueは見つからない(未発見?) 放置しておくと問題が起きそうだから、そのうち修正されるかも。

Slide 50

Slide 50 text

(c) 2025 Kouji Matsui 移植した結果 CLRはスタックマシンなので、関数の戻り値を捨てる場合にこ れを考慮に入れる必要があるが、元のchibiccはそうではない。 ◦ chibiccは、戻り値が常にレジスタraxに入っていると仮定していて、戻 り値が不要な場合はraxの値を無視しているだけ。 ◦ スタックマシンではそうはいかない。戻り値が不要な場合は、スタック から値を削除する必要があり、誤っているとクラッシュする。

Slide 51

Slide 51 text

(c) 2025 Kouji Matsui 移植した結果 レジスタなら無視するだけで良 いが、スタックマシンのCLRで は捨てなければならない

Slide 52

Slide 52 text

(c) 2025 Kouji Matsui 移植した結果 ◦ コードジェネレータの基本構造に手を入れて、関数の戻り値が存在する かどうかを追跡するように変更。 ◦ 関数のシグネチャを無理やり偽ると、x86-64と同様に未定義動作: ◦ x86-64: voidを返す関数でintを返すように偽ると、でたらめな値が返される(raxの偶然の値 が読める)。 ◦ CLI: voidを返す関数でintを返すように偽ると、クラッシュする。 無理やりキャストして呼び出す

Slide 53

Slide 53 text

(c) 2025 Kouji Matsui 移植した結果 C言語の配列は、値型配列に相当するが、対応するCILの型が無 い。 ◦ .NETで配列と言えば、System.Array型の「参照型 (ObjRef)」であり、 値型(ValueType)ではない。 ◦ C言語の配列は、.NETにおける値型と同じ。配列を指すポインターを計 算することで、初めて参照型と同じような立ち位置になる(C言語のキ モい構文規則のためにわかりにくい)。 ◦ .NETのSystem.Arrayをそのまま利用させると、ポインター計算との整 合性を取ることが困難。やはり値型として振る舞う必要がある。

Slide 54

Slide 54 text

(c) 2025 Kouji Matsui 移植した結果 構造体に無理やりn個のフィールドを埋めた型(値型配列)を出力 して、配列として扱えるようにした。 配列の 要素数

Slide 55

Slide 55 text

(c) 2025 Kouji Matsui 移植した結果 ◦ 同じような構造体型が多数生成されてしまうので、型名に規則性を持た せて、同じ型名なら再利用可能にする(後述)。 ◦ メンバーアクセス時は「オフセット計算式の出力をコンパイラが行う」 ので、メンバーがprivateでも問題ない。ストレージスペースだけ担保で きれば良い。 注意: メタデータ上のメンバーレイ アウトが、オフセット計算式と厳密 に一致する必要がある

Slide 56

Slide 56 text

(c) 2025 Kouji Matsui 移植した結果 chibiccを.NETに移植する (54): Add struct [2] https://youtu.be/eAvlo8HaF_8?si=i8NGHZrwbpdCSMnE

Slide 57

Slide 57 text

(c) 2025 Kouji Matsui 移植した結果 異なる生成イメージ内の全く同じ名称の型が、CILメタデータ 上では区別されてしまう。 ◦ 前述の値型配列でも(特に大量に)発生。 ◦ .NETでは、異なるアセンブリに定義された同じ名称の型が区別される。 ◦ C言語では、処理系が出力したタイミングが異なるだけで、同じヘッダ ファイルを使用していれば、定義された型が同じと見なす必要がある (わざと定義を変えない限り)。

Slide 58

Slide 58 text

(c) 2025 Kouji Matsui 移植した結果 Sbyte_len5 libc.a Sbyte_len5 Sbyte_len5 Sbyte_len5 大量に生成されてしまう値型配列

Slide 59

Slide 59 text

(c) 2025 Kouji Matsui 移植した結果 ◦ chibildが、同じ名称の型を集約して、単一の型を参照するようにアセン ブリを出力する。 ◦ それでも、異なるアセンブリ間では差異が発生しうるが、実はランタイ ムはこれを検出しない(CLR/CoreCLR/mono)ので、しれっと放置する。

Slide 60

Slide 60 text

(c) 2025 Kouji Matsui 移植した結果 ◦ ポインター型は、評価スタック上は単純な「*」と言う種別に分類され るので、多分、「Foo*」の「Foo」が一致するかどうかは見ていない。 ポインタを評価スタックにpush した時点でFooの情報が失われる(?)

Slide 61

Slide 61 text

(c) 2025 Kouji Matsui 移植した結果 ◦ 関数引数や戻り値の値渡しで構造体が渡される場合も、現状では問題が 発生しないが、将来のランタイムでは問題が発生するかもしれない(パ フォーマンスに影響がありそうなので、そういうチェックはやらないか もとは思う)。 ポインタではなく 値渡しすると明確に Fooは異なるが…

Slide 62

Slide 62 text

(c) 2025 Kouji Matsui 移植した結果 ◦ 万が一問題が起きる場合は… 構造体をポインター渡しに変更して、受信 側で内容を(サイズ基準で)コピーするとかですかね… ◦ NOTE: chibicc-cilは全てがプリミティブ型か値型であり、参照型 (ObjRef)を扱わないので、値渡しの型が違っていても問題ないと推測 (ObjRefの物理レイアウトはCLRの仕様から見て不透明で、値型のコ ピーよりも何か問題が起きそうではある)。

Slide 63

Slide 63 text

(c) 2025 Kouji Matsui 移植した結果 VLA (可変長配列・Variable length array)への対応。 ◦ alloca()に相当。実行時にサイズを決定できて、ストレージはスタックに 配置される。 ◦ C#で言う所のstack_alloc。なので、alloca()の単純なマッピングは実現 可能。CILのlocalloc命令 (https://learn.microsoft.com/en- us/dotnet/api/system.reflection.emit.opcodes.localloc)を使えばいい。

Slide 64

Slide 64 text

(c) 2025 Kouji Matsui 移植した結果 ◦ CLRはスタックマシンであるため、locallocで確保される領域も評価ス タックに積むことになり、評価スタックをスクラッチバッファとして使 うchibiccは、スタックバランスが崩れてクラッシュしやすい(なので、 alloca()使用時もスタックが底にある事をチェックしている)。 ◦ 問題となる条件はalloca()と同じだが、VLAだと言語構文なので、どこ にでも書けるように感じるため、この問題に気が付きにくいと感じた…

Slide 65

Slide 65 text

(c) 2025 Kouji Matsui 移植した結果 ◦ スクラッチバッファとして使う箇所を全部テンポラリローカル変数に格 納するようにすれば対応は可能だが... ◦ C#はそうしていた。OpCodeだけ見ると、スクラッチバッファをわざわざローカル変数として 割り当てていて無駄なコードだなとは思っていたけど、どうやらこれが背景にありそう。 ◦ そういうわけで諦めた。多分VLA使う人いない… ローカル変数に保存(stloc)して直ぐにまたローカル変数から 値を取り出す(ldloc)操作は、一見無意味のように思える

Slide 66

Slide 66 text

(c) 2025 Kouji Matsui 移植した結果 移動するグローバル変数 ◦ 以下のコード、fooの保持位置がメモリ上で移動する (.NET Core以降) ◦ スタティック変数なので、GCHandle.Alloc()でpinする事も出来ない… ◦ &fooとかやられたらアウト。 ◦ .NETの世界に閉じていれば、気が付かないと思われる(Issueにもない) 仮想メモリ空間内で 移動する…

Slide 67

Slide 67 text

(c) 2025 Kouji Matsui 移植した結果 ◦ グローバル変数は常にポインタ型で保持して、chibiccがmalloc()して割り 当てたメモリを指すようにし、アクセス時にdereferenceするようにした。 ◦ malloc()関数の中身は、Marshal.AllocCoTaskMem()なので移動しない。 ポインタ malloc() 初期化式

Slide 68

Slide 68 text

(c) 2025 Kouji Matsui 移植した結果 MMX, SSE, AVXなどのintrinsic ◦ .NET環境でこれに対応させる意味が良く分からん感あるのでスルー まともなデバッグ情報を出したい ◦ ilasmを使っている限り、その制約で無理ゲーなので、chibiasを作ることに。 ◦ 流れでchibiarも作ることになり、結局chibicc-cil-toolchainとした。 ◦ emitされるコードは、Mono.Cecil (https://github.com/jbevain/cecil) を使 用しています。 ◦ ドキュメントはかなり書いたので、これらの使い方はリポジトリを参照してく ださい。 https://github.com/kekyo/chibicc-cil-toolchain

Slide 69

Slide 69 text

(c) 2025 Kouji Matsui 移植した結果 ランタイムライブラリの用意 ◦ chibicc自身のビルドは、chibicc内で使用している標準関数や定義だけ が用意出来れば良いので、「libc-bootstrap.dll」としてC#で実装。 ◦ これにより、Stage1, 2, 3コンパイル(つまりセルフビルド)を実現。 ◦ Stage4(完全なCランタイムライブラリを使用するchibiccのビルド)を 実現するために、newlibを移植する。 ◦ newlib (https://sourceware.org/newlib/) は、主に組み込み環境向けのlibc互換実装。しん どかった… 結局完成してません。一応ビルドには成功し、libc.aとlibc.mは生成できました。 ◦ 他にもuclibcやmuslといった選択肢があります。newlibを選択すべきだったかどうかはわかり ません。

Slide 70

Slide 70 text

(c) 2025 Kouji Matsui 移植した結果 ◦ newlibは内部で「複素数型 _Complex の計算関数」も公開していて、 これを実現するためにはコンパイラが複素数型を扱える必要があります。 ◦ しかし、chibiccは複素数型を実装しておらず… ◦ つまり、一から複素数型をサポートするコードを実装しました(” .NET related: Added complex type basis.”)。 ◦ といっても、複素数型に対する実数と虚数パートそれぞれへのアクセスと、四則演算に対応す る関数が呼び出せるようにするだけなので、chibiccをここまで移植していれば誰でも実装でき るはずです。その他の複素数計算はnewlibに任せる…

Slide 71

Slide 71 text

(c) 2025 Kouji Matsui 移植した結果 ◦ 子プロセス起動のハンドリング ◦ fork(), exec()が無いので、posix_spawn()を実装してお茶を濁した。 ◦ 標準入出力ハンドルをマルチプラットフォーム安全に転送出来ないので、イベントハンドラで データをバイパスするワーカースレッドが必要だった。あまり効率が良くないと思う。 ◦ POSIXシグナル・スレッドの扱い ◦ pthreadの移植をがんばる(一部のみ実装)。内部はもちろん.NETのSystem.Threadingを使う。 ◦ POSIXシグナルは目下の所無視…

Slide 72

Slide 72 text

(c) 2025 Kouji Matsui 移植した結果 関数の可変引数への対応(vararg) ◦ C#の可変引数(param array)とは違います。相互運用機能。 ◦ CILのvarargメタデータ・arglist命令・System.ArgIteratorを使う varargメタデータ arglist ArgIterator 一対一に対応していて ネイティブコード連携のために 存在する事がうかがえる

Slide 73

Slide 73 text

(c) 2025 Kouji Matsui 移植した結果 ◦ CILのvarargメタデータを使うようにする。これの生成はchibildで行う 必要がある。 ◦ 最初、varargを使うもうまく動かない事があった。これはnetstandard TFMでのみ発生し、.NETランタイムのissueにも上がっていない問題で、 どうしようもないことから、CIL vararg関連の機能を使わず独自の実装 で回避。 ◦ 独自実装なので、chibiccの世界では問題なく動作する。しかし、ネイ ティブコードとの連携は出来ない。

Slide 74

Slide 74 text

(c) 2025 Kouji Matsui 移植した結果 他にも細かい問題は山のように存在しましたが… ざっくりしたまとめ(ここに書いてない事も多数): https://gist.github.com/kekyo/d3bec6e1427bc8c0d459f7fcb7a1fcac)

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

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

Slide 77

Slide 77 text

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

Slide 78

Slide 78 text

(c) 2025 Kouji Matsui ラスボス 関数の可変引数への対応 (vararg) ◦ vararg命令を使わず独自の実装で回避。これは動作した。 ◦ しかし、P/Invokeで可変引数関数を呼び出したりコールバックで呼び出 し可能にするには、.NETランタイムがvarargを処理できる必要がある…

Slide 79

Slide 79 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 80

Slide 80 text

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

Slide 81

Slide 81 text

(c) 2025 Kouji Matsui クロージング もしかしたら、将来ランタイムでvararg対応されるかもしれません。しか し、その頃には色々忘れてしまって、もう続けられなさそうです… JVMでもがんばれば出来そうですが、多分sun.misc.Unsafeが〇されてし まったので、難しいと思います… と思ってたら、jdk.unsupportedに移動されたとの事なので、ワンチャン あるかも知れません(私はJava詳しくないのでJVM側のアドバイスは出来 ないと思います。 CILでどうやったのかについては質問どうぞ) Unsafeクラス:どんなスピードでも危険: https://blogs.oracle.com/otnjp/post/the-unsafe-class- unsafe-at-any-speed-ja

Slide 82

Slide 82 text

(c) 2025 Kouji Matsui 質疑応答 成果物を公開します: ◦ chibicc-cil-build: https://github.com/kekyo/chibicc-cil-build この登壇のために最後の整理を行いましたが、基本的にもう触 る事もないので、PRの対応とか期待しないでください… 類似プロジェクト: Cesium(ForNeVerさん/JBの中の人) 同じ問題がIssueで上がっています(もちろん未解決) https://github.com/ForNeVeR/Cesium

Slide 83

Slide 83 text

(c) 2025 Kouji Matsui Center CLR connpass: https://centerclr.connpass.com/ Discord: https://discord.gg/JMA4uzNUKj