Skip to content

Commit

Permalink
Merge branch 'feature/newld' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
kekyo committed May 6, 2024
2 parents e05ad9b + b425b01 commit 85ff49b
Show file tree
Hide file tree
Showing 143 changed files with 16,460 additions and 7,596 deletions.
6 changes: 5 additions & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@

<DebugSymbols>true</DebugSymbols>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<CheckEolTargetFramework>false</CheckEolTargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<CheckEolTargetFramework>false</CheckEolTargetFramework>
<SuppressNETCoreSdkPreviewMessage>true</SuppressNETCoreSdkPreviewMessage>

<PublishRepositoryUrl>true</PublishRepositoryUrl>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/kekyo/chibicc-cil-toolchain.git</RepositoryUrl>
Expand Down Expand Up @@ -49,6 +51,8 @@

<ItemGroup>
<PackageReference Include="RelaxVersioner" Version="3.3.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="1.0.3" PrivateAssets="All" />
<PackageReference Include="PolySharp" Version="1.14.1" PrivateAssets="All" />
</ItemGroup>

<ItemGroup Condition="'$(Configuration)' == 'Release'">
Expand Down
93 changes: 58 additions & 35 deletions README.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ $ dotnet tool install -g chibild-cli
```bash
$ cil-chibild

cil-chibild [0.51.0,net6.0] [...]
cil-chibild [0.60.0,net6.0] [...]
This is the CIL object linker, part of chibicc-cil project.
https://github.com/kekyo/chibicc-cil-toolchain
Copyright (c) Kouji Matsui
Expand All @@ -105,6 +105,7 @@ usage: cil-chibild [options] <input path> [<input path> ...]
-s, -g0 Omit debug symbol file
-O, -O1 Apply optimization
-O0 Disable optimization (defaulted)
-e <symbol> Entry point symbol (defaulted: _start)
-v <version> Apply assembly version (defaulted: 1.0.0.0)
-m <tfm> Target framework moniker (defaulted: net6.0)
-m <arch> Target Windows architecture [AnyCPU|Preferred32Bit|X86|X64|IA64|ARM|ARMv7|ARM64] (defaulted: AnyCPU)
Expand Down Expand Up @@ -139,7 +140,7 @@ chibildを使って "Hello world" を実行してみましょう。
新しいソースコード・ファイル `hello.s` を作り、以下のようにコードを書きます。この4行だけでOKです:

```
.function public void() main
.function public void() _start
ldstr "Hello world with chibild!"
call void(string) System.Console.WriteLine
ret
Expand All @@ -148,7 +149,7 @@ chibildを使って "Hello world" を実行してみましょう。
出来たら、chibildを呼び出します:

```bash
$ cil-chibild -f net45 -L/mnt/c/Windows/Microsoft.NET/Framework64/v4.0.30319 -lmscorlib -o hello.exe hello.s
$ cil-chibild -mnet45 -L/mnt/c/Windows/Microsoft.NET/Framework64/v4.0.30319 -lmscorlib -o hello.exe hello.s
```

実行します:
Expand All @@ -167,15 +168,15 @@ Linuxや他のOSでも、必要な参照を追加することで同じように
また、ビルトイン型(後述)だけを使用するコードをアセンブルした場合は、他のアセンブリへの参照は必要ありません:

```
.function public int32() main
.function public int32() _start
ldc.i4.1
ldc.i4.2
add
ret
```

