[インデックス 18321] ファイルの概要
このコミットは、Go言語のリンカ(liblink
)におけるPlan 9スタイルのフォーマッタに関する修正です。具体的には、フォーマッタが正しく動作するために必要なvarargck
プラグマの追加と、既存のフォーマット指定子の変更を行っています。
コミット
commit f69391dd9e33132f5082636ffcfd847d7ac07b53
Author: Jeff Sickel <jas@corpus-callosum.com>
Date: Wed Jan 22 06:23:19 2014 +0100
liblink: include missing pragmas for plan9 formatter
R=rsc, r, 0intro
CC=golang-codereviews
https://golang.org/cl/36060047
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/f69391dd9e33132f5082636ffcfd847d7ac07b53
元コミット内容
diff --git a/include/plan9/link.h b/include/plan9/link.h
index f65971efce..b499260274 100644
--- a/include/plan9/link.h
+++ b/include/plan9/link.h
@@ -3,3 +3,15 @@
// license that can be found in the LICENSE file.
#include "../link.h"
+
+#pragma varargck type "@" Addr*
+#pragma varargck type "A" int
+#pragma varargck type "$" char*
+#pragma varargck type "D" Addr*
+#pragma varargck type "lD" Addr*
+#pragma varargck type "L" int
+#pragma varargck type "lS" LSym*
+#pragma varargck type "M" Addr*
+#pragma varargck type "P" Prog*
+#pragma varargck type "R" int
+#pragma varargck type "S" char*
diff --git a/src/liblink/list5.c b/src/liblink/list5.c
index ec954f6461..69650e5ff3 100644
--- a/src/liblink/list5.c
+++ b/src/liblink/list5.c
@@ -43,7 +43,7 @@ static int Aconv(Fmt *fp);\n static int Dconv(Fmt *fp);\n static int Mconv(Fmt *fp);\n static int Pconv(Fmt *fp);\n-static int Rconv(Fmt *fp);\n+static int RAconv(Fmt *fp);\n static int DSconv(Fmt *fp);\n \n void\n@@ -54,7 +54,7 @@ listinit5(void)\n \tfmtinstall(\'$\', DSconv);\n \tfmtinstall(\'M\', Mconv);\n \tfmtinstall(\'D\', Dconv);\n-\tfmtinstall(\'R\', Rconv);\n+\tfmtinstall(\'@\', RAconv);\n }\n \n static char *extra [] = {\n@@ -85,10 +85,10 @@ Pconv(Fmt *fp)\n \t\tstrcat(sc, \".U\");\n \tif(a == AMOVM) {\n \t\tif(p->from.type == D_CONST)\n-\t\t\tsprint(str, \"\t%A%s\t%R,%D\", a, sc, &p->from, &p->to);\n+\t\t\tsprint(str, \"\t%A%s\t%@,%D\", a, sc, &p->from, &p->to);\n \t\telse\n \t\tif(p->to.type == D_CONST)\n-\t\t\tsprint(str, \"\t%A%s\t%D,%R\", a, sc, &p->from, &p->to);\n+\t\t\tsprint(str, \"\t%A%s\t%D,%@\", a, sc, &p->from, &p->to);\n \t\telse\n \t\t\tsprint(str, \"\t%A%s\t%D,%D\", a, sc, &p->from, &p->to);\n \t} else\n@@ -210,7 +210,7 @@ Dconv(Fmt *fp)\n }\n \n static int\n-Rconv(Fmt *fp)\n+RAconv(Fmt *fp)\n {\n \tchar str[STRINGSZ];\n \tAddr *a;\n```
## 変更の背景
このコミットは、Go言語のリンカ(`liblink`)が使用するPlan 9スタイルのフォーマッタにおいて、特定のフォーマット指定子(`%R`)が正しく機能しない、または意図しない動作を引き起こす可能性があったために行われました。Plan 9の`fmt`ライブラリは、C言語における`printf`のような機能を提供しますが、独自の拡張と厳密な型チェック(`varargck`)を備えています。
問題の根本は、`liblink`内で使用されている`%R`フォーマット指定子に対応する`varargck`プラグマが`include/plan9/link.h`に存在しなかったこと、および`src/liblink/list5.c`内で`%R`が使用されている箇所で、より適切な新しいフォーマット指定子`%@`に切り替える必要があったことにあります。これにより、リンカの出力が期待通りにフォーマットされず、デバッグや解析が困難になる可能性がありました。
この修正は、リンカの内部的な整合性を保ち、Plan 9のフォーマット規則に厳密に従うことで、将来的な互換性問題や予期せぬバグを防ぐことを目的としています。
## 前提知識の解説
### Go言語のリンカ (`liblink`)
Go言語のコンパイルプロセスにおいて、リンカは非常に重要な役割を担います。Goのツールチェインは、ソースコードをアセンブリコードに変換し、それをオブジェクトファイルにコンパイルした後、最終的に実行可能なバイナリを生成します。この最後のステップを担当するのがリンカです。
`liblink`は、Goのリンカのコア部分を構成するライブラリであり、Goプログラムのオブジェクトファイルを結合し、必要なランタイムライブラリとリンクして実行ファイルを生成します。この過程で、シンボル解決、アドレスの再配置、デバッグ情報の生成など、様々な低レベルの処理が行われます。
### Plan 9の`fmt`ライブラリと`varargck`プラグマ
Plan 9は、ベル研究所で開発された分散オペレーティングシステムです。Go言語は、その設計思想や一部のツール(特にアセンブラやリンカの初期実装)においてPlan 9の影響を強く受けています。
Plan 9の`fmt`ライブラリは、C言語の`printf`に似た機能を提供しますが、より強力な型チェック機構を備えています。この型チェックは、`#pragma varargck`ディレクティブによって実現されます。
* **`#pragma varargck`**: これは、可変引数関数(`...` を引数に取る関数、例: `fmtprint`)の引数の型と、対応するフォーマット指定子との整合性をコンパイル時にチェックするためのプラグマです。これにより、`printf`のような関数で誤った型の引数を渡してしまうことによる実行時エラーを防ぐことができます。
* **`#pragma varargck type "X" Type*`**: この形式のプラグマは、「フォーマット指定子`"X"`が期待する引数の型は`Type*`である」というルールをコンパイラに伝えます。例えば、`#pragma varargck type "D" Addr*`は、`%D`というフォーマット指定子が`Addr*`型の引数を期待することを示します。
これらのプラグマは、コンパイラが可変引数関数の呼び出しを検証し、型安全性を確保するために不可欠です。
## 技術的詳細
このコミットの技術的な核心は、Plan 9の`fmt`ライブラリの厳密な型チェックシステムと、`liblink`内部でのフォーマット処理の整合性を確保することにあります。
1. **`include/plan9/link.h`への`varargck`プラグマの追加**:
このファイルは、`liblink`が使用するPlan 9関連のヘッダファイルです。以前は、`liblink`内で使用されるいくつかのカスタムフォーマット指定子(例: `%@`, `%A`, `%$`, `%D`など)に対応する`varargck`プラグマが不足していました。これらのプラグマがないと、コンパイラは`fmtprint`のような関数がこれらのフォーマット指定子と共に呼び出された際に、引数の型が正しいかどうかを検証できませんでした。
追加されたプラグマは、各フォーマット指定子(`@`, `A`, `$`, `D`, `lD`, `L`, `lS`, `M`, `P`, `R`, `S`)が期待するC言語のポインタ型や基本型を明示的に定義しています。これにより、コンパイル時に型ミスマッチが検出されるようになり、より堅牢なコードが保証されます。
2. **`src/liblink/list5.c`におけるフォーマット指定子の変更**:
`list5.c`は、`liblink`内でアセンブリ命令やデータ構造を文字列として表現するためのフォーマット処理を担当するファイルです。
* **関数名の変更**: `Rconv`関数が`RAconv`にリネームされました。これは、おそらく既存の`R`フォーマット指定子との混同を避けるため、または新しい`@`フォーマット指定子との関連を明確にするための変更です。
* **`fmtinstall`の変更**: `fmtinstall('R', Rconv);`が`fmtinstall('@', RAconv);`に変更されました。`fmtinstall`は、特定の文字(フォーマット指定子)と、その文字に対応する変換関数を`fmt`ライブラリに登録するために使用されます。この変更により、以前`%R`が担当していたフォーマット処理が、新しい`%@`指定子と`RAconv`関数によって行われるようになりました。
* **`sprint`呼び出しの変更**: `sprint`関数は、C言語の`sprintf`に相当するPlan 9の関数です。このコミットでは、`sprint`のフォーマット文字列内で`%R`が使用されていた箇所が`%@`に置き換えられました。これは、`RAconv`関数が新しい`%@`指定子に対応するように変更されたため、それと整合性を取るための変更です。
これらの変更は、`liblink`の内部的なフォーマット処理をPlan 9の`fmt`ライブラリの設計原則に合わせ、型安全性を高めることを目的としています。
## コアとなるコードの変更箇所
### `include/plan9/link.h`
```c
#pragma varargck type "@" Addr*
#pragma varargck type "A" int
#pragma varargck type "$" char*
#pragma varargck type "D" Addr*
#pragma varargck type "lD" Addr*
#pragma varargck type "L" int
#pragma varargck type "lS" LSym*
#pragma varargck type "M" Addr*
#pragma varargck type "P" Prog*
#pragma varargck type "R" int
#pragma varargck type "S" char*
このセクションでは、様々なフォーマット指定子(@
, A
, $
, D
, lD
, L
, lS
, M
, P
, R
, S
)が、それぞれどのC言語の型(例: Addr*
, int
, char*
, LSym*
, Prog*
)に対応するかをvarargck
プラグマで定義しています。これにより、コンパイラはこれらのフォーマット指定子を使用する可変引数関数の呼び出しにおいて、引数の型が正しいかを静的にチェックできるようになります。
src/liblink/list5.c
-static int Rconv(Fmt *fp);
+static int RAconv(Fmt *fp);
Rconv
という関数がRAconv
にリネームされました。
-\tfmtinstall(\'R\', Rconv);\n+\tfmtinstall(\'@\', RAconv);\
fmtinstall
関数への呼び出しが変更され、フォーマット指定子'R'
とそれに対応するRconv
関数の登録が削除され、代わりに新しいフォーマット指定子'@'
とRAconv
関数が登録されました。
-\t\t\tsprint(str, \"\t%A%s\t%R,%D\", a, sc, &p->from, &p->to);\n+\t\t\tsprint(str, \"\t%A%s\t%@,%D\", a, sc, &p->from, &p->to);\
-\t\t\tsprint(str, \"\t%A%s\t%D,%R\", a, sc, &p->from, &p->to);\n+\t\t\tsprint(str, \"\t%A%s\t%D,%@\", a, sc, &p->from, &p->to);\
sprint
関数のフォーマット文字列内で、%R
が使用されていた箇所が%@
に置き換えられました。これは、fmtinstall
の変更と整合性を取るためのものです。
-Rconv(Fmt *fp)\n+RAconv(Fmt *fp)\
Rconv
関数の定義自体もRAconv
にリネームされました。
コアとなるコードの解説
このコミットの主要な目的は、liblink
の内部的なフォーマット処理を、Plan 9のfmt
ライブラリの厳格な型チェックシステムに完全に準拠させることです。
-
varargck
プラグマの追加:include/plan9/link.h
に追加された#pragma varargck type
行は、liblink
が使用するカスタムフォーマット指定子(例:%@
,%D
など)と、それらが期待するC言語の引数型とのマッピングをコンパイラに明示的に伝えます。これにより、fmtprint
のような可変引数関数がこれらの指定子と共に呼び出された際に、コンパイラが引数の型を静的に検証できるようになり、型安全性が向上します。これは、実行時エラーのリスクを減らし、コードの信頼性を高める上で非常に重要です。 -
フォーマット指定子の変更 (
%R
から%@
へ):src/liblink/list5.c
におけるRconv
からRAconv
への関数名変更、fmtinstall
での登録変更、そしてsprint
呼び出しでのフォーマット文字列の変更は、すべて%R
フォーマット指定子を%@
に置き換えるという一貫した変更を示しています。Rconv
がRAconv
にリネームされたのは、おそらくR
という文字が他の文脈で既に使われていたか、あるいは@
という新しい指定子との関連を明確にするためと考えられます。fmtinstall
の変更は、fmt
ライブラリが%R
ではなく%@
を見たときにRAconv
関数を呼び出すように設定し直すものです。sprint
呼び出しでの%R
から%@
への変更は、実際にフォーマット処理を行う箇所で新しい指定子を使用するように修正したものです。
これらの変更により、liblink
はPlan 9のfmt
ライブラリの型チェック機構を最大限に活用し、より堅牢で予測可能なフォーマット処理を実現します。これは、特にリンカのような低レベルのツールにおいて、正確な出力とデバッグの容易さを確保するために不可欠です。
関連リンク
- Go言語のリンカに関する一般的な情報: https://go.dev/doc/articles/go-toolchain
- Plan 9の
fmt
ライブラリに関する情報 (Goのfmt
パッケージのルーツ): https://pkg.go.dev/fmt (Goのfmt
パッケージはPlan 9のfmt
ライブラリにインスパイアされていますが、直接的なドキュメントはPlan 9の資料を参照する必要があります。)
参考にした情報源リンク
- Go言語の公式ドキュメント
- Plan 9 from Bell Labsのドキュメント (特に
fmt(2)
やvarargck(2)
に関するmanページ) - Go言語のソースコードリポジトリ (特に
src/cmd/link
やsrc/liblink
ディレクトリ) - Go言語のコードレビューシステム (Gerrit) の該当コミットページ: https://golang.org/cl/36060047 (これはコミットメッセージに記載されているリンクです。) I have generated the detailed technical explanation in Markdown format, following all the specified instructions and chapter structure. The output is now ready to be displayed.# [インデックス 18321] ファイルの概要
このコミットは、Go言語のリンカ(liblink
)におけるPlan 9スタイルのフォーマッタに関する修正です。具体的には、フォーマッタが正しく動作するために必要なvarargck
プラグマの追加と、既存のフォーマット指定子の変更を行っています。
コミット
commit f69391dd9e33132f5082636ffcfd847d7ac07b53
Author: Jeff Sickel <jas@corpus-callosum.com>
Date: Wed Jan 22 06:23:19 2014 +0100
liblink: include missing pragmas for plan9 formatter
R=rsc, r, 0intro
CC=golang-codereviews
https://golang.org/cl/36060047
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/f69391dd9e33132f5082636ffcfd847d7ac07b53
元コミット内容
diff --git a/include/plan9/link.h b/include/plan9/link.h
index f65971efce..b499260274 100644
--- a/include/plan9/link.h
+++ b/include/plan9/link.h
@@ -3,3 +3,15 @@
// license that can be found in the LICENSE file.
#include "../link.h"
+
+#pragma varargck type "@" Addr*
+#pragma varargck type "A" int
+#pragma varargck type "$" char*
+#pragma varargck type "D" Addr*
+#pragma varargck type "lD" Addr*
+#pragma varargck type "L" int
+#pragma varargck type "lS" LSym*
+#pragma varargck type "M" Addr*
+#pragma varargck type "P" Prog*
+#pragma varargck type "R" int
+#pragma varargck type "S" char*
diff --git a/src/liblink/list5.c b/src/liblink/list5.c
index ec954f6461..69650e5ff3 100644
--- a/src/liblink/list5.c
+++ b/src/liblink/list5.c
@@ -43,7 +43,7 @@ static int Aconv(Fmt *fp);\n static int Dconv(Fmt *fp);\n static int Mconv(Fmt *fp);\n static int Pconv(Fmt *fp);\n-static int Rconv(Fmt *fp);\n+static int RAconv(Fmt *fp);\n static int DSconv(Fmt *fp);\n \n void\n@@ -54,7 +54,7 @@ listinit5(void)\n \tfmtinstall(\'$\', DSconv);\n \tfmtinstall(\'M\', Mconv);\n \tfmtinstall(\'D\', Dconv);\n-\tfmtinstall(\'R\', Rconv);\n+\tfmtinstall(\'@\', RAconv);\n }\n \n static char *extra [] = {\n@@ -85,10 +85,10 @@ Pconv(Fmt *fp)\n \t\tstrcat(sc, \".U\");\n \tif(a == AMOVM) {\n \t\tif(p->from.type == D_CONST)\n-\t\t\tsprint(str, \"\t%A%s\t%R,%D\", a, sc, &p->from, &p->to);\n+\t\t\tsprint(str, \"\t%A%s\t%@,%D\", a, sc, &p->from, &p->to);\n \t\telse\n \t\tif(p->to.type == D_CONST)\n-\t\t\tsprint(str, \"\t%A%s\t%D,%R\", a, sc, &p->from, &p->to);\n+\t\t\tsprint(str, \"\t%A%s\t%D,%@\", a, sc, &p->from, &p->to);\n \t\telse\n \t\t\tsprint(str, \"\t%A%s\t%D,%D\", a, sc, &p->from, &p->to);\n \t} else\n@@ -210,7 +210,7 @@ Dconv(Fmt *fp)\n }\n \n static int\n-Rconv(Fmt *fp)\n+RAconv(Fmt *fp)\n {\n \tchar str[STRINGSZ];\n \tAddr *a;\n```
## 変更の背景
このコミットは、Go言語のリンカ(`liblink`)が使用するPlan 9スタイルのフォーマッタにおいて、特定のフォーマット指定子(`%R`)が正しく機能しない、または意図しない動作を引き起こす可能性があったために行われました。Plan 9の`fmt`ライブラリは、C言語における`printf`のような機能を提供しますが、独自の拡張と厳密な型チェック(`varargck`)を備えています。
問題の根本は、`liblink`内で使用されている`%R`フォーマット指定子に対応する`varargck`プラグマが`include/plan9/link.h`に存在しなかったこと、および`src/liblink/list5.c`内で`%R`が使用されている箇所で、より適切な新しいフォーマット指定子`%@`に切り替える必要があったことにあります。これにより、リンカの出力が期待通りにフォーマットされず、デバッグや解析が困難になる可能性がありました。
この修正は、リンカの内部的な整合性を保ち、Plan 9のフォーマット規則に厳密に従うことで、将来的な互換性問題や予期せぬバグを防ぐことを目的としています。
## 前提知識の解説
### Go言語のリンカ (`liblink`)
Go言語のコンパイルプロセスにおいて、リンカは非常に重要な役割を担います。Goのツールチェインは、ソースコードをアセンブリコードに変換し、それをオブジェクトファイルにコンパイルした後、最終的に実行可能なバイナリを生成します。この最後のステップを担当するのがリンカです。
`liblink`は、Goのリンカのコア部分を構成するライブラリであり、Goプログラムのオブジェクトファイルを結合し、必要なランタイムライブラリとリンクして実行ファイルを生成します。この過程で、シンボル解決、アドレスの再配置、デバッグ情報の生成など、様々な低レベルの処理が行われます。
### Plan 9の`fmt`ライブラリと`varargck`プラグマ
Plan 9は、ベル研究所で開発された分散オペレーティングシステムです。Go言語は、その設計思想や一部のツール(特にアセンブラやリンカの初期実装)においてPlan 9の影響を強く受けています。
Plan 9の`fmt`ライブラリは、C言語の`printf`に似た機能を提供しますが、より強力な型チェック機構を備えています。この型チェックは、`#pragma varargck`ディレクティブによって実現されます。
* **`#pragma varargck`**: これは、可変引数関数(`...` を引数に取る関数、例: `fmtprint`)の引数の型と、対応するフォーマット指定子との整合性をコンパイル時にチェックするためのプラグマです。これにより、`printf`のような関数で誤った型の引数を渡してしまうことによる実行時エラーを防ぐことができます。
* **`#pragma varargck type "X" Type*`**: この形式のプラグマは、「フォーマット指定子`"X"`が期待する引数の型は`Type*`である」というルールをコンパイラに伝えます。例えば、`#pragma varargck type "D" Addr*`は、`%D`というフォーマット指定子が`Addr*`型の引数を期待することを示します。
これらのプラグマは、コンパイラが可変引数関数の呼び出しを検証し、型安全性を確保するために不可欠です。
## 技術的詳細
このコミットの技術的な核心は、Plan 9の`fmt`ライブラリの厳密な型チェックシステムと、`liblink`内部でのフォーマット処理の整合性を確保することにあります。
1. **`include/plan9/link.h`への`varargck`プラグマの追加**:
このファイルは、`liblink`が使用するPlan 9関連のヘッダファイルです。以前は、`liblink`内で使用されるいくつかのカスタムフォーマット指定子(例: `%@`, `%A`, `%$`, `%D`など)に対応する`varargck`プラグマが不足していました。これらのプラグマがないと、コンパイラは`fmtprint`のような関数がこれらのフォーマット指定子と共に呼び出された際に、引数の型が正しいかどうかを検証できませんでした。
追加されたプラグマは、各フォーマット指定子(`@`, `A`, `$`, `D`, `lD`, `L`, `lS`, `M`, `P`, `R`, `S`)が期待するC言語のポインタ型や基本型を明示的に定義しています。これにより、コンパイル時に型ミスマッチが検出されるようになり、より堅牢なコードが保証されます。
2. **`src/liblink/list5.c`におけるフォーマット指定子の変更**:
`list5.c`は、`liblink`内でアセンブリ命令やデータ構造を文字列として表現するためのフォーマット処理を担当するファイルです。
* **関数名の変更**: `Rconv`関数が`RAconv`にリネームされました。これは、おそらく既存の`R`フォーマット指定子との混同を避けるため、または新しい`@`フォーマット指定子との関連を明確にするための変更です。
* **`fmtinstall`の変更**: `fmtinstall('R', Rconv);`が`fmtinstall('@', RAconv);`に変更されました。`fmtinstall`は、特定の文字(フォーマット指定子)と、その文字に対応する変換関数を`fmt`ライブラリに登録するために使用されます。この変更により、以前`%R`が担当していたフォーマット処理が、新しい`%@`指定子と`RAconv`関数によって行われるようになりました。
* **`sprint`呼び出しの変更**: `sprint`関数は、C言語の`sprintf`に相当するPlan 9の関数です。このコミットでは、`sprint`のフォーマット文字列内で`%R`が使用されていた箇所が`%@`に置き換えられました。これは、`fmtinstall`の変更と整合性を取るためのものです。
これらの変更は、`liblink`の内部的なフォーマット処理をPlan 9の`fmt`ライブラリの設計原則に合わせ、型安全性を高めることを目的としています。
## コアとなるコードの変更箇所
### `include/plan9/link.h`
```c
#pragma varargck type "@" Addr*
#pragma varargck type "A" int
#pragma varargck type "$" char*
#pragma varargck type "D" Addr*
#pragma varargck type "lD" Addr*
#pragma varargck type "L" int
#pragma varargck type "lS" LSym*
#pragma varargck type "M" Addr*
#pragma varargck type "P" Prog*
#pragma varargck type "R" int
#pragma varargck type "S" char*
このセクションでは、様々なフォーマット指定子(@
, A
, $
, D
, lD
, L
, lS
, M
, P
, R
, S
)が、それぞれどのC言語の型(例: Addr*
, int
, char*
, LSym*
, Prog*
)に対応するかをvarargck
プラグマで定義しています。これにより、コンパイラはこれらのフォーマット指定子を使用する可変引数関数の呼び出しにおいて、引数の型が正しいかを静的にチェックできるようになります。
src/liblink/list5.c
-static int Rconv(Fmt *fp);
+static int RAconv(Fmt *fp);
Rconv
という関数がRAconv
にリネームされました。
-\tfmtinstall(\'R\', Rconv);\n+\tfmtinstall(\'@\', RAconv);\
fmtinstall
関数への呼び出しが変更され、フォーマット指定子'R'
とそれに対応するRconv
関数の登録が削除され、代わりに新しいフォーマット指定子'@'
とRAconv
関数が登録されました。
-\t\t\tsprint(str, \"\t%A%s\t%R,%D\", a, sc, &p->from, &p->to);\n+\t\t\tsprint(str, \"\t%A%s\t%@,%D\", a, sc, &p->from, &p->to);\
-\t\t\tsprint(str, \"\t%A%s\t%D,%R\", a, sc, &p->from, &p->to);\n+\t\t\tsprint(str, \"\t%A%s\t%D,%@\", a, sc, &p->from, &p->to);\
sprint
関数のフォーマット文字列内で、%R
が使用されていた箇所が%@
に置き換えられました。これは、fmtinstall
の変更と整合性を取るためのものです。
-Rconv(Fmt *fp)\n+RAconv(Fmt *fp)\
Rconv
関数の定義自体もRAconv
にリネームされました。
コアとなるコードの解説
このコミットの主要な目的は、liblink
の内部的なフォーマット処理を、Plan 9のfmt
ライブラリの厳格な型チェックシステムに完全に準拠させることです。
-
varargck
プラグマの追加:include/plan9/link.h
に追加された#pragma varargck type
行は、liblink
が使用するカスタムフォーマット指定子(例:%@
,%D
など)と、それらが期待するC言語の引数型とのマッピングをコンパイラに明示的に伝えます。これにより、fmtprint
のような可変引数関数がこれらの指定子と共に呼び出された際に、コンパイラが引数の型を静的に検証できるようになり、型安全性が向上します。これは、実行時エラーのリスクを減らし、コードの信頼性を高める上で非常に重要です。 -
フォーマット指定子の変更 (
%R
から%@
へ):src/liblink/list5.c
におけるRconv
からRAconv
への関数名変更、fmtinstall
での登録変更、そしてsprint
呼び出しでのフォーマット文字列の変更は、すべて%R
フォーマット指定子を%@
に置き換えるという一貫した変更を示しています。Rconv
がRAconv
にリネームされたのは、おそらくR
という文字が他の文脈で既に使われていたか、あるいは@
という新しい指定子との関連を明確にするためと考えられます。fmtinstall
の変更は、fmt
ライブラリが%R
ではなく%@
を見たときにRAconv
関数を呼び出すように設定し直すものです。sprint
呼び出しでの%R
から%@
への変更は、実際にフォーマット処理を行う箇所で新しい指定子を使用するように修正したものです。
これらの変更により、liblink
はPlan 9のfmt
ライブラリの型チェック機構を最大限に活用し、より堅牢で予測可能なフォーマット処理を実現します。これは、特にリンカのような低レベルのツールにおいて、正確な出力とデバッグの容易さを確保するために不可欠です。
関連リンク
- Go言語のリンカに関する一般的な情報: https://go.dev/doc/articles/go-toolchain
- Plan 9の
fmt
ライブラリに関する情報 (Goのfmt
パッケージのルーツ): https://pkg.go.dev/fmt (Goのfmt
パッケージはPlan 9のfmt
ライブラリにインスパイアされていますが、直接的なドキュメントはPlan 9の資料を参照する必要があります。)
参考にした情報源リンク
- Go言語の公式ドキュメント
- Plan 9 from Bell Labsのドキュメント (特に
fmt(2)
やvarargck(2)
に関するmanページ) - Go言語のソースコードリポジトリ (特に
src/cmd/link
やsrc/liblink
ディレクトリ) - Go言語のコードレビューシステム (Gerrit) の該当コミットページ: https://golang.org/cl/36060047 (これはコミットメッセージに記載されているリンクです。)