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

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

このコミットは、Go言語のツールチェインにおけるアセンブラ(cmd/5a, cmd/6a, cmd/8a)に関連する修正です。具体的には、Yacc/Bisonの文法定義ファイルである.yファイル内で使用されている型名LAddrが、以前のグローバルなリネーム作業でAddrに更新されずに残っていた問題を修正しています。これにより、生成されるy.tab.cおよびy.tab.hファイルとの整合性が失われ、ビルドプロセスにおいて問題を引き起こす可能性がありました。

コミット

commit 426b48a77522c0e411cf328372bcfaae3dc7bcc9
Author: Russ Cox <rsc@golang.org>
Date:   Wed Dec 11 12:11:37 2013 -0500

    cmd/5a, cmd/6a, cmd/8a: fix .y files to match y.tab.[ch]
    
    When I renamed LAddr back to Addr (before sending the
    original linker CLs), I missed the .y files in my global substitute.
    Since the .y files are only processed when running make in
    one of those directories (not during all.bash), they were
    behind the generated files.
    
    R=golang-dev, iant
    CC=golang-dev
    https://golang.org/cl/40770044

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

https://github.com/golang/go/commit/426b48a77522c0e411cf328372bcfaae3dc7bcc9

元コミット内容

このコミットの元々の内容は、Go言語のリンカ関連の変更において、LAddrという型名をAddrにリネームした際に、一部のファイル、特にYacc/Bisonの文法定義ファイル(.yファイル)での置換が漏れていたことを修正するものです。コミットメッセージによると、この見落としは、.yファイルが特定のディレクトリでmakeを実行したときにのみ処理され、all.bashのような全体ビルドスクリプトでは直接処理されないため、生成されたファイル(y.tab.c, y.tab.h)との間に不整合が生じていたことが原因です。

変更の背景

Go言語のコンパイラおよびアセンブラは、様々なアーキテクチャをサポートするために、それぞれに対応するツールチェインを持っています。cmd/5aはARMアーキテクチャ用のアセンブラ、cmd/6aはx86-64アーキテクチャ用のアセンブラ、cmd/8aはARM64またはx86アーキテクチャ用のアセンブラ(文脈により異なるが、この時期は主にx86)を指します。

これらのアセンブラは、アセンブリ言語の構文解析にYacc/Bisonを使用しています。Yacc(Yet Another Compiler Compiler)やBisonは、文法定義ファイル(通常.y拡張子を持つ)からC言語のパーサコード(y.tab.cy.tab.hなど)を生成するツールです。

コミットメッセージにある「LAddr back to Addr」という記述は、Go言語のリンカやアセンブラ内部でアドレスを表現するためのデータ構造または型名が、一度LAddrと命名された後、何らかの理由で元のAddrに戻されたことを示唆しています。このような大規模なリネーム作業では、コードベース全体にわたる変更が必要となり、手動または自動の置換ツールが使用されます。しかし、特定のビルドプロセスや依存関係を持つファイル(この場合は.yファイル)では、その変更が適切に反映されないことがあります。

このコミットの背景にある問題は、.yファイル内のLAddrAddrに更新されなかったために、Yacc/Bisonが生成するC言語のヘッダファイルやソースファイル(y.tab.h, y.tab.c)と、.yファイル自体との間で型定義の不一致が生じたことです。これにより、アセンブラのビルド時にコンパイルエラーや予期せぬ動作が発生する可能性がありました。特に、.yファイルがall.bashのようなトップレベルのビルドスクリプトではなく、各アセンブラディレクトリ内でのmake実行時にのみ処理されるという特性が、この不整合が発覚しにくかった原因として挙げられています。

前提知識の解説

