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

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

このコミットは、Go言語のランタイムおよびリンカに関連する2つのファイル、src/cmd/ld/pcln.csrc/libmach/sym.c におけるPlan 9環境でのコンパイル時の警告を修正するものです。具体的には、未使用の変数に関する警告と、非割り込み可能な一時変数に関する警告に対処しています。

コミット

commit ef0100c7d73acdc0403fe82664be29c2d6c336f4
Author: David du Colombier <0intro@gmail.com>
Date:   Wed Dec 18 20:19:59 2013 +0100

    libmach, cmd/8l: fix Plan 9 warnings
    
    warning: src/libmach/sym.c:1861 non-interruptable temporary
    warning: src/cmd/8l/../ld/pcln.c:29 set and not used: p
    
    R=golang-dev, gobot, rsc
    CC=golang-dev
    https://golang.org/cl/40500043

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

https://github.com/golang/go/commit/ef0100c7d73acdc0403fe82664be29c2d6c336f4

元コミット内容

libmach, cmd/8l: fix Plan 9 warnings
    
warning: src/libmach/sym.c:1861 non-interruptable temporary
warning: src/cmd/8l/../ld/pcln.c:29 set and not used: p

変更の背景

このコミットは、Go言語のビルドプロセスにおいて、Plan 9オペレーティングシステム環境で発生していたコンパイル警告を解消することを目的としています。Plan 9はベル研究所で開発された分散オペレーティングシステムであり、Go言語の開発初期にはその影響を強く受けていました。Goのツールチェイン(特にリンカやデバッガ関連のコンポーネント)は、Plan 9の設計思想や一部のユーティリティを継承している部分がありました。

報告された警告は以下の2点です。

  1. src/libmach/sym.c:1861 non-interruptable temporary: この警告は、libmach(Goのデバッガやプロファイラがシンボル情報を扱うためのライブラリ)内のコードが、Plan 9のコンパイラが「非割り込み可能な一時変数」と見なすようなパターンを使用していることを示唆しています。これは、特定の最適化やコード生成の文脈で、コンパイラが潜在的な問題(例えば、割り込みハンドラ内で安全でない操作が行われる可能性)を検出した場合に発生することがあります。
  2. src/cmd/8l/../ld/pcln.c:29 set and not used: p: この警告は、Goのリンカ(8lはx86アーキテクチャ向けのリンカを指す)の一部であるpcln.cファイル内で、変数pが値が設定されたにもかかわらず、その後使用されていないことを示しています。これは典型的なデッドコードや論理エラーの兆候であり、コンパイラが最適化の過程で検出します。

これらの警告は、直接的なバグを引き起こすものではないかもしれませんが、コードの品質を低下させ、将来的なメンテナンスやデバッグを困難にする可能性があります。また、クリーンなビルド環境を維持することは、開発者が重要なエラーメッセージを見落とさないためにも重要です。したがって、これらの警告を修正することは、Goプロジェクトのコードベースの健全性を保つ上で必要な作業でした。

