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

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

このコミットは、Goコンパイラおよびリンカのツールチェーン(cmd/8c, cmd/8g, cmd/8l)における、Plan 9環境でのコンパイル時に発生していた書式指定子の不一致に関する警告を修正するものです。具体的には、printf系の関数呼び出しにおいて、long long型の引数に対して誤った書式指定子(%d%ux)が使用されていた問題を、適切な書式指定子(%lld%llux)に修正することで解決しています。

コミット

commit 58005207d2404c8f6454c522c44d44926974496d
Author: David du Colombier <0intro@gmail.com>
Date:   Mon Dec 9 18:47:22 2013 -0500

    cmd/8c, cmd/8g, cmd/8l: fix Plan 9 warnings
    
    warning: src/cmd/8c/list.c:124 format mismatch d VLONG, arg 3
    warning: src/cmd/8c/list.c:134 format mismatch d VLONG, arg 3
    warning: src/cmd/8c/list.c:142 format mismatch d VLONG, arg 3
    warning: src/cmd/8c/list.c:152 format mismatch d VLONG, arg 3
    warning: src/cmd/8c/list.c:156 format mismatch d VLONG, arg 4
    warning: src/cmd/8c/list.c:160 format mismatch d VLONG, arg 4
    warning: src/cmd/8c/list.c:165 format mismatch d VLONG, arg 4
    warning: src/cmd/8c/list.c:167 format mismatch d VLONG, arg 3
    warning: src/cmd/8c/list.c:172 format mismatch d VLONG, arg 4
    warning: src/cmd/8c/list.c:174 format mismatch d VLONG, arg 3
    warning: src/cmd/8c/list.c:178 format mismatch d VLONG, arg 3
    warning: src/cmd/8c/list.c:184 format mismatch d VLONG, arg 3
    
    warning: src/cmd/8g/list.c:91 format mismatch d VLONG, arg 4
    warning: src/cmd/8g/list.c:100 format mismatch d VLONG, arg 4
    warning: src/cmd/8g/list.c:114 format mismatch d VLONG, arg 5
    warning: src/cmd/8g/list.c:118 format mismatch d VLONG, arg 5
    warning: src/cmd/8g/list.c:122 format mismatch d VLONG, arg 5
    warning: src/cmd/8g/list.c:126 format mismatch d VLONG, arg 5
    warning: src/cmd/8g/list.c:136 format mismatch d VLONG, arg 4
    
    warning: src/cmd/8l/list.c:107 format mismatch d VLONG, arg 4
    warning: src/cmd/8l/list.c:125 format mismatch ux VLONG, arg 4
    warning: src/cmd/8l/list.c:128 format mismatch ux VLONG, arg 4
    warning: src/cmd/8l/list.c:130 format mismatch d VLONG, arg 4
    warning: src/cmd/8l/list.c:134 format mismatch d VLONG, arg 5
    warning: src/cmd/8l/list.c:138 format mismatch d VLONG, arg 6
    warning: src/cmd/8l/list.c:143 format mismatch d VLONG, arg 5
    warning: src/cmd/8l/list.c:148 format mismatch d VLONG, arg 5
    warning: src/cmd/8l/list.c:150 format mismatch d VLONG, arg 4
    warning: src/cmd/8l/list.c:154 format mismatch d VLONG, arg 4
    warning: src/cmd/8l/list.c:158 format mismatch d VLONG, arg 4
    warning: src/cmd/8l/obj.c:132 format mismatch ux VLONG, arg 2
    
    R=golang-dev, rsc
    CC=golang-dev
    https://golang.org/cl/39710043

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

https://github.com/golang/go/commit/58005207d2404c8f6454c522c44d44926974496d

元コミット内容

このコミットは、Go言語のコンパイラ(8c8g)とリンカ(8l)のソースコードにおいて、Plan 9環境でコンパイルした際に発生する書式指定子の不一致に関する警告を修正するものです。具体的には、src/cmd/8c/list.csrc/cmd/8g/list.csrc/cmd/8l/list.csrc/cmd/8l/obj.cの各ファイルで、sprintfsnprintfといった書式付き出力関数において、long long型の引数(Plan 9の内部表現ではVLONGと示される)に対して、int型を想定する%dunsigned int型を想定する%uxといった書式指定子が誤って使用されていた箇所を、それぞれlong long int型を想定する%lldunsigned long long int型を想定する%lluxに修正しています。

