Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 19180] ファイルの概要

このコミットは、Go言語のツールチェインにおける内部関数 linkwriteobj の名称を writeobj に変更するものです。この変更は、元の関数名がその実際の機能(リンカとは無関係なオブジェクトファイルの書き出し)に関して誤解を招くものであったため、より正確な名称に修正することを目的としています。

コミット

  • コミットハッシュ: 58b86e50138adaed962ad12a55ede7fb8b0886d9
  • Author: Ian Lance Taylor iant@golang.org
  • Date: Wed Apr 16 14:36:44 2014 -0700

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/58b86e50138adaed962ad12a55ede7fb8b0886d9

元コミット内容

liblink, cmd/gc, cmd/{5,6,8}{a,c}: rename linkwriteobj to writeobj

The name linkwriteobj is misleading because it implies that
the function has something to do with the linker, which it
does not. The name is historical: the function performs an
operation that was previously performed by the linker, but no
longer is.

LGTM=rsc
R=rsc, minux.ma
CC=golang-codereviews
https://golang.org/cl/88210045

変更の背景

このコミットの主な背景は、Go言語のツールチェイン内部で使用されていた linkwriteobj という関数名が、その実際の役割と一致していなかった点にあります。コミットメッセージにも明記されている通り、この関数名は「リンカ」との関連を示唆していますが、実際にはリンカとは無関係なオブジェクトファイルの書き出し処理を行っていました。

この誤解を招く名称は、歴史的な経緯によるものです。かつてこの関数が実行していた処理はリンカによって行われていましたが、Goツールチェインの進化に伴い、その役割が変更されました。しかし、関数名だけが古い役割を示唆したまま残っていたため、コードの可読性や理解を妨げる要因となっていました。

開発者は、コードベースの健全性を保ち、将来の開発者が混乱することなくコードを理解できるようにするため、この誤解を招く名称をより正確な writeobj に変更することを決定しました。これは、コードのセマンティクスを明確にし、保守性を向上させるための典型的なリファクタリングの一環です。

前提知識の解説

このコミットを理解するためには、Go言語のビルドプロセスとツールチェインに関する基本的な知識が必要です。

  1. Goツールチェイン: Go言語のソースコードを実行可能なバイナリに変換するための一連のツール群を指します。主要なコンポーネントには以下が含まれます。

    • コンパイラ (cmd/gc など): Goのソースコードをアセンブリコードや中間表現に変換します。
    • アセンブラ (cmd/{5,6,8}a など): アセンブリコードを機械語のオブジェクトファイルに変換します。5a はARM、6a はx86-64、8a はx86-32アーキテクチャに対応するアセンブラを指します。
    • リンカ (cmd/ld): 複数のオブジェクトファイルやライブラリを結合し、最終的な実行可能ファイルを生成します。
    • 標準ライブラリ (liblink など): ツールチェインが内部的に使用する共通のライブラリやユーティリティ群。
  2. オブジェクトファイル: コンパイラやアセンブラによって生成される中間ファイルで、機械語コードやデータ、シンボル情報などが含まれます。これらはまだ単独では実行可能ではなく、リンカによって結合されることで最終的な実行可能ファイルや共有ライブラリが生成されます。

  3. liblink: Goツールチェインの内部ライブラリの一つで、主にリンカに関連する共通のユーティリティ関数やデータ構造を提供します。しかし、このコミットが示すように、その中にリンカの直接的な機能ではないが、オブジェクトファイルの処理に関連する関数も含まれることがあります。

  4. cmd/{5,6,8}{a,c}:

    • 5, 6, 8 はそれぞれ異なるCPUアーキテクチャ(ARM, x86-64, x86-32)を指します。
    • a はアセンブラ(assembler)を意味し、cmd/5a はARMアセンブラ、cmd/6a はx86-64アセンブラ、cmd/8a はx86-32アセンブラです。
    • c はCコンパイラ(compiler)を意味し、GoのコンパイラがC言語で書かれていた時代の名残です。cmd/5c, cmd/6c, cmd/8c は、それぞれのアーキテクチャ向けのGoコンパイラのバックエンドの一部を指します。