前提知識の解説

  • Plan 9 from Bell Labs: ベル研究所で開発された分散オペレーティングシステム。Go言語の設計思想や一部のツール(特にアセンブラやリンカ)に影響を与えています。Plan 9のツールチェインは、Goの初期のビルドシステムで利用されていました。
  • libmach: Goのデバッグツールやプロファイリングツールが、実行中のGoプログラムのメモリレイアウト、シンボルテーブル、スタックトレースなどを解析するために使用するライブラリです。Goのバイナリ形式やランタイムの内部構造を理解し、それらの情報にアクセスするための低レベルな機能を提供します。
  • cmd/8l (リンカ): Goのビルドツールチェインの一部で、コンパイルされたオブジェクトファイル(.oファイル)を結合して実行可能なバイナリを生成する役割を担います。8lはx86アーキテクチャ(32ビット)向けのリンカを指し、6lはx86-64、5lはARMなど、アーキテクチャごとに異なるリンカが存在しました(現在はcmd/linkに統合されています)。
  • pcln.c: "PC-Line"情報の処理に関連するコードが含まれるファイルです。PC-Line情報とは、プログラムカウンタ(PC)のアドレスとソースコードの行番号とのマッピングを指します。これはデバッガがスタックトレースを表示したり、プロファイラが実行プロファイルを生成したりする際に不可欠な情報です。Goのバイナリには、このPC-Line情報が埋め込まれています。
  • sym.c: シンボルテーブルの処理に関連するコードが含まれるファイルです。シンボルテーブルは、プログラム内の変数、関数、型などの名前と、それらがメモリ上でどこに配置されているか(アドレス)をマッピングする情報を含みます。デバッガやリンカがシンボルを解決するために使用します。
  • non-interruptable temporary 警告: Plan 9のコンパイラが生成する可能性のある警告の一つ。特定のコードパターンが、割り込み処理中に安全でない一時変数の使用を引き起こす可能性があると判断された場合に発生します。これは、コンパイラがコードの実行コンテキスト(特に割り込みの可能性)を考慮して、より厳密なチェックを行うことによって生じます。
  • set and not used 警告: 変数が宣言され、値が代入されたにもかかわらず、その後のコードで一度も使用されていない場合にコンパイラが生成する警告です。これは、プログラミングミス、デッドコード、または意図しない副作用の可能性を示唆します。

技術的詳細

このコミットは、2つの異なるファイルにおける2つの異なる警告に対処しています。

1. src/cmd/ld/pcln.c の修正

警告: warning: src/cmd/8l/../ld/pcln.c:29 set and not used: p

この警告は、addvarint 関数内で変数 p が宣言され、値が代入されたものの、その後の行でその値が使用されていないことを示していました。

元のコード:

// src/cmd/ld/pcln.c
// ...
addvarint(Pcdata *d, uint32 val)
{
	uint32 v;
	int n;
	uint8 *p; // 変数pがここで宣言される

	n = 1;
	for(v = val; v >= 0x80; v >>= 7)
		n++;
	
	// ... (メモリ確保などの処理)

	p = d->p + d->n; // pに値が代入される
	for(v = val; v >= 0x80; v >>= 7)
		*p++ = v | 0x80;
	*p++ = v; // ここでpがインクリメントされるが、その後のpの値は使用されない
	d->n += n;
}

修正後のコード:

// src/cmd/ld/pcln.c
// ...
addvarint(Pcdata *d, uint32 val)
{
	uint32 v;
	int n;
	uint8 *p;

	n = 1;
	for(v = val; v >= 0x80; v >>= 7)
		n++;
	
	// ... (メモリ確保などの処理)

	p = d->p + d->n;
	for(v = val; v >= 0x80; v >>= 7)
		*p++ = v | 0x80;
	*p = v; // p++ が p に変更された
	d->n += n;
}

変更点: *p++ = v;*p = v; に変更されました。 元のコードでは、最後のバイトを書き込んだ後に p がインクリメントされていましたが、そのインクリメントされた p の値はその後どこでも使用されていませんでした。これは、pd->p + d->n の位置から開始し、可変長整数(varint)の各バイトを書き込むたびにインクリメントされ、最終的に書き込みが完了した次の位置を指すように意図されていたと考えられます。しかし、d->nn だけ増加しており、p の最終的な値は d->n の更新には影響しませんでした。*p = v; に変更することで、最後のバイトを書き込んだ後も p の値は変化せず、未使用のインクリメントが解消され、警告が抑制されます。

2. src/libmach/sym.c の修正

警告: warning: src/libmach/sym.c:1861 non-interruptable temporary

この警告は、libmach/sym.chavefile ラベルの後のコードブロックで発生していました。具体的には、fpclpc の初期化に関するものです。

元のコード:

// src/libmach/sym.c
// ...
havefile:
	// ...
	fpc = lpc = entry; // fpcとlpcが同時にentryで初期化される
	fstartpc = fpc;
	while(step(&fp, &fpc, &fval, fpc==entry)) {
	// ...

修正後のコード:

// src/libmach/sym.c
// ...
havefile:
	// ...
	lpc = entry; // lpcのみがentryで初期化される
	fpc = lpc;   // その後fpcがlpcの値で初期化される
	fstartpc = fpc;
	while(step(&fp, &fpc, &fval, fpc==entry)) {
	// ...

変更点: fpc = lpc = entry;lpc = entry; fpc = lpc; に変更されました。 この変更は、fpclpc の初期化順序を明示的に分離することで、Plan 9コンパイラが「非割り込み可能な一時変数」と見なすパターンを回避することを目的としています。C言語では、a = b = c; のような連鎖代入は、右から左に評価されます(b = c; の結果が a に代入される)。この場合、entry の値が一時的に保持され、それが lpc に代入され、さらにその一時変数の値が fpc に代入されるという一連の操作が行われます。Plan 9のコンパイラは、この「一時変数」の生成と使用が、特定の割り込みコンテキストで問題を引き起こす可能性があると判断したのかもしれません。

lpc = entry; fpc = lpc; とすることで、entry の値がまず lpc に直接代入され、その後 lpc の値が fpc に代入されます。これにより、コンパイラが懸念するような「非割り込み可能な一時変数」のパターンが解消されると考えられます。これは、コードの論理的な意味を変えることなく、コンパイラがより安全と判断するようなコード生成を促すための、コンパイラフレンドリーな修正と言えます。

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

src/cmd/ld/pcln.c

--- a/src/cmd/ld/pcln.c
+++ b/src/cmd/ld/pcln.c
@@ -26,7 +26,7 @@ addvarint(Pcdata *d, uint32 val)
 	p = d->p + d->n;
 	for(v = val; v >= 0x80; v >>= 7)
 		*p++ = v | 0x80;
-	*p++ = v;
+	*p = v;
 	d->n += n;
 }
 

src/libmach/sym.c

--- a/src/libmach/sym.c
+++ b/src/libmach/sym.c
@@ -1858,7 +1858,8 @@ havefile:
 		fp = pcline + pcswal(*(uint32*)(func+FuncPCFile));
 		lp = pcline + pcswal(*(uint32*)(func+FuncPCLine));
 		fval = lval = -1;
-		fpc = lpc = entry;
+		lpc = entry;
+		fpc = lpc;
 		fstartpc = fpc;
 		while(step(&fp, &fpc, &fval, fpc==entry)) {
 			if(fval == fno && fstartpc < fpc) {

コアとなるコードの解説

src/cmd/ld/pcln.c の変更

addvarint 関数は、可変長整数(varint)をバイト列として Pcdata 構造体内のバッファに書き込む役割を担っています。varintは、小さな数値を少ないバイト数で表現し、大きな数値をより多くのバイト数で表現するエンコーディング方式です。Goのバイナリでは、PC-Line情報などのメタデータを効率的に格納するために使用されます。

元のコードの *p++ = v; は、最後のバイト v を現在の p が指すアドレスに書き込み、その後 p をインクリメントしていました。しかし、このインクリメントされた p の値は、この関数内でその後一切使用されていませんでした。これは、コンパイラが「p が設定されたが使用されていない」という警告を出す原因となっていました。

修正後の *p = v; は、最後のバイト v を現在の p が指すアドレスに書き込むだけで、p をインクリメントしません。これにより、不要なインクリメントが削除され、コンパイラの警告が解消されます。この変更は、関数の論理的な動作には影響を与えません。なぜなら、d->n が書き込まれたバイト数 n だけ増加することで、次の書き込み位置が正しく更新されるためです。

src/libmach/sym.c の変更

sym.c は、Goの実行可能ファイルからシンボル情報を読み取り、解析するためのコードを含んでいます。この特定のコードブロックは、PC-Line情報(プログラムカウンタとソースコードの行番号のマッピング)を処理する部分に関連しています。fpc (file program counter) と lpc (line program counter) は、それぞれファイルと行番号のPC情報を追跡するための変数です。entry は、関数のエントリポイントのアドレスを示します。

元のコードの fpc = lpc = entry; は、entry の値を lpcfpc の両方に代入する連鎖代入です。C言語の連鎖代入は、一時的な値を生成することがあります。Plan 9のコンパイラは、この一時変数の生成が、特定の割り込みコンテキストにおいて「非割り込み可能な一時変数」として問題を引き起こす可能性があると判断したと考えられます。これは、コンパイラが割り込み処理の安全性を確保するために、より厳密なルールを適用しているためです。

修正後の lpc = entry; fpc = lpc; は、まず entry の値を lpc に代入し、次に lpc の値を fpc に代入するという、より明示的な2段階の代入を行います。この変更により、コンパイラが懸念するような一時変数の生成パターンが回避され、警告が解消されます。この修正もまた、コードの論理的な意味を変えることなく、コンパイラがより安全と判断するようなコードパターンに適合させるためのものです。

関連リンク

参考にした情報源リンク

  • Go言語のソースコード (GitHub): https://github.com/golang/go
  • Plan 9のコンパイラ警告に関する一般的な情報 (Stack Overflow, フォーラムなど): (具体的なリンクは検索結果によるため、ここでは一般的なカテゴリを示す)
    • "Plan 9 compiler warnings non-interruptable temporary"
    • "C language set but not used warning"
  • Go言語のリンカ (cmd/link) およびデバッグ情報に関するドキュメント (Goの公式ドキュメントやブログ記事): (具体的なリンクは検索結果によるため、ここでは一般的なカテゴリを示す)
    • "Go linker internals"
    • "Go PC-Line table"
    • "Go symbol table"
  • Goのコードレビューシステム (Gerrit): https://go-review.googlesource.com/ (コミットメッセージに記載されている https://golang.org/cl/40500043 はGerritの変更リストへのリンクです)

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

このコミットは、Go言語のランタイムおよびリンカに関連する2つのファイル、src/cmd/ld/pcln.csrc/libmach/sym.c におけるPlan 9環境でのコンパイル時の警告を修正するものです。具体的には、未使用の変数に関する警告と、非割り込み可能な一時変数に関する警告に対処しています。

コミット

commit ef0100c7d73acdc0403fe82664be29c2d6c336f4
Author: David du Colombier <0intro@gmail.com>
Date:   Wed Dec 18 20:19:59 2013 +0100

    libmach, cmd/8l: fix Plan 9 warnings
    
    warning: src/libmach/sym.c:1861 non-interruptable temporary
    warning: src/cmd/8l/../ld/pcln.c:29 set and not used: p
    
    R=golang-dev, gobot, rsc
    CC=golang-dev
    https://golang.org/cl/40500043

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

https://github.com/golang/go/commit/ef0100c7d73acdc0403fe82664be29c2d6c336f4

元コミット内容

libmach, cmd/8l: fix Plan 9 warnings
    
warning: src/libmach/sym.c:1861 non-interruptable temporary
warning: src/cmd/8l/../ld/pcln.c:29 set and not used: p

変更の背景

このコミットは、Go言語のビルドプロセスにおいて、Plan 9オペレーティングシステム環境で発生していたコンパイル警告を解消することを目的としています。Plan 9はベル研究所で開発された分散オペレーティングシステムであり、Go言語の開発初期にはその影響を強く受けていました。Goのツールチェイン(特にリンカやデバッガ関連のコンポーネント)は、Plan 9の設計思想や一部のユーティリティを継承している部分がありました。

報告された警告は以下の2点です。

  1. src/libmach/sym.c:1861 non-interruptable temporary: この警告は、libmach(Goのデバッガやプロファイラがシンボル情報を扱うためのライブラリ)内のコードが、Plan 9のコンパイラが「非割り込み可能な一時変数」と見なすようなパターンを使用していることを示唆しています。これは、特定の最適化やコード生成の文脈で、コンパイラが潜在的な問題(例えば、割り込みハンドラ内で安全でない操作が行われる可能性)を検出した場合に発生することがあります。
  2. src/cmd/8l/../ld/pcln.c:29 set and not used: p: この警告は、Goのリンカ(8lはx86アーキテクチャ向けのリンカを指す)の一部であるpcln.cファイル内で、変数pが値が設定されたにもかかわらず、その後使用されていないことを示しています。これは典型的なデッドコードや論理エラーの兆候であり、コンパイラが最適化の過程で検出します。

これらの警告は、直接的なバグを引き起こすものではないかもしれませんが、コードの品質を低下させ、将来的なメンテナンスやデバッグを困難にする可能性があります。また、クリーンなビルド環境を維持することは、開発者が重要なエラーメッセージを見落とさないためにも重要です。したがって、これらの警告を修正することは、Goプロジェクトのコードベースの健全性を保つ上で必要な作業でした。

前提知識の解説

  • Plan 9 from Bell Labs: ベル研究所で開発された分散オペレーティングシステム。Go言語の設計思想や一部のツール(特にアセンブラやリンカ)に影響を与えています。Plan 9のツールチェインは、Goの初期のビルドシステムで利用されていました。
  • libmach: Goのデバッグツールやプロファイリングツールが、実行中のGoプログラムのメモリレイアウト、シンボルテーブル、スタックトレースなどを解析するために使用するライブラリです。Goのバイナリ形式やランタイムの内部構造を理解し、それらの情報にアクセスするための低レベルな機能を提供します。
  • cmd/8l (リンカ): Goのビルドツールチェインの一部で、コンパイルされたオブジェクトファイル(.oファイル)を結合して実行可能なバイナリを生成する役割を担います。8lはx86アーキテクチャ(32ビット)向けのリンカを指し、6lはx86-64、5lはARMなど、アーキテクチャごとに異なるリンカが存在しました(現在はcmd/linkに統合されています)。
  • pcln.c: "PC-Line"情報の処理に関連するコードが含まれるファイルです。PC-Line情報とは、プログラムカウンタ(PC)のアドレスとソースコードの行番号とのマッピングを指します。これはデバッガがスタックトレースを表示したり、プロファイラが実行プロファイルを生成したりする際に不可欠な情報です。Goのバイナリには、このPC-Line情報が埋め込まれています。
  • sym.c: シンボルテーブルの処理に関連するコードが含まれるファイルです。シンボルテーブルは、プログラム内の変数、関数、型などの名前と、それらがメモリ上でどこに配置されているか(アドレス)をマッピングする情報を含みます。デバッガやリンカがシンボルを解決するために使用します。
  • non-interruptable temporary 警告: Plan 9のコンパイラが生成する可能性のある警告の一つ。特定のコードパターンが、割り込み処理中に安全でない一時変数の使用を引き起こす可能性があると判断された場合に発生します。これは、コンパイラがコードの実行コンテキスト(特に割り込みの可能性)を考慮して、より厳密なチェックを行うことによって生じます。
  • set and not used 警告: 変数が宣言され、値が代入されたにもかかわらず、その後のコードで一度も使用されていない場合にコンパイラが生成する警告です。これは、プログラミングミス、デッドコード、または意図しない副作用の可能性を示唆します。

技術的詳細

このコミットは、2つの異なるファイルにおける2つの異なる警告に対処しています。

1. src/cmd/ld/pcln.c の修正

警告: warning: src/cmd/8l/../ld/pcln.c:29 set and not used: p

この警告は、addvarint 関数内で変数 p が宣言され、値が代入されたものの、その後の行でその値が使用されていないことを示していました。

元のコード:

// src/cmd/ld/pcln.c
// ...
addvarint(Pcdata *d, uint32 val)
{
	uint32 v;
	int n;
	uint8 *p; // 変数pがここで宣言される

	n = 1;
	for(v = val; v >= 0x80; v >>= 7)
		n++;
	
	// ... (メモリ確保などの処理)

	p = d->p + d->n; // pに値が代入される
	for(v = val; v >= 0x80; v >>= 7)
		*p++ = v | 0x80;
	*p++ = v; // ここでpがインクリメントされるが、その後のpの値は使用されない
	d->n += n;
}

修正後のコード:

// src/cmd/ld/pcln.c
// ...
addvarint(Pcdata *d, uint32 val)
{
	uint32 v;
	int n;
	uint8 *p;

	n = 1;
	for(v = val; v >= 0x80; v >>= 7)
		n++;
	
	// ... (メモリ確保などの処理)

	p = d->p + d->n;
	for(v = val; v >= 0x80; v >>= 7)
		*p++ = v | 0x80;
	*p = v; // p++ が p に変更された
	d->n += n;
}

変更点: *p++ = v;*p = v; に変更されました。 元のコードでは、最後のバイトを書き込んだ後に p がインクリメントされていましたが、そのインクリメントされた p の値はその後どこでも使用されていませんでした。これは、pd->p + d->n の位置から開始し、可変長整数(varint)の各バイトを書き込むたびにインクリメントされ、最終的に書き込みが完了した次の位置を指すように意図されていたと考えられます。しかし、d->nn だけ増加しており、p の最終的な値は d->n の更新には影響しませんでした。*p = v; に変更することで、最後のバイトを書き込んだ後も p の値は変化せず、未使用のインクリメントが解消され、警告が抑制されます。

2. src/libmach/sym.c の修正

警告: warning: src/libmach/sym.c:1861 non-interruptable temporary

この警告は、libmach/sym.chavefile ラベルの後のコードブロックで発生していました。具体的には、fpclpc の初期化に関するものです。

元のコード:

// src/libmach/sym.c
// ...
havefile:
	// ...
	fpc = lpc = entry; // fpcとlpcが同時にentryで初期化される
	fstartpc = fpc;
	while(step(&fp, &fpc, &fval, fpc==entry)) {
	// ...

修正後のコード:

// src/libmach/sym.c
// ...
havefile:
	// ...
	lpc = entry; // lpcのみがentryで初期化される
	fpc = lpc;   // その後fpcがlpcの値で初期化される
	fstartpc = fpc;
	while(step(&fp, &fpc, &fval, fpc==entry)) {
	// ...

変更点: fpc = lpc = entry;lpc = entry; fpc = lpc; に変更されました。 この変更は、fpclpc の初期化順序を明示的に分離することで、Plan 9コンパイラが「非割り込み可能な一時変数」と見なすパターンを回避することを目的としています。C言語では、a = b = c; のような連鎖代入は、右から左に評価されます(b = c; の結果が a に代入される)。この場合、entry の値が一時的に保持され、それが lpc に代入され、さらにその一時変数の値が fpc に代入されるという一連の操作が行われます。Plan 9のコンパイラは、この「一時変数」の生成と使用が、特定の割り込みコンテキストで問題を引き起こす可能性があると判断したのかもしれません。

lpc = entry; fpc = lpc; とすることで、entry の値がまず lpc に直接代入され、その後 lpc の値が fpc に代入されます。これにより、コンパイラが懸念するような「非割り込み可能な一時変数」のパターンが解消されると考えられます。これは、コードの論理的な意味を変えることなく、コンパイラがより安全と判断するようなコード生成を促すための、コンパイラフレンドリーな修正と言えます。

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

src/cmd/ld/pcln.c

--- a/src/cmd/ld/pcln.c
+++ b/src/cmd/ld/pcln.c
@@ -26,7 +26,7 @@ addvarint(Pcdata *d, uint32 val)
 	p = d->p + d->n;
 	for(v = val; v >= 0x80; v >>= 7)
 		*p++ = v | 0x80;
-	*p++ = v;
+	*p = v;
 	d->n += n;
 }
 

src/libmach/sym.c

--- a/src/libmach/sym.c
+++ b/src/libmach/sym.c
@@ -1858,7 +1858,8 @@ havefile:
 		fp = pcline + pcswal(*(uint32*)(func+FuncPCFile));
 		lp = pcline + pcswal(*(uint32*)(func+FuncPCLine));
 		fval = lval = -1;
-		fpc = lpc = entry;
+		lpc = entry;
+		fpc = lpc;
 		fstartpc = fpc;
 		while(step(&fp, &fpc, &fval, fpc==entry)) {
 			if(fval == fno && fstartpc < fpc) {

コアとなるコードの解説

src/cmd/ld/pcln.c の変更

addvarint 関数は、可変長整数(varint)をバイト列として Pcdata 構造体内のバッファに書き込む役割を担っています。varintは、小さな数値を少ないバイト数で表現し、大きな数値をより多くのバイト数で表現するエンコーディング方式です。Goのバイナリでは、PC-Line情報などのメタデータを効率的に格納するために使用されます。

元のコードの *p++ = v; は、最後のバイト v を現在の p が指すアドレスに書き込み、その後 p をインクリメントしていました。しかし、このインクリメントされた p の値は、この関数内でその後一切使用されていませんでした。これは、コンパイラが「p が設定されたが使用されていない」という警告を出す原因となっていました。

修正後の *p = v; は、最後のバイト v を現在の p が指すアドレスに書き込むだけで、p をインクリメントしません。これにより、不要なインクリメントが削除され、コンパイラの警告が解消されます。この変更は、関数の論理的な動作には影響を与えません。なぜなら、d->n が書き込まれたバイト数 n だけ増加することで、次の書き込み位置が正しく更新されるためです。

src/libmach/sym.c の変更

sym.c は、Goの実行可能ファイルからシンボル情報を読み取り、解析するためのコードを含んでいます。この特定のコードブロックは、PC-Line情報(プログラムカウンタとソースコードの行番号のマッピング)を処理する部分に関連しています。fpc (file program counter) と lpc (line program counter) は、それぞれファイルと行番号のPC情報を追跡するための変数です。entry は、関数のエントリポイントのアドレスを示します。

元のコードの fpc = lpc = entry; は、entry の値を lpcfpc の両方に代入する連鎖代入です。C言語の連鎖代入は、一時的な値を生成することがあります。Plan 9のコンパイラは、この一時変数の生成が、特定の割り込みコンテキストにおいて「非割り込み可能な一時変数」として問題を引き起こす可能性があると判断したと考えられます。これは、コンパイラが割り込み処理の安全性を確保するために、より厳密なルールを適用しているためです。

修正後の lpc = entry; fpc = lpc; は、まず entry の値を lpc に代入し、次に lpc の値を fpc に代入するという、より明示的な2段階の代入を行います。この変更により、コンパイラが懸念するような一時変数の生成パターンが回避され、警告が解消されます。この修正もまた、コードの論理的な意味を変えることなく、コンパイラがより安全と判断するようなコードパターンに適合させるためのものです。

関連リンク

参考にした情報源リンク

  • Go言語のソースコード (GitHub): https://github.com/golang/go
  • Go言語のリンカ (cmd/link) およびデバッグ情報に関するドキュメント (Goの公式ドキュメントやブログ記事): (具体的なリンクは検索結果によるため、ここでは一般的なカテゴリを示す)
    • "Go linker internals"
    • "Go PC-Line table"
    • "Go symbol table"
  • Goのコードレビューシステム (Gerrit): https://go-review.googlesource.com/ (コミットメッセージに記載されている https://golang.org/cl/40500043 はGerritの変更リストへのリンクです)
  • Plan 9のコンパイラ警告に関する一般的な情報 (Stack Overflow, フォーラムなど):
    • "Plan 9 compiler warnings non-interruptable temporary"
    • "C language set but not used warning"