```bash
$ cil-chibild -f net45 -o adder.exe adder.s
$ cil-chibild -mnet45 -o adder.exe adder.s
$ ./adder.exe
$ echo $?
3
Expand All @@ -184,12 +185,12 @@ $ echo $?
* 注意: この例では、アセンブル時に属性に関する警告が発生しますが、無視して構いません。
* `main` 関数の `argc``argv` に相当する引数を使用する場合は、FCLである `mscorlib.dll` アセンブリへの参照が必要です。

### .NET 6や.NET Coreなどで動かすには
### .NET Coreなどで動かすには

ターゲットフレームワークを指定して、かつ参照アセンブリに`System.Private.CoreLib.dll`が含まれるようにします:

```bash
$ cil-chibild -f net6.0 -L$HOME/.dotnet/shared/Microsoft.NETCore.App/6.0.13 -lSystem.Private.CoreLib \
$ cil-chibild -mnet6.0 -L$HOME/.dotnet/shared/Microsoft.NETCore.App/6.0.13 -lSystem.Private.CoreLib \
-o hello.exe hello.s
```

Expand Down Expand Up @@ -247,7 +248,7 @@ ILAsmと比較しても、はるかに簡単に書けるはずです。
### 最小でエントリーポイントのみ含む例

```
.function public int32() main
.function public int32() _start
ldc.i4 123 ; これはコメントです
ret
```
Expand All @@ -272,27 +273,35 @@ ILAsmと比較しても、はるかに簡単に書けるはずです。
|`file`|現在のソースコードファイルからのみ参照可能。|

* コマンドラインのオプションに `-mexe` を指定するなどして、実行可能形式を生成する場合、
関数名が `main` であれば、自動的にエントリポイントとみなされます。
* エントリポイントのスコープ記述子は、`public`又は`internal`が必要です
関数名が `_start` であれば、自動的にエントリポイントとみなされます。
* `-efoo` と指定すると、エントリポイントのシンボルを `foo` に変更することが出来ます

`main`関数のシグネチャは、以下のバリエーションを受け付けます:
エントリポイントのシグネチャは、CLRの要求に従います。つまり、以下の組み合わせが可能です:

|関数シグネチャ|対応するC言語でのシグネチャ例|
|関数シグネチャ|対応するC#でのシグネチャ例|
|:----|:----|
|`int32(argc:int32,argv:sbyte**)`|`int main(int argc, char** argv)`|
|`void(argc:int32,argv:sbyte**)`|`void main(int argc, char** argv)`|
|`int32()`|`int main(void)`|
|`void()`|`void main(void)`|
|`void()`|`static void _start()`|
|`int32()`|`static int32 _start()`|
|`void(string[])`|`static void _start(string[] args)`|
|`int32(string[])`|`static int32 _start(string[] args)`|

* 関数シグネチャについては、後述の解説を参照してください。

奇妙に思えるかもしれませんが、引数の`argv`は、現実にポインタへのポインタです。
そしてその先は、終端文字を含むUTF-8文字列を示します。
#### 補足: スタートアップコード

chibildは`wmain`による、UTF-16LEワイド幅文字列を含むエントリポイントをサポートしていません。
chibiccを使う場合、エントリポイントはあくまでC言語の `main` 関数として定義する事を想定しています。
例えば、 `int main(int argc, char **argv)` です。

このシグネチャの違いは、スタートアップコードを含む `crt0.o` のようなオブジェクトファイルをchibiccが供給し、
その中でC言語で必要な引数を生成することによって実現しています。

このドキュメントでは、スタートアップコードを省いて解説しています。
従って、スタートアップコードの規則は、常に上記の表に従います。

### リテラル

```
.function public int32() main
.function public int32() _start
ldc.i4 123
ldc.r8 1.234
ldstr "abc\"def\"ghi"
Expand All @@ -311,7 +320,7 @@ chibildは`wmain`による、UTF-16LEワイド幅文字列を含むエントリ
### ラベル

```
.function public int32() main
.function public int32() _start
ldc.i4 123
br NAME
nop
Expand Down Expand Up @@ -400,7 +409,7 @@ string(int8,int32,...)*
### ローカル変数

```
.function public int32() main
.function public int32() _start
.local int32
.local int32 abc
ldc.i4 1
Expand Down Expand Up @@ -444,7 +453,7 @@ string(int8,int32,...)*
### 別の関数を呼び出す

```
.function public int32() main
.function public int32() _start
ldc.i4 1
ldc.i4 2
call add2
Expand Down Expand Up @@ -490,7 +499,7 @@ C#では、可変引数を.NET配列で受け取りますが、chibildではCIL
例えば、上記の`add_n`を呼び出す場合は:

```
.function public int32() main
.function public int32() _start
ldc.i4.s 123
ldc.r8 123.456 ; <-- 追加引数
ldstr "ABC" ; <-- 追加引数
Expand Down Expand Up @@ -520,7 +529,7 @@ $ chibild -c test.s
その後、以下のように、上記アセンブリの関数を呼び出します:

```
.function public int32() main
.function public int32() _start
ldc.i4 1
ldc.i4 2
call add2
Expand All @@ -534,7 +543,7 @@ $ chibild -ltest main.s
関数(.NET CILメソッド)は、`C.text`という名前のクラス内に配置されます。
そのマッピングは:

* `int32() main` --> `public static int32 C.text::main()`
* `int32() _start` --> `public static int32 C.text::main()`
* `int32(a:int32,b:int32) add2` --> `public static int32 C.text::add2(int32 a, int32 b)`

疑似的にC#で記述すると (test.dll):
Expand Down Expand Up @@ -584,7 +593,6 @@ CABIが適用されるのは、外部アセンブリから参照可能な場合

メソッドのシグネチャは、メソッドのオーバーロードを特定するために使用されます。
シグネチャを指定せず、オーバーロードメソッドが複数存在する場合は、誤ったメソッドを選択する可能性があります。
通常、戻り値の型は検証されませんが、 `op_Implicit` 及び `op_Explicit` メソッドの場合のみ、戻り値の型も一致する事が確認されます。

.NETメソッドを参照するために、コマンドラインオプション `-l` で、メソッド定義を含むアセンブリを指定する必要があります。
これは、最も標準的な `mscorlib.dll``System.Runtime.dll` にも当てはまります。
Expand Down Expand Up @@ -618,7 +626,7 @@ chibildでは、関数ポインタ型と同じような構文で指定します
`calli` オプコードで使用します:

```
.function public int32() main
.function public int32() _start
ldstr "123"
ldftn int32(string) System.Int32.Parse
calli int32(string)
Expand All @@ -631,7 +639,7 @@ chibildでは、関数ポインタ型と同じような構文で指定します
ただし、関数本体定義の外側に配置します:

```
.function public int32() main
.function public int32() _start
ldc.i4 123
stsfld foo
ldsfld foo
Expand Down Expand Up @@ -878,13 +886,28 @@ public struct foo
public int32[*] c
```

配列の要素数を`*`と指定すると、この値型配列は要素数を特定しない型となります
配列の要素数を`*`と指定すると、この値型配列は要素数を特定しない型(フレックス配列)となります
この型は特殊な値型配列で、配列のインデクサアクセスは、要素数の範囲外チェックが行われません。
当然、存在しない要素にアクセスした場合の結果は未定義となるため、注意が必要です。

フレックス配列は、構造体型の最後のメンバーに使用することを想定していますが、
chibildはこのチェックを行いません。

注意: 構造体型を使用するには、`System.ValueType` 型への参照が解決される必要があります。
`mscorlib.dll` 又は `System.Private.CoreLib.dll` への参照を追加して下さい。

### シンボルの重複について

chibildは、任意の型・グローバル変数・関数(これらをメンバーと呼称します)を検索する際に、以下のように検索を実行します:

1. 同一のオブジェクトファイル内に定義された、`file` スコープのメンバーが見つかれば、それを参照します。
2. 異なる入力に定義された、 `public` または `internal` スコープのメンバーが見つかれば、それを参照します。
この時、検索の優先順位は、コマンドラインオプションに指定した入力群(オブジェクトファイル・アーカイブファイル・アセンブリファイル)の順に検索されます。
3. 見つからないため、エラーが発生します。

メンバーのシンボル名は、それぞれのメンバー種別に応じて検索されます。
シンボル名が同一でも、型・グローバル変数・関数は、それぞれ別として扱われます。

### 位置情報を明示する

`.file``.location`ディレクティブは、シーケンスポイントと呼ばれるデバッグ情報を生成します。
Expand All @@ -895,7 +918,7 @@ public struct foo

```
.file 1 "/home/kouji/Projects/test.c" c
.function public int32() main
.function public int32() _start
.location 1 10 5 10 36
ldc.i4 123
ldc.i4 456
Expand All @@ -918,6 +941,7 @@ public struct foo
* 第4オペランド: 終了行のインデックス (0ベースのインデックス、かつ開始行以上)
* 第5オペランド: 終了桁のインデックス (0ベースのインデックス、かつ開始桁より大きい)
* `.location`ディレクティブは、関数本体でのみ宣言可能です。
* `.location`ディレクティブを指定した直後のオプコードにのみ、適用されます。

言語名称の例(すべてではありません):

Expand All @@ -933,12 +957,11 @@ public struct foo
言語名称は、[Mono.Cecil.Cil.DocumentLanguage](https://github.com/jbevain/cecil/blob/7b8ee049a151204997eecf587c69acc2f67c8405/Mono.Cecil.Cil/Document.cs#L27) に由来しています。

これらのディレクティブを適用しなかった場合は、CILソースファイル自身を示すようなデバッグ情報を生成します。

`.hidden`ディレクティブを使用すると、以降のコードでシーケンスポイントを生成しなくなります:
しかし、`.hidden`ディレクティブを使用すると、以降のコードでシーケンスポイントを生成しなくなります:

```
.hidden
.function public int32() main
.function public int32() _start
.hidden
ldc.i4 123 ; <-- シーケンスポイントは出力されない
ldc.i4 456
add
Expand Down
Loading

0 comments on commit 85ff49b

Please sign in to comment.