このコミットは、これらのツールチェインコンポーネントがオブジェクトファイルを生成する際に使用する内部関数 linkwriteobj の名称を変更するものです。

技術的詳細

linkwriteobj (変更後は writeobj) 関数は、Goのコンパイラ (cmd/gc) やアセンブラ (cmd/{5,6,8}a)、そして古いCコンパイラ (cmd/{5,6,8}c) が、Goのオブジェクトファイルをディスクに書き出すために使用する重要な内部関数です。

コミットメッセージが強調しているように、この関数の名前が linkwriteobj であったことは、その機能がリンカ (link) と密接に関連しているかのような誤解を与えていました。しかし、実際にはこの関数は、コンパイラやアセンブラが生成した中間表現やシンボル情報を、Go独自のオブジェクトファイル形式でシリアライズし、出力ストリーム(Biobuf)に書き出す役割を担っています。リンカはこれらのオブジェクトファイルを読み込む側であり、書き出す側ではありません。

この名称の変更は、Goツールチェインの設計思想におけるモジュール性と役割分担の明確化を反映しています。オブジェクトファイルの生成はコンパイラやアセンブラの責任であり、リンカの責任ではありません。過去にはリンカがこの処理の一部を担っていた時期があったかもしれませんが、コミット時点ではその役割は分離されていました。

writeobj へのリネームは、この関数の真の目的、すなわち「オブジェクトを書き出す」という動作を直接的に表現しており、コードベース全体のセマンティックな整合性を向上させます。これにより、Goツールチェインの内部構造を理解しようとする開発者にとって、混乱の元が一つ解消されることになります。

この変更は、関数のシグネチャや動作自体には影響を与えません。単に関数名が変更され、その関数を呼び出すすべての箇所が新しい名前に更新されただけです。しかし、このようなリファクタリングは、大規模なコードベースにおいて長期的な保守性と理解の容易さを確保するために不可欠です。

コアとなるコードの変更箇所

このコミットでは、以下のファイル群において linkwriteobj から writeobj への関数名の変更と、それに伴う呼び出し箇所の修正が行われています。

変更されたファイルは以下の通りです。

  • include/link.h: linkwriteobj 関数のプロトタイプ宣言が writeobj に変更されました。
  • src/cmd/5a/lex.c: ARMアセンブラのソースファイルで、linkwriteobj の呼び出しが writeobj に変更されました。
  • src/cmd/5c/swt.c: ARMアーキテクチャ向けGoコンパイラのバックエンドの一部で、linkwriteobj の呼び出しが writeobj に変更されました。
  • src/cmd/6a/lex.c: x86-64アセンブラのソースファイルで、linkwriteobj の呼び出しが writeobj に変更されました。
  • src/cmd/6c/swt.c: x86-64アーキテクチャ向けGoコンパイラのバックエンドの一部で、linkwriteobj の呼び出しが writeobj に変更されました。
  • src/cmd/8a/lex.c: x86-32アセンブラのソースファイルで、linkwriteobj の呼び出しが writeobj に変更されました。
  • src/cmd/8c/swt.c: x86-32アーキテクチャ向けGoコンパイラのバックエンドの一部で、linkwriteobj の呼び出しが writeobj に変更されました。
  • src/cmd/gc/obj.c: Goコンパイラのオブジェクトファイル出力関連のソースファイルで、linkwriteobj の呼び出しが writeobj に変更されました。
  • src/liblink/objfile.c: linkwriteobj 関数の定義自体が writeobj に変更されました。また、この関数に対するコメントが追加され、その役割がリンカとは無関係であることが明確化されました。

合計9つのファイルが変更され、12行が追加され、9行が削除されています。これは主に名称変更によるものです。

コアとなるコードの解説

このコミットの核となる変更は、src/liblink/objfile.c における関数定義の変更と、include/link.h における関数プロトタイプ宣言の変更、そしてその関数を呼び出すすべての箇所での名称更新です。