このコミットを理解するためには、以下の技術的知識が役立ちます。

  1. Go言語のツールチェイン: Go言語は、ソースコードをコンパイルして実行可能ファイルを生成するための一連のツール(コンパイラ、アセンブラ、リンカなど)を提供しています。これらはGoのソースコードと共に配布され、cmd/ディレクトリ以下に配置されています。
    • cmd/5a: GoのARMアーキテクチャ用アセンブラ。
    • cmd/6a: Goのx86-64アーキテクチャ用アセンブラ。
    • cmd/8a: GoのARM64またはx86アーキテクチャ用アセンブラ。
  2. アセンブラ: アセンブリ言語で書かれたプログラムを機械語に変換するプログラムです。Goのアセンブラは、Goのコンパイラが生成する中間表現を最終的な機械語に変換する役割を担います。
  3. Yacc/Bison: Yacc (Yet Another Compiler Compiler) は、文法定義から構文解析器(パーサ)を生成するプログラムです。BisonはGNU版のYaccで、より高機能です。
    • .yファイル: Yacc/Bisonの文法定義ファイルです。BNF(Backus-Naur Form)に似た形式で文法規則と、各規則が認識されたときに実行されるアクション(C言語のコード)を記述します。
    • y.tab.c / y.tab.h: .yファイルをYacc/Bisonで処理すると生成されるC言語のソースファイルとヘッダファイルです。これらには、定義された文法に基づいて入力ストリームを解析するためのコードが含まれています。
  4. リンカ: コンパイラやアセンブラによって生成されたオブジェクトファイル(機械語コードやデータを含む)を結合し、最終的な実行可能ファイルを生成するプログラムです。リンカは、異なるオブジェクトファイル間の参照(関数呼び出しや変数アクセスなど)を解決し、必要なライブラリをリンクします。
  5. 型定義とスコープ: プログラミング言語において、型はデータの種類を定義し、変数がどのような値を保持できるかを決定します。型名の変更は、その型を使用しているすべての箇所で更新される必要があります。C言語のようなコンパイル言語では、型定義の不一致はコンパイルエラーを引き起こします。

技術的詳細

このコミットの技術的な核心は、Goツールチェインのビルドプロセスにおける依存関係と、Yacc/Bisonによって生成されるコードの特性にあります。

Goのアセンブラは、アセンブリ言語のソースコードを解析するために、Yacc/Bisonで定義された文法を使用しています。.yファイルは、アセンブリ言語の命令やオペランドの構文を定義し、それらがどのように解析されるべきかを記述します。Yacc/Bisonは、この.yファイルを読み込み、C言語のパーサコード(y.tab.c)と、パーサが使用するトークンや型定義を含むヘッダファイル(y.tab.h)を生成します。

問題は、Goのリンカ関連のコードベース全体でLAddrという型名がAddrにリネームされた際に、この変更が.yファイルに適用されなかったことです。通常、大規模なリネームは、IDEのグローバル置換機能やスクリプトを使って行われますが、特定のファイルタイプやビルドプロセスの特殊性により、一部のファイルが見落とされることがあります。

このケースでは、.yファイルは直接Goのビルドシステム(all.bash)によって処理されるのではなく、各アセンブラのディレクトリ内でmakeコマンドが実行されたときに、Yacc/Bisonによって処理されます。つまり、y.tab.cy.tab.hは、.yファイルから生成されるため、.yファイルが古い型名LAddrを保持していると、生成されるy.tab.hにもLAddrの定義が含まれることになります。

しかし、Goのリンカや他の関連コードはすでにAddrという新しい型名を使用しているため、y.tab.hが提供するLAddrと、他のコードが期待するAddrとの間で型定義の不一致が発生します。これはC言語のコンパイル時において、未定義の型や型の不一致としてエラー(例: error: unknown type name 'LAddr')を引き起こします。

このコミットは、この不整合を解消するために、src/cmd/5a/a.ysrc/cmd/6a/a.ysrc/cmd/8a/a.yの各ファイル内で、LAddrと記述されている箇所をAddrに修正しています。これにより、Yacc/Bisonがこれらのファイルを処理してy.tab.cy.tab.hを生成する際に、正しい型名Addrが使用されるようになり、ツールチェイン全体の整合性が保たれます。

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

変更は以下の3つのファイルにわたります。

  1. src/cmd/5a/a.y (ARMアセンブラの文法定義ファイル)
  2. src/cmd/6a/a.y (x86-64アセンブラの文法定義ファイル)
  3. src/cmd/8a/a.y (ARM64/x86アセンブラの文法定義ファイル)

