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

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

このコミットは、Goコンパイラ 6g におけるコード生成のバグ修正に関するものです。具体的には、i2s (integer to string) 変換の呼び出しに関連する問題に対処しています。

コミット

commit 498ed5006158c7ce40ce3dce1fe4e4e2eba8c232
Author: Ken Thompson <ken@golang.org>
Date:   Fri Jun 6 15:01:02 2008 -0700

    code gen bug calling i2s
    
    SVN=121497

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

https://github.com/golang/go/commit/498ed5006158c7ce40ce3dce1fe4e4e2eba8c232

元コミット内容

このコミットは、Go言語の初期のコンパイラである 6g (AMD64アーキテクチャ向けのGoコンパイラ) において、「i2s を呼び出す際のコード生成バグ」を修正したものです。i2s は "integer to string" の略であると推測され、整数から文字列への変換処理に関連する問題を示唆しています。コミットメッセージは簡潔ですが、コンパイラのコード生成段階で特定の変換処理が正しく行われないバグが存在したことを示しています。

変更の背景

Go言語において、整数を文字列に変換する際には注意が必要です。特に初期のGoコンパイラでは、string(int) のような直接的な型変換が、多くのプログラマが期待する「数値を10進数表記の文字列に変換する」動作とは異なる挙動を示すことがありました。

具体的には、Goにおいて string(n) (ここで n は整数) は、整数 n をUnicodeコードポイントとして解釈し、そのコードポイントに対応するUTF-8文字列に変換します。例えば、string(65) はASCIIコード65に対応する文字である "A" を返します。これは、数値を文字列 "65" に変換したいという意図とは異なります。

このコミットは、このような string(int) 変換の誤解釈に起因する、あるいはそれに類似したコンパイラのコード生成上のバグを修正している可能性があります。コンパイラが特定の状況下で i2s 変換を処理する際に、誤った命令を生成したり、期待される結果とは異なるコードパスを選択したりしていたことが考えられます。

この種のバグは、プログラムの実行時に予期せぬ結果を引き起こし、デバッグを困難にするため、コンパイラの正確性を保つ上で非常に重要です。

前提知識の解説

  • Goコンパイラ 6g: Go言語の初期のコンパイラの一つで、特にAMD64アーキテクチャをターゲットとしていました。Go 1.5以降は、より新しいコンパイラツールチェーンに置き換えられています。
  • i2s (Integer to String): 整数型から文字列型への変換を指す一般的な略語です。Go言語では、この変換には strconv パッケージの strconv.Itoa()strconv.FormatInt() を使用するのが一般的で、推奨される方法です。
  • string(int) 型変換の挙動: Go言語における string(int) は、整数値をUnicodeコードポイントとして解釈し、そのコードポイントに対応するUTF-8文字の文字列を生成します。これは、数値をその文字列表現(例: 整数 123 を文字列 "123" に)に変換するものではありません。
  • コード生成 (Code Generation): コンパイラのフェーズの一つで、ソースコードの抽象構文木 (AST) や中間表現 (IR) を、ターゲットマシンが実行できる機械語やアセンブリコードに変換するプロセスです。この段階でバグがあると、生成されるプログラムが意図しない動作をしたり、クラッシュしたりする可能性があります。
  • src/cmd/6g/gen.c: Goコンパイラ 6g のソースコードの一部で、コード生成に関連するロジックが含まれているC言語のファイルです。

技術的詳細

このコミットは src/cmd/6g/gen.c ファイルの変更を含んでいます。このファイルは、Goコンパイラ 6g のバックエンド、特にコード生成部分を担当しています。

変更箇所は agen_inter 関数内にあります。agen_inter は、インターフェース型に関連するコード生成を行う関数であると推測されます。Go言語では、インターフェースは動的な型情報を持つため、型変換やメソッド呼び出しの際に特別なコード生成が必要になります。

元のコードでは、i2s 変換に関連すると思われる特定の条件下で、gmove(n->left, &nodo) が呼び出されていました。ここで gmove は、Goコンパイラにおける一般的なデータ移動操作(generative move)を行う関数であると考えられます。これは、あるレジスタやメモリ位置から別の場所へ値をコピーするような低レベルの操作に対応します。

しかし、バグの修正では、この gmove の代わりに cgen(n->left, &nodo) が呼び出されるように変更されています。cgen は "code generation" の略である可能性が高く、より高レベルな、あるいは特定の意味を持つコード生成操作を行う関数であると推測されます。つまり、単なるデータの移動ではなく、n->left の式を評価し、その結果を nodo に格納するための適切な機械語命令を生成する必要があったと考えられます。

この変更は、i2s 変換の際に、単に値をコピーするだけでは不十分であり、その値が持つ意味(例えば、それが表すUnicodeコードポイント)を考慮した上で、適切な文字列表現を生成するためのより複雑なコードパスが必要であったことを示唆しています。

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

diff --git a/src/cmd/6g/gen.c b/src/cmd/6g/gen.c
index 09b90ac3a3..4f4c4d122c 100644
--- a/src/cmd/6g/gen.c
+++ b/src/cmd/6g/gen.c
@@ -388,8 +388,9 @@ agen_inter(Node *n, Node *res)\n 		\tagen(n->left, &nodr);\n 		\tgmove(&nodr, &nodo);\n 		\tfatal("agen_inter i2s");\n-\t\t} else\n-\t\t\tgmove(n->left, &nodo);\n+\t\t} else {\n+\t\t\tcgen(n->left, &nodo);\n+\t\t}\n \n \t\tnodtypesig(&nodt, n->type);\n \t\tagen(&nodt, &nodr);\

コアとなるコードの解説

変更は src/cmd/6g/gen.c ファイルの agen_inter 関数内で行われています。

元のコード:

-		} else
-		\tgmove(n->left, &nodo);

この行では、特定の条件(i2s 変換に関連すると思われる)が満たされない場合に、n->left の内容を nodogmove (汎用的なデータ移動) していました。

修正後のコード:

+		} else {
+		\tcgen(n->left, &nodo);
+		}

修正では、gmove の代わりに cgen(n->left, &nodo) が呼び出されるように変更されています。

この変更の意図は以下の通りです。

  • gmove から cgen への変更:
    • gmove は、コンパイラが生成するアセンブリコードにおいて、単に値をある場所から別の場所へコピーするような、比較的単純な操作に対応します。
    • 一方、cgen は "code generation" の略であり、より複雑な式や操作に対して、その評価と結果の格納に必要な一連の機械語命令を生成する役割を担います。
  • バグの原因と修正:
    • 元のコードでは、i2s 変換が必要な状況で、単なる値のコピー (gmove) では不十分だったと考えられます。例えば、n->left が評価されるべき式であり、その評価結果が文字列変換の入力となるべきだったのに、単にその式の「アドレス」や「未評価の値」がコピーされてしまっていた可能性があります。
    • cgen を使用することで、コンパイラは n->left が表す式を正しく評価し、その結果(例えば、整数値)を nodo に格納するための適切なコードを生成するようになります。これにより、i2s 変換が期待通りに機能するための正しい入力が提供されるようになり、バグが修正されたと考えられます。

この修正は、コンパイラが特定の型変換(特に整数から文字列への変換)を処理する際のコード生成ロジックの正確性を向上させるものであり、Goプログラムが意図した通りに動作するために不可欠な変更でした。

関連リンク

参考にした情報源リンク