src/liblink/objfile.c の変更

--- a/src/liblink/objfile.c
+++ b/src/liblink/objfile.c
@@ -114,8 +114,11 @@ static char *rdstring(Biobuf*);\n static void rddata(Biobuf*, uchar**, int*);\n static LSym *rdsym(Link*, Biobuf*, char*);\n \n+// The Go and C compilers, and the assembler, call writeobj to write\n+// out a Go object file.  The linker does not call this; the linker\n+// does not write out object files.\n void
-linkwriteobj(Link *ctxt, Biobuf *b)\n+writeobj(Link *ctxt, Biobuf *b)\n {\n  \tint flag;\n  \tHist *h;\n```

この差分は、`linkwriteobj` 関数の実際の定義が `writeobj` に変更されたことを示しています。注目すべきは、新しい関数名 `writeobj` の上に、その役割を明確にするためのコメントが追加されている点です。

```c
// The Go and C compilers, and the assembler, call writeobj to write
// out a Go object file.  The linker does not call this; the linker
// does not write out object files.

このコメントは、writeobj がGoおよびCコンパイラ、そしてアセンブラによってGoオブジェクトファイルを書き出すために呼び出されること、そしてリンカはこの関数を呼び出さない(リンカはオブジェクトファイルを書き出さない)ことを明確に述べています。これは、関数名の変更の背景にある「誤解を招く」という問題を直接的に解消するための重要な説明です。

include/link.h の変更

--- a/include/link.h
+++ b/include/link.h
@@ -571,7 +571,7 @@ void	linkprfile(Link *ctxt, int32 l);\n \n // objfile.c\n void	ldobjfile(Link *ctxt, Biobuf *b, char *pkg, int64 len, char *path);\n-void	linkwriteobj(Link *ctxt, Biobuf *b);\n+void	writeobj(Link *ctxt, Biobuf *b);\n \n // pass.c
 Prog*	brchain(Link *ctxt, Prog *p);

include/link.h は、liblink ライブラリのヘッダファイルであり、linkwriteobj 関数のプロトタイプ宣言が含まれていました。この変更は、そのプロトタイプ宣言も新しい関数名 writeobj に更新されたことを示しています。これにより、この関数を使用する他のツールチェインコンポーネントが新しい関数名でコンパイルできるようになります。

各種 cmd ディレクトリ内の変更

例えば、src/cmd/5a/lex.c の変更は以下のようになっています。

--- a/src/cmd/5a/lex.c
+++ b/src/cmd/5a/lex.c
@@ -172,7 +172,7 @@ assemble(char *file)\n 			return nerrors;\n 	}\n \n-\tlinkwriteobj(ctxt, &obuf);\n+\twriteobj(ctxt, &obuf);\n 	Bflush(&obuf);\n 	return 0;\n }

これは、assemble 関数内で linkwriteobj が呼び出されていた箇所が、writeobj に変更されたことを示しています。同様の変更が、src/cmd/5c/swt.c, src/cmd/6a/lex.c, src/cmd/6c/swt.c, src/cmd/8a/lex.c, src/cmd/8c/swt.c, src/cmd/gc/obj.c の各ファイルで行われています。

これらの変更は、linkwriteobj の定義と宣言が変更されたことに伴い、その関数を呼び出すすべての箇所で新しい関数名を使用するように更新されたことを意味します。これにより、ツールチェイン全体で一貫性が保たれ、コンパイルエラーが発生することなく、リファクタリングが完了します。

関連リンク

参考にした情報源リンク

  • Go言語のコミット履歴: https://github.com/golang/go/commits/master
  • Go Code Review (CL 88210045): https://golang.org/cl/88210045 (元コミットメッセージに記載されているリンク)
  • Go言語のツールチェインに関する一般的な知識 (Goの公式ドキュメントや関連ブログ記事など)
  • Go言語のソースコード (特に src/cmd および src/liblink ディレクトリ)