変更の背景

Go言語の初期のツールチェーンは、Bell Labsが開発したオペレーティングシステムであるPlan 9のツールチェーン(8c, 8g, 8lなど)をベースにしていました。Plan 9のコンパイラは、C言語の標準ライブラリ関数であるprintf系の書式指定子に対して非常に厳格な型チェックを行います。

このコミットが修正している警告は、まさにこの厳格な型チェックに起因するものです。Goのコンパイラやリンカの内部処理では、オフセット値やアドレスなど、64ビット整数(long long型)を扱う場面が多く存在します。しかし、これらの値を文字列に変換して出力する際に、誤って32ビット整数を想定する%d%uxといった書式指定子を使用していたため、Plan 9のコンパイラが「d(またはux)書式指定子にはint(またはunsigned int)が期待されるが、実際にはVLONGlong long)が渡されている」という警告を発していました。

これらの警告は、プログラムの動作に直接的なバグを引き起こすものではありませんでしたが、潜在的な問題を示唆し、コンパイル時のノイズとなっていました。開発プロセスにおいて警告をゼロに保つことは、将来的なバグの混入を防ぎ、コードの品質を維持するために重要です。そのため、このコミットでは、これらの書式指定子の不一致警告を解消し、コードの健全性を向上させることを目的としています。

前提知識の解説

Plan 9とGo言語のツールチェーン

  • Plan 9 from Bell Labs: ベル研究所で開発された分散オペレーティングシステムです。その設計思想やツールチェーンは、Go言語の開発に大きな影響を与えました。特に、Go言語の初期のコンパイラやリンカは、Plan 9のツールチェーン(8c, 8g, 8lなど)の構造や命名規則を踏襲していました。
  • 8c, 8g, 8l:
    • 8c: x86アーキテクチャ向けのCコンパイラ。Go言語のコンパイラ自体はC言語で書かれていたため、このコンパイラでビルドされていました。
    • 8g: x86アーキテクチャ向けのGoコンパイラ。Goソースコードをアセンブリコードに変換します。
    • 8l: x86アーキテクチャ向けのリンカ。コンパイルされたオブジェクトファイルを結合して実行可能ファイルを生成します。 これらのツールは、Go言語の初期のビルドシステムにおいて中心的な役割を担っていました。

C言語の書式指定子と型

C言語のprintfsprintfなどの書式付き出力関数では、出力する変数の型に合わせて適切な書式指定子を使用する必要があります。

  • %d: 符号付き10進整数(通常はint型、32ビット)
  • %ld: 符号付き10進整数(long int型)
  • %lld: 符号付き10進整数(long long int型、64ビット)
  • %u: 符号なし10進整数(通常はunsigned int型)
  • %lu: 符号なし10進整数(unsigned long int型)
  • %llu: 符号なし10進整数(unsigned long long int型)
  • %x: 符号なし16進整数(通常はunsigned int型)
  • %lx: 符号なし16進整数(unsigned long int型)
  • %llx: 符号なし16進整数(unsigned long long int型)

書式指定子と引数の型が一致しない場合、コンパイラは警告を発したり、未定義の動作を引き起こす可能性があります。特に、引数のサイズが書式指定子が期待するサイズと異なる場合(例: 64ビット整数を%dで出力しようとする場合)、値が切り捨てられたり、メモリ上の予期しないデータが読み込まれたりする可能性があります。

VLONG

Plan 9のコンパイラが警告メッセージで示すVLONGは、その内部で定義されているデータ型で、通常は64ビット整数(long long型に相当)を指します。この警告は、コンパイラがVLONG型の引数を受け取ったにもかかわらず、int型を期待する書式指定子(%d)が使われていることを指摘しています。

技術的詳細

このコミットの技術的詳細は、C言語における書式指定子の厳密な型マッチングに集約されます。Goのコンパイラとリンカのコードベースでは、a->offseta->offset2といったフィールドが、おそらく64ビットのオフセット値やアドレスを格納するためにlong long型(またはそれに相当する型)として定義されていました。

これらの値をsprintfsnprintf関数で文字列に変換する際、開発者が誤って32ビット整数用の書式指定子である%d(10進数)や%ux(符号なし16進数)を使用していました。Plan 9のコンパイラは、このような型と書式指定子の不一致を検出し、警告として報告します。

例えば、src/cmd/8c/list.cの以下の行が修正されています。

// 修正前
sprintf(str, "$%d-%d", a->offset, a->offset2);
// 修正後
sprintf(str, "$%lld-%d", a->offset, a->offset2); // a->offsetがlong long型

この例では、a->offsetlong long型であるにもかかわらず、%dが使われていたため、%lldに修正されています。a->offset2は引き続き%dが使われていることから、こちらはint型であると推測できます。

同様に、src/cmd/8l/obj.cでは、unsigned long long型の値に対して%uxが使われていた箇所が%lluxに修正されています。

// 修正前
print("warning: -D0x%ux is ignored because of -R0x%ux\\n", INITDAT, INITRND);
// 修正後
print("warning: -D0x%llux is ignored because of -R0x%ux\\n", INITDAT, INITRND); // INITDATがunsigned long long型

これらの修正は、単に警告を消すだけでなく、コードの正確性と移植性を向上させます。異なるコンパイラやプラットフォームでは、書式指定子の不一致がより深刻な問題(クラッシュや誤った値の出力)を引き起こす可能性があるため、このような修正はベストプラクティスとされています。

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

このコミットでは、以下の4つのファイルが変更されています。

  1. src/cmd/8c/list.c
  2. src/cmd/8g/list.c
  3. src/cmd/8l/list.c
  4. src/cmd/8l/obj.c

これらのファイルは、Go言語のx86アーキテクチャ向けコンパイラ(8c8g)とリンカ(8l)の内部で、アセンブリコードのリスト出力やオブジェクトファイルの処理に関連する部分です。変更のほとんどは、sprintfまたはsnprintf関数呼び出しにおける書式指定子の変更です。

具体的には、%d%lldに、%ux%lluxに変更されています。

コアとなるコードの解説

変更された各ファイルは、Goのツールチェーンにおける異なる役割を担っています。

  • src/cmd/8c/list.c: Cコンパイラ8cのリスト出力部分。アセンブリコードの生成過程で、定数、オフセット、シンボル名などを文字列として整形する際に使用されます。Dconv関数内で、a->offseta->offset2といった構造体メンバーの値を整形する際に書式指定子が修正されています。
  • src/cmd/8g/list.c: Goコンパイラ8gのリスト出力部分。8cと同様に、Goコードから生成されるアセンブリコードの要素(オフセット、シンボルなど)を整形する際に使用されます。ここでもDconv関数が修正の中心です。
  • src/cmd/8l/list.c: リンカ8lのリスト出力部分。リンク処理中に、プログラムカウンタ(PC)のオフセット、外部シンボル、自動変数、パラメータなどのアドレスやオフセットを整形して出力する際に使用されます。Dconv関数内で、a->offsetbigP->pcond->pcといった値の書式指定子が修正されています。
  • src/cmd/8l/obj.c: リンカ8lのオブジェクトファイル処理部分。初期化データやランダム化に関する警告メッセージを出力する際に使用されます。archinit関数内で、INITDATという値の書式指定子が%uxから%lluxに修正されています。これは、INITDATunsigned long long型の値であるためです。

これらの変更は、Goのツールチェーンが内部で扱うアドレスやオフセットが64ビット幅であることを反映し、それらの値を正しく文字列に変換するための修正です。これにより、Plan 9の厳格なコンパイラでも警告なしにビルドできるようになり、コードの正確性と保守性が向上しました。

関連リンク

  • Go言語の公式リポジトリ: https://github.com/golang/go
  • Go言語の初期のツールチェーンに関する議論(Plan 9との関連): Go言語の歴史や設計思想に関するドキュメントやブログ記事を参照すると、Plan 9の影響について詳しく知ることができます。

参考にした情報源リンク

  • C言語のprintf書式指定子に関するドキュメント(例: cppreference.com, man pages)
  • Plan 9のドキュメント(特にfmtライブラリやコンパイラの警告に関する情報)
  • Go言語の初期のツールチェーンに関する設計ドキュメントやメーリングリストのアーカイブ(golang-devなど)
  • コミットメッセージに記載されているGoのコードレビューシステムへのリンク: https://golang.org/cl/39710043 (現在はGo Gerritにリダイレクトされます)