各ファイルにおいて、LAddrという文字列がAddrに置換されています。

src/cmd/5a/a.y の変更点:

--- a/src/cmd/5a/a.y
+++ b/src/cmd/5a/a.y
@@ -41,7 +41,7 @@
  int32	lval;
  double	dval;
  char	sval[8];
-	LAddr	addr;
+	Addr	addr;
 }
 %left	'|'
 %left	'^'
@@ -175,7 +175,7 @@ inst:
  */
 |	LTYPE8 cond ioreg ',' '[' reglist ']'
  	{
-		LAddr g;
+		Addr g;
  
  		g = nullgen;
  		g.type = D_CONST;
@@ -184,7 +184,7 @@ inst:
  	}
 |	LTYPE8 cond '[' reglist ']' ',' ioreg
  	{
-		LAddr g;
+		Addr g;
  
  		g = nullgen;
  		g.type = D_CONST;
@@ -279,7 +279,7 @@ inst:
  */
 |	LTYPEJ cond con ',' expr ',' spreg ',' creg ',' creg oexpr
  	{
-		LAddr g;
+		Addr g;
  
  		g = nullgen;
  		g.type = D_CONST;

src/cmd/6a/a.y の変更点:

--- a/src/cmd/6a/a.y
+++ b/src/cmd/6a/a.y
@@ -40,7 +40,7 @@
  vlong	lval;
  double	dval;
  char	sval[8];
-	LAddr	addr;
+	Addr	addr;
  	Addr2	addr2;
 }
 %left	'|'

src/cmd/8a/a.y の変更点:

--- a/src/cmd/8a/a.y
+++ b/src/cmd/8a/a.y
@@ -44,7 +44,7 @@
  } con2;
  double	dval;
  char	sval[8];
-	LAddr	addr;
+	Addr	addr;
  	Addr2	addr2;
 }
 %left	'|'

コアとなるコードの解説

これらの変更は非常にシンプルで、LAddrという文字列をAddrに置き換えるだけです。

Yacc/Bisonの文法定義ファイル(.y)では、%unionディレクティブを使って、パーサが扱う様々な値の型を定義します。このコミットでは、%unionブロック内で定義されているaddrというフィールドの型がLAddrからAddrに変更されています。

例えば、src/cmd/5a/a.yの以下の部分が該当します。

%union{
	int32	lval;
	double	dval;
	char	sval[8];
	LAddr	addr; // ここが変更対象
}

このaddrフィールドは、アセンブリ命令のオペランドとしてアドレス値を扱う際に使用される共用体メンバーです。LAddrからAddrへの変更は、このアドレス型がGoのリンカや他のツールチェインコンポーネントで統一的にAddrとして扱われるようにするためのものです。

また、inst:ルール内のアクションブロック(C言語のコードが記述されている部分)でも、LAddr g;というローカル変数の宣言がAddr g;に変更されています。これは、パーサが構文解析中に一時的にアドレス値を保持するために使用する変数であり、型定義の変更に合わせて修正されています。

これらの変更は、Goツールチェインの内部的な型システムの一貫性を保ち、ビルド時のコンパイルエラーを防ぐための、クリーンアップかつ重要な修正と言えます。

関連リンク

参考にした情報源リンク

  • Yacc/Bisonのドキュメント (一般的な情報):
  • Go言語のツールチェインに関するドキュメント (一般的な情報):
  • Go言語のソースコード (コミット内容の理解のため):
    • src/cmd/5a/a.y (Goリポジトリ内)
    • src/cmd/6a/a.y (Goリポジトリ内)
    • src/cmd/8a/a.y (Goリポジトリ内)
  • Go言語のリンカに関する情報 (一般的な情報):
    • Go linker source code (e.g., src/cmd/link/internal/ld/)
    • "Go's linker" by Russ Cox (blog post or presentation if available) - このコミットの作者であるRuss Cox氏によるリンカに関する解説は、背景理解に非常に役立つ可能性がありますが、特定の記事への直接リンクは現時点では